对象引用具有固有的方向性;关联是从一个对象到另一个对象。它们是指针。如果对象之间的关联应该在两个方向导航,就必须定义两次关联,在每个关联的类中定义一次。你已经在领域模型类中见过:
public class User{ private Set billingDetails; ... } public class BillingDetails{ private User user; ... }另一方面,外键关联不是生来就有方向性。导航(navigation)对于关系型数据模型没有任何意义,因为可以用表联结(table join)和投影创建任意的数据关联。
不可能只看Java类就确定一个单向关联的多样性。Java关联可以有多对多(many-to-many)的多样性。例如,类可以看起来像下面这样:
public class User{ private Set billingDetails; ... } public class BillingDetails{ private Set users; ... }另一方面,表关联始终是一对多(one-to-many)或者一对一(one-to-one)。通过查看外键的定义,你立即就会知道多样性。
你如果想在一个关系数据库中表示一个多对多的关联,就必须引入一张新表,称作链接表(link table)。这个表不会出现在领域模型中。对于我们的例子来说,如果认为用户和帐单信息之间的关系为多对多,链接表就可以定义如下:
create table USER_BILLING_DETAILS( USER_ID bigint foreign key references USERS, BILLING_DETAILS_ID bigint foreign key references BILLING_DETAILS, PRIMARY KEY(USER_ID,BILLING_DETAILS_ID) );
因此,使用SQL有效地访问关系型数据通常需要在有关的表之间使用联结。获取数据时联结中包括的表数目决定了能够在内存中遍历对象网络的深度。例如,如果需要获取一个User,而对用户的帐单明细不感兴趣,可以编写这个简单的查询:
select * from USERS u where u.USER_ID = 123
另一方面,如果需要获取一个User,随便访问每个关联的BillingDetails实例(比如,列出用户的所有信用卡),可以编写一个不同的查询:
select * from USERS u left outer join BILLING_DETAILS bd on bd.USER_ID = u.USER_ID where u.USER_ID = 123;另一方面,只有当对象被初次访问时,所有对象持久化解决方案才提供抓取关联对象的数据的功能。然而,这种渐进风格(piecemeal)的数据访问在关系数据库的上下文中效率很低,因为它要给每个节点或者每个被访问的对象网络的集合执行一条语句。这就是可以的n+1查询问题(n+1 select problem)。
刚开始学Hibernate,正好老师给了一本Hibernate的电子书,就打算花些时间学习深入下。
这3段笔记中,主要从为什么持久化、SQL认知、面向对象操作SQL到领域模型与关系模型范示的不匹配。
主要对领域模型与关系模型范未的不匹配总结如下:
1、粒度问题
就像例子中所说的User类为粗粒度,而Address为细粒度,当然Address也可以分解成多个属性放置User类中,但是如果有多个实体类需要引用Address类的话,将Address设计成一个单独的类,更是恰当。
2、子类型问题
1)继承映射主要有一颗继承树映射单独的一张表(操作方便,就是如果子类字段多了之后,可以表中出现非常多的NULL字段)
2)父类单独映射到一张表,子类各自映射到一张表,且子类引用父类中的公共字段(查询操作需要涉及到多张表的)
3)每个具体类,映射成一张表(比如说有A父类、B子类、C子类,就是说A父类+B子类映射一张表、A父类+C子类映射一张表,不过说到底如此映射增、删、改只需操作一张表,但查询的话得多张表咯)
3、同一性问题
领域模型引用对象、equals()方法
关系模型使用代理键(即ID)
4、与关联相关的问题
领域模型通过对象引用实现关联关系
关系模型则通过外键来实现关联关系
5、数据导航的问题
领域模型通过遍历对象网络实现数据导航
关系模型则通过表连接实现数据导航
嘿嘿,总结了一下,今天下午没算白费,大家有问题的一起交流呼呼。
Hibernate实战_笔记3,布布扣,bubuko.com
原文:http://blog.csdn.net/com185272358/article/details/20645493