Results 1 to 3 of 3

Thread: Testing jdbctemplate with rollback

  1. #1
    Join Date
    Oct 2012
    Posts
    2

    Default Testing jdbctemplate with rollback

    I'm having problems testing a transaction flagged readOnly=true. Maybe it's just the way I've implemented it. I have a DAO class with @Transactional(readOnly = true) for all methods. One method is a SAVE, but I forgot to override to readOnly=false. I ran a test against the DAO and the transaction was rolled back, but I thought it should have failed because it was read only. Here's the setup:

    PersonDaoImplTest.java
    Code:
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {"classpath*:context.xml" })
    @TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
    @Transactional
    public class PersonDaoImplTest {
        @Autowired
        PersonDao dao;
    
        @Test
        public void testSaveWithReadOnlyTrue() throws Exception {
            final Long personId = dao.savePerson(new Person("Steve"));
            assertIsNull(personId);
        }
    }
    context.xml
    Code:
    <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"
    	xmlns:context="http://www.springframework.org/schema/context"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
    
    	<context:component-scan base-package="com.example" />
    
    	<context:property-placeholder location="spring.properties" />
    
    	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    		destroy-method="close">
    		<property name="driverClassName" value="${jdbc.driver}" />
    		<property name="url" value="${jdbc.url}" />
    		<property name="username" value="${jdbc.username}" />
    		<property name="password" value="${jdbc.password}" />
    		<property name="defaultAutoCommit" value="false" />
    	</bean>
    	
    	<tx:annotation-driven transaction-manager="transactionManager" />
    	
    	<bean id="transactionManager"
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" />
        </bean>
    
    </beans>
    PersonDaoImpl.java
    Code:
    @Repository
    @Transactional(readOnly = true,propagation = Propagation.REQUIRED)
    public class PersonDaoImpl implements PersonDao {
    
    
        private JdbcTemplate jdbcTemplate;
    
    
        @Autowired
        @Override
        public void setDataSource(final DataSource dataSource) {
            this.jdbcTemplate = new JdbcTemplate(dataSource);
        }
    
    
        @Override
        public Long savePerson(final Person person) {
            final SqlUpdate insert = new SqlUpdate(jdbcTemplate.getDataSource(), "insert into person (name) values (?)");
            insert.declareParameter(new SqlParameter(Types.VARCHAR));
    
            insert.setGeneratedKeysColumnNames(new String[]{"ID" });
            insert.compile();
            final GeneratedKeyHolder keyHolder = new GeneratedKeyHolder();
            insert.update(
                    new Object[]{person.getName() }, keyHolder);
    
            return keyHolder.getKey().longValue();
        }
    }

  2. #2
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,624

    Default

    I suggest a read of the test chapter and transaction chapter again....

    The testcase starts a transaction (not-readonly) and your dao simply uses this transaction. Also even if there would be no transaction there probably wouldn't be an exception as readonly is only an indication and forces nothing (I suggest a read of the jdbc driver specification). It only does something if the jdbc driver vendor has decided to act upon it, most simply ignore it.

    It makes more sense in a ORM world where the ORM provider (for instance hibernate) does some optimizations.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  3. #3
    Join Date
    Oct 2012
    Posts
    2

    Default

    Marten

    Thanks for the advice. I'll look @ the testing stuff again. I was just surprised the readonly was ignored for the test. In my debug logs I see the readonly registered in the transaction and it's enforced without the @Transactional in the test class. Here's my log
    Code:
    2012-10-27 13:53:54,142 DEBUG [AbstractFallbackTransactionAttributeSource.java:106] Adding transactional method 'test' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
    2012-10-27 13:53:54,143 DEBUG [TransactionalTestExecutionListener.java:148] Explicit transaction definition [PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''] found for test context [[TestContext@1a5f739 testClass = PersonDaoImplIT, testInstance = com.example.dao.PersonDaoImplIT@109fd93, testMethod = test@PersonDaoImplIT, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@e6ff0d testClass = PersonDaoImplIT, locations = '{classpath*:context.xml}', classes = '{}', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader']]]
    2012-10-27 13:53:54,143 DEBUG [TransactionalTestExecutionListener.java:469] Retrieved @TransactionConfiguration [@org.springframework.test.context.transaction.TransactionConfiguration(defaultRollback=true, transactionManager=transactionManager)] for test class [class com.example.dao.PersonDaoImplIT]
    2012-10-27 13:53:54,144 DEBUG [TransactionalTestExecutionListener.java:486] Retrieved TransactionConfigurationAttributes [[TransactionConfigurationAttributes@1f1bd98 transactionManagerName = 'transactionManager', defaultRollback = true]] for class [class com.example.dao.PersonDaoImplIT]
    2012-10-27 13:53:54,144 DEBUG [TestContext.java:162] Retrieved ApplicationContext for test class [class com.example.dao.PersonDaoImplIT] from cache with key [[MergedContextConfiguration@e6ff0d testClass = PersonDaoImplIT, locations = '{classpath*:context.xml}', classes = '{}', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader']].
    2012-10-27 13:53:54,144 DEBUG [AbstractBeanFactory.java:245] Returning cached instance of singleton bean 'transactionManager'
    2012-10-27 13:53:54,148 DEBUG [AbstractPlatformTransactionManager.java:365] Creating new transaction with name [test]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
    2012-10-27 13:53:54,420 DEBUG [DataSourceTransactionManager.java:204] Acquired Connection [jdbc:hsqldb:hsql://localhost:9001/tiber, UserName=SA, HSQL Database Engine Driver] for JDBC transaction
    2012-10-27 13:53:54,424 DEBUG [TransactionalTestExecutionListener.java:357] No method-level @Rollback override: using default rollback [true] for test context [[TestContext@1a5f739 testClass = PersonDaoImplIT, testInstance = com.example.dao.PersonDaoImplIT@109fd93, testMethod = test@PersonDaoImplIT, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@e6ff0d testClass = PersonDaoImplIT, locations = '{classpath*:context.xml}', classes = '{}', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader']]]
    2012-10-27 13:53:54,424 INFO [TransactionalTestExecutionListener.java:275] Began transaction (1): transaction manager [org.springframework.jdbc.datasource.DataSourceTransactionManager@1642bd6]; rollback [true]
    2012-10-27 13:53:54,425 DEBUG [AbstractFallbackTransactionAttributeSource.java:106] Adding transactional method 'savePerson' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly; ''
    2012-10-27 13:53:54,426 DEBUG [AbstractBeanFactory.java:245] Returning cached instance of singleton bean 'transactionManager'
    2012-10-27 13:53:54,427 DEBUG [AbstractPlatformTransactionManager.java:470] Participating in existing transaction
    2012-10-27 13:53:54,430 DEBUG [RdbmsOperation.java:343] RdbmsOperation with SQL [INSERT INTO PERSON (NAME) VALUES (?)] compiled
    2012-10-27 13:53:54,432 DEBUG [JdbcTemplate.java:841] Executing SQL update and returning generated keys

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •