Spring JDBC测试的事务回滚

时间:2010-10-29 01:20:01

标签: spring testing jdbc transactions rollback

我在尝试使用Spring-test时没有成功地获得JDBC事务回滚。当我运行以下内容时,始终会提交SQL更新。

package my.dao.impl;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.transaction.TransactionConfiguration;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.Statement;

@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class})
@ContextConfiguration(locations={"classpath:ApplicationContext-test-DAOs.xml"})
@TransactionConfiguration(defaultRollback = true)
public class ConfirmationMatchingDAOImplTest {

    @Autowired
    private DataSource dataSource;

    @Test
    public void shouldInsertSomething() throws Exception {
        final Connection connection = dataSource.getConnection();
        final Statement statement = connection.createStatement();
        statement.executeUpdate("insert into TEST_INSERT values (1, 'hello')");
        statement.close();
        connection.close();
    }
}

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
    <property name="url" value="jdbc:sqlserver://makeitfunky:1490;databaseName=fonzie"/>
    <property name="username" value="ralph"/>
    <property name="password" value="p0n1es_R_kew1"/>
</bean>

我做错了什么?

另外,我使用了太多的注释吗?我可以让它更清洁吗?

8 个答案:

答案 0 :(得分:17)

如果未使用@TestExecutionListeners注释显式配置测试执行侦听器,则默认情况下Spring配置为DependencyInjectionTestExecutionListenerDirtiesContextTestExecutionListenerTransactionalTestExecutionListenerTransactionalTestExecutionListener使用默认回滚语义提供事务测试执行。通过在测试类上明确声明@TestExecutionListeners并从侦听器列表中省略TransactionalTestExecutionListener,您将禁用事务支持。

您还必须在类或方法级别添加@Transactional注释。

您还必须使用DataSourceUtils来获取由DataSourceTransactionManager管理的事务性连接。

答案 1 :(得分:2)

如果你使用的是非xml方法,那么从版本3.1开始就可以很好地工作了

@Transactional
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {TestDbConfig.class, SomeService.class})
public class SomeTest {

@Inject
private SomeService someService;

@PersistenceContext
private EntityManager em;

@Test
public void someTest() {}

然后测试配置采用这种形式。注意@EnableTransactionManagement以及您可以声明全局测试defaultRollback的事实。这对大型项目尤其有用。

@Configuration
@PropertySource(value = "classpath:app.properties")
@EnableTransactionManagement
@TransactionConfiguration(defaultRollback = true)
public class TestDbConfig {

//read the parameters from properties
@Value("${hibernate.dialect:unset}")
private String hibernateDialect;

@Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
    return new PropertySourcesPlaceholderConfigurer();
}

@Bean
public PlatformTransactionManager transactionManager() {
    //for example
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactoryBean().getObject());
    return transactionManager;
}

@Bean
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
    //set the datasource
    //set the JpaVendorAdapter
    //set the packagesToScan
    return some sort of LocalContainerEntityManagerFactoryBean;
}

@Bean
DataSource dataSource() {
    return dataSource from jndi or a DriverManagerDataSource();
}

}

答案 2 :(得分:2)

添加此注释,测试用例中不会回滚:

 @TransactionConfiguration(defaultRollback=false)

我的注释看起来像这样:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/../applicationContext.xml" })
@TransactionConfiguration(defaultRollback=true)
public class DBCreatorTest {

答案 3 :(得分:1)

可能是因为你的测试方法没有@Transactional吗?

答案 4 :(得分:0)

在Spring中使用 @Transactional 注释时,必须将以下行添加到Spring配置文件中:

<tx:annotation-driven transaction-manager="transactionManager"/>

transaction-manager属性包含对Spring配置文件中定义的事务管理器bean的引用。此代码告诉Spring在应用事务拦截器时使用@Transaction注释。如果没有它,将忽略@Transactional注释,导致代码中没有使用任何事务。

Source on IBM website

答案 5 :(得分:0)

其他信息:

这一行

<tx:annotation-driven transaction-manager="transactionManager"/>

transaction-manager属性的默认值是“transactionManager”。 仅当transactionManager的bean id / name不是“transactionManager”时才需要此属性。 所以你只需要设置:

<tx:annotation-driven />

答案 6 :(得分:0)

您需要在班级添加@Transactional。 像这样:

@TransactionConfiguration(transactionManager = "txManager",defaultRollback = true)
@Transactional

此处txManager是来自application context的事务管理器的实例或bean ID。

<!-- Transaction Manager -->
    <bean id="txManager"
          class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <tx:annotation-driven transaction-manager="txManager" />

答案 7 :(得分:0)

尝试了许多上述组合后,以下设置对我有效,并在测试成功后进行了完全回滚。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:datasource-context-test.xml"})
@TransactionConfiguration(defaultRollback = true)
@Transactional
public class DataAccessTest 
{


    @Test
    public void testSaveRecords()
    { ... }
}