【问题标题】:Does JPA open two sessions if called twice?如果调用两次,JPA 会打开两个会话吗?
【发布时间】:2021-06-28 21:31:39
【问题描述】:

我希望这对于那些熟悉 JPA/Hibernate 的人来说是一个简单的答案。

因此,如果我在 Spring 中有一个扩展 JPA 接口的存储库接口,并且我连续两次调用它以获取数据库中的单个条目,它会打开两个会话吗?还是会议对双方都开放?还是第一次将数据加载到内存中,然后再次使用?

我没有明确启用任何缓存,所以我猜它不会将它加载到内存中并使用它两次,但我对幕后的细节并不是非常熟悉。一切也都设置为延迟加载,所以不确定这是否会导致会话快速关闭。

只是好奇,感谢您的回复!

【问题讨论】:

  • 这取决于你的事务分界在哪里。如果那是在调用 2 个方法的方法上,那么它将是一个会话,否则您将有 2 个会话。

标签: spring hibernate jpa caching


【解决方案1】:

因此,如果我在 Spring 中有一个扩展 JPA 接口的存储库接口,并且我连续两次调用它以获取数据库中的单个条目,它会打开两个会话吗?或者会话是否对双方都开放?

如果两个调用都是同一事务的一部分,则只会使用一个会话(与当前事务上下文相关联的会话)。

由于没有周围事务,因为默认情况下存储库方法是事务性的,每个调用都将在一个单独的事务中处理,这意味着两个单独的会话。

还是第一次将数据加载到内存中,然后再次使用?

如果您使用findById(即EntityManager.find())在同一事务中请求同一实体,则第二次将由一级缓存提供服务。

如果您使用查询请求相同的实体,第二次将执行该查询,但 Hibernate 将通过检索到的 id 实现实体已在缓存中找到,因此将从 1st-level 提供结果缓存也是如此。

【讨论】:

  • 感谢您的回复,这是有道理的。这些调用是 findOne(),它们没有标记为@Transactional,所以听起来会有两个查询,但它只会从数据库加载一次,第二次从缓存加载。我肯定需要阅读更多关于一级缓存的内容。
  • 请注意,如果调用没有包装在同一个事务中,会话将在第一次调用后连同它的缓存一起被销毁,因此从第二次开始将没有缓存来提供结果.
  • 我们如何强制它从数据库而不是缓存中获取结果?
  • 您可以在原始结果上使用EntityManager.detach(),或在EntityManager 上使用clear 来重置持久性上下文。但是,如果您在事务的上下文中,99% 的时间强制它是无用的,因为事务隔离保证结果将完全相同
猜你喜欢
  • 2015-04-14
  • 1970-01-01
  • 1970-01-01
  • 2019-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-21
  • 1970-01-01
相关资源
最近更新 更多