Java 如何在Spring中对两个查询使用相同的连接?
我在基于Spring JdbcTemplate的dao中有以下代码-Java 如何在Spring中对两个查询使用相同的连接?,java,mysql,database,spring,jdbc,Java,Mysql,Database,Spring,Jdbc,我在基于Spring JdbcTemplate的dao中有以下代码- getJdbcTemplate().update("Record Insert Query..."); int recordId = getJdbcTemplate().queryForInt("SELECT last_insert_id()"); 问题是,有时使用连接池中的不同连接执行my update和queryForInt查询 这会导致返回不正确的recordId,因为MySql last_insert_id()应该是
getJdbcTemplate().update("Record Insert Query...");
int recordId = getJdbcTemplate().queryForInt("SELECT last_insert_id()");
问题是,有时使用连接池中的不同连接执行my update和queryForInt查询
这会导致返回不正确的recordId,因为MySql last_insert_id()应该是从发出insert查询的同一个连接调用的
我考虑过SingleConnectionDataSource,但不想使用它,因为它会降低应用程序的性能。对于这两个查询,我只需要一个连接。并非针对所有服务的所有请求
所以我有两个问题:
public <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action)
throws DataAccessException {
//Lots of code
Connection con = DataSourceUtils.getConnection(getDataSource());
//Lots of code
}
public T执行(PreparedStatementCreator psc,PreparedStatementCallback操作)
抛出DataAccessException{
//很多代码
Connection con=DataSourceUtils.getConnection(getDataSource());
//很多代码
}
因此,与我的想法相反,每个事务不一定有一个数据库连接,而是每个执行的查询都有一个连接。
这让我回到我的问题上来。我想从同一个连接执行两个查询:-(
更新-
<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的事务拦截器)。然后,相同的连接将用于两个调用 更好的做法是在服务层将事务提高一个级别 文件: 更新: 如果查看更新中引用的
DataSourceUtils.getConnection()
方法的JavaDoc,您将看到它获得与当前线程关联的连接:
例如,知道绑定到当前线程的相应连接
使用{@link DataSourceTransactionManager}时,将绑定到
如果事务同步处于活动状态(例如在
{@link org.springframework.transaction.jta.JtaTransactionManager jta}事务)
根据这一点,它应该像您设置的那样工作。我已经多次使用这种模式,从未遇到过您描述的任何问题
也请看一下这个帖子,有人在那里处理类似的问题:这是我的方法:
namedJdbcTemplate.execute(savedQuery, map, new PreparedStatementCallback<Object>() {
@Override
public Object doInPreparedStatement(PreparedStatement paramPreparedStatement)
throws SQLException, DataAccessException {
paramPreparedStatement.execute("SET @userLogin = 'blabla123'");
paramPreparedStatement.executeUpdate();
return null;
}
});
namedJdbcTemplate.execute(savedQuery,map,new PreparedStatementCallback()){
@凌驾
公共对象doInPreparedStatement(PreparedStatement参数PreparedStatement)
抛出SQLException、DataAccessException{
paramPreparedStatement.execute(“SET@userLogin='blablabla123'”);
paramPreparedStatement.executeUpdate();
返回null;
}
});
这没有任何并发问题,是吗?服务的多次调用仍将使用不同的事务,从而使用不同的连接。对吗?没错,这就是在服务层使用事务划分的要点。每个服务调用将在其自己的事务中运行,并将使用专用的数据库连接。提交或回滚事务后,连接将返回到池中,并可在下一个事务中使用。非常感谢。帮我省去了很多文档:-)嗯,那我猜你还是做错了什么。您可以发布您的Spring配置,包括数据源和事务管理吗?Spring代码段来自哪个类?你在哪里找到的?代码来自JdbcTemplate类。每次执行查询时都会调用它,因此我对此表示怀疑。请查看我的更新答案。。。