多对一 单向关联 匹配 关系数据库中的外键参照关系


2008-09-06 12:22


映射 多对一 单向关联





读完 Java对象持久化技术详解6.1节,写一下读书笔记:

多对一 单向关联 匹配 关系数据库中的外键参照关系。

     在关系数据库中,只存在外键参照关系,而且是由many--->one,是单向关联。

    以Customer和Order为例。

 

        单向关联中,Order中包含一个customer属性。这样定义了一个Order到Customer的关联,是多对一的。Customer中未包含Order属性.

       在Order.hbm.xml中,要进行关联映射Order类与ORDERS表。

      

mysql再参照关系上定义外码的描述_读书

       

mysql再参照关系上定义外码的描述_mysql再参照关系上定义外码的描述_02

单向关联中,Order中包含一个customer属性。这样定义了一个Order到Customer的关联,是多对一的。Customer中未包含Order属性.

       在Order.hbm.xml中,要进行关联映射Order类与ORDERS表。

      

mysql再参照关系上定义外码的描述_读书

       

mysql再参照关系上定义外码的描述_mysql再参照关系上定义外码的描述_02

id------ID         customer------CUSTOMER_ID
         映射 customer------CUSTOMER_ID需要 使用 many-to-one
many-to-one用来建立customer属性和ORDERS表的外键CUSTOMER_ID之间的映射
         <many-to-one
 //待映射的持久化类的属性名
//设定和该属性对应的表的外键
//设定该属性的类型
//表示customer属性不能为null,默认为false
//级联更新与Order类对象相关联的对象
        />
       一个概念:
临时对象(transient)
                刚刚通过new( )创建,并且未被持久化的对象。
//transient
//执行完该语句后,customer成为持久化对象
 
     //------------------不同的配置出现的不同情况-----------------------
    cascade取默认值的情况
 <many-to-one
     Order order = new Order(); 
     order.setCustomer(customer); 
 
session.save(order);

order时,

这样cascade取默认值none,当持久化order时,会执行类似如下语句:

null
not null

   抛出异常:

net.sf.hibernate.PropertyValueException: not-null property references a null or transient
     value: Order.customer

    删除 not-null = "true"后,

会把order与customer一起持久化。

insert into CUSTOMERS(ID,NAME) values( 1 haha")
insert into ORDERS( ID, CUSTOMER_ID) values (1,1
      
 
 <many-to-one
Order order = new Order();
order.setCustomer(customer);
session.save(order);
order时,  
null

      这次成功持久化了order对象,不再抛出PropertyValueException,因为ORDERS表的CUSTOMER_ID允许null值出现

     但当Hibernate自动清理(flush)缓存中所有持久化对象时,抛出新的异常:

net.sf.hibernate.TransientObjectException: object references an unsaved transient instance -
    save the transient instance before flushing: Customer

内存中持久化对象的状态

Hibernate发现持久化对象order引用transient对象customer,而ORDERS表中相应的记录的

CUSTOMER_ID字段为null,也就是说内存中的持久化对象的状态与数据库中的记录不一致。

而且在这种情况下,Hibernate没办法使两者同步,因为Hibernate不会自动持久化customer对象,

所以,Hibernate抛出 TransientObjectException异常。

    这时需要设置cascade属性来解决问题

<many-to-one
 //待映射的持久化类的属性名
//设定和该属性对应的表的外键
//设定该属性的类型
 cascade = "save-update"           //当保存或更新当前对象时
                                                          //级联保存或更新与Order类对象相关联的对象
        />
       这样当执行
    //transient
      customer.setName("haha");
Order order = new Order();
order.setCustomer(customer);
session.save(order);
 
name = "customer"         //待映射的持久化类的属性名
column = "CUSTOMER_ID"   //设定和该属性对应的表的外键
class = "Customer"        //设定该属性的类型
/>
 Customer customer = new Customer();    //transient
 
name = "customer"         //待映射的持久化类的属性名
column = "CUSTOMER_ID"   //设定和该属性对应的表的外键
class = "Customer"        //设定该属性的类型
                not-null = "true"         //表示customer属性不能为null,默认为false
/>
 Customer customer = new Customer();    //transient