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中添加如下代码:

 public class BusinessService{
public static void main(String[] args){
Customer customer = new Customer("lisi","123","李四","青岛","123123");
Order order = new Order("3",new Date(),1000.0);//并没有传入customer对象
//建立关联关系,实现级联保存
customer.getOrders().add(order); Session session = HibernateUtils.getSession(); Transaction trans = session.beginTransaction();
session.save(customer);
trans.commit();
HibernateUtils.closeSession();
}
}
 Customer.hbm.xml
<hibernate-mapping package="com.haiersoft.ch05.pojos">
<class name="Custoemr" table="CUSTOMER">
... ...省略其它代码
<!-- 1-N关联关系 -->
<set name="orders" cascade="save-update">
<key column="CUSTOMER_ID"/>
<one-to-many class="Order"/>
</set>
</class>
</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对象必须关联到该对象,如下代码:
 
 public class BusinessService{
public static void main(String[] args){
//添加客户和订单信息
Customer customer = new Customer("lisi","123","李四","青岛市","123123123");
Order order = new Order("3",new Date(),1000.0);
//建立关联关系,实现级联保存
customer.getOrders().add(order);
//order对象必须关联customer对象,inverse才起作用
order.setCustomer(customer); Transaction trans = session.beginTransaction();
session.save(customer);
trans.commit();
HibernateUtils.closeSession(); }
}

上述代码中,利用语句“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语句就可以完成两个关联对象之间的级联操作。

最新文章

  1. 【CentOS7之防火墙命令】
  2. js对Cookie的读写操作
  3. C#中base 关键字的作用
  4. spider_getModelInformation
  5. word2vec模型原理与实现
  6. TCP/IP详解学习笔记(8)-- UDP:用户数据报协议
  7. ios frame bounds applicationframe
  8. kali 安装完成后,无法进入界面
  9. JavaScript笔记(一)
  10. 转载 DevOps的基本原则与介绍
  11. Python_day1 基础语法
  12. 删数方案数(regex)
  13. Mysql使用中文字段排序的实现--order by
  14. zabbix企业级监控dell硬件服务状态
  15. flash Air 在同一个目录下面创建txt,写入字
  16. JavaScript 中 如何判断一个元素是否在一个数组中
  17. jquery Nestable 获取改变排序后的json数据 拖动排序
  18. postman学习笔记(二)
  19. Apache Jmeter 教程
  20. 用adb来修改android嵌入式设备的system只读目录下的东西

热门文章

  1. Python字符串相关
  2. Custom LDAP Monitor Does Not Work
  3. 发现JDK的3个bug
  4. Tensorflow 载入数据的三种方式
  5. P2625 豪华游轮 (背包$dp$,数学)
  6. 为什么说for循环设置循环变量的那部分是一个父作用域?
  7. div盒子模型(一图胜千言)
  8. shell-总结【摘录】
  9. 汕头市队赛 SRM 08 B
  10. sqlmap注入一般步骤