当前位置: 首页 > 面试题库 >

在@Transactional内部提交try-catch中的更改

司知
2023-03-14
问题内容

考虑一下我有一个方法以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将不会保留。我看到的唯一方法是手动调用flush()after
persist()

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

谢谢。

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

问题答案:

首先,调用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();
    }
}


 类似资料:
  • 我正在尝试编写一个具有事务和try/catch块的MS sql脚本。如果它捕获异常,则回滚事务。如果没有,则提交事务。我见过几个不同的网站说这样做: 但是,即使在捕获异常的情况下,我们也不会仍然命中“提交事务”行吗?这不会导致 SQL 错误,因为事务已经回滚吗?我认为应该这样做: 为什么通常发布的解决方案不包括@成功变量?提交已经回滚的事务时没有发生sql错误吗?我说第一个代码示例的“提交事务”行

  • 问题内容: 是否可以在lambda函数内部使用try catch块。我需要lambda函数将某个变量转换为整数,但并非所有值都可以转换为整数。 问题答案: 不。Python lambda只能是单个表达式。使用命名函数。 编写用于转换类型的通用函数很方便: 然后,您可以编写lambda: 您也可以这样编写,使其 返回 一个将要转换的值的函数。那么您就不需要lambda了: 现在返回一个将值转换为整数

  • 问题内容: 在PHP 5中使用try-catch语句时,要考虑什么样的性能影响? 以前,我已经在网上阅读了一些有关该主题的古老的,看似矛盾的信息。我目前必须使用的许多框架都是在php 4上创建的,并且缺少php 5的许多优点。因此,我在使用try-catchs与php方面经验不足。 问题答案: 要考虑的一件事是,没有引发异常的try块的开销与实际引发和捕获异常的开销是一个不同的问题。 如果仅在失败

  • 我试图在while循环中执行try-catch块。当我要求用户输入一个数字(应该是双精度的)时,我使用try-catch来捕获任何输入不匹配异常。我将其嵌套在while循环中,这样如果捕获到任何异常,用户可以根据需要重新输入输入。问题在于,如果捕获到异常,扫描仪将不允许用户出于某种原因重新输入输入。在第二次迭代中,当您返回到hours=kb.nextDouble的行时,会发现错误。这是代码。

  • 问题内容: 可以在Swift中捕获异常吗?给出以下代码: 是否可以防止异常导致整个程序崩溃?也就是说,Objective-C中的Swift等效于什么: 问题答案: 它没有异常处理,并且在开发人员论坛中的讨论讨论了为什么会这样: 但请记住,可可和可可触控传统上并不打算让您捕获异常。他们打算让您不要将它们放在首位。普通错误应使用可选类型和inout NSError参数处理;您应该通过编写更好的代码来解

  • 是否有像java try catch finally这样的linux bash命令?还是linux shell总是在运行?