Hibernate中outer-join、lazy 、fetch join关键字的使用

本文深入探讨了Hibernate中outer-join关键字的应用,包括其三种状态、与集合懒加载的关系、HQL语句的外连接行为、fetchjoin的使用限制以及与延迟加载的交互。详细解释了join与joinfetch的区别,提供了关于如何优化查询性能和调整加载策略的实用建议。

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

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 p 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".


 
<think>嗯,用户问的是Hibernate映射中的default-lazy="true"是什么意思。首先,我需要确定用户对Hibernate的理解程度。可能他们正在学习Hibernate,或者在开发中遇到了延迟加载的问题。 用户之前的问题是关于DTD中属性的默认值确认,现在转向Hibernate的配置,说明他们可能在配置实体映射,特别是延迟加载相关的设置。需要解释清楚default-lazy的作用,以及如何影响实体和关联的加载行为。 首先,回顾Hibernate的延迟加载机制。延迟加载是为了优化性能,避免不必要的数据库查询。default-lazy是设置在hibernate-mapping元素中的属性,影响当前映射文件中所有实体的默认行为。 需要明确,default-lazy="true"意味着默认启用延迟加载,但具体的实现可能因Hibernate版本而异。比如,在旧版本中,这可能仅影响普通属性的加载,而关联(如集合或many-to-one)可能有自己的默认值。但在较新版本中,Hibernate可能更智能地处理这些设置。 还要注意,用户可能会混淆default-lazy和具体的lazy属性(如集合的lazy设置)。需要区分全局默认和局部覆盖的情况。例如,如果在hibernate-mapping设置了default-lazy="true",但某个实体显式设置lazy="false",则该实体将立即加载,覆盖默认。 用户可能的问题包括:如何确认某个实体的实际加载行为,或者为什么他们的应用没有按预期延迟加载。需要说明配置的优先级和检查方法,比如查看日志或使用调试工具。 此外,要提醒用户不同Hibernate版本的行为差异,建议查阅对应版本的文档,因为新版本可能有不同的默认设置或废弃某些配置选项。 最后,总结default-lazy的作用,确保用户明白它是设置全局默认,但可以被更具体的配置覆盖,帮助他们在优化应用性能时做出正确配置。</think>在 Hibernate 的映射配置中,`hibernate-mapping` 元素的 `default-lazy="true"` 表示**设置当前映射文件(或作用域)内所有类和集合的默认延迟加载(Lazy Loading)行为为启用**。以下是详细解释: --- ### 一、核心概念 1. **延迟加载(Lazy Loading)** Hibernate 的核心优化策略之一,目的是**推迟对象或关联数据的加载时机**,直到实际需要访问这些数据时才从数据库查询。这能有效减少不必要的 SQL 查询,提升性能。 2. **`default-lazy` 的作用范围** - 定义在 `hibernate-mapping` 根元素中。 - 影响当前映射文件内所有 `<class>`(实体类)和 `<collection>`(集合关联)的**默认延迟行为**。 - 可通过局部配置(如 `<class lazy="...">` 或 `<set lazy="...">`)覆盖默认值。 --- ### 二、`default-lazy="true"` 的含义 #### 1. **对 `<class>` 的影响** - 若未显式配置某个 `<class>` 的 `lazy` 属性,则其实体的**普通属性**(非关联属性)默认会**立即加载**,而**关联对象**(如 `many-to-one`、`one-to-many` 等)的加载行为由关联自身的 `lazy` 配置决定。 - **注意**:Hibernate 3.x 后,实体类本身的延迟加载(即代理对象的生成)需显式配置 `<class lazy="true">`,`default-lazy="true"` 不会自动启用类的延迟代理。 #### 2. **对 `<collection>` 的影响** - 若未显式配置集合(如 `<set>`、`<list>`)的 `lazy` 属性,则默认启用延迟加载。例如: ```xml <hibernate-mapping default-lazy="true"> <class name="Order"> <!-- 未配置 lazy,但 default-lazy 对普通属性无效 --> <set name="items"> <!-- 默认 lazy="true" --> <!-- 集合会延迟加载 --> </set> </class> </hibernate-mapping> ``` --- ### 三、常见误解与注意事项 1. **`default-lazy="true"` 不作用于实体类的普通属性** - 实体类的普通属性(如 `String name`)默认总是立即加载。 - 若需对实体类生成延迟代理(即返回代理对象,直到调用非 `id` 方法时才加载数据),需显式配置 `<class lazy="true">`。 2. **延迟加载的优先级规则** - 局部配置 > `default-lazy`。例如: ```xml <hibernate-mapping default-lazy="true"> <class name="User" lazy="false"> <!-- 显式覆盖默认值 --> <!-- 此类的关联集合仍可能受 default-lazy 影响 --> </class> </hibernate-mapping> ``` 3. **Hibernate 版本的差异** - Hibernate 5.x 后,集合的默认延迟行为从 `lazy="true"` 改为 `lazy="extra"`(更智能的延迟策略)。 - 建议结合具体版本文档验证行为。 --- ### 四、实际效果示例 #### 场景 1:默认配置 ```xml <hibernate-mapping default-lazy="true"> <class name="Product"> <set name="reviews"> <!-- 未显式设置 lazy --> <!-- 默认 lazy="true",集合延迟加载 --> </set> </class> </hibernate-mapping> ``` - **行为**:加载 `Product` 对象时,`reviews` 集合不会立即查询数据库,只有在调用 `product.getReviews()` 时才会触发加载。 #### 场景 2:显式覆盖 ```xml <hibernate-mapping default-lazy="true"> <class name="Product"> <set name="reviews" lazy="false"> <!-- 强制立即加载 --> </set> </class> </hibernate-mapping> ``` - **行为**:加载 `Product` 对象时,`reviews` 集合会立即通过 `JOIN` 或额外 SQL 加载。 --- ### 五、总结 | 配置项 | 作用范围 | 默认行为(Hibernate 3.x+) | |-------------------------|---------------|--------------------------------------------| | `hibernate-mapping default-lazy="true"` | 当前映射文件 | 对集合(`<set>`、`<list>` 等)默认启用延迟加载,但对实体类普通属性无效。 | | `<class lazy="true">` | 单个实体类 | 实体类返回代理对象,延迟加载普通属性(需显式配置)。 | | `<set lazy="true">` | 单个集合关联 | 集合延迟加载(默认受 `default-lazy` 影响)。 | **建议**: - 优先通过局部配置(如 `<set lazy="...">`)明确行为,避免依赖全局默认值。 - 通过 Hibernate 的 `show_sql` 配置或日志观察 SQL 生成,验证延迟加载是否生效。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值