gpt4 book ai didi

java - 为什么 @Transactional(propagation = Propagation.SUPPORTS, readOnly = true) 修复 Hibernate 延迟加载异常?

转载 作者:IT老高 更新时间:2023-10-28 13:52:09 30 4
gpt4 key购买 nike

我将我正在开发的应用程序从使用 AspectJ 加载时间编织切换到使用 Spring CGlib 代理,并且在我这样做之后,我开始在代码的许多部分中获得 hibernate 延迟加载异常,而在过去有没有抛出异常。

我已经能够通过将 @Transactional(propagation = Propagation.SUPPORTS, readOnly = true) 添加到之前没有任何事务属性的公共(public)方法中来解决这些延迟加载异常但调用 spring 存储库从数据库中读取数据。

任何人都知道为什么添加 @Transactional(propagation = Propagation.SUPPORTS, readOnly = true) 会消除 hibernate 延迟加载异常,以及为什么 AspectJ 加载时间编织不需要这些注释但需要出来了吗?

更新 2我认为删除 AspectJ 不是问题,但问题是我并不真正了解 SUPPORTS 传播的实际行为。特别是 SUPPORTS 如何与 JPA EntityManager 交互,因此我删除了一堆导致延迟加载异常的 SUPPORTS 传播。在阅读了 Spring Transaction Manager 的源代码之后,该做什么就变得很清楚了。 Spring 文档并没有很好地指出的关键思想是 @Transactional 注释用作将 EntityManager 的生命周期与事务方法的开始和结束联系起来的同步点。也强烈推荐http://www.ibm.com/developerworks/java/library/j-ts1/上的这一系列文章和这篇博文 http://doanduyhai.wordpress.com/2011/11/21/spring-persistencecontext-explained/

更新 1

这不是通过 AOP 代理调用私有(private) @Transactional 方法的情况。这些问题发生在从其他服务调用的公共(public)方法中。

这是代码结构的示例,我在其中看到了问题的发生。

@Service
public class FooService
{
@Autowired
private BarService barService;

public void someMethodThatOnlyReads() {
SomeResult result = this.barService.anotherMethodThatOnlyReads()

// the following line blows up with a HibernateLazyLoadingEcxeption
// unless there is a @Transactional supports annotation on this method
result.getEntity().followSomeRelationship();
}

}

@Service
public class BarService
{
@Autowired
private BarRepository barRepo;

public SomeResult anotherMethodThatOnlyReads()
{
SomeEntity entity = this.barRepo.findSomeEntity(1123);
SomeResult result = new SomeResult();
result.setEntity(entity);
return result;
}
}

@Repository
public class BarRepository
{
@PersistenceContext
private EntityManager em;

public SomeEntity findSomeEntity(id Integer)
{
em.find(SomeEntity.class,id);
}
}

最佳答案

我假设您的代码没有使用 OpenSessionInViewFilter或类似的东西。

没有 @Transactional注解,Hibernate session 在离开 BarRepository.findSomeEntity() 后关闭方法。

当一个 @Transactional方法被调用,TransactionalInterceptor正确绑定(bind)到方法(通过 cglib 代理或您在 Spring 上下文中拥有的任何其他 AOP 配置),然后 Spring 为整个带注释的方法保持打开状态,从而防止任何延迟加载异常。

如果您将日志记录设为 DEBUGorg.springframework.transactionorg.springframework.orm.hibernate3 (或 hibernate4 如果您使用的是 Hibernate 4)记录器,尤其是 HibernateTransactionManager类(class)和org.springframework.transaction.support.AbstractPlatformTransactionManager ,您应该确切地看到 Spring 在代码流中的哪些点决定它需要打开和关闭 Hibernate Session。日志还应显示 session 或事务在每个点打开/关闭的原因。

关于java - 为什么 @Transactional(propagation = Propagation.SUPPORTS, readOnly = true) 修复 Hibernate 延迟加载异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16062893/

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