Hibernate中的fetch, lazy, inverse和cascade

本文详细介绍了Hibernate框架中fetch、lazy、inverse和cascade等属性的使用方法,特别是它们在关联查询和级联操作中的作用。通过具体的配置示例说明了如何实现不同场景下的需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载自http://blog.sina.com.cn/s/blog_4f925fc30100m7eo.html


English Title:The Fetch in Hibernate, lazy, inverse and Cascade
1.fetch 和 lazy 主要用于级联查询(select) 而 inverse和cascade主要用于级联增、加删、除修

  改(sava-update,delete)

2.想要删除父表中的记录,但希望子表中记录的外键引用值设为null的情况:

  父表的映射文件应该如下配置:

  <set name="emps" inverse="false" cascade="all">

      < key>

          < column name="DEPTNO" precision="2" scale="0" />

      < /key>

      < one-to-many class="com.sino.hibernate.Emp" />

 < /set>

  inverse="false"是必须的,cascade可有可无,并且子表的映射文件中inverse没必要设置,cascade也可以不

  设置,如果设置就设置成为cascade="none"或者cascade="sava-update"

 < many-to-one name="dept" class="com.sino.hibernate.Dept" fetch="select" cascade="save-update">

      < column name="DEPTNO" precision="2" scale="0" />

  </many-to-one>

3.关于级联查找 对子表的持久化类进行查找的时候,会一起把子表持久化类中的父表持久化类的对象一起查询

  出来,在页面中可以直接取值的情况: 要把父表的映射文件中设置 lazy 属性如下:

  <class name="com.sino.hibernate.Emp" table="EMP" schema="SCOTT" lazy="false">

  这样就可以直接在页面中取值 (类似于这样的取值 client.cmanager.id)如果没有设置 lazy="false" 则会抛

  出异常javax.servlet.ServletException: Exception thrown by getter for property cmanager.realName

  of bean cl在Action中取值的话就会抛出 could not initialize proxy - the owning Session was closed

  的异常

 

--------------------------------------------------------------------------------------------------

1、outer-join关键字(many-to-one的情况)

outer-join关键字有3个值,分别是true,false,auto,默认是auto。
true: 表示使用外连接抓取关联的内容,这里的意思是当使用load(OrderLineItem.class,"id")时,Hibernate只生成一条SQL语句将OrderLineItem与他的父亲Order全部初始化。

select * from OrderLineItem o left join Order on o.OrderId=p.OrderId  where o.OrderLineItem_Id=?

false:表示不使用外连接抓取关联的内容,当load(OrderLineItem.class,"id")时,Hibernate生成两条SQL语句,一条查询OrderLineItem表,另一条查询Order表。这样的好处是可以设置延迟加载,此处要将Order类设置为lazy=true。

select * from OrderLineItem o where o.OrderLineItem_Id=?
select * from Order p where p.OrderId=?

auto:具体是ture还是false看hibernate.cfg.xml中的配置

注意:如果使用HQL查询OrderLineItem,如 from OrderLineItem o where o.id='id',总是不使用外部抓取,及outer-join失效。

2、outer-join(集合)

由于集合可以设置lazy="true",所以lazy与outer-join不能同时为true,当lazy="true"时,outer-join将一直是false,如果lazy="false",则outer-join用法与1同

3、HQL语句会将POJO配置文件中的关联一并查询,即使在HQL语句中没有明确join

4、In HQL, the "fetch join" clause can be used for per-query specific outer join fetching. One important thing many people miss there, is that HQL queries will ignore the outer-join attribute you specified in your mapping. This makes it possible to configure the default loading behaviour of session.load() and session.get() and of objects loaded by navigating relationship. So if you specify

and then do
MyObject obj = session.createQuery("from MyObject").uniqueResult();
obj.getMySet().iterator().next();

you will still have an additional query and no outer-join. So you must explicily request the outer-join fetching:

MyObject obj = session.createQuery(
    "from MyObject mo left join fetch mo.mySet").uniqueResult();
obj.getMySet().iterator().next();

Another important thing to know is that you can only fetch one collection reference in a query. That means you can just use one fetch join. You can however fetch "one" references in addition, as this sample from the Hibernate Docs demonstrates:

from eg.Cat as cat
    inner join fetch cat.mate
    left join fetch cat.kittens

We have once considered lifting this limitation, but then decided against it, because using more than one fetch-join would be a bad idea generally: The generated ResultSet becomes huge and is a major performance loss.

So alltogether the "fetch join" clause is an important instrument Hibernate users should learn how to leverage, as it allows tuning the fetch behaviour of a certain use case.

5、join fetch join 的区别

如果HQL使用了连接,但是没有使用fetch关键字,则生成的SQL语句虽然有连接,但是并没有取连接表的数据,还是需要单独的sql取数据,也就是 select a,b,d...中没有连接表的字段

6、如果集合被声明为lazy=true,在HQL中如果显式的使用 join fetch 则延迟加载失效。

7、在one-to-many的one端显式设置fecth="join",则无论如何都采取预先抓取(生成一个SQl),延迟加载失效(生成两个SQL)

8、many-to-one的延迟加载是在配置文件的class标签设置lazy="true",one-to-many和many-to-many的延迟加载是在set标签中设置lazy="true"。而one-to-one不只要在calss标签设置lazy="true",而且要在one-to-one标签中设置constrained="true".

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值