簡體   English   中英

Spring JDBC測試的事務回滾

[英]Transaction rollback on Spring JDBC tests

我在嘗試使用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>

我究竟做錯了什么?

另外,我使用了太多的注釋嗎? 我可以讓它更干凈一點嗎?

如果未使用@TestExecutionListeners批注顯式配置測試執行偵聽器,則Spring默認配置DependencyInjectionTestExecutionListenerDirtiesContextTestExecutionListenerTransactionalTestExecutionListener TransactionalTestExecutionListener使用默認回滾語義提供事務測試執行。 通過在測試類上顯式聲明@TestExecutionListeners並從偵聽器列表中省略TransactionalTestExecutionListener ,您將禁用事務支持。

您還必須在類或方法級別添加@Transactional注釋。

您還必須使用DataSourceUtils來獲取由DataSourceTransactionManager管理的事務連接。

如果您使用的是非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 {

可能是因為你沒有測試方法的@Transactional

其他信息:

這條線

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

transaction-manager屬性的默認值是“transactionManager”。 僅當transactionManager的bean id / name不是“transactionManager”時才需要此屬性。 所以你只需要設置:

<tx:annotation-driven />

您需要在班級添加@Transactional 像這樣的東西:

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

這里txManager是來自application context的事務管理器的實例或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" />

在Spring中使用@Transactional注釋時,必須將以下行添加到Spring配置文件中:

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

transaction-manager屬性包含對Spring配置文件中定義的事務管理器bean的引用。 此代碼告訴Spring在應用事務攔截器時使用@Transaction注釋。 如果沒有它,將忽略@Transactional注釋,導致代碼中不使用任何事務。

來自IBM網站

在嘗試了很多上述組合之后,在測試成功后,以下設置為我提供了完全回滾。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:datasource-context-test.xml"})
@TransactionConfiguration(defaultRollback = true)
@Transactional
public class DataAccessTest 
{


    @Test
    public void testSaveRecords()
    { ... }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM