Spring的@Transactional超时未按预期工作

7

我有一个JDBC批量更新操作,可能需要很长时间,因此我使用事务超时来处理这个问题。

@Override
@Transactional(propagation=Propagation.REQUIRES_NEW,timeout=10)
public void saveAllUsingBatch(List<KillPrintModel> list){
    PreparedStatmentMapper ps=  new HibernateDao.PreparedStatmentMapper<KillPrintModel>() {

        @Override
        public void prepareStatement(PreparedStatement ps, KillPrintModel t)
                throws SQLException {
            ps.setString(1, t.getOffice());
            ps.setString(2, t.getAccount());
            ps.setDate(3, new java.sql.Date(t.getUpdatedOn().getTime()));
        }
    };
    String sql = String.format("INSERT INTO dbo.%s (%s,%s,%s) VALUES (?,?,?)",KillPrintModel.TABLE_NAME,KillPrintModel.FIELD_Office,KillPrintModel.FIELD_Account,KillPrintModel.FIELD_UpdatedOn);
    this.jdbcBatchOperation(list, sql, ps);
}

即使我设置了10秒的事务超时,该方法仍会持续一分钟或更长时间(且返回成功)。当超时为0时,它可以正常工作。


是因为我的线程一旦开始执行就一直处于运行状态吗?


“当超时时间为0时,它正常工作”这句话的意思是什么? - Betlista
HibernateDao 是从哪个库(library)中来的? - Betlista
当超时时间为0时,它甚至不会进入方法。HibernateDao是我的自定义类,它继承了HibernateDaoSupport(Spring框架类)。 - Rahul
你能分享一下 HibernateDao.PreparedStatmentMapper 的代码(这只是一个接口?),以及 this.jdbcBatchOperation() 吗? - Betlista
当超时时间为0时,意味着您没有为事务指定超时时间,它是无限期开放的。 - Ali Faradjpour
1个回答

1
如果在追踪模式下调试无法帮助,只需在以下Hibernate类中设置断点,它们最终会从@Transactional注释中的preparedstatement.setQueryTimeout(...)设置超时。
org.hibernate.engine.jdbc.internal.StatementPreparerImpl
private void setStatementTimeout(PreparedStatement preparedStatement) throws SQLException {
            final int remainingTransactionTimeOutPeriod = jdbcCoordinator.determineRemainingTransactionTimeOutPeriod();
            if ( remainingTransactionTimeOutPeriod > 0 ) {
                preparedStatement.setQueryTimeout( remainingTransactionTimeOutPeriod );
            }
        }

甚至更好的是,早在事务管理器中,一直步进到达statement.setQueryTimout(..)语句。

org.springframework.orm.hibernate4.HibernateTransactionManager
int timeout = determineTimeout(definition);
            if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
                // Use Hibernate's own transaction timeout mechanism on Hibernate 3.1+
                // Applies to all statements, also to inserts, updates and deletes!
                hibTx = session.getTransaction();
                hibTx.setTimeout(timeout);
                hibTx.begin();
            }
            else {
                // Open a plain Hibernate transaction without specified timeout.
                hibTx = session.beginTransaction();
            }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接