交易退出前的春季提交

时间:2014-07-31 13:57:57

标签: spring transactions spring-transactions autocommit

我们正在尝试从Spring 2.5.2升级到4.0.5.RELEASE,但发现Spring的事务管理不再起作用。

在我们的生产应用程序中,所有数据库操作都通过标记有@Transactional注释的Spring bean(使用默认设置)。多年来,这已按预期工作,如果在事务边界内抛出RuntimeException,则会发生回滚。但是,当我们升级到Spring 4.0.5.RELEASE时,它充当autocommit设置为true。

我们通过查看堆栈跟踪验证了问题代码仍然在事务代理中运行。但是,当我们在输入事务后立即对表执行简单的一行更新时,更新已提交。这令人费解,因为我们所做的就是改变Spring版本。

自动提交行为是否在以后的Spring版本中发生了变化?在4.05下我们需要做一些额外的配置吗?


以下是我们的交易管理器的配置(在2.52和4.05版本中都相同):

<tx:annotation-driven transaction-manager="transactionManager" />
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="efmsDataSource" />
</bean>

<bean id="efmsDataSource" class="com.uprr.eni.commons.dao.OracleDataSource">
    <property name="driverClassName" value="oracle.jdbc.OracleDriver" />
    <property name="url" value="jdbc:oracle:thin:@${db_instance}.oracle.uprr.com:1521:${db_instance}" />
    <property name="username" value="${db_user}" />
    <property name="password" value="${db_password}" />
    <property name="maxActive" value="8" />
</bean>

这是在我们的代码中有@Transactional方法的bean:

<bean id="efmsExecutor" class="com.uprr.eni.commons.dao.exec.DataSourceExecutorBean">
    <property name="dataSource" ref="efmsDataSource" />
</bean>

以下是我们创建应用程序上下文的方法。获取transational bean,然后将其保存为静态变量:

context = new ClassPathXmlApplicationContext(CONFIG_FILES);
efmsExecutorBean = (DataSourceExecutorBean)context.getBean(EFMS_EXECUTOR_BEAN);

我们将该bean保存在静态变量&amp;在我们执行交易时参考它。我们应该采取不同的做法吗?


当我们想要开始交易时,我们称之为:

efmsExecutorBean.executeTransaction(executor);

这是我们在DataSourceExecutorBean中调用以启动事务的方法。它基本上只是将其内部数据源传递给执行程序(实际上将执行数据库工作的代码)。

@Transactional public void executeTransaction(final DataSourceExecutor executor) {

    executor.execute(source);                                   // Perform the unit of work
    final StringList errors = executor.getResult().getErrors(); // Did any errors occur?
    if (!errors.isEmpty()) {                                    // If so
        for (final String error : errors) {
            ApiLog.error(error);                                // Record them
        }
        throw new ExecutorError(ERROR, executor.getName());     // Abort
    }
}

当我重新检查两个版本的日志时,我注意到4.0.5(已损坏)版本有一些2.5.2版本的条目。这些条目在事务开始时出现:

  

2014-07-31 09:34:43,476 [btpool0-0] DEBUG - 创建单例bean的共享实例'efmsDataSource'2014-07-31 09:34:43,576 [btpool0-0]   DEBUG - 创建bean的实例'efmsDataSource'2014-07-31   09:34:43,576 [btpool0-0] DEBUG - 急切地缓存bean'eframDataSource'   允许解决潜在的循环引用

也许这解释了发生了什么(但不是为什么)。它看起来像单例数据源bean实际上不是单例。谷歌显示了一些有类似问题的人,但没有说明如何解决它。这会和任何人发出铃声吗?

1 个答案:

答案 0 :(得分:0)

您的代码是否直接使用Oracle数据源(而不是通过例如JdbcTemplate?)如果是这样,您需要将其包装在TransactionAwareDataSourceProxy中并将其注入您的数据访问bean。