级联关系(内容大部分来自JavaEE轻量型解决方案其余的是我的想法)

来源:互联网 发布:怎样ping端口号 编辑:程序博客网 时间:2024/04/30 02:24
1. 级联关系

在Hibernate程序中持久化的对象之间会通过关联关系互相引用。对象进行保存、更新和删除等操作时,有时需要被关联的对象也执行相应的操作,如:假设需要关联关系的主动方对象执行操作时,被关联的对象也会同步执行同一操作。这一问题可以通过使用Hibernate的级联(cascade)功能来解决。

例如:当试图删除顾客对象时,通过级联关系让Hibernate决定是否删除该对象对应的所有订单对象。
cascade是<set>元素的一个属性,该属性常用值及描述如下表:
 属性值   描述  none                   默认值,表示关联对象之间无级联操作  save-update表示主动方对象在调用save(),update()和saveOrUpdate()方法时对被关联对象执行保存或更新操作  delete 表示主动方对象在调用delete()方法时被关联对象执行删除操作 delete-orphan用在1-N关联中,表示主动方对象调用delete()方法时删除不被任何一个关联对象所引用的关联对象,多用于父子关联对象中。  all 等价于save-update和delete的联合使用 注意:在实际开发中,级联通常用在1-N和1-1 关联关系中。而对于N-1和N-N关联使用级联操作则没有意义。此外,cascade属性值save-update最为常用。
 
  
接下来将演示如何使用级联,以及级联使用哪些SQL语句?
假设Customer类、Order类如下:
要求:当添加一个顾客对象时,同时保存该顾客的所有订单。在BusinessService中添加如下代码:
 1 public class BusinessService{ 2     public static void main(String[] args){ 3           Customer customer = new Customer("lisi","123","李四","青岛","123123"); 4         Order order = new Order("3",new Date(),1000.0);//并没有传入customer对象 5         //建立关联关系,实现级联保存 6         customer.getOrders().add(order); 7  8         Session session = HibernateUtils.getSession(); 9 10         Transaction trans = session.beginTransaction();11         session.save(customer);12         trans.commit();13         HibernateUtils.closeSession();14     }15 }

 

 1 Customer.hbm.xml 2 <hibernate-mapping package="com.haiersoft.ch05.pojos"> 3     <class name="Custoemr" table="CUSTOMER"> 4     ... ...省略其它代码 5         <!-- 1-N关联关系 --> 6         <set name="orders" cascade="save-update"> 7             <key column="CUSTOMER_ID"/> 8             <one-to-many class="Order"/> 9         </set>10     </class>11 </hibernate-mapping>
上述代码中,配置了级联保存或更新操作,当保存顾客对象时,会把其对应的订单对象级联保存。
当运行main方法时,Hibernate执行了以下几条SQL语句:
insert into CUSTOMER (USERNAME , PASSWORD , REALNAME , ADDRESS , MOBILE )
values(?,?,?,?,?)   ①
insert into ORDERS (ORDERNO , ORDERDATE , TOTAL , CUSTOMER_ID )
values(?,?,?,?)   ②
update ORDER set CUSTOMER_ID =?  where ID=?   ③
 
上述结果中,执行了两条insert语句和一条update语句。
Hibernate首先在CUSTOMER 表中插入一条记录(①),然后再往ORDERS表中插入一条没有customer参数的记录,也就是说,插入的这句中的参数CUSTOMER_ID是没有值的(②),那么就需要用到第三条update语句了,它会根据前两条语句的记录,从中获取得到CUSTOMER_ID、ORDERS表的ID值,然后给ORDERS表中的记录中的CUSTOMER_ID外键进行赋值(③)。从而完成两张表之间的关联关系。
 
小结:级联关系方便了我们对有关联关系的数据操作,有了Hibernate的级联,你只要把有级联关系的主动关联方包含了被关联方的对象,那么我们只要对主动方进行操作就可以了,至于被关联方的数据它自己会按着我们关联关系被处理。
也就是说,由上面的例子中Customer对象是主动关联方,而Order是被关联方。当需要想数据库插入一条Customer记录,并且还要把它相应的Order记录一并插入数据库中时,那么我们只需要把order对象添加到customer对象的orders属性中,并直接对customer进行操作就可以了,其中order对象并不需要传入Customer参数,也不需要手动的去操作order对象保存到数据库中,Hibernate会帮我们解决掉它。
 
2. 级联控制反转
在1-N关联关系中,通常讲控制权交给“N” 方,这可以在<set>元素中通过配置inverse属性来实现,当inverse=“true”时表示关联关系由对方维护。修改后的Customer.hbm.xml代码如下:
<!-- 配置控制反转 -->
<set name="orders" inverse="true" cascade="save-update">
<key column="CUSTOMER_ID" />
<one-to-many class="Order" />
</set>
通过上面的配置,设置将关联的控制权交给Order对象,所以在保存Customer对象前Order对象必须关联到该对象,如下代码:
 
 1 public class BusinessService{ 2     public static void main(String[] args){ 3         //添加客户和订单信息 4         Customer customer = new Customer("lisi","123","李四","青岛市","123123123"); 5         Order order = new Order("3",new Date(),1000.0); 6         //建立关联关系,实现级联保存 7         customer.getOrders().add(order); 8         //order对象必须关联customer对象,inverse才起作用 9         order.setCustomer(customer);10 11 12         Transaction trans = session.beginTransaction();13         session.save(customer);14         trans.commit();15         HibernateUtils.closeSession();16 17     }18 }

 

上述代码中,利用语句“order.setCustomer(customer)”实现了order到customer对象的关联,当运行main()方法时,Hibernate执行了以下两条insert语句。

insert into CUSTOMER (USERNAME , PASSWORD , REALNAME , ADDRESS , MOBILE )
values(?,?,?,?,?)   ①
insert into ORDERS (ORDERNO , ORDERDATE , TOTAL , CUSTOMER_ID )
values(?,?,?,?)   ②
小结:当将关联的控制权交给“N”方时,无需执行update语句就可以完成两个关联对象之间的级联操作。
0 0
原创粉丝点击