从另一个方法调用的@Transactional 方法没有获得事务
Posted
技术标签:
【中文标题】从另一个方法调用的@Transactional 方法没有获得事务【英文标题】:@Transactional method called from another method doesn't obtain a transaction 【发布时间】:2011-07-03 19:40:57 【问题描述】:在 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。我在这里做错了什么?谢谢。
【问题讨论】:
【参考方案1】:这是 Springs AOP 的限制之一。因为dao bean在spring创建的时候实际上是一个代理,这意味着从同一个类中调用一个方法不会调用advice(也就是事务)。任何其他切入点也是如此
【讨论】:
用@Transactional 注释saveWrap 方法没有坏处。事务传播的默认行为是必需的,这意味着如果你要获得一个嵌套事务(即你在一个事务中,然后你调用另一个也是 @Transactional 的方法)将只是使用现有事务而不是创建如果那是您所害怕的,则另一种) 用cglib做代理怎么样?我记得 cglib 代理建议每个方法,即使你在同一个类中调用它。 @ClintonBosch 如果这个新的 Transactional 方法(通过 REQUIRED 传播从另一个 Transactional 方法调用)将传播设置为 REQUIRES_NEW 怎么办?我实际上正在查看一个代码库做这件事,我很好奇它是否仍将使用相同的事务或创建一个新事务。【参考方案2】:是的,这是预期的行为。 @Transactional
告诉 spring 在对象周围创建一个代理。代理拦截来自其他对象的对该对象的调用。代理不会拦截对象内的调用。
如果您想完成这项工作,请在从“外部”调用的方法上添加@Transactional
。
【讨论】:
另一种选择是将整个类标记为事务性,方法是将@Transactional()(可能为 readOnly=true/false,propagation=something 等)放在类的顶部,然后覆盖 readOnly和/或根据需要每个方法的传播值。【参考方案3】:我知道这有点晚了,但我想添加一个方法来克服这个限制,即在方法中从应用程序上下文中获取 spring bean 并调用该方法。当从应用程序上下文中获取 spring bean 时,它将是代理 bean 而不是原始 bean。由于代理 bean 现在调用的是方法而不是原始 bean,因此将在其上实现事务建议。
【讨论】:
【参考方案4】:一种可能的解决方法是调用该方法,就像它是从“外部”调用一样
你可以通过获取组件的当前代理然后调用方法来做到这一点:
((MyService) AopContext.currentProxy()).innerMethod();
来源:https://www.programmersought.com/article/58773839126/
【讨论】:
以上是关于从另一个方法调用的@Transactional 方法没有获得事务的主要内容,如果未能解决你的问题,请参考以下文章
@Transactional 方法调用另一个没有@Transactional 注释的方法?
如何使用 React 和 Redux 从另一个组件访问 ref?