如何在Play框架中回滚捕获的异常?

时间:2017-11-16 00:43:12

标签: java hibernate jpa playframework transactions

我最近遇到了play frame 2 @Transactional的问题。根据我的测试,在异常的情况下,只有在未选中异常时才会回滚事务方法(没有catch块)。 这是我的控制者:

@Transactional
public Result myController(){
    ObjectNode result = Json.newObject();
    try{
        JsonNode json = request().body().asJson();

        someFunction(json);      
        //doing some stuff using the json object inside someFunction
        //which I may intentionally throw an exception
        //based on some logic from within
        //(using "throw new RuntimeException()")

        result.put("success", true);
        return ok(Json.toJson(result));
    }catch(Exception e){
        result.put("success", false);
        result.put("msg", e.getMessage());
        return internalServerError(Json.toJson(result));
    }

}

我希望我的控制器总是返回一个JSON作为响应。但这是以我在代码中抛出异常时没有数据库回滚为代价的。我知道在春天你可以将它添加到@Transactional注释中,但我使用的是play.db.jpa.Transactional。有没有办法在不使用弹簧的情况下在我的catch块中进行回滚?

1 个答案:

答案 0 :(得分:2)

@Transactional注释基本上会将您的操作代码包含在对DefaultJpaApi.withTransaction的调用中。如果查看the source,您可以看到此方法如何处理事务。

由于您希望捕获异常,但仍希望使用withTransaction行为,因此您可以尝试删除@Transactional注释并在操作中自己调用withTransaction

E.g。

class MyController {
  private final JPAApi jpa;
  @Inject
  public MyController(JPAApi jpa) {
    this.jpa = jpa;
  }

  public myAction() {
    ObjectNode result = Json.newObject();
    try {
      JsonNode json = request().body().asJson();

      // Calls someFunction inside a transaction.
      // If there's an exception, rolls back transaction
      // and rethrows.
      jpa.withTransaction(() -> someFunction(json));

      // Transaction has been committed.
      result.put("success", true);
      return ok(Json.toJson(result));
    } catch(Exception e) {
      // Transaction has been rolled back.
      result.put("success", false);
      result.put("msg", e.getMessage());
      return internalServerError(Json.toJson(result));
    }
  }
}