Closed roberthunt closed 7 years ago
Well that didn't take long, I started poking around in our applicationContext-core-transactionManager.xml
configuration to discover we're using a JpaTransactionManager
which binds the transaction to the JPA EntityManager
which I guess explains why DBUnit it operating outside the scope of it.
I've swapped it for a DataSourceTransactionManager
Binds a JDBC Connection from the specified DataSource to the current thread
This sounds a lot more like what I want and how I assumed it was working. The tests seem to run fine now:
Well the DataSourceTransactionManager
may have fixed the test case but it turned out not to be the correct solution in the end but it did point me in the right direction. When using JPA the JpaTransactionManager
needs to be used for things to work properly so I had to reinstate it in our project, the thing that fixed it in the end though was to specify the jpaDialect
on the entityManagerFactory
bean.
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="jpaDialect" ref="jpaDialect" />
</bean>
For reference here was the full definition:
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="jpaDialect" ref="jpaDialect" />
<property name="entityManagerInterface" value="org.hibernate.jpa.HibernateEntityManager" />
<property name="packagesToScan" value="com.example,org.springframework.data.jpa.convert.threeten"/>
<property name="persistenceProviderClass" value="org.hibernate.jpa.HibernatePersistenceProvider"/>
<property name="dataSource" ref="dataSource"/>
<property name="jpaPropertyMap">
<map>
<entry key="hibernate.hbm2ddl.auto" value="create-drop"/>
<entry key="hibernate.dialect" value="${database.dialect}"/>
<entry key="hibernate.format_sql" value="true"/>
<entry key="hibernate.use_sql_comments" value="true"/>
<entry key="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>
<entry key="hibernate.max_fetch_depth" value="3"/>
<entry key="hibernate.show_sql" value="false"/>
<entry key="hibernate.generate_statistics" value="false"/>
<entry key="hibernate.connection.release_mode" value="auto"/>
<entry key="hibernate.transaction.auto_close_session" value="false"/>
</map>
</property>
</bean>
This is part of the problem with an old project that you introduce Spring Boot to, sometimes the existing configuration has interesting quirks that you don't spot immediately until they cause you problems. The mess above can be handled better by specifying a JpaVendorAdapter which will configure most of these settings.
I've been having issues with the
@DatabaseSetup
not being rolled back after tests in our project which is causing constraint violations as the data from the previous test is still in the database. I created a small standalone Spring Boot project but can't seem to replicate the behaviour despite using the same versions of the dependencies. I am still trying but even the simplest test case in our project fails (see test code below).By observing the general log in the database I can see that for some reason the test and DBUnit operations are being executed on different connections (note the 3rd column - thread_id). The new connection obtained for the DBUnit data sets
autocommit=1
so the writes are permanent. Had the DBUnit operations been executed in the existing connection thenautocommit=0
and arollback
would prevent this data from being written permanently.The failure reason is:
Dataset for reference:
I'm not completely familiar with the inner workings of
@Transactional
but my assumption was that a database connection would be obtained once per thread and stored in aThreadLocal
to be used for the various operations that are needed during the transaction and then being released at the end of the execution.Hopefully I can either replicate or resolve the issue but any input would be appreciated.