在Spring中,使用@Transactional
注释的方法将获得一个新事务(如果还没有),但我注意到如果从非调用事务方法调用事务方法则不会获得任何事务交易的。这是代码。
@Component
public class FooDao {
private EntityManager entityManager;
@PersistenceContext
protected void setEntityManager(EntityManager entityManager) {
this.entityManager = entityManager;
}
@Transactional
public Object save(Object bean) {
return this.entityManager.merge(bean);
}
public Object saveWrap(Object bean) {
return save(bean);
}
}
@Component
public class FooService {
private FooDao fooDao;
public void save(Object bean) {
this.fooDao.saveWrap(bean); // doesn't work.
this.fooDao.save(bean); // works
}
}
saveWrap()
是一种调用save()
的常规方法,它是事务性的,但saveWrap()
不会保留任何更改。
我正在使用Spring 3和Hibernate 3.我在这里做错了什么?感谢。
答案 0 :(得分:37)
这是Springs AOP的限制之一。因为dao bean实际上是spring创建的代理,这意味着从同一个类中调用方法不会调用通知(这是事务)。任何其他切入点都是如此
答案 1 :(得分:12)
是的,这是预期的行为。 @Transactional
告诉spring在对象周围创建代理。代理拦截从其他对象调用对象。代理不拦截对象内的调用。
如果您想使其工作,请在“外部”调用的方法上添加@Transactional
。
答案 2 :(得分:2)
我知道这有点晚了,但是只想添加一种方法来克服这个限制,即在方法中从应用程序上下文中获取spring bean并调用该方法。当从应用程序上下文获取spring bean时,它将是代理bean而不是原始bean。由于代理bean现在正在调用方法而不是原始bean,因此将在其上实现事务通知。
答案 3 :(得分:0)
一种可能的解决方法是调用该方法,就像它是从“外部”调用一样
你可以通过获取组件的当前代理然后调用方法来实现:
((MyService) AopContext.currentProxy()).innerMethod();