休眠中一对一关联的延迟加载问题

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 关系是错误的解决方法。