您的位置:首页 > 编程语言 > Java开发

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

2009-07-15 11:28 513 查看
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的话,都可以操作了,至于说效率方面的考虑,呵呵……先就不用管了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息