间接Hibernate/JPA方法调用丢失事务

Coj*_*nes 3 java spring hibernate jpa-2.0

我正在使用Spring/JPA2/hibernate代码:

class A {
  @Autowired
  B b;

  @RequestMapping("/test")
  public void test(final HttpServletRequest r1, HttpServletResponse r2) throws ... {

    b.inner();   // Works

    b.outer();   // javax.persistence.TransactionRequiredException: 
                 // no transaction is in progress ... :|
}

@Component
class B {
   @PersistenceContext
   EntityManager em;

   public void outer() { inner(); }

   @Transactional
   public void inner() { em.flush(); }
}
Run Code Online (Sandbox Code Playgroud)

为什么inner()只有在间接调用时才会松散交易?

Dan*_*Dan 5

http://static.springsource.org/spring/docs/current/reference/transaction.html#transaction-declarative-annotations

在代理模式(默认设置)下,只拦截通过代理进入的外部方法调用.这意味着实际上,自调用目标对象中的一个方法调用目标对象的另一个方法,即使被调用的方法用@Transactional标记,也不会在运行时导致实际的事务.

如果您希望自我调用也包含在事务中,请考虑使用AspectJ模式(请参阅下表中的mode属性).在这种情况下,首先不会有代理; 相反,目标类将被编织(即,它的字节代码将被修改),以便在任何类型的方法上将@Transactional转换为运行时行为.

@Autowired参考B b(内部类A),被包裹着的Spring AOP事务感知代理.

b.inner()被调用时,要调用它的交易意识的实例,并将其标记为@Transactional.因此,启动了Spring托管事务.

b.outer()调用时,它也在事务感知实例上,但事实并非如此 @Transactional.因此,Spring管理的事务启动.

一旦你在里面的调用outer()调用inner()通过交易感知代理下去,它被直接调用.它是一样的this.inner().由于您是直接调用它,而不是通过代理调用它,因此它没有Spring事务感知语义.

由于没有启动任何事务,因此导致了TransactionRequiredException.

可能的解决方案包括制定方法outer() @Transactional.

   @Transactional
   public void outer() { inner(); }
Run Code Online (Sandbox Code Playgroud)

或者整个班级 @Transactional.

@Transactional   
@Component
class B {
   @PersistenceContext
   EntityManager em;
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

1549 次

最近记录:

14 年,6 月 前