【问题标题】:commit changes in try-catch inside @Transactional在 @Transactional 内的 try-catch 中提交更改
【发布时间】:2016-08-22 20:21:24
【问题描述】:

考虑一下我有一个方法在 ActiveRecord 模式样式中做一些事情和记录机制:

@Transactional
public void doSmt() {
    try {
        someOperation(); // can throw exception
        Logger.logIntoDb(); // if everything is OK
    } catch {Exception e} {
        Logger.logIntoDbWithException(e.getMessage()); // log error into db

        throw new MyCustomException(e);
    }
}

public static void logIntoDbWithException(String message) {
    final LogEntry logEntry = new LogEntry();
    logEntry.setDate(new Date());
    logEntry.setMessage(message);
    logEntry.persist();
}

我想在失败的情况下保留一条错误消息,但如果我在 catch 子句中重新抛出异常,事务将被回滚并且我的 LogEntry 将不会被保留。我看到的唯一方法是在persist() 之后手动调用flush()

是否有更干净的解决方案来执行此操作?

谢谢。

UPD:

由于我有一个执行持久化的静态方法,因此我需要将以下技巧应用于已接受的答案:

public static void logIntoDbWithException(String message) {
    new Runnable() {
        @Transactional(propagation = Propagation.REQUIRES_NEW)
        public void run() {
            final LogEntry logEntry = new LogEntry();
            logEntry.setDate(new Date());
            logEntry.setMessage(message);
            logEntry.persist();
        }
    }.run();
}

【问题讨论】:

  • 尝试将其分成两个事务。下面的链接也有同样的答案。 Check here

标签: java spring hibernate jpa jdbc


【解决方案1】:

首先,调用flush() 对您没有任何好处:flush() 不会提交任何内容,并且当您在同一事务中记录错误时,插入将被回滚。

因此,您需要启动一个新的“嵌套”事务来记录错误。

public class A {

    @Autowired
    private B b;

    @Transactional
    public void doSmt() {
        try {
            someOperation(); // can throw exception
            b.logIntoDb(); // if everything is OK
        } catch {Exception e} {
            b.logIntoDbWithException(e.getMessage()); // log error into db

            throw new MyCustomException(e);
        }
    }
}

public class B{

    //outer transaction is still active
    public  void logIntoDb(String message) {
        final LogEntry logEntry = new LogEntry();
        logEntry.setDate(new Date());
        logEntry.setMessage(message);
        logEntry.persist();
    }

    // 'outer' transaction will be suspended until this method completes
    // this new transaction will commit/rollback independently of the outer transaction
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public  void logIntoDbWithException(String message) {
        final LogEntry logEntry = new LogEntry();
        logEntry.setDate(new Date());
        logEntry.setMessage(message);
        logEntry.persist();
    }
}

【讨论】:

  • 你好 - 如果我们有一个类级别的 @Transactional 怎么办?
猜你喜欢
  • 2011-07-19
  • 1970-01-01
  • 1970-01-01
  • 2021-12-25
  • 2014-11-02
  • 2021-11-25
  • 1970-01-01
  • 2020-01-15
  • 1970-01-01
相关资源
最近更新 更多