休眠中一对一关联的延迟加载问题
Lazy loading issue with One to one association in hibernate
我有一个关于 OneToOne
关联映射延迟加载的问题。
案例 1 外键在子节点中 table(地址)
@Entity
public class User {
..........
@OneToOne(mappedBy="user")
private Address address;
@Entity
public class Address{
.........
@OneToOne
@JoinColumn(name = "user_id")
private User user;
在上面的地址延迟加载不起作用。
案例 2 外键在父项中 table(用户)
@Entity
public class User {
.............
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name="address_id")
private Address address;
@Entity
public class Address {
........
@OneToOne(mappedBy="address")
private User user;
在上面的地址中延迟加载有效。
有人可以解释一下为什么 One to one
延迟加载在第一种情况下不起作用但在第二种情况下有效吗?
@OneToOne
处理起来有点棘手。
这完全取决于您使用的持久性提供程序。
一些供应商不尊重 FetchType.LAZY
提示。
你可以尝试指定(在关系的两端)
@OneToOne(optional = true, fetch = FetchType.LAZY)
要了解这里发生了什么,让我们看一下关卡:
第一种情况:
+-----------------+ +------------------+
| USER | | Address |
| |1 1| |
| +-------------+ USER_ID (FK) |
| | | |
| | | |
+-----------------+ +------------------+
加载用户时,Hibernate 必须知道地址是否存在。
所以 Hibernate 发出了一个 SQL 类似于这样的请求:
SELECT * FROM USER WHERE ID = ?
SELECT * FROM ADDRESS WHERE user_id = ?
当得到结果时,实体已经加载,所以没有必要将 LazyProxy 分配给地址。 Hibernate 分配获取的对象。
第二种情况:
+-----------------+ +------------------+
| USER | | Address |
| |1 1| |
| ADDRESS_ID +-------------+ |
| | | |
| | | |
+-----------------+ +------------------+
SELECT * FROM USER WHERE ID = ?
Hibernate 不需要检查地址是否存在。这就是创建代理的原因。
阅读这篇文章。它会让您理解为什么反向(映射)属性上的一对一不能按预期工作。One to One Lazy explanation。
实际上在反面hibernate需要知道映射的值是什么,因为用户可以立即请求值。
阅读这篇文章,您将清楚地了解事情是如何运作的。
谢谢
我无法让它工作,所以我最终使用了一个准备好的语句,其中我 JOIN FETCH
Hibernate 无论如何在事后查询的东西。
在我看来,添加 optional=true
或伪造 OneToMany
关系是错误的解决方法。
我有一个关于 OneToOne
关联映射延迟加载的问题。
案例 1 外键在子节点中 table(地址)
@Entity
public class User {
..........
@OneToOne(mappedBy="user")
private Address address;
@Entity
public class Address{
.........
@OneToOne
@JoinColumn(name = "user_id")
private User user;
在上面的地址延迟加载不起作用。
案例 2 外键在父项中 table(用户)
@Entity
public class User {
.............
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name="address_id")
private Address address;
@Entity
public class Address {
........
@OneToOne(mappedBy="address")
private User user;
在上面的地址中延迟加载有效。
有人可以解释一下为什么 One to one
延迟加载在第一种情况下不起作用但在第二种情况下有效吗?
@OneToOne
处理起来有点棘手。
这完全取决于您使用的持久性提供程序。
一些供应商不尊重 FetchType.LAZY
提示。
你可以尝试指定(在关系的两端)
@OneToOne(optional = true, fetch = FetchType.LAZY)
要了解这里发生了什么,让我们看一下关卡:
第一种情况:
+-----------------+ +------------------+
| USER | | Address |
| |1 1| |
| +-------------+ USER_ID (FK) |
| | | |
| | | |
+-----------------+ +------------------+
加载用户时,Hibernate 必须知道地址是否存在。
所以 Hibernate 发出了一个 SQL 类似于这样的请求:
SELECT * FROM USER WHERE ID = ?
SELECT * FROM ADDRESS WHERE user_id = ?
当得到结果时,实体已经加载,所以没有必要将 LazyProxy 分配给地址。 Hibernate 分配获取的对象。
第二种情况:
+-----------------+ +------------------+
| USER | | Address |
| |1 1| |
| ADDRESS_ID +-------------+ |
| | | |
| | | |
+-----------------+ +------------------+
SELECT * FROM USER WHERE ID = ?
Hibernate 不需要检查地址是否存在。这就是创建代理的原因。
阅读这篇文章。它会让您理解为什么反向(映射)属性上的一对一不能按预期工作。One to One Lazy explanation。
实际上在反面hibernate需要知道映射的值是什么,因为用户可以立即请求值。
阅读这篇文章,您将清楚地了解事情是如何运作的。
谢谢
我无法让它工作,所以我最终使用了一个准备好的语句,其中我 JOIN FETCH
Hibernate 无论如何在事后查询的东西。
在我看来,添加 optional=true
或伪造 OneToMany
关系是错误的解决方法。