2010-10-29 109 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 {