Ho il seguente codice in un dao basato primavera JdbcTemplate -Come utilizzare la stessa connessione per due query in primavera?
getJdbcTemplate().update("Record Insert Query...");
int recordId = getJdbcTemplate().queryForInt("SELECT last_insert_id()");
Il problema è che il mio a volte il mio aggiornamento e le query queryForInt vengono eseguiti utilizzando le connessioni diverse dal pool di connessioni.
Ciò restituisce un recordId errato che viene restituito poiché MySql last_insert_id() deve essere chiamato dalla stessa connessione che ha generato la query di inserimento.
Ho considerato SingleConnectionDataSource ma non voglio usarlo poiché peggiora le prestazioni dell'applicazione. Voglio solo una singola connessione per queste due query. Non per tutte le richieste di tutti i servizi.
Così ho due domande:
- Posso gestire la connessione utilizzata dalla classe template?
- JdbcTemplate esegue la gestione automatica delle transazioni? Se applico manualmente una transazione al mio metodo Dao significa che verranno create due transazioni per query?
Sperando che voi ragazzi possiate far luce sull'argomento.
Aggiornamento - Ho provato l'approccio di nwinkler e ho avvolto il mio livello di servizio in una transazione. Sono stato sorpreso di vedere lo stesso bug apparire di nuovo dopo un po '. Scavando nel codice sorgente primavera ho trovato questo -
public <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action)
throws DataAccessException {
//Lots of code
Connection con = DataSourceUtils.getConnection(getDataSource());
//Lots of code
}
Quindi, contrariamente a quello che ho pensato, non c'è necessariamente una connessione al database per ogni transazione, ma una connessione per ogni query eseguita. Che mi riporta al mio problema. Voglio eseguire due query dalla stessa connessione. :-(
Aggiornamento -
<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, quindi suppongo che stai ancora facendo qualcosa di sbagliato. Potete per favore pubblicare la vostra configurazione di primavera, inclusa l'origine dati e la gestione delle transazioni? Da quale classe proviene il frammento di Spring? dove lo hai trovato? – nwinkler
Questo codice proviene dalla classe JdbcTemplate. Si chiama ogni volta che viene eseguita una query, quindi il mio dubbio. –
Si prega di dare un'occhiata alla mia risposta aggiornata ... – nwinkler