随笔-10  评论-22  文章-1  trackbacks-0

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


posted on 2009-10-16 00:29 独孤行 阅读(3328) 评论(2)  编辑  收藏 所属分类: Hibernate

评论:
# re: 精通Hibernate——映射一对多关联关系 2009-10-18 20:26 | 梦芭莎女性内衣
应该同时修改关联两端的对象属性  回复  更多评论
  
# re: 精通Hibernate——映射一对多关联关系 2009-10-20 03:31 | 美容
精通Hibernate——映射一对多关联关系 good  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: