SpringJDBC测试中的事务回滚
我试图在使用Spring测试时回滚JDBC事务,但没有成功。当我运行以下命令时,SQL更新总是提交的SpringJDBC测试中的事务回滚,spring,testing,jdbc,transactions,rollback,Spring,Testing,Jdbc,Transactions,Rollback,我试图在使用Spring测试时回滚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; impor
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();
}
}
我做错了什么
此外,我是否使用了过多的注释?我可以让它更干净一点吗?这可能是因为您没有测试方法的
@Transactional
吗?如果您没有使用@TestExecutionListeners
注释显式配置测试执行侦听器,Spring默认配置DependencyInjectionTestExecutionListener
,DirtiesContextTestExecutionListener
和TransactionalTestExecutionListener
TransactionalTestExecutionListener
提供具有默认回滚语义的事务测试执行。通过在测试类上显式声明@TestExecutionListeners
,并从侦听器列表中省略TransactionalTestExecutionListener
,可以禁用事务支持
还必须在类或方法级别添加@Transactional
注释
您还必须使用来获取由DataSourceTransactionManager管理的事务连接。在Spring中使用@transactional注释时,必须将以下行添加到Spring配置文件中:
<tx:annotation-driven transaction-manager="transactionManager"/>
事务管理器属性保存对Spring配置文件中定义的事务管理器bean的引用。这段代码告诉Spring在应用事务拦截器时使用@Transaction注释。没有它,@Transactional注释将被忽略,导致代码中没有使用任何事务
其他信息: 这条线
<tx:annotation-driven transaction-manager="transactionManager"/>
您需要在类级别添加
@Transactional
。
大概是这样的:
@TransactionConfiguration(transactionManager = "txManager",defaultRollback = true)
@Transactional
这里,txManager
是来自应用程序上下文
的事务管理器的实例或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" />
如果您使用的是非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();
}
}添加此注释,测试用例中将不会回滚:
@TransactionConfiguration(defaultRollback=false)
我的注释如下所示:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/../applicationContext.xml" })
@TransactionConfiguration(defaultRollback=true)
public class DBCreatorTest {
在尝试了上述许多组合之后,下面的设置对我有效,在测试成功后完全回滚
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:datasource-context-test.xml"})
@TransactionConfiguration(defaultRollback = true)
@Transactional
public class DataAccessTest
{
@Test
public void testSaveRecords()
{ ... }
}
我添加了@Transactional,但没有效果。我还添加了@Rollback,但仍然没有效果。我删除了@TestExecutionListeners并添加了@Transactional。然后,我不得不将transactionManager bean添加到应用程序上下文(DataSourceTransactionManager)。Txn没有回滚,所以我添加了@TransactionConfiguration(defaultRollback=true)。Txn仍然没有回滚,所以我在测试方法中添加了@Rollback。直到那时,我才看到Spring日志,它正在回滚txn,但更新仍然被持久化到DB。可能与SQL Server及其驱动程序有关?在我的回答中添加了DataSourceUtils。啊,我没有收到你上次评论的通知。同时,我更改了上下文,将数据源包装在TransactionWaredataSourceProxy中。成功了。好了,两种方法做同样的事情。现在看看这7个注释中哪一个我可以去掉,并且仍然可以使用。我不记得问题到底是什么,但是谢谢你提供的额外信息。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/../applicationContext.xml" })
@TransactionConfiguration(defaultRollback=true)
public class DBCreatorTest {
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:datasource-context-test.xml"})
@TransactionConfiguration(defaultRollback = true)
@Transactional
public class DataAccessTest
{
@Test
public void testSaveRecords()
{ ... }
}