3

私の 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;
        }
    });
}

以下は私の春の設定です。

<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 が同じ接続オブジェクトを取得することを確認しますか? 私の理解では、それが起こらない場合、ロールバックまたはコミットは機能しませんよね? 誰かがこれにもっと光を当てることができますか?

4

1 に答える 1

3

JdbcTemplate(execute(...)メソッドの 1 つ)のコードを見ると、

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

に登録されたConnectionからを取得しようとします。ConnectionHolderTransactionSynchronizationManager

そのようなオブジェクトがない場合は、 から接続を取得して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());
}

接続を解放しますが、これは非トランザクション環境にいる場合にのみ発生します。

外部で管理されていない (つまり、スレッドにバインドされていない) 場合。

したがって、トランザクションの世界では、は同じオブジェクトJdbcTemplateを再利用します。Connection

于 2013-08-26T18:58:21.897 に答える