如何使用Hibernate Session.doWork(...)进行保存点/嵌套事务? [英] How to use Hibernate Session.doWork(...) for savepoints / nested transactions?

查看:1445
本文介绍了如何使用Hibernate Session.doWork(...)进行保存点/嵌套事务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用Oracle DB和Hibernate使用JavaEE / JPA管理事务,并需要实现某种嵌套事务。据我所知,这种东西并不支持开箱即用,但我应该可以使用保存点。



正如 https://stackoverflow.com/a/7626387/173689 我试过以下内容:

  @Transactional(value = TxType.REQUIRES_NEW)
public boolean doImport(Import importer,Row row)throws ImportRowFailedException {
//剥离代码.. 。
//我们需要尝试不同的可能性,从中获得成功...
// ...以前的失败必须回滚!
for(Possibility poss:importer.getPossibilities()){
if(this.tryPossibility(poss,row))break;
}
//被剥离的代码...
}

public boolean tryPossibility(可能性,行列){
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(!possible.importRow(row)){
connection.rollback(before);
throw new ImportRowFailedException();
}
}
});
}
catch(ImportRowFailedException ex){
return false;
}
返回true;

connection.rollback(before)我得到以下异常:

 原因:java.sql.SQLException:IJ031040:连接没有关联托管连接: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语句来解决问题:

  //将当前状态标记为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() ;
}
});

//
//执行所有有风险的更改...验证...决定...
//

//回滚到SAVEPOINT如有必要!
session.doWork(new Work(){
@Override
public void execute(Connection connection)throws SQLException {
connection.prepareStatement(ROLLBACK TO SAVEPOINT TRY_POSSIBILITY)。executeUpdate ();
}
});

这允许在较大的嵌套事务中解决我的问题。


I'm using JavaEE/JPA managed transactions with Oracle DB und Hibernate and need to achieve some kind of nested transaction. As far as I've learned such thing is not supported out of the box but I should be able to use savepoints for that purpose.

As suggested by https://stackoverflow.com/a/7626387/173689 I've tried the following:

@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;
}

Upon connection.rollback(before) I get the following exception:

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)

How must I deal with that?

解决方案

The initial java.sql.SQLException: IJ031040 seems related to a specific outcome during our import. It later has been replaced with another java.sql.SQLException that forbid the rollback for managed transactions. But I could finally solve the problem by issuing native SQL statements:

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

This allows a "nested Transaction" within the larger one and solved my problems.

这篇关于如何使用Hibernate Session.doWork(...)进行保存点/嵌套事务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆