java - 如何使用 Hibernate Session.doWork(...) 进行保存点/嵌套事务?

标签 java oracle hibernate transactions savepoints

我正在使用 JavaEE/JPA 托管事务与 Oracle DB 和 Hibernate,并且需要实现某种嵌套事务。据我所知,此类事情不受开箱即用的支持,但我应该能够为此目的使用保存点。

根据https://stackoverflow.com/a/7626387/173689的建议我尝试过以下方法:

@Transactional(value = TxType.REQUIRES_NEW)
public boolean doImport(Import importer, Row row) throws ImportRowFailedException {
    // stripped code ...
    // We need to try different possibilities from which one may succeed...
    // ...former failures must be rolled back!
    for (Possibility poss : importer.getPossibilities()) {
        if (this.tryPossibility(poss, row)) break;
    }
    // stripped code ...
}

public boolean tryPossibility(Possibility possibility, Row row) {
    try {
        Session session = this.em.unwrap(Session.class);
        session.doWork(new Work() {
            @Override
            public void execute(Connection connection) throws SQLException {
                Savepoint before = connection.setSavepoint();
                if (!possibility.importRow(row)) {
                    connection.rollback(before);
                    throw new ImportRowFailedException();
                }
            }
        });
    }
    catch (ImportRowFailedException ex) {
        return false;
    }
    return true;
}

connection.rollback(before) 上,我收到以下异常:

Caused by: java.sql.SQLException: IJ031040: Connection is not associated with a managed connection: org.jboss.jca.adapters.jdbc.jdk8.WrappedConnectionJDK8@40a6a460
    at org.jboss.jca.adapters.jdbc.WrappedConnection.lock(WrappedConnection.java:164)
    at org.jboss.jca.adapters.jdbc.WrappedConnection.rollback(WrappedConnection.java:883)

我该如何处理这个问题?

最佳答案

最初的java.sql.SQLException: IJ031040似乎与我们导入期间的特定结果相关。后来它被另一个 java.sql.SQLException 取代,该异常禁止托管事务的回滚。但我最终可以通过发出原生 SQL 语句来解决问题:

// Mark the current state as SAVEPOINT...
Session session = this.em.unwrap(Session.class);
session.doWork(new Work() {
    @Override
    public void execute(Connection connection) throws SQLException {
        connection.prepareStatement("SAVEPOINT TRY_POSSIBILITY").executeUpdate();
    }
});

// 
// Do all the risky changes... verify... decide...
// 

// Rollback to SAVEPOINT if necessary!
session.doWork(new Work() {
    @Override
    public void execute(Connection connection) throws SQLException {
        connection.prepareStatement("ROLLBACK TO SAVEPOINT TRY_POSSIBILITY").executeUpdate();
    }
});

这允许在较大的事务中进行“嵌套事务”并解决了我的问题。

关于java - 如何使用 Hibernate Session.doWork(...) 进行保存点/嵌套事务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45672431/

相关文章:

java - 如何优化 Java 中多项式求根的二分法?

java - 在实例重新启动之前,从 GAE HRD 中的 Json 创建的 JDO 无法正确转换回 Json

java - Oracle 时间戳到 BST 时间的转换

sql-server - 在oracle中使用sql server表创建表

sql - 如何在Windows中将Oracle SQL结果输出到文件中?

java - querydsl spring data jpa 运算符优先级

java - session 工厂不知道带注释的实体

Java:如何从内部类获取直接父类(不是顶级类)?

java - 无法使用 Spring 4 和 Hibernate 4 创建与 Oracle 11g 的连接

java - 使用 java selenium 从 img src 获取链接