Spring JDBC 测试的事务回滚
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4048340/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Transaction rollback on Spring JDBC tests
提问by Synesso
I'm trying to get JDBC transaction rollback when using Spring-test without success. When I run the following the SQL update is always committed.
我试图在使用 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>
What am I doing wrong?
我究竟做错了什么?
Additionally, am I using too many annotations? Can I make it a bit cleaner?
此外,我是否使用了太多注释?我可以让它更干净一点吗?
回答by Chin Huang
If you do not explicitly configure test execution listeners using the @TestExecutionListenersannotation, Spring configures by default DependencyInjectionTestExecutionListener, DirtiesContextTestExecutionListener, and TransactionalTestExecutionListener. TransactionalTestExecutionListenerprovides transactional test execution with default rollback semantics. By explicitly declaring @TestExecutionListenerson your test class and omitting TransactionalTestExecutionListenerfrom the listeners list, you are disabling transactional support.
如果使用不明确配置测试执行监听器@TestExecutionListeners在默认情况下注解,Spring配置DependencyInjectionTestExecutionListener,DirtiesContextTestExecutionListener和TransactionalTestExecutionListener。 TransactionalTestExecutionListener提供具有默认回滚语义的事务测试执行。通过显式声明@TestExecutionListeners您的测试类并TransactionalTestExecutionListener从侦听器列表中省略,您将禁用事务支持。
You must also add the @Transactionalannotation at the class or method level.
您还必须@Transactional在类或方法级别添加注释。
You must also use DataSourceUtilsto get a transactional Connection managed by DataSourceTransactionManager.
您还必须使用DataSourceUtils来获取由 DataSourceTransactionManager 管理的事务连接。
回答by msduk
If you are using the non-xml method this works nicely since about version 3.1
如果您使用的是非 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() {}
The test config then takes this form. Notice @EnableTransactionManagement and the fact you can declare a global test defaultRollback. This becomes particularly useful on a large projects.
然后测试配置采用这种形式。注意@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();
}
}
}
回答by grep
add this annotation, and no roll back will be in test cases:
添加这个注解,测试用例不会回滚:
@TransactionConfiguration(defaultRollback=false)
My annotation looks like this:
我的注释是这样的:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/../applicationContext.xml" })
@TransactionConfiguration(defaultRollback=true)
public class DBCreatorTest {
回答by Raghuram
Could it be because you do not have an @Transactionalfor the test method?
可能是因为您没有@Transactional测试方法吗?
回答by codester
After trying out a lot of the above combinations, the following setup worked for me with full rollback after the test is successful.
在尝试了很多上述组合后,以下设置对我有用,测试成功后完全回滚。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:datasource-context-test.xml"})
@TransactionConfiguration(defaultRollback = true)
@Transactional
public class DataAccessTest
{
@Test
public void testSaveRecords()
{ ... }
}
回答by jkatt
When using the @Transactionalannotation in Spring, you must add the following line to your Spring configuration file:
在 Spring 中使用@Transactional注解时,必须将以下行添加到 Spring 配置文件中:
<tx:annotation-driven transaction-manager="transactionManager"/>
The transaction-manager property holds a reference to the transaction manager bean defined in the Spring configuration file. This code tells Spring to use the @Transaction annotation when applying the transaction interceptor. Without it, the @Transactional annotation is ignored, resulting in no transaction being used in your code.
事务管理器属性包含对 Spring 配置文件中定义的事务管理器 bean 的引用。这段代码告诉 Spring 在应用事务拦截器时使用 @Transaction 注释。没有它,@Transactional 注释将被忽略,导致您的代码中没有使用任何事务。
回答by herau
additional informations :
附加信息:
for this line
对于这条线
<tx:annotation-driven transaction-manager="transactionManager"/>
The default value of the transaction-managerattribute is "transactionManager".
This attribute is required only if the bean id/name of the transactionManager is not 'transactionManager'.
So you just have to set :
该transaction-manager属性的默认值为“transactionManager”。仅当 transactionManager 的 bean id/name 不是“transactionManager”时才需要此属性。所以你只需要设置:
<tx:annotation-driven />
回答by user3145373 ツ
You need to add @Transactionalat class level.
Something like this :
您需要@Transactional在类级别添加。像这样的事情:
@TransactionConfiguration(transactionManager = "txManager",defaultRollback = true)
@Transactional
Here txManageris an instance or bean id of Transaction manager from application context.
这txManager是来自 的事务管理器的实例或 bean id application context。
<!-- Transaction Manager -->
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />

