2010-10-29 53 views
12

Tôi đang cố gắng để có được các giao dịch JDBC rollback khi sử dụng Spring-test mà không thành công. Khi tôi chạy bản cập nhật SQL sau đây luôn được cam kết.Khôi phục giao dịch trên các thử nghiệm 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> 

Tôi đang làm gì sai?

Ngoài ra, tôi có đang sử dụng quá nhiều chú thích không? Tôi có thể làm cho nó sạch hơn một chút không?

Trả lời

16

Nếu bạn không định cấu hình rõ ràng trình nghe thử nghiệm bằng cách sử dụng chú thích @TestExecutionListeners, Cấu hình mùa xuân theo mặc định DependencyInjectionTestExecutionListener, DirtiesContextTestExecutionListenerTransactionalTestExecutionListener. TransactionalTestExecutionListener cung cấp thực thi kiểm tra giao dịch với ngữ nghĩa rollback mặc định. Bằng cách khai báo rõ ràng @TestExecutionListeners trên lớp thử nghiệm của bạn và bỏ qua TransactionalTestExecutionListener từ danh sách người nghe, bạn đang tắt hỗ trợ giao dịch.

Bạn cũng phải thêm chú thích @Transactional ở cấp lớp hoặc phương thức.

Bạn cũng phải sử dụng DataSourceUtils để có được kết nối giao dịch do DataSourceTransactionManager quản lý.

+0

Tôi đã xóa @TestExecutionListeners và thêm @Transactional. Sau đó, tôi đã phải thêm bean transactionManager vào ngữ cảnh ứng dụng (DataSourceTransactionManager). Txn không được khôi phục vì vậy tôi đã thêm @TransactionConfiguration (defaultRollback = true). Txn vẫn chưa được khôi phục vì vậy tôi đã thêm @Rollback vào phương thức thử nghiệm. Chỉ sau đó tôi mới thấy Spring log rằng nó đã quay trở lại txn, nhưng bản cập nhật vẫn được tiếp tục tồn tại cho DB. Một cái gì đó để làm với SQL Server và trình điều khiển của nó có lẽ? – Synesso

+1

Đã thêm DataSourceUtils vào câu trả lời của tôi. –

+0

Ah, tôi không nhận được thông báo về nhận xét cuối cùng của bạn. Trong khi đó, tôi đã thay đổi bối cảnh của mình để bọc nguồn dữ liệu trong một TransactionAwareDataSourceProxy. Điều đó hiệu quả. Vì vậy, có bạn đi, hai cách để làm điều tương tự. Bây giờ, hãy xem chú thích nào trong số 7 chú thích này mà tôi có thể loại bỏ và vẫn có công việc. – Synesso

1

Có thể vì bạn không có @Transactional cho phương pháp thử nghiệm?

+1

tôi thêm @Transactional và nó không có hiệu lực. Tôi cũng đã thêm @Rollback và nó vẫn không có hiệu lực. – Synesso

0

Khi sử dụng @Transactional chú thích trong mùa xuân, bạn phải thêm dòng sau vào tập tin cấu hình Spring của bạn:

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

Thuộc tính giao dịch quản lý giữ một tham chiếu đến bean quản lý giao dịch quy định tại các Tệp cấu hình mùa xuân. Mã này báo cho Spring sử dụng chú thích @Transaction khi áp dụng trình chặn chặn giao dịch. Không có nó, chú thích @Transactional bị bỏ qua, dẫn đến không có giao dịch nào được sử dụng trong mã của bạn.

Source on IBM website

+1

Tôi không thể nhớ vấn đề thực sự là gì, nhưng cảm ơn thông tin bổ sung. – Synesso

0

thông tin thêm:

cho dòng này

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

Giá trị mặc định của thuộc tính transaction-manager là "transactionManager". Thuộc tính này chỉ bắt buộc nếu id/tên bean của transactionManager không phải là 'transactionManager'. Vì vậy, bạn chỉ cần đặt:

<tx:annotation-driven /> 
0

Bạn cần thêm @Transactional ở cấp lớp. Something như thế này:

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

Đây txManager là một ví dụ hay bean id của người quản lý giao dịch từ 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" /> 
2

Nếu bạn đang sử dụng phương pháp phi xml này làm việc độc đáo từ khoảng phiên bản 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() {} 

Các cấu hình thử nghiệm sau đó sẽ đưa mẫu này. Lưu ý @EnableTransactionManagement và thực tế bạn có thể khai báo một defaultRollback thử nghiệm chung. Điều này trở nên đặc biệt hữu ích đối với một dự án lớn.

@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

thêm chú thích này, và không có cuộn lại sẽ nằm trong trường hợp thử nghiệm:

@TransactionConfiguration(defaultRollback=false) 

chú thích của tôi trông như thế này:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = { "/../applicationContext.xml" }) 
@TransactionConfiguration(defaultRollback=true) 
public class DBCreatorTest { 
Các vấn đề liên quan