2010-10-29 68 views
12

我试图在使用Spring-test时没有成功的情况下获取JDBC事务回滚。当我运行以下时,SQL更新始终被提交。Spring JDBC测试上的事务回滚

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> 

我在做什么错?

此外,我是否使用了太多注释?我可以让它更清洁一点吗?

回答

16

如果不使用@TestExecutionListeners标注明确配置测试执行监听器,Spring配置默认DependencyInjectionTestExecutionListenerDirtiesContextTestExecutionListenerTransactionalTestExecutionListenerTransactionalTestExecutionListener使用默认的回滚语义提供事务性测试执行。通过在测试类中明确声明@TestExecutionListeners,并从侦听器列表中省略TransactionalTestExecutionListener,即表示禁用事务性支持。

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

,也必须使用DataSourceUtils度日的DataSourceTransactionManager管理事务连接。

+0

我删除了@TestExecutionListeners并添加了@Transactional。然后我必须添加一个transactionManager bean到应用程序上下文(DataSourceTransactionManager)。 Txn没有回滚,所以我添加了@TransactionConfiguration(defaultRollback = true)。 Txn仍然没有回滚,所以我在测试方法中添加了@Rollback。只有那时我才看到Spring日志回滚了txn,但更新仍然持续到数据库。可能与SQL Server及其驱动程序有关? – Synesso 2010-10-29 02:21:43

+1

添加DataSourceUtils到我的答案。 – 2010-10-29 02:35:09

+0

啊,我没有得到你最后的评论通知。在此期间,我改变了我的上下文以将数据源包装在TransactionAwareDataSourceProxy中。这工作。所以你去了,有两种方法来做同样的事情。现在看看我可以摆脱这7个注释中的哪一个,并且仍然有效。 – Synesso 2010-10-29 03:41:31

1

难道是因为您的测试方法没有@Transactional

+1

我加@Transactional和它没有效果。我还加了@Rollback,但它仍然没有效果。 – Synesso 2010-10-29 02:07:20

0

当使用Spring中的@Transactional 注解,则必须在下面一行添加到您的Spring配置文件:

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

事务经理属性保存在定义的事务管理器bean的引用Spring配置文件。这段代码告诉Spring在应用事务拦截器时使用@Transaction注解。没有它,@Transactional注释被忽略,导致你的代码中没有使用事务。

Source on IBM website

+1

我不记得实际存在的问题,但感谢您的额外信息。 – Synesso 2011-02-11 04:53:38

0

附加的信息:

此订单

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

transaction-manager属性的缺省值是 “transactionManager的”。 此属性只需要当的TransactionManager的bean的ID /名称不是“transactionManager的”。 所以,你只需要设置:

<tx:annotation-driven /> 
0

你需要在类级别添加@Transactional。 事情是这样的:

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

这里txManager是事务管理器从application context实例或豆ID。

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

    <tx:annotation-driven transaction-manager="txManager" /> 
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

添加此注释,也没有回退将在测试用例:

@TransactionConfiguration(defaultRollback=false) 

我的注释是这样的:

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