Hibernate 映射一对多关联关系

 

        前言:在域对象(1.实体域对象2.过程域对象3.事件域对象)中,类与类之间最普遍的关系就是关联关系(还有1.依赖:类使用另一个类的方法或属性2.聚集:类聚集成整体3.一般化:类之间的继承),用它来描述一对一或多对一的数据关系

建立多对一的单向关联关系

类与类的多对一单向关联和关系数据库中的外键参照关系匹配.Order到Customer的多对一单向关联,在Order类中定义一个Customer类型的customer属性,而Customer无需定义用于存放Order对象的集合。注意这是单向关联(ORDER表中有一个外键CUSTOMER_ID引用CUSTOMER的ID),映射文件配置如:


<many-to-one name=”customer” column=” CUSTOMER_ID” class=”mypack.Customer” not-null=”true”/ >//自动生成的SQL脚本有创建ORDER表外键的语句
       在过程域中的相关方法说明如下:
1.         savaCustomerAndOrder(){
tx=session.beginTransaction();
Customer customer=new Customer(“Tom”);
session.sava(customer);
//order与customer关联
Order order=new Order(“Tom_Order 001”,customer);
session.save(order);
tx.commit();
}
2.         savaCustomerAndOrderWithCascade(){
tx=session.beginTransaction();
Customer customer=new Customer(“Tom”);
//session.sava(customer);不保存customer对象,保存order会出异常
因为外键引用不存在,
Order order=new Order(“Tom_Order001”,customer);
session.save(order);
tx.commit();
}
3.         findOrdersByCustomer(Customer customer){
tx = session.beginTransaction();
List orders=(List)session.find("from Order as o where o.customer.id= "+customer.getId());
tx.commit();
return orders;
}

<many-to-one>元素的not-null属性
如上配置,把not-null去掉,意识着外键值可以为空.这样执行以上2的方法

savaCustomerAndOrderWithCascade()时会保存order成功,但是在Hibernate自动清理(flush,即同步更新数据库)时,会抛出异常(1.不先保存customer,customer就没有主键。)


级联保存和更新

Hibernate持久化一个对象时,不会自动持久化与其关联的对象.如果希望Hibernate持久化Order对象时自动持久化所关联的Customer对象.配置如下:

<many-to-one name=”customer” not-null=”true”
column=”CUSTOMER_ID” class=”mypack.Customer” cascade= ”sava-update”/>

保存或更新当前对象时会级联保存或更新与它关联的对象


映射一对多双向关联关系

当类与类建立关联,可以方便从一个对象导航到另一个或一组对象,如

Customer customer=order.getCustomer();从而获取如两表连接的信息,而又不用去数据库查询,速度快.如何获得与某个Customer关联的所有Order对象?这需要在Customer类中增加一个集合类型的orders属性如:private Set orders=new HashSet();有了这个属性,对于给指定的客户查询其所有订单只要调用customer.getOrders()方法就可以了.注意hbm2java只会生成:private Set orders;=new HashSet()是手工添加的,以提高程序健壮性,避免程序访问null的orders时发生异常.映射文件配置如下:

<set name=”orders” cascade=”save-update” >//order属性为java.uitl.Set集合类型,cascade表明当保存或更新Customer对象时,会级联保存或更新orders集合中的Orders对象
       <key column=”CUSTOMER_ID”/>//ORDER表连接customer表的外键
       <one-to-many class=”mypack.Order”/>//一对多关系
</set>.                                       //CUSTOMER表中没有与ORDER对应的字段

一些方法说明如下:
1.         savaCustomerAndOrderWithCascade(){
tx=session.beginTransaction();
Customer customer=new Customer(“Tom” ,new HashSet());
Order order=new Order();
order.setCustomer(customer);
customer.getOrders().add(order);
//保存customer时级联保存与orders属性关联的order对象
       session.save(customer);
       tx.commit();
}

元素的inverse(反转)属性
saveCustomerAndOrderWithInverse()用于演示inverse属性的用户,它调用以下两个方法.
1.       saveCustomerAndOrderSeparately(){
tx=session.beginTransaction();
Customer customer=new Customer();
customer.setName=”Jack”;
Order order=new Order();
order.setOrderNumber(“Jack_Order001”);
session.save(customer);
//order没有设置与customer关联,保存出异常,因为它的customer属性在映射时指定不为空
session.save(order);
}
2.       associateCustomerAndOrder(){
tx=session.beginTransaction();
//加载以上代码持久化的对象
Customer customer=(Customer)session.load(Customer.class, new Long(2));
Order order=( Order)session.load(Order.class, new Long(2));
//建立Customer和Order的关联关系
order.setCustomer(customer);
//order发生变化,执行uddate ORDER SET ….where ID=2;
customer.getOrders().add(order);
// customer发生变化,执行uddate ORDER SET ….where ID=2;
        tx.commit();
}

以上执行两次SQL语句结果都是一样,影响了JAVA应用性能,解决方法是把<set>元素的inverse属性设为true;如:
<set name=”orders” cascade=”save-update” inverse=”true” >//只按照ORDER级联更新,CUSTOMER变化不会级联到ORDER
       <key column=”CUSTOMER_ID”/>
       <one-to-many class=”mypack.Order”/>
</set>

这样Customer和Order双向关联中,Hibernate探测到持久化对象Customer和Order的状态发生变化时,仅按照Order对象状态的变化来同步更新数据库.为了程序健壮,在建立两个对象的双向关联时,应同时修改两端对象的相应属性,如:
customer.getOrders().add(order);
order.setCustomer(customer);
解除关联时:
customer.getOrders().remove(order);

order.setCustomer(null);


级联删除
如果希望Hibernate删除Customer对象时,自动删除和Customer关联的Order对象,可以把cascade属性设为”delete”,Customer的映射文件配置如下:
<set  name=”orders” cascade=”delete” inverse=”true”>
       <key column=”CUSTOMER_ID”/>
       <one-to-many class=”mypack.Order”/>
</set>

删除一个持久化对象,就是从数据库中删除相关记录,内存中的对象依然存在,不过由持久化状态变为临时状态了


父子关系(由父类控制子类的持久化生命周期)
tx=session.beginTransaction();
Customer customer=(Customer)session.load(Customer.class, new Long(2));
Order order=(Order)customer.getOrders().iterator().next();
//解除Customer对象和Order对象的关联关系
customer.getOrders().remove(order)
order.setCustomer(null);
//执行update ORDERS set CUSTOMER_ID=null wher ID=2;
tx.commit();

如果希望Hibernate自动删除不再和Customer对象关联的Order对象,可以把cascade设为”all-ete-orphan(孤立)”,映射文件配置为:
<set name=”orders” cascade=”all-delete-orphan” inverse=”true”>
       <key column=”CUSTOMER_ID”/>

       <one-to-many class=”mypack.Order”/>

</set>

当Customer.hbm.xml的<set>元素的cascade属性取为”all-delete-orphan”.当保存或更新Customer对象时,级联保存或更新有关的Order对象,当删除Customer对象时,级联删除有关的Order对象.


映射一对多双向自身关联关系(可以看作是三个相同的表关联)
这种类的特点是有一个属性是他本身类型(外键引用自身表的ID),还有一个集合属性用来装载自身类(主键被自身表的外键引用),它的映射文件如:
  <set
        name="childCategories"
        cascade="save-update"//对save或update起作用
        inverse="true"//对非增删改查引起的对象状态变化起作用?2007-3-9
        >
        <key column="CATEGORY_ID" />
        <one-to-many class="mypack.Category" />//Category: 种类
     </set>  
 
   <many-to-one
        name="parentCategory"
        column="CATEGORY_ID"
        class="mypack.Category"
       />
自解:如人这个类,它有一个属性人,用来装载它的父亲信息,还有一个集合用来装载它的儿子信息
.这里父我子都使用同一个类(主键与外键的关系,以后我都说是父子关系),这样一个对象就可以装载

多表关联的信息了
一些相关方法说明如下:
saveCategoryWithCascade(){
       tx=session.geginTransaction();
       Category foodCategory=new Category(“food”,null,new HashSet());//食品种类
       Category fruitCategory=new Category(“fruit”,null,new HashSet());//水果种类
       foodCategory.getChildCategories().add(fruitCategory);//建立关联
       fruitCategory.setParentCategory(foodCategory); //建立关联
       session.save(foodCategory);//会级联保存
       tx.commit();
}

改进持久化类

通过hbm2java工具自动生成的持久化类,可以根据实际需要加入适当的业务逻辑或实用方法(这个方

法供应用程序调用,Hibernate只调用属性的getXXX和setXXX)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值