У меня есть следующий код в дао основе Spring JdbcTemplate -Как использовать одно соединение для двух запросов весной?
getJdbcTemplate().update("Record Insert Query...");
int recordId = getJdbcTemplate().queryForInt("SELECT last_insert_id()");
Проблема заключается в том, что мой иногда мое обновление и запросы queryForInt получить выполняются с использованием различных соединений из пула соединений.
Это приводит к неправильной записи, возвращаемой с момента вызова MySql last_insert_id() из того же соединения, которое выдало запрос на вставку.
Я рассмотрел источник SingleConnectionDataSource, но не хочу его использовать, так как он ухудшает производительность приложения. Я хочу только одно соединение для этих двух запросов. Не для всех запросов на все услуги.
Поэтому у меня есть два вопроса:
- Могу ли я управлять соединением, используемым классом шаблона?
- Выполняет ли 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
}
Так вопреки тому, что я думал, там не обязательно один подключение к базе данных за одну транзакцию, но одно соединение для каждого запроса выполняется. Что возвращает меня к моей проблеме. Я хочу выполнить два запроса из одного и того же соединения. :-(
Update -
<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>
Mh, тогда, я думаю, вы все еще делаете что-то неправильно. Можете ли вы разместить конфигурацию Spring, включая источники данных и управление транзакциями? Каким классом является этот фрагмент Spring? Где ты нашел это? – nwinkler
Этот код из класса JdbcTemplate. Он вызывается всякий раз, когда выполняется запрос, поэтому я сомневаюсь. –
Пожалуйста, взгляните на мой обновленный ответ ... – nwinkler