java - 在@Transactional 类中处理异常

标签 java spring hibernate

在我的 Spring 管理类(@Transactional@Service 注释)中,我有以下方法:

@Transactional
@Service
public class Foo {

    @Autowired
    private MyService service; // MyService has @Service and @Transactional annotations


      public void save(...) { 
          try { 
              service.save(...); // gets a Hibernate Session & calls `merge(...)`
          } catch(DataIntegrityViolationException e) {
             logMessage("save failed with exception: " + e);
          }
      }

在我对应的表中(Foo#save 执行保存工作),我有一个unique constraint

当上面的 Foo#save 代码以违反唯一约束的方式执行时,我在日志中看到抛出了 DataIntegrityViolationException,但它没有被我的 Foo#savecatch block 捕获。

   org.springframework.orm.jpa.JpaTransactionManager 891 doRollbackOnCommitException - 
     Initiating transaction rollback after commit exception 
   org.springframework.dao.DataIntegrityViolationException: Could not execute 
       JDBC batch update; SQL [insert into MY_TABLE ...; constraint 
         [MY_CONSTRAINT]; nested exception is 
       org.hibernate.exception.ConstraintViolationException: Could not execute 
    JDBC batch update

对于未捕获 DataIntegrityViolationException 感到困惑,我为所有 RuntimeException 添加了另一个捕获:

      public save(...) { 
          try { 
              service.save(...); // `service` is marked with 
                                 //  @Service and @Transactional
          } catch(DataIntegrityViolationException e) {
             logMessage("save failed with exception: " + e);
          } catch(RuntimeException e) {
             logMesssage("runtime exception e: " + e);
          }
      }

但是,同样,当我运行违反唯一约束的相同代码时,我没有看到来自 catch(RuntimeException e) block 的日志消息。

我不完全的理解是,由于我使用的是 @TransactionalFoo 的代理(由 Spring 创建)将执行 save 方法调用。

但是,我是否有可能捕获 service.save(...) 调用的 DataIntegrityViolationException

最佳答案

方法 session.merge(...) 不会立即执行插入/更新 SQL 查询,而是将此操作放入队列中。 SQL 查询将在 session 刷新时执行。在您的情况下, session 将在您的方法执行后在事务建议中刷新,并且会在那里抛出异常。

因此,要在您的方法中捕获异常,请在 session.merge(...) 之后添加 session.flush(),如下所示:

  public class MyService {

      public void save(Object o) {
         Session session = //get session somehow
         session.merge(o);
         session.flush();  // In case of data integrity violation Exception will be thrown here
      }
  }

关于java - 在@Transactional 类中处理异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25462526/

相关文章:

java - Java中的隐式(继承对象),更适合的方式?

java - 使用 Spring Cloud Streams 测试错误流

java - Hibernate 在从注解创建表时不会创建索引

java - 错误 : com. jayway.maven.plugins.android.generation2 :android-maven-plugin:3. 6.0:generate-sources

java - 分配参数类型对整数溢出的影响

java - 请求权限错误

java - Jpa 事务 javax.persistence.RollbackException : Transaction marked as rollbackOnly

java - Hibernate HQL NULL 比较模式

java - Hibernate XML 读取时出错

java - Mockito 不使用 @Spy 模拟私有(private)变量