10

I have following configuration.

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx.xsd">

<bean id="dataSource" class="org.springframework.jdbc.datasource.IsolationLevelDataSourceAdapter">
    <property name="targetDataSource">
        <bean class="com.microsoft.sqlserver.jdbc.SQLServerConnectionPoolDataSource">
            <property name="user" value="user"/>
            <property name="password" value="password"/>
            <property name="serverName" value="someserver"/>
            <property name="databaseName" value="someDBName"/>
            <property name="portNumber" value="somePortNumber"/>
        </bean>
    </property>
</bean>

<!-- this is bean is only used for data extraction module only -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
            <prop key="hibernate.format_sql">true</prop>
            <prop key="hibernate.show_sql">true</prop>
        </props>
    </property>
</bean>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" lazy-init="true">
    <property name="persistenceXmlLocation" value="classpath:persistence.xml" />
    <property name="dataSource" ref="dataSource"/>
    <property name="jpaDialect">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
    </property>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>                
            <prop key="hibernate.format_sql">false</prop>
            <prop key="hibernate.show_sql">false</prop>
            <prop key="hibernate.cache.use_second_level_cache">true</prop>
            <prop key="hibernate.cache.use_query_cache">true</prop>                
        </props>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

<!--
    Instruct Spring to perform declarative transaction management automatically
    on annotated classes.  transaction-manager="transactionManager"
-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

Then, when I ran tests that had an insert statement, they produced error messages as such:

javax.persistence.TransactionRequiredException: Executing an update/delete query
    at org.hibernate.ejb.QueryImpl.executeUpdate(QueryImpl.java:47)

After much deliberation, I tried this:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:services.xml" })
@Transactional(propagation = Propagation.REQUIRED)
@TransactionConfiguration(defaultRollback = true)
@TestExecutionListeners(value = { DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})
public class SimpleUnitTest {

    @Test
    public void simpleTest() throws Exception {
        System.out.println(entityManager.getTransaction().isActive());
        assertTrue(entityManager.getTransaction().isActive());
   }
}

And it failed. entityManager.getTransaction().isActive() was in fact false.

Why wouldn't Transactional test does not begin a transaction?

tim_wonil
  • 14,970
  • 6
  • 29
  • 42
  • It looks like you have a correct configuration, but something is missing. Enable logs, in mine I see `DEBUG [AnnotationTransactionAttributeSource] Adding transactional method 'XXX' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT;` at context loading stage and later `DEBUG [HibernateTransactionManager] Creating new transaction with name [XXX]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT` when the test is run. So I am sure, the transaction is there. – dma_k Sep 27 '10 at 17:10
  • Did you manage to resolve this problem? – ziggy Jun 06 '12 at 22:13
  • Have you tried this using a TransactionTemplate instead of the @Transactional annotations? – stringy05 Feb 25 '15 at 00:43
  • Could you show me how you get the `EntityManager` instance? – V G Feb 27 '15 at 16:34

3 Answers3

4

You need to either add

@TestExecutionListeners(TransactionalTestExecutionListener.class)

or extend from

AbstractTransactionalJUnit4SpringContextTests

to get transactional behavior. (remember, your test class is not a bean, so regular transaction configuration does not apply)

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • I tried using those two, but I'm not getting much success. I thougth @RunWith(SpringJUnit4ClassRunner.class) would make the test class to be recognised by Spring anyway? No? How should I configure the test to use those two you suggested? – tim_wonil Aug 02 '10 at 01:01
  • I've edited my original question to reflect what I have tried after your suggestion. – tim_wonil Aug 02 '10 at 03:05
0

The TransactionalTestExecutionListener is enabled by default, if you use SpringJUnit4ClassRunner.

You need to make sure you include the transaction management configuration in your Test context config:

@ContextConfiguration(locations = { "classpath:services.xml" })

So you can check it out by injecting the TM bean:

@Autowired
private PlatformTransactionManager transactionManager;

If the dependency is not resolved, then the transaction config isnot properly located.

During debugging your test, check for the TransactionInterceptor in your stacktrace.

Vlad Mihalcea
  • 142,745
  • 71
  • 566
  • 911
  • I have everything you said, however, I noticed in the log there is no trace of transaction starting. I used to see the following log when a transaction is started: INFO - Began transaction (1): transaction manager See my new question at: http://stackoverflow.com/q/28669280/353985 – redochka Feb 23 '15 at 08:08
0

Because you got two answers related to the configuration, I suppose the problem is not the configuration, but rather the problem how you check whether the transaction is active, and namely how you get that EntityManager instance.

A possible problem could be: EntityManagerFactory.createEntityManager() method is used instead of getting an injected EntityManager.

V G
  • 18,822
  • 6
  • 51
  • 89