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

标签 java hibernate spring 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(); }
}

为什么 inner() 只有在间接调用时才会松动事务?

最佳答案

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

In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual transaction at runtime even if the invoked method is marked with @Transactional.

Consider the use of AspectJ mode (see mode attribute in table below) if you expect self-invocations to be wrapped with transactions as well. In this case, there will not be a proxy in the first place; instead, the target class will be weaved (that is, its byte code will be modified) in order to turn @Transactional into runtime behavior on any kind of method.

@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(); }

或者使整个类成为@Transactional

@Transactional   
@Component
class B {
   @PersistenceContext
   EntityManager em;

关于java - 间接 Hibernate/JPA 方法调用丢失事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6499618/

相关文章:

java - 在 pom.xml 中包含 jar

mysql - 我如何使用hibernate在jsp页面中登录

java - 除主以外的 Hibernate OneToMany 关联

java - 对带有删除标志的数据使用 HQL 的正确方法是什么

Java 主类在运行时重写属性文件

java - spring中如何将JSON请求转换为特定格式的列表?

java - 从 Spring MVC XML 文件移动到 javaconfig。我真的迷失了我的数据库 XML 文件

java - Java 中是否有一个好的替代 URL 解析器

java - Java中的数字时钟

Java 1.4 工厂问题