Java 利用Spring transactionManager进行集成测试

Java 利用Spring transactionManager进行集成测试,java,spring,spring-test,Java,Spring,Spring Test,我已经有一段时间了&有种下沉的感觉,我忽略了一些愚蠢的事情。我试图使用事务管理器进行一个非常简单的集成测试,但似乎无法让它像我认为应该的那样回滚 测试类别: public class JdbcUserDAO implements UserDAO { @Autowired private DataSource dataSource; private static final String TERM_USER_SQL = "UPDATE USER " + "SET

我已经有一段时间了&有种下沉的感觉,我忽略了一些愚蠢的事情。我试图使用事务管理器进行一个非常简单的集成测试,但似乎无法让它像我认为应该的那样回滚

测试类别:

public class JdbcUserDAO implements UserDAO {

@Autowired
private DataSource dataSource;

private static final String TERM_USER_SQL =
        "UPDATE USER " +
        "SET TERM_DATE = date('now') " +
        "WHERE USER_NAME = ?";

@Override
public void terminateUser(String userName) {

    try (Connection conn = dataSource.getConnection()){
        PreparedStatement stmt = conn.prepareStatement(TERM_USER_SQL);
        stmt.setString(1, userName);
        stmt.executeUpdate();
    } catch (SQLException e) {
        throw new RuntimeException("Caught SQLException in persistence service", e);
    }
}
Spring上下文(applicationContext.xml):

好的,TransactionConfiguration的defaultRollback行为是“true”,默认transactionManager bean名称是“transactionManager”,所以我应该在那里设置。我运行这个测试,并期望“TERM_DATE”列在测试完成后恢复为“null”(其起始值),但它不是(我在测试完成后查询,可以看到它仍然是=今天的日期)

我甚至得到了看起来非常有前途的日志:

Jun 17, 2014 1:25:48 PM org.springframework.test.context.transaction.TransactionalTestExecutionListener startNewTransaction
INFO: Began transaction (1): transaction manager [org.springframework.jdbc.datasource.DataSourceTransactionManager@10279954]; rollback [true]
Jun 17, 2014 1:25:48 PM org.springframework.test.context.transaction.TransactionalTestExecutionListener endTransaction
INFO: Rolled back transaction after test execution for test context [TestContext@41cbd50f testClass = JdbcUserDAOTest, testInstance = com.mycompany.persistence.dao.JdbcUserDAOTest@2d10ed88, testMethod = test_terminateUser@JdbcUserDAOTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@325a92d5 testClass = JdbcUserDAOTest, locations = '{classpath:/applicationContext.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]]
Jun 17, 2014 1:25:48 PM org.springframework.context.support.GenericApplicationContext doClose
INFO: Closing org.springframework.context.support.GenericApplicationContext@3304e92a: startup date [Tue Jun 17 13:25:48 MDT 2014]; root of context hierarchy
我到底忽略了什么???非常感谢

如果有帮助,相关的POM依赖项如下所示:

<dependencies>
    <dependency>
        <groupId>org.xerial</groupId>
        <artifactId>sqlite-jdbc</artifactId>
        <version>3.7.2</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.hamcrest</groupId>
        <artifactId>hamcrest-core</artifactId>
        <version>1.3</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
        <scope>test</scope>
    </dependency>
</dependencies>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring.version>3.2.9.RELEASE</spring.version>
</properties>

org.xerial
sqlite jdbc
3.7.2
org.springframework
春豆
${spring.version}
org.springframework
SpringJDBC
${spring.version}
朱尼特
朱尼特
4.11
测试
org.hamcrest
汉克雷斯特岩芯
1.3
测试
org.springframework
弹簧试验
${spring.version}
测试
org.springframework
spring上下文
${spring.version}
测试
UTF-8
3.2.9.1发布

使用
DataSourceUtils.getConnection(dataSource)
而不是
dataSource.getConnection()
。前者为事务性支持准备连接,而后者只是绕过Spring事务性基础架构,要求您处理事务性细节。

如果您使用Spring,请不要编写样板JDBC代码

相反,使用Spring的
JdbcTemplate
,它会自动与当前Spring管理的事务一起工作消除所有样板JDBC代码

您应该用以下内容替换整个DAO实现:

public class JdbcUserDAO {

    private static final String TERM_USER_SQL = "UPDATE USER "
            + "SET TERM_DATE = date('now') WHERE USER_NAME = ?";

    private final JdbcTemplate jdbcTemplate;

    @Autowired
    public JdbcUserDAO(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public void terminateUser(String userName) {
        jdbcTemplate.update(TERM_USER_SQL, userName);
    }

}
问候,


Sam

只是为了好玩,你愿意用SQLite交换H2或HSQL吗?我怀疑这是问题所在,但确保这一点不会有什么坏处:)有趣的是,你提到了这一点-真正的代码使用了Oracle,但我切换到SQLite以消除这一问题:)谢谢你,山姆-你搞定了。可悲的是,我真的不知道如何使用JDBC,但我真的很盲目(我花了<15分钟的时间重构到JdbcTemplate,效果非常好。如果有人以上面的代码为例,我完成的代码看起来几乎与Sam的完全相同-我唯一改变的是从上下文中去掉了“注释驱动”标记。再次感谢!
<dependencies>
    <dependency>
        <groupId>org.xerial</groupId>
        <artifactId>sqlite-jdbc</artifactId>
        <version>3.7.2</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.hamcrest</groupId>
        <artifactId>hamcrest-core</artifactId>
        <version>1.3</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
        <scope>test</scope>
    </dependency>
</dependencies>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <spring.version>3.2.9.RELEASE</spring.version>
</properties>
public class JdbcUserDAO {

    private static final String TERM_USER_SQL = "UPDATE USER "
            + "SET TERM_DATE = date('now') WHERE USER_NAME = ?";

    private final JdbcTemplate jdbcTemplate;

    @Autowired
    public JdbcUserDAO(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public void terminateUser(String userName) {
        jdbcTemplate.update(TERM_USER_SQL, userName);
    }

}