Mon*_*ael 6 java mysql database spring jdbc
我在基于Spring JdbcTemplate的dao中有以下代码 -
getJdbcTemplate().update("Record Insert Query...");
int recordId = getJdbcTemplate().queryForInt("SELECT last_insert_id()");
Run Code Online (Sandbox Code Playgroud)
问题是我有时使用连接池中的不同连接来执行update和queryForInt查询.
这导致返回错误的recordId,因为应该从发出插入查询的同一连接调用MySql last_insert_id().
我考虑过SingleConnectionDataSource但不想使用它,因为它会降低应用程序性能.我只想要这两个查询的单一连接.并非所有服务的所有请求.
所以我有两个问题:
希望你们能够对这个话题有所了解.
更新 - 我尝试了nwinkler的方法并将我的服务层包装在一个事务中.我很惊讶地发现在一段时间之后会再次弹出相同的错误.深入研究Spring源代码我发现了这个 -
public <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action)
throws DataAccessException {
//Lots of code
Connection con = DataSourceUtils.getConnection(getDataSource());
//Lots of code
}
Run Code Online (Sandbox Code Playgroud)
因此,与我的想法相反,每个事务不一定有一个数据库连接,但每个查询执行一个连接.这让我回到了我的问题.我想从同一个连接执行两个查询.:-(
更新 -
<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>
Run Code Online (Sandbox Code Playgroud)
nwi*_*ler 10
确保您的DAO包含在事务中(例如,使用Spring的Interceptor for Transactions).然后,两个呼叫将使用相同的连接.
更好的方法是在服务层将事务更高一级.
文档:http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html
更新:
如果您查看DataSourceUtils.getConnection()更新中引用的方法的JavaDoc ,您将看到它获得与当前线程关联的连接:
知道绑定到当前线程的相应Connection,例如使用{@link DataSourceTransactionManager}时.如果事务同步处于活动状态,则会将Connection绑定到线程,例如,在{@link org.springframework.transaction.jta.JtaTransactionManager JTA}事务中运行时.
根据这个,它应该像你设置它一样工作.我已经使用过这种模式很多次了,从来没有遇到像你描述的任何问题......
还请看一下这个帖子,有人在那里处理类似的问题:Spring Jdbc声明的事务创建但没有做任何事情