java之hibernate之 cascade和inverse

2019-09-11 14:51:28 浏览数 (3)

1.Cascade是级联动作,在many_to_one中如果使用cascade可以级联操作关联对象,如下代码可以级联保存Category对象。

在Book的映射文件设置

代码语言:javascript复制
<many-to-one name="category" column="cid" cascade="save-update"/>

在保存book时,如果book所对应的category没有保存,那么先保存category再保存book,完成级联保存数据的动作。

Cascade默认值是none,不进行级联动作;

Cascade可以为delete, 在many_to_one中cascade不会设置为delete,因为可能会造成异常,除非是基于外键的一对一。

Cascade还可以为all, all表示可以进行所有的级联动作。

在one_to_many中使用cascade:

代码语言:javascript复制
<!-- 双向一对多的设置 -->
        <set name="books" cascade="save-update">
            <!-- 设置外键 -->
            <key column="cid"></key>
            <!-- 设置多的一端的类型 -->
            <one-to-many class="Book"/>
        </set>

在保存一端数据时,如果发现关系对象多端数据没有保存,那么会级联保存book; 但是在一端使用级联保存,会多出n条更新语句,所以效率比较低。(即如果多的一端未保存,在一的一端使用级联保存时,会多出n条更新语句,效率较低;所以这种情况下,推荐在多端使用级联,而不推荐在一端使用)

如果在一端cascade="delete",那么在删除一端数据时,会级联将多端的所有数据删除。(慎用)

注意:cascade要起作用,那么一定要设置关联对象。如果关联对象不存在,那么cascade不会有作用。建议少用cascade,甚至不用。

2. inverse:反转, 在hibernate中用于在一的一端来控制关系(外键)由谁来管理(crud)。

代码语言:javascript复制
<!-- 双向一对多的设置 -->
        <set name="books" cascade="save-update" inverse="true">
            <!-- 设置外键 -->
            <key column="cid"></key>
            <!-- 设置多的一端的类型 -->
            <one-to-many class="Book"/>
        </set>

表示关系(外键)由Book一端来维护(即多的一端)。也就是说要为book对象设置好book对象对应的Category属性,外键才会被维护(保存)。

代码语言:javascript复制
  @Test
    public void testInit(){
        Session session = null;
        Transaction tx = null;
        try {
            session = HibernateUtil.getSession();
            tx = session.beginTransaction();
            Category c1 = new Category("计算机类");
            Category c2 = new Category("文学");
            Category c3 = new Category("历史");
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            Book b1 = new Book("java","sun",30,df.parse("1995-05-23"));
            b1.setCategory(c1);
            Book b2 = new Book("struts","apache",40,df.parse("2006-09-12"));
            b2.setCategory(c1);
            Book b3 = new Book("明朝那些事儿","当年明月",70,df.parse("2008-05-23"));
            b3.setCategory(c3);
            Book b4 = new Book("水浒传","老撕",20,df.parse("1985-05-23"));
            b4.setCategory(c2);
            c1.getBooks().add(b1);
            c1.getBooks().add(b2);
            c2.getBooks().add(b4);
            c3.getBooks().add(b3);
            session.save(c1);
            session.save(c2);
            session.save(c3);
            tx.commit();
            
        } catch (Exception e) {
            if(tx!=null)
                tx.rollback();
        }finally {
            HibernateUtil.close();
        }
    }

如果 inverse=false ,说明一的一端也可以维护关系,也就是说可以通过在一的一端添加多的一端数据,来保存外键关系。

代码语言:javascript复制
  @Test
    public void testInit(){
        Session session = null;
        Transaction tx = null;
        try {
            session = HibernateUtil.getSession();
            tx = session.beginTransaction();
            Category c1 = new Category("计算机类");
            Category c2 = new Category("文学");
            Category c3 = new Category("历史");
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
            Book b1 = new Book("java","sun",30,df.parse("1995-05-23"));
            Book b2 = new Book("struts","apache",40,df.parse("2006-09-12"));
            Book b3 = new Book("明朝那些事儿","当年明月",70,df.parse("2008-05-23"));
            Book b4 = new Book("水浒传","老撕",20,df.parse("1985-05-23"));
            c1.getBooks().add(b1);
            c1.getBooks().add(b2);
            c2.getBooks().add(b4);
            c3.getBooks().add(b3);
            session.save(c1);
            session.save(c2);
            session.save(c3);
            tx.commit();
            
        } catch (Exception e) {
            if(tx!=null)
                tx.rollback();
        }finally {
            HibernateUtil.close();
        }
    }

但是要通过更新语句来完成。所以一般情况下,inverse=true.

在多的一端没有inverse, 因为多的一端默认可以维护关系。

注意:级联和 inverse 都是通过关联对象来完成的,如果没有设置关联对象,这两者均不起作用。在两者都设置的情况,要注意区分谁管理级联,谁管理关系。有可能一个关联对象既管理关系又管理级联。

0 人点赞