@从另一种方法调用的交易方法不会获得交易

@从另一种方法调用的交易方法不会获得交易

问题描述:

在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.我在这里做错了什么?谢谢。

这是Springs AOP的局限性之一。由于dao bean实际上是一个由Spring创建的代理,这意味着从同一个类中调用方法不会调用advice(这是事务)。其他切入点也是如此

+2

用@Transactional注释saveWrap方法没有什么坏处。事务传播的默认行为是REQUIRED,这意味着如果您要获得嵌套事务(即,您处于事务中,然后调用另一个也是@Transactional的方法),则只需使用现有事务,而不是创建另一个如果这就是你害怕的) – 2011-02-24 19:38:12

+0

如何使用cglib来代理?我记得cglib代理的建议,即使你在同一个类中调用它。 – hiway 2018-01-29 04:08:28

是的,这是预期的行为。 @Transactional告诉spring在对象周围创建一个代理。代理拦截从其他对象调用对象。代理不会拦截对象内的调用。

如果你想做这个工作,在从“外部”调用的方法上添加@Transactional

+1

另一种选择是将整个类标记为事务性的,方法是在类的顶部放置@Transactional()(有可能是readOnly = true/false,propagation = something等),然后重写readOnly和/根据需要的每个方法的值。 – esaj 2011-02-24 19:31:14

我知道这有点晚,但只是想增加一种方法来克服这个限制,就是在方法中从应用程序上下文中获取spring bean并调用方法。当从应用程序上下文获得spring bean时,它将是代理bean而不是原始bean。由于代理bean现在正在调用该方法而不是原始bean,交易建议将在其上实施。