gpt4 book ai didi

java - JPA - 如果在 JPQL 查询获取子对象之前引用了父实体,则在忽略延迟加载的结果中获取父实体

转载 作者:行者123 更新时间:2023-11-30 10:16:39 24 4
gpt4 key购买 nike

已编辑

我有一个简单的单向@ManyToOne Lazy 关系:

public class UserLog {
...
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "userId", updatable=false,insertable=false)
private User user;
...
}

我使用延迟加载,因为有些情况下我希望用户字段被填充,但有时不会。我使用 spring,我的应用程序配置了 hibernate,我在我的配置中使用了 hibernate 5 模块,所以我的实体只有在我请求时才会在我的 json 结果中获取。

@Bean
public Module hibernate5Module()
{
return new Hibernate5Module();
}

所以问题是,当我想以这种方式获取例如用户的日志时:

User user = userRepository.findOne(userId);
...
/*Checking user object before requesting logs...*/
...
List<UserLog> userlogs = userLogRepository.getUserLogs(userId);

// (query looks like this: "select u from UserLog u where u.userId = ?1")

当我返回我的 userlogs 列表时,用户字段会填充到 json 响应中。如果我不从 userRepository 中获取 user 对象(注释掉第一行),则 user 字段正确为空。

我测试了修改我的 getUserLogs 查询以不对 userId 字段进行任何引用,但仍获取用户。

所以我的问题是,如何让 JPA 在我直接访问用户字段时获取它(例如,在我的查询中使用 JOIN FETCH u.user)?为什么提取了 user 字段,即使我没有访问我的 userlog 对象中的用户字段?

如果有任何建议,我将不胜感激。

编辑:在请求userlogs 之前使用entityManager.clear();user 字段是不再有人居住。这个解决方案似乎有点 hacky,除了分离实体之外,还必须有另一种方法吗?因为如果我想在请求日志后修改 User 对象,我必须再次请求 User 对象。

最佳答案

发生的事情很简单:

您通过他的 id 从 db 询问某个 User,并在 UserLog 之后通过相同的 userId 询问。

现在,在第一个请求之后,hibernate 会将 User 保存在它的一级缓存中。

在您的第二个请求中,您为 User 关系指定了延迟获取,正如您所指出的,它正在运行:

(commenting out the first line), then the user field is empty correctly.

这里的重点是hibernate已经在缓存中有相应的User所以不需要查询数据库直接给你。

相反,如果您在尝试时清除缓存,您会强制 hibernate 访问数据库,然后根据延迟获取为您提供一个代理

您应该能够从日志中验证没有其他查询正在执行。

关于java - JPA - 如果在 JPQL 查询获取子对象之前引用了父实体,则在忽略延迟加载的结果中获取父实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49958084/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com