我最近遇到了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块中进行回滚?
答案 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));
}
}
}