zoukankan      html  css  js  c++  java
  • 级联关系(内容大部分来自JavaEE轻量型解决方案其余的是我的想法)

    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语句就可以完成两个关联对象之间的级联操作。
  • 相关阅读:
    java字符串的遍历以及字符串中各类字符的统计
    Java Jvm运行机制原理
    为什么面试要问 hashmap 的原理
    HashMap的实现原理
    redis两种持久化方式的优缺点
    2018No-java面试知识
    从架构演进的角度聊聊spring cloud都做了些什么?
    MySQL索引优化
    2018java面试知识汇总
    多线程—7种同步方法
  • 原文地址:https://www.cnblogs.com/JamKong/p/4447090.html
Copyright © 2011-2022 走看看