在JPA中,回滚语句和事务的区别是什么?

4

JPA查询 javadoc (参见 http://docs.oracle.com/javaee/6/api/javax/persistence/Query.html#executeUpdate()) 中提到:

int executeUpdate() Execute an update or delete statement. 
Returns: the number of entities updated or deleted 
Throws: 
IllegalStateException - if called for a Java Persistence query language SELECT statement or for a criteria query 
TransactionRequiredException - if there is no transaction 
QueryTimeoutException - if the statement execution exceeds 
  the query timeout value set and only the statement is rolled back 
PersistenceException - if the query execution exceeds 
  the query timeout value set and the transaction is rolled back

回滚语句和事务有什么区别?我的意思是,回滚事务非常明显,它将设置事务为回滚状态,所有操作都将被撤销。但如果语句被回滚(因为它是一个更新/删除/插入操作),那么整个事务在这种情况下也会被回滚吗?

这个QueryTimeoutException是否设计成可以捕获并允许用户在超时时重试而不影响事务?


你还在寻找答案吗? - Paul Wasilewski
1个回答

4

当查询超时并且仅语句被回滚时,持久性提供程序会抛出QueryTimeoutException。如果当前存在活动事务,则不会标记该事务为回滚。

QueryTimeoutExceptionPersistenceException的一种特殊情况。

当出现问题时,持久性提供程序会抛出PersistenceException。除了QueryTimeoutException、NoResultException、NonUniqueResultException、LockTimeoutException之外的所有PersistenceException实例都将导致当前事务(如果存在活动事务且已将持久性上下文加入其中)被标记为回滚。

因此,如果查询超时,无论是哪个查询,它都不会默认导致事务回滚。这就是为什么您必须始终明确执行此操作的原因。例如,如果您想无论发生哪个 PersistenceException 都要回滚事务。
catch(PersistenceException e) { ... tx.rollback(); ... }

但有时即使语句不成功并出现QueryTimeoutException,继续事务也是有意义的。

一个例子是在执行仅持久化附加日志记录的语句时超时。根据您的用例,执行日志语句的超时可能不是关键问题,否则如果核心业务流程(例如持久化订单)超时,则为关键问题。因此,您不希望失败的日志语句影响订单的持久化。另一方面,如果订单的持久化失败,则应回滚日志记录的持久化。因此,您始终可以决定哪个查询超时应导致回滚。

示例如下:

...
try {
    ...
    queryNonCritical.execute(...);
}
catch(QueryTimeoutException e) {
    // not critical move on
    ...
}
...
try {
    ...
    queryCritical.execute(...);
}
catch(QueryTimeoutException e) {
    ...
    tx.rollback();
    ...
}
...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接