ams*_*ams 17 java spring hibernate
我使用AspectJ加载时间编织切换到我正在使用的应用程序,使用Spring CGlib代理,在我做了之后,我开始得到hibernate延迟加载异常的代码的许多部分,在过去没有例外是抛出.
我已经能够通过添加@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
一堆以前没有任何事务属性的公共方法来解决这些延迟加载异常,但是调用spring存储库来从数据库中读取数据.
任何人都知道为什么添加会@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
消除hibernate延迟加载异常以及为什么这些注释不需要使用AspectJ加载时间编织但是是否需要输出?
更新2 我相信删除AspectJ不是问题,但问题是我并不真正了解SUPPORTS传播的实际行为.特别是SUPPORTS如何与JPA EntityManager交互,因此我删除了一堆SUPPORTS传播,导致延迟加载异常.在阅读了Spring事务管理器的源代码之后,一切都变得清晰了.Spring文档没有真正指出的关键思想是@Transactional注释被用作将EntityManager的生命周期与事务方法的开始和结束联系起来的同步点.同时强烈推荐这一系列文章,网址为http://www.ibm.com/developerworks/java/library/j-ts1/,此博客文章http://doanduyhai.wordpress.com/2011/11/21/spring- persistencecontext解释的/
更新1
这不是调用不通过AOP代理的私有@Transactional方法的情况.这些问题发生在从其他服务调用的公共方法中.
这是代码结构的一个例子,我看到问题发生了.
@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);
}
}
Run Code Online (Sandbox Code Playgroud)
我假设您的代码没有使用OpenSessionInViewFilter
或类似的东西.
没有@Transactional
注释,Hibernate会话在离开BarRepository.findSomeEntity()
方法后关闭.
当一个@Transactional
方法被调用并且TransactionalInterceptor
正确绑定到该方法时(通过cglib代理或Spring上下文中的任何其他AOP配置),Spring会为整个注释方法保持打开Session,从而防止任何延迟加载异常.
如果您将日志记录调到DEBUG
on org.springframework.transaction
和org.springframework.orm.hibernate3
(或者hibernate4
如果你在Hibernate 4上)记录器,特别是HibernateTransactionManager
类和org.springframework.transaction.support.AbstractPlatformTransactionManager
,你应该确切地看到代码流中的哪些点Spring正在决定它需要打开和关闭Hibernate Session.日志还应显示在每个点打开/关闭会话或事务的原因.
我不完全确定它为什么会发生,但我的理论如下.
当您从AspectJ编织移动到CGLIB代理时,@Transactional
放置在从同一对象调用的方法上的注释将停止生效.这意味着这些方法中的代码将以非事务方式执行(除非您@Transacional
的调用堆栈中有另一个方法@Transacional
真正生效).
注意:对于具有事务同步的事务管理器,PROPAGATION_SUPPORTS与根本没有事务略有不同,因为它定义了同步将应用的事务范围.因此,将为整个指定范围共享相同的资源(JDBC连接,Hibernate会话等).请注意,这取决于事务管理器的实际同步配置.
因此,当您的代码非事务性地执行时,Session
用于加载对象的Hibernate 将无法用于后续的惰性属性初始化.当您在代码堆栈中注释顶级方法时@Transactional(propagation = Propagation.SUPPORTS)
,Hibernate Session
将一直可用,直到您离开该方法.
归档时间: |
|
查看次数: |
8454 次 |
最近记录: |