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();
...
}
...