搞定Hibernate表与表之间的关联,搞懂cascade、inverse、lazy等属性

原创 2007年09月24日 14:57:00
2个类,书(Book),类别(BookType)

public class Book {
    private Long id;
    private BookType type;
}


public class BookType {
    private Long id;
}

好了,我们开始

情况一  
 

它们相互不关联

情况二

   /**
     * @hibernate.many-to-one column="col_booktype_id"
     */    
    public BookType getType() {
        return type;
    }

也就是说,一个类有多本书,比如有很多书是历史类别,很多其他书是数学类别,非常好理解

那么:

        BookType bookType = new BookType();       
       
        Book book1 = new Book();
        book1.setType(bookType);
       
        Book book2 = new Book();
        book2.setType(bookType);

        bookService.save(book1);
        bookService.save(book2);

先创建一个 “书本类” 的实例,再创建 2本书,都是属于这本书,保存这2本书,结果出错。为什么?因为没有把BookTpye保存,所以那2本书的类别字段就不能保存了。这时cascade登场了——
cascade有2个级别   cascade=“save-update”   cascade=“delete”   我们先来看 cascade=“save-update”


   /**
     * @hibernate.many-to-one column="col_booktype_id" cascade=“save-update”
     */    
    public BookType getType() {
        return type;
    }

这时,在保存book1的时候自动能把booktype也保存掉,在保存book2的时候,发现booktype已经存在了,于是去更新了booktype,总之要级联过去。

所以说,其实这个功能是比较偷懒的功能,呵呵。

好了,现在我们来看看  cascade=“delete” 

假设上述已经都保存完毕,那么把book1删除,OK……接着删除book2,这时,它会先去删除booktype,再删除book2,可见就是这个意思。Hibernate会认为,你历史类的书都没了,我还要历史这个类干嘛用?于是都删了。

情况三

那么现在我们有一个新的需求了,要通过booktype去得到book,比如 getBooks(“历史”) 返回一个book的Set,在没有Hibernate这些框架的时代,我们要先去 booktype表,找历史的那个id,再拿这个Id去book中,把这些book给找出来,当然,有了Hibernate,其实内部也是这么执行的,只是大大简化了我们的编码量。好!那么这个当然是属于 one-to-many了,我们在BookType中这么去设置

        <set name="books" lazy="false" inverse="true" cascade="all">
            <key column="col_booktype_id"></key>
            <one-to-many class="hdu.management.library528.entity.Book"/>
        </set>

我们一个个属性来讲解,这里的set其实没有对应数据库的任何表和任何字段,首先这点大家要明确。
lazy     当设置为true的时候——我们得到一个 历史类 ,并没有把这个类里的书全部读出来,而是当用的时候才去读
当设置为false的时候,我们得到一个历史类,里面已经把books都封装好了,全部读出来了
很好理解吧?lazy就是懒惰的意思嘛。这里有点需要注意,一般我们在用spring进行事务操作的时候,当lazy=“true”的时候很容易会出错。解决办法:
一、如果不考虑效率的话,大家可以干脆把 lazy=“false”
二、可以去参考下 openSessionInView这个spring的拦截器

好了,我们讲重点吧,首先来看
cascade="all"  这个其实不用理解的很难,和many-to-one是一样的,我们这么理解,cascade是写在哪个类里的?答:booktype。它在对哪个类进行声明?答:这里是对book进行声明。 好了,那么意思就是,我们在删除booktype和更新添加的时候,需不需要对book也进行操作的意思。
比如,在情况二中,我们是无法对booktype进行删除的,因为有外键关联它,那么在这里我们设置了one-to-many后,OK了,当我们删除booktype的时候,会先把相关的book全部删除,接着把booktype给删除。

最后讲讲重点   inverse="true"  我在刚刚接触Hibernate的时候,对inverse、cascade这两个东西最为头痛,现在cascade已经理解的非常清楚了吧?那么我来总结inverse
第一、概念,指定要不要当自己来维护关系。(其实根本不用去理解)
第二、在one-to-many的时候,设置inverse=“true” 当然是在 one这个地方设置
第三、在many-to-many的时候,随便在哪端先设置inverse=“true”,另一个地方设置inverse=“false”
第四、别问我:“那我不这么设置行不行,换个方法设置下看看”,取消念头,回到第二和第三条。

情况四

现在又有了新的要求,刚才一直是 一个书本类下面有很多书,那么在现实中,一本书它也有可能是属于很多类别的,比如它既是历史类的又是属于地理类的。这个时候就要用many-to-many了。前面的关系中,我们用的是2张表来维护相互之间的关系,当多对多的时候,就需要在构建出一张表来维护了。
这里我们构建出一个  书本——书本类   这样一张表 ,里面有2个字段,书本ID,书本类ID,在映射到Oracle中是自动转换成联合主键的,没有重复。

    /**
     * @hibernate.set table="lib_book_booktype" lazy="false" cascade="all" inverse="true"
     *               
     * @hibernate.collection-key column="col_book_id"
     * @hibernate.collection-many-to-many column="col_booktype_id" class="hdu.management.library528.entity.BookType"
     
*/


    
public Set getBookTypes() {
        
return bookTypes;
    }

    /**
     * @hibernate.set table="lib_book_booktype" lazy="false" cascade="all"
     *               
     * @hibernate.collection-key column="col_booktype_id"
     * @hibernate.collection-many-to-many column="col_book_id" class="hdu.management.library528.entity.Book"
     
*/

    
public Set getBooks() {
        
return books;
    }

注意:不要忘记  private Set books = new HashSet();

设置和上面一样,意思也一样,唯一不同的就是多了个 table,column自然也要指向那个table了,这是设置之后,其实book和booktype这2张表图了个安宁,什么外键都没有了,只是他们的关系表在控制它们两个了。


我们继续针对,在多对多中,inverse的问题,这里我们把 book  的inverse=true    booktype的inverse=false   当我们做这样的操作时


        book1.getBookTypes().add(bookType1);
        book1.getBookTypes().add(bookType2);
        book1.getBookTypes().add(bookType3);

        bookService.saveOrUpdate(book1);


会发现 book1  保存了,
bookType1、2、3也保存了,但是他们的关系却没有保存,为什么?因为 book 把关系的inverse=true了,踢给别人去处理了,所以它不来理会关系的处理。所以,我们就要对 booktype这么操作才可以处理关系。当然如果,2端我们都去设置 inverse=false的话,都可以操作了,至于说效率方面的考虑,呵呵……先就不用管了。

相关文章推荐

深入理解Hibernate表与表之间的关联,搞懂cascade、inverse、lazy等属性,和注解版Hibernate实例

1.搞定Hibernate表与表之间的关联,搞懂cascade、inverse、lazy等属性
  • he90227
  • he90227
  • 2014年07月28日 13:34
  • 5492

在hibernate中一对多关联时会经常用到inverse和cascade属性

原文网址:http://hi.baidu.com/icehua521/blog/item/eb6b5099a98271006e068cbf.html 在hibernate中一对多关联时会经常用到in...

重新学习 Hibernate fetch lazy cascade inverse 关键字

转载:http://www.blogjava.net/pear/archive/2006/11/05/79251.html 重新学习 Hibernate fetch lazy cascade inve...

[hibernate] 配置文件中的 lazy, inverse, cascade 和 fetch

[hibernate] 配置文件中的 lazy, inverse, cascade 和 fetch 2009-06-10 13:52 转自:http://hi.baidu....

重点学习 Hibernate fetch lazy cascade inverse 关键字

重点学习 Hibernate fetch lazy cascade inverse 关键字文章分类:Java编程Hibernate最让人头大的就是对集合的加载形式。 书看了N次了,还是没有真正理解Hi...

Hibernate中的fetch, lazy, outer-join,inverse和cascade作用

1.fetch,outer-join 和 lazy 主要用于级联查询(select) 而 inverse和cascade主要用于级联增加,删除,修改(sava-update,delete)。    ...

hibernate cascade,inverse和lazy的用法

设置 inverse=”false” cascade=”save-update” ,删除父表记录时,子表对应外键置空。 设置 inverse=”false” cascade=”all”,删除父表...
  • jwdstef
  • jwdstef
  • 2012年08月16日 17:02
  • 3416

Hibernate中hbm.xml文件的inverse、cascade、fetch、outer-join、lazy

inverse : 用于控制表与表之间的关系,默认值为“false”,一般在多对多或一对多双向关联中常见,例如在student和courser表中,产生一个sc表,如果我们对hbm文件中inverse...

学习 Hibernate fetch lazy cascade inverse 关键字

Hibernate最让人头大的就是对集合的加载形式。 书看了N次了,还是没有真正理解Hibernate。所以下午专门做了下测试,对配置文件的意思加深了认识。 假设有两个表,Photos(一) ...

Hibernate中的fetch, lazy, inverse和cascade

转载自http://blog.sina.com.cn/s/blog_4f925fc30100m7eo.html English Title:The Fetch in Hibernate,...
  • Wei_K
  • Wei_K
  • 2016年07月17日 02:51
  • 142
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:搞定Hibernate表与表之间的关联,搞懂cascade、inverse、lazy等属性
举报原因:
原因补充:

(最多只允许输入30个字)