为什么@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)修复休眠延迟加载异常?
我将我正在开发的一个应用程序从使用AspectJ加载时间编织切换到使用Spring CGlib代理,在我完成之后,代码的许多部分开始获得休眠延迟加载异常,而在过去没有抛出异常。
我已经能够通过添加一堆以前的公共方法来解决这些延迟加载异常,这些方法上没有任何事务属性,但称为spring存储库以从数据库中读取数据。@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
任何人都知道为什么添加可以消除休眠延迟加载异常,以及为什么AspectJ加载时间编织不需要这些注释,而是在不需要的情况下?@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
更新2 我相信删除AspectJ不是问题所在,但问题是我没有真正理解支持传播的实际行为。特别是支持如何与JPA EntityManager交互,所以我删除了一堆导致延迟加载异常的支持传播。在通读了Spring事务管理器的源代码之后,一切都很清楚该怎么做。Spring文档没有真正很好地指出的关键思想是,@Transactional注释被用作同步点,将EntityManager的生命周期与事务方法的开始和结束联系起来。还强烈推荐 http://www.ibm.com/developerworks/java/library/j-ts1/ 的这一系列文章,这篇博客文章 http://doanduyhai.wordpress.com/2011/11/21/spring-persistencecontext-explained/
更新 1
这不是对私有@Transactional方法的调用不通过 AOP 代理的情况。从其他服务调用的公共方法会发生这些问题。
下面是代码结构的一个示例,我看到问题发生。
@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);
}
}