Spring Boot 如何处理 Hibernate 会话?
Posted
技术标签:
【中文标题】Spring Boot 如何处理 Hibernate 会话?【英文标题】:How Spring Boot Handle Hibernate Session? 【发布时间】:2019-10-01 06:50:28 【问题描述】:我看到使用 Spring Boot 你不需要打开和关闭休眠会话。
但为了了解它在内部是如何工作的,它在哪一层打开休眠会话以及何时关闭。
我创建了一个 POC。
我有一个 Spring Boot 应用程序,它有两个实体,一个是 Customer
,另一个是 Address
,Customer
和 Address
之间存在一对多关系。
我有一个两个 API,一个是添加记录,另一个是获取所有记录。 这些 API 位于 CustomerEndpoint 中,并带有注释
@RestController
@RequestMapping(value="/customer").
还创建了 CustomerRepository
扩展 CrudRepository
用于保存和获取 Customer
记录。
所以根据我的理解,当我们说customer.getAddress
(因为它的 fetchtype 是 LAZY)时,在 CustomerEndpoint
class 中使用 CustomerRepository
获取客户时应该会抛出 LazyInitialization 错误。
但它没有抛出任何错误,它工作正常。
我在想 CustomerEndpoint
类中不存在休眠会话。
谁能帮我这个 Hibernate 会话是如何由 Spring Boot 维护的?
因为每个人都认为它是另一个问题的重复,但我的问题不是他们解释的首要问题,因为根据他们的说法,会话在存储库之前是有效的,所以根据我应该在说 customer.getAddress 时得到 LazyInitialization 异常在 CustomerEndpoint 中,因为它不是存储库,但我没有收到任何异常
【问题讨论】:
也许你正在寻找这个答案:***.com/questions/25709976/… Spring Boot & Spring Data: how are Hibernate Sessions managed?的可能重复 @DeepakKhillare 我已经浏览了该帖子,但他们无法回答我的问题,即如果会话处于存储库级别,那么我如何能够在 CustomerEndpoint 中获取 LAZY 初始化的地址实体,为什么我没有得到 LazyInitialization 异常 为实体添加源代码(如果已使用注释)。即使您认为它是延迟加载的,它也可能已经急切地加载了。 【参考方案1】:首先,在您的Presentation layer
中使用Repository layer
不是一个好习惯。
OSIV(Open Session in View)在 Spring Boot 中默认启用,OSIV 从性能和可扩展性的角度来看确实是个坏主意。
因此,您不会遇到异常并且能够在表示层中工作。 通过将以下内容放入您的 application.properties 文件中进行检查
spring.jpa.open-in-view=false
您可以参考OSIV AntiPattern了解更多详情
【讨论】:
谢谢,没错,这就是我要找的。如果我错了,请纠正我,所以在 Spring Boot 中,如果此标志为 false,则休眠会话仅在 Repository 中打开,并且无论您将 @Transactional 放在哪里,其他地方都没有。 哪种做法?使用 spring.jpa.open-in-view=true 还是使用 @Transactional? 是的,现在我明白了,谢谢【参考方案2】:我认为,如果您的 customer.getAddress 在交易中,它仍然有效
【讨论】:
那么我怎么知道它是否在 transaction 中,因为我没有明确添加任何 Transaction 注释 并且按照 link shared 上面他们解释说会话在 Repository 之前有效,但我在 CustomerEndpoint 类中。所以根据那篇文章,我应该得到 LazyInitialization 异常。以上是关于Spring Boot 如何处理 Hibernate 会话?的主要内容,如果未能解决你的问题,请参考以下文章
在 Spring Boot 中验证 JWT 时如何处理 InvalidSignatureException?
如何处理 Spring Boot、AngularJS 应用程序中的 CORS 错误?