在域模型(实体域)中,关联关系是类与类之间最普遍的关系。根据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-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,所谓父子关系,是由父方来控制子方的生命周期.