gpt4 book ai didi

java - 如何在 Spring 中对两个查询使用相同的连接?

转载 作者:可可西里 更新时间:2023-11-01 06:43:10 25 4
gpt4 key购买 nike

我在基于 Spring JdbcTemplate 的 dao 中有以下代码 -

getJdbcTemplate().update("Record Insert Query...");
int recordId = getJdbcTemplate().queryForInt("SELECT last_insert_id()");

问题是有时我的 update 和 queryForInt 查询会使用来自连接池的不同连接来执行。

这会导致返回不正确的 recordId,因为 MySql last_insert_id() 应该从发出插入查询的同一连接中调用。

我考虑过 SingleConnectionDataSource,但不想使用它,因为它会降低应用程序性能。我只想为这两个查询建立单一连接。并非针对所有服务的所有请求。

所以我有两个问题:

  1. 我可以管理模板类使用的连接吗?
  2. JdbcTemplate 是否执行自动事务管理?如果我手动将一个事务应用于我的 Dao 方法,是否意味着每个查询将创建两个事务?

希望你们能对这个话题有所启发。

更新 - 我尝试了 nwinkler 的方法并将我的服务层包装在事务中。一段时间后,我很惊讶地看到同样的错误再次弹出。深入研究 Spring 源代码,我发现了这个 -

public <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action) 
throws DataAccessException {
//Lots of code
Connection con = DataSourceUtils.getConnection(getDataSource());
//Lots of code
}

所以与我的想法相反,每个事务不一定有一个数据库连接,而是每个执行的查询都有一个连接。这让我回到我的问题。我想从同一个连接执行两个查询。 :-(

更新 -

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${db.driver}" />
<property name="url" value="${db.jdbc.url}" />
<property name="username" value="${db.user}" />
<property name="password" value="${db.password}" />
<property name="maxActive" value="${db.max.active}" />
<property name="initialSize" value="20" />
</bean>

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
autowire="byName">
<property name="dataSource">
<ref local="dataSource" />
</property>
</bean>


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

<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRES_NEW" rollback-for="java.lang.Exception" timeout="30" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* service.*.*(..))" />
<aop:pointcut id="pointcut2" expression="execution(* *.ws.*.*(..))" />

<aop:advisor pointcut-ref="pointcut" advice-ref="transactionAdvice" />
<aop:advisor pointcut-ref="pointcut2" advice-ref="transactionAdvice" />
</aop:config>

最佳答案

确保您的 DAO 包装在事务中(例如,通过使用 Spring 的事务拦截器)。然后,相同的连接将用于两个调用。

更好的办法是在服务层有更高一层的交易。

文档:http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html

更新:如果您查看更新中引用的 DataSourceUtils.getConnection() 方法的 JavaDoc,您将看到它获取与当前线程关联的连接:

Is aware of a corresponding Connection bound to the current thread, for example when using {@link DataSourceTransactionManager}. Will bind a Connection to the thread if transaction synchronization is active, e.g. when running within a {@link org.springframework.transaction.jta.JtaTransactionManager JTA} transaction).

据此,它应该像您设置的那样工作。我已经多次使用这种模式,并且从未遇到过您描述的任何问题......

另请查看此线程,那里有人正在处理类似的问题:Spring Jdbc declarative transactions created but not doing anything

关于java - 如何在 Spring 中对两个查询使用相同的连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9809100/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com