Groovy / Hibernate / @Transaction non restituisce nessuna sessione trovata per il thread corrente
-
29-10-2019 - |
Domanda
Ho uno stack Spring/JPA/Groovy/Hibernate, (Nota: non graals), e sto scoprendo che sto ricevendo un No session found for current thread
Quando si cerca di eseguire un po ' @Transactional
lavorare sull'avvio.
Ho una classe di controller che, su @PostConstruct
, invoca a @Transactional
Metodo su un'altra classe che cerca di popolare il database con alcuni dati di esempio da utilizzare in una simulazione.
Ecco il controller
classe:
@Component
public class SimulationController {
private TransactionTemplate transactionTemplate;
@Autowired
private PlatformTransactionManager transactionManager;
@Autowired
private IPublisher publisher;
@PostConstruct
public void intialize()
{
this.transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus arg0) {
racePublisher.populateData();
}
});
}
// Also tried, with no success:
// @PostConstruct
// public void initialize()
// {
// publisher.populateData();
// }
}
Come puoi vedere, mi sono allontanato da un puro @Transactional
approccio nel @PostConstruct
Per ragioni discusse qui.
Mio IPublisher
è una classe groovy, come segue:
@Component
class Publisher implements IPublisher {
@Autowired
IStockDAO stockDAO
void populateData()
{
createStock()
}
@Transactional
void createStock()
{
def list = [new Stock(ticker: "ADBE", name: "Adobe"),
new Stock(ticker: "MSFT", venueCode: "Microsoft")]
list.each { stockDAO.create it }
}
Che è un'implementazione di:
public interface IPublisher {
public void populateData();
public void createStock();
}
Nota, ho anche provato a contrassegnare populateData()
come @Transactional
, senza alcun effetto.
Nella mia classe di contesto di primavera, sto definendo <tx:annotation-driven/>
.
Per quanto ne so, ho fatto tutto correttamente. Tuttavia, non riesco a farlo funzionare.
Cos'altro è richiesto?
Aggiornato:Ecco i fagioli che impostano i miei fagioli relativi al dataAccess:
<beans>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://${database.host}:${database.port}/${database.name}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
<property name="initialSize" value="5" />
<property name="maxActive" value="50" />
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<list>
<value>com.mangofactory.concorde</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider
</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop><!-- use create for full drop/create -->
<prop key="hibernate.connection.autocommit">true</prop>
<prop key="hibernate.statement_cache.size">0</prop>
<prop key="hibernate.jdbc.batch_size">20</prop>
</props>
</property>
</bean>
<beans>
Soluzione
Dovresti usare HibernateTransactionManager
invece di DataSourceTransactionManager
.
Altri suggerimenti
Ci sono problemi di base con il codice. Il confine transazionale inizia nel metodo createstock della classe dell'editore e finisce lì. Non si propaga al tuo controller. Utilizzare le chiamate di query DB all'interno di una transazione. cioè all'interno di un metodo che ha l'annotazione transazionale. Altrimenti non funzionerebbe mai.