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

精通Hibernate——映射一对多关联关系
http://www.blogjava.net/yuwenlin/archive/2009/10/16/298483.html

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

package mypack;
import  java.io.Serializable;
public   class  Order  implements  Serializable {
   
private int id;
   
private String orderNumber;
   
private Customer customer;
   

   //构造方法及set方法get方法
   
}
在以上代码中customer属性要使用来映射:
多对一单向关联(many方)
< many - to - one >
    name 
=   " customer "     -- 待映射的持久化类属性名
    column 
=   " customer_Id "    -- 数据库外键字段
    
class   =   " mypack.Customer "    -- 持久化类
    not
- null   =   " true " />
a.  的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没有.
    注:是否应该把的not-null属性设为true,这根据实际业务而定。通常,订单总是由客户自己发出,因此建议设为true.
b.  级联保存与更新
默认情况下,Hibernate持久化一个对象,不会自动持久化所关联的其它临时对象,因此会有TransientObjectException,
想它关联也可以,中加个属性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.  元素的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,所谓父子关系,是由父方来控制子方的生命周期.

你可能感兴趣的:(精通Hibernate——映射一对多关联关系)