在JPA中回滚语句和事务的区别

时间:2016-05-28 20:46:21

标签: java jpa rollback

JPA Query 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是否被设计为被捕获并允许用户在超时时重试而不影响事务?

1 个答案:

答案 0 :(得分:3)

  当查询超时且仅回滚语句时,持久性提供程序抛出

[QueryTimeoutException]。当前事务(如果一个处于活动状态)将不会标记为回滚。 [QueryTimeoutException]

QueryTimeoutExceptionPersistenceException的特化。

  发生问题时,持久性提供程序抛出[p> PersistenceException]。 PersistenceException 的所有实例(NoResultException,NonUniqueResultException,LockTimeoutException和QueryTimeoutException 的实例除外)将导致当前事务(如果其中一个处于活动状态且已连接到持久性上下文)被标记为回滚。 [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();
    ...
}
...