Hibernate框架笔记之数据表关联关系

来源:互联网 发布:淘宝个体户营业执照 编辑:程序博客网 时间:2024/06/07 09:30

持久类之间是has-a关系(比如Worker类中有Pay类),在Worker.hbm.xml中对Pay属性使用component元素。component元素中配置Pay的属性。结果只生成一张数据表,包含Worker的属性和Pay的属性。


如果Order中有对Customer的引用,则是单向多对一关联;

如果Customer中有对Order集合的引用,则是单向一对多关联;

如果Order中有对Customer的引用,同时Customer中有对Order集合的引用,则是双向关联。


单向多对一关联只能从多的一端访问一的一端。(如Order中有对Customer的引用)

其域模型是在order类中定义一个Customer属性。

其关系数据模型:orders表中的外键customer_id参照Customer表的主键id。

.hbm.xml中的配置:

<many-to-one name="customer" class="com.hibernate.XXX.Customer" column="CUSTOMER_ID"></many-to-one>

name: order类中的Customer成员属性的名字,class:该成员属性对应的全类名,column:order表中关联customer表的外键名,不必与Customer表中的主键名一致。

执行save操作时,推荐先插入一的一端,再插入多的一端。

执行查询操作时,若查的是多的一端的对象,则只查询对象本身,暂不查询关联对象。在需要使用到关联对象时,再去查。如果在查询关联对象之前关闭了session,则会抛出LazyInitializationException异常。

执行删除操作时,如果没有设定级联关系,且多的一端有对象在引用一的一端的对象,则不能直接删除一的一端的对象。


双向1-n(与双向n-1完全相同):

域模型:Order中有对Customer的引用,同时Customer中有对Order集合的引用。

关系数据模型:order表中的外键Customer_id参照Customer表的主键。

Order.hbm.xml中的配置:不变,与上面单向多对一关联相同

Customer.hbm.xml的配置:

<set name="orders" table="ORDERS">

<key column="COSTOMER_ID"></key>

<one-to-many class="Order"/>

</set>

name:Customer中的属性名,table:对应到哪个数据表,column:ORDERS数据表中关联到Customer表的外键,one-to-many指定映射类型为一对多,class:多的一端对应的类名。

在一的一端的set节点中设置inverse=true使一的一端放弃维护关联关系。这样在执行save操作时可以去掉一的一端的update操作。


对一的一端执行查询操作时,获得的orders属性时使用延迟加载,获得的orders属性是hibernate内置的一种集合类型,该集合类型具有延迟加载和存放代理对象的功能。所以在Customer类中定义orders集合成员属性时,注意要把其类型声明为接口类型,因为如果orders属性不定义成接口类型,会发生类型转换异常。另外定义orders属性时要同时将其初始化,避免空指针异常。

对一的一端执行查询操作时,由于使用延迟加载,同样可能出现LazyInitializationException异常。



基于外键映射实现1-1关联:对外键加上unique约束,以Department和Manager为例

域模型:Department中有Manager的引用,Manager中有Department的引用

关系数据模型:Department数据表中的外键参照Manager表的主键,并加unique约束

Department.hbm.xml:

<many-to-one name="mgr" class="xxx' column="MGR_ID" unique="true"/>

Manager.hbm.xml:

<one-to-one name="dept" class="xxx" property-ref="mgr"/>

没有外键的一端需要使用one-to-one元素,该元素使用 property-ref 属性指定使用被关联实体(dept)主键以外的字段(mgr)作为关联字段
        

property-ref属性的作用体现在:当需要从没有外键的一端(Manager)查询有外键的一端的相关的对象(Department),需要使用左外连接,左外连接的条件就是根据  property-ref属性来设置的。以<one-to-one name="dept" class="xxx" property-ref="mgr"/>为例,左外连接的条件就是manager.id=department.mgr_id。



基于主键映射的1-1:以主键作为外键  

域模型:Department中有Manager的引用,Manager中有Department的引用

关系数据模型:Department数据表中的主键作为外键,参照Manager表的主键,并加unique约束

Department.hbm.xml:

id节点的generator子节点有所不同:

<generator class="foreign">

<param name="property">mgr</param>

</generator>

class="foreign"表示Department的主键也作为外键;<param>子节点配置以谁的主键作为Department的外键,其中,name="property"表示参照的是当前持久化类的哪个成员属性,这里是以成员属性mgr的主键作为Department的外键。

也不再像基于外键映射的1-1用many-to-one来映射,改用one-to-one:

<one-to-one name="mgr" class="Manager" constrained="true"/>constrained属性为true表示在当前主键生成器上添加一个外键约束。

Manager.hbm.xml:

<one-to-one name="dept" class="xxx"/>;与基于外键映射的1-1相比,去掉property-ref即可。

执行save操作时,不管是先插入以主键作外键的对象(Department)还是相反(先插入Manager),都是先插入Manager,后插入Department,因为Department的主键(也是外键)是依赖Manager的主键的,所以必须先插入Manager以便生成Department的主键。


原创粉丝点击