精通Hibernate——映射一对多关联关系

在域模型(实体域)中,关联关系是类与类之间最普遍的关系。根据UML语言,关系是有方向的。下面以客户(Customer)和订单(Order)的关系为例,阐述一下ORM的中的一对多映射:
我们知道,在关系数据库中,只存在外键参照关系,而且总是由“many”方参照“one“方。
1.建立多对一单向关联——Order(many)--->Customer(one):
-------------------------------Order.java--------------------------------

pack mypack;
import  java.io.Serializable;
public   class  Order  implements  Serializable {
   
private int id;
   
private String orderNumber;
   
private Customer customer;
   
   
//构造方法及set方法get方法
   
}

在以上代码中customer属性要使用<many-to-one>来映射:
多对一单向关联(many方)

< many - to - one >
    name 
=   " customer "     -- 待映射的持久化类属性名
    column 
=   " customer_Id "    -- 数据库外键字段
    
class   =   " mypack.Customer "    -- 持久化类
    not
- null   =   " true " />

a.  <many-to-one>的not-null属性 
not-null属性会影响Hiberntae的运行时行为,Hibernate在保存Order对象时,会先检查它的customer属性是否为null:
若为null:在执行session.save(Order)时会抛出PropertyValueException异常;
原因很简单:既然Customer为null,那么对应的外键Customer_Id也为null,试问外键都没有,Order表的数据能插得进去吗
若将not-null 属性设为false:表示外键引用可以为null,试想一下,数据库数据可以插进去吗?
我们来看:在执行session.save(Order)时,发出了sql语句:insert into......
但是当Hibernate自动清理(flush)缓存时,抛出新的异常:TransientObjectException
所谓清理是提交事务或手动Flush,将session与数据库保持同步,很显然不可能同步嘛,Order对象虽然持久化,但Customer没有.
    注:是否应该把<many-to-one>的not-null属性设为true,这根据实际业务而定。通常,订单总是由客户自己发出,因此建议设为true.
b.  级联保存与更新
默认情况下,Hibernate持久化一个对象,不会自动持久化所关联的其它临时对象,因此会有TransientObjectException,
想它关联也可以,<many-to-one>中加个属性cascade="save-update"即可.

2.建立一对多关联——Customer(one)--->Order(many):
-----------------------------Customer.java-------------------------------

package  mypack;
import  
public  calss Customer  implements  Serlizliab;e {
    
private int id;
    
private String name;
    
private Set orders = new HsahSet();

    
//构造方法及set方法get方法
}

一对多关联(one方)

< set 
      name 
=   " orders "    -- 持久化对象的属性
      cascade 
=   " save-update "   -- 级联操作
      
< key cloumn  =   " customer_Id " />   -- 外键
      
< one - to - many  class   =   " mypack.Order " />   -- 持久化类
</ set >

a.  <set>元素的inverse属性
  在映射一对多的双向关联时,应该在“one”方把inverse属性设为true,这样可提高应用性能。
                    inverse:控制反转,为true表示反转,由它方负责;反之,不反转,自己负责;
                    如果不设,one和many两方都要负责控制,因此,会引发重复的sql语句以及重复添加数据,
        在建立两个象的双向关系时,应该同时修改关联两端的对象属性:
                    customer.getOrders().add(order);
                    order.setCustomer(customer);

        这样做可提高业务逻辑的独立性,使业务逻辑的程序代码不受Hibernate实现的影响。同理解除双向关系也一样。
b.  级联删除(从数据库删除相关表记录)
         当删除Customer对象时,及联删除Order对象.只需将cascad属性设为delete即可.
          注:删除后的对象,依然存在于内存中,只不过由持久化态变为临时态.
c.  父子关系(逻辑删除,只是解除了关联关系)
         自动删除不再和Customer对象关联的Order对象.只需将cascade属性设为delete-orphan.
                     customer.getOrders().remove(order);
                     order.setCustomer(null);
          注:当关联双方都存在父子关系,就可以把父方的cascade属性设为delete-orphan,所谓父子关系,是由父方来控制子方的生命周期.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值