我有一个与延迟加载OneToOne
关联映射有关的问题。
案例1 外键位于子表(地址)
中@Entity
public class User {
..........
@OneToOne(mappedBy="user")
private Address address;
@Entity
public class Address{
.........
@OneToOne
@JoinColumn(name = "user_id")
private User user;
在上面的地址中,延迟加载不起作用。
案例2 外键位于父表(用户)
中@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
延迟加载在第一种情况下不起作用但在第二种情况下有效吗?
答案 0 :(得分:2)
@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分配给Address是没有意义的。 Hibernate分配获取的对象。
第二种情况:
+-----------------+ +------------------+
| USER | | Address |
| |1 1| |
| ADDRESS_ID +-------------+ |
| | | |
| | | |
+-----------------+ +------------------+
SELECT * FROM USER WHERE ID = ?
Hibernate不需要检查地址是否存在。这就是创建代理的原因。
答案 1 :(得分:1)
我无法使它工作,所以我最后使用了一个准备好的声明,其中JOIN FETCH
Hibernate事后无论如何都要查询的事情。
添加optional=true
或伪造OneToMany
关系是IMO错误的解决方法。
答案 2 :(得分:0)
阅读这篇文章。它将帮助您理解为什么反向(映射)属性中的一对一不能按预期工作。One to One Lazy explanation。
实际上在反面hibernate需要知道映射的价值是什么,因为用户可以立即询问值。
阅读文章,您将清楚地了解事情是如何运作的。
由于