java 从另一个方法调用的@Transactional 方法不获取事务

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5109343/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 09:29:45  来源:igfitidea点击:

@Transactional method called from another method doesn't obtain a transaction

javahibernatespringjpa

提问by Tom Tucker

In Spring, a method that is annotated with @Transactionalwill obtain a new transaction if there isn't one already, but I noticed that a transactional method does not obtain any transaction if it is called from a non-transactional one. Here's the code.

在 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()is a regular method that calls save()which is transactional, but saveWrap()won't persist any changes.

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

I'm using Spring 3 and Hibernate 3. What am I doing wrong here? Thanks.

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

回答by Clinton Bosch

It is one of the limitations of Springs AOP. Because the dao bean is in fact a proxy when it is created by spring, it means that calling a method from within the same class will not call the advice (which is the transaction). The same goes for any other pointcut

这是 Springs AOP 的局限性之一。因为dao bean在spring创建的时候其实就是一个proxy,也就是说从同一个类内部调用一个方法不会调用advice(也就是事务)。任何其他切入点也是如此

回答by Bozho

Yes, this is expected behaviour. @Transactionaltells spring to create a proxy around the object. The proxy intercepts calls to the object from other objects. The proxy does not intercept calls within the object.

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

If you want to make this work, add @Transactionalon the method that is invoked from "outside".

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

回答by prashant

This is a bit late I know, but would just like to add a way to overcome this limitation is that within the method obtain the spring bean from the application context and invoke the method. When the spring bean is obtained from the application context it will be the proxy bean not the original bean . Since the proxy bean is now invoking the method instead of the original bean the transaction advice will be implemented on it.

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