在Spring bean中启动新事务 [英] Starting new transaction in Spring bean

查看:143
本文介绍了在Spring bean中启动新事务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有:

@Transactional(propagation = Propagation.REQUIRED)
public class MyClass implementes MyInterface { ...

MyInterface有一个方法: go()

MyInterface has a single method: go().

当go()执行时,我们启动一个新的事务,当方法完成时提交/回滚 - 这很好。

When go() executes we start a new transaction which commits/rollbacks when the method is complete - this is fine.

现在让我们说在go()中我们在MyClass中调用一个私有方法,该方法有 @Transactional(propagation = Propagation.REQUIRES_NEW 。看来Spring忽略了 REQUIRES_NEW注释并没有启动新事务。我相信这是因为Spring AOP在接口级别(MyInterface)上运行,并且不拦截对MyClass方法的任何调用。这是正确的吗?

Now let's say in go() we call a private method in MyClass that has @Transactional(propagation = Propagation.REQUIRES_NEW. It seems that Spring "ignores" the REQUIRES_NEW annotation and does not start a new transaction. I believe this is because Spring AOP operates on the interface level (MyInterface) and does not intercept any calls to MyClass methods. Is this correct?

有没有办法在go()事务中启动一个新事务?是否只能调用另一个 Spring管理bean,其事务配置为REQUIRES_NEW?

Is there any way to start a new transaction within the go() transaction? Is the only way to call another Spring managed bean that has transactions configured as REQUIRES_NEW?

更新:在客户执行 go()时添加他们是通过引用接口而不是类来实现的:

Update: Adding that when clients execute go() they do so via a reference to the interface, not the class:

@Autowired
MyInterface impl;

impl.go();


推荐答案

从Spring参考2.5:

From the Spring reference 2.5:


使用代理时, @Transactional 注释应仅应用于具有公共可见性的
方法。如果您使用 @Transactional 注释注释protected,private或
包可见方法,则不会产生错误
,但带注释的方法将不显示配置的事务
设置。

When using proxies, the @Transactional annotation should only be applied to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error will be raised, but the annotated method will not exhibit the configured transactional settings.

所以Spring忽略 @Transactional 关于非公开方法的注释。

So Spring ignores @Transactional annotation on non-public methods.

此外,


在代理中模式(这是默认值),只有通过代理进入
的外部方法调用才会被截获。这意味着'自调用',
即目标对象中调用目标
对象的其他方法的方法,即使被调用的$ b $也不会在运行时导致实际的事务。 b方法标有 @Transactional

所以即使你做了你的方法 public ,在同一个类的方法中调用它不会启动新的事务。

So even if you make your method public, calling it from within a method of same class will not start a new transaction.

你可以使用事务设置中的 aspectj 模式,以便在类中编译与事务相关的代码,并且不会在运行时创建代理。

You can use aspectj mode in transaction settings so that the transaction related code is weaved in the class and no proxy is created at runtime.

参见参考文件更多细节。

另一种可能的方法是在类本身中获取类的spring代理并在其上调用方法而不是这个

Another possible way of doing this is fetching the spring proxy of the class in the class itself and call methods on it rather than this:

@Service
@Transactional(propagation = Propagation.REQUIRED)
public class SomeService {

    @Autowired
    private ApplicationContext applicationContext;

    private SomeService  getSpringProxy() {
        return applicationContext.getBean(this.getClass());
    }

    private void doSomeAndThenMore() {
        // instead of
        // this.doSometingPublicly();
        // do the following to run in transaction
        getSpringProxy().doSometingPublicly();
    }

    public void doSometingPublicly() {
        //do some transactional stuff here
    }

}

这篇关于在Spring bean中启动新事务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆