0

我们正在尝试从 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>

以下是我们如何创建应用程序上下文并获取事务 bean,然后将其保存为静态变量:

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

我们将该 bean 保存在一个静态变量中,并在我们执行事务时引用它。我们应该做一些不同的事情吗?


当我们想开始一个事务时,我们调用:

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,576 [btpool0-0] 调试 - 创建单例 bean 'efmsDataSource' 的共享实例 2014-07-31 09:34:43,576 [btpool0-0] 调试 - 创建 bean 'efmsDataSource' 的实例2014-07-31 09:34:43,576 [btpool0-0] 调试 - 急切地缓存 bean 'efmsDataSource' 以允许解析潜在的循环引用

也许这解释了正在发生的事情(但不是为什么)。看起来单例数据源 bean 并不是真正的单例。谷歌显示了一些有类似问题的人,但没有说明如何解决它。这会和任何人一起敲响警钟吗?

4

1 回答 1

0

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

于 2014-07-31T18:55:15.073 回答