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



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

当查询超时且仅回滚语句时,持久性提供程序会抛出QueryTimeoutException。如果当前事务处于活动状态,则不会将其标记为回滚。[QueryTimeoutException]

QueryTimeoutException是PersistenceException的特殊化。

[A PersistenceException是在出现问题时由持久性提供程序引发的。除NoResultException、NonUniqueResultException、LockTimeoutException和QueryTimeoutException实例外,PersistenceException的所有实例都将导致当前事务(如果其中一个事务处于活动状态并且持久性上下文已加入其中)被标记为回滚。[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();
...
}
...

最新更新