spring - TransactionTemplate 和 TransactionManager 连接对象

标签 spring transactions datasource

我的 DAO 中的以下代码运行良好。

public void insert(final Person person) {
    transactionTemplate.execute(new TransactionCallback<Void>() {
        public Void doInTransaction(TransactionStatus txStatus) {
            try {
                getJdbcTemplate().execute("insert into person(username, password) values ('" + person.getUsername() + "','" + person.getPassword() + "')");
            } catch (RuntimeException e) {
                txStatus.setRollbackOnly();
                throw e;
            }
            return null;
        }
    });
}

以下是我的 spring 配置。

<bean id="derbyds" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="org.apache.derby.jdbc.EmbeddedDriver" />
    <property name="username" value="app" />
    <property name="password" value="app" />
    <property name="url" value="jdbc:derby:mytempdb" />
</bean>

<bean id="persondaojdbc" class="com.napp.dao.impl.PersonDaoJdbcImpl">
    <property name="dataSource" ref="derbyds" />
    <property name="transactionTemplate">
        <bean class="org.springframework.transaction.support.TransactionTemplate">
            <property name="transactionManager" ref="transactionManager" />
        </bean>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="derbyds"/>
</bean>

我想知道的是

<bean id="persondaojdbc" class="com.napp.dao.impl.PersonDaoJdbcImpl">
    <property name="dataSource" ref="derbyds" />
    <property name="transactionTemplate">
        <bean class="org.springframework.transaction.support.TransactionTemplate">
            <property name="transactionManager" ref="transactionManager" />
        </bean>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="derbyds"/>
</bean>

现在,TransactionManager 和代码(在我的例子中是 jdbc 模板)必须在同一个连接上运行。我假设他们都从 DataSource 获取 Connection 对象。 DataSource 池连接和它的机会,当您多次调用 getConnection 时,您将获得不同的连接对象。 spring 如何确保 TransactionManager 和 JdbcTemplate 最终获得相同的连接对象。我的理解是,如果不发生这种情况,回滚或提交将不起作用,对吗?有人能对此有更多的了解吗。

最佳答案

如果您查看JdbcTemplate(execute(...) 方法之一)的代码,您将看到

Connection con = DataSourceUtils.getConnection(getDataSource());

它尝试从使用 TransactionSynchronizationManager 注册的 ConnectionHolder 检索 Connection

如果没有这样的对象,它只是从 DataSource 获取连接并注册它(如果它在事务环境中,即你有一个事务管理器)。否则,它会立即返回注册的对象。

这是代码(去掉了日志和东西)

ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {
    conHolder.requested();
    if (!conHolder.hasConnection()) {
        conHolder.setConnection(dataSource.getConnection());
    }
    return conHolder.getConnection();
}
// Else we either got no holder or an empty thread-bound holder here.

Connection con = dataSource.getConnection();

// flag set by the TransactionManager
if (TransactionSynchronizationManager.isSynchronizationActive()) {
    // Use same Connection for further JDBC actions within the transaction.
    // Thread-bound object will get removed by synchronization at transaction completion.
    ConnectionHolder holderToUse = conHolder;
    if (holderToUse == null) {
        holderToUse = new ConnectionHolder(con);
    }
    else {
        holderToUse.setConnection(con);
    }
    holderToUse.requested();
    TransactionSynchronizationManager.registerSynchronization(
                new ConnectionSynchronization(holderToUse, dataSource));
    holderToUse.setSynchronizedWithTransaction(true);
    if (holderToUse != conHolder) {
        TransactionSynchronizationManager.bindResource(dataSource, holderToUse);
    }
}

return con;

你会注意到 JdbcTemplate 试图

finally {
    DataSourceUtils.releaseConnection(con, getDataSource());
}

释放连接,但这只会在您处于非事务环境中时发生,即。

if it is not managed externally (that is, not bound to the thread).

因此,在事务世界中,JdbcTemplate 将重用相同的 Connection 对象。

关于spring - TransactionTemplate 和 TransactionManager 连接对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18450866/

相关文章:

grails - 如何在运行时从另一个数据库获取数据

c# - 使用列表作为 DataGridView 的数据源

java - 返回字符串而不是模型

java - Spring Boot jdbc 数据源自动配置在独立 tomcat 上失败

c# - Braintree所有交易搜索

python - 测试 ndb 实体是否已放入数据存储

java - 无法将 Spring Batch MongoItemReader 上的属性的 Query 类型的值转换为所需类型 'java.lang.String'

java - 如何通过两个帐户使用 AmazonSQS 监听器

c# - 我拔下客户端工作站的插头,长时间运行的数据库进程会发生什么情况?

date - kendo ui grid数据源过滤日期格式