从另一个方法调用的@Transactional方法不会获得事务

Tom*_*ker 22 java spring hibernate jpa

在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
    }
}
Run Code Online (Sandbox Code Playgroud)

saveWrap()是一种常规方法,它调用save()哪些是事务性的,但saveWrap()不会保留任何更改.

我正在使用Spring 3和Hibernate 3.我在这里做错了什么?谢谢.

Cli*_*sch 37

这是Springs AOP的局限之一.因为dao bean实际上是spring创建的代理,这意味着从同一个类中调用方法不会调用通知(这是事务).任何其他切入点也是如此

  • 使用@Transactional注释saveWrap方法没有任何害处.事务传播的默认行为是REQUIRED,这意味着如果你要获得一个嵌套事务(即你在一个事务中,然后你调用另一个也是@Transactional的方法)只是使用现有事务而不是创建另一个,如果这是你害怕的) (3认同)

Boz*_*zho 12

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

如果要使其工作,请添加@Transactional从"外部"调用的方法.

  • 另一种选择是将整个类标记为事务性的,方法是将 @Transactional()(可能带有 readOnly=true/false、propagation=something 等)放在类的顶部,然后覆盖每个类的 readOnly 和/或传播值。需要的方法。 (2认同)

pra*_*ant 5

我知道这有点晚了,但我想添加一种方法来克服这个限制,那就是在方法内从应用程序上下文中获取 spring bean 并调用该方法。当从应用程序上下文获取 spring bean 时,它将是代理 bean 而不是原始 bean。由于代理 bean 现在调用该方法而不是原始 bean,因此将在其上实现事务建议。