두 개의 다른 테이블에 삽입하는 DAO 메소드의 스프링 유닛 테스트가 있습니다. 테스트가 완료되면 삽입물 중 하나가 예상대로 롤백되지만 은 다른 하나가 아닙니다.! 나는 정말로 무슨 일이 일어나는지 알 수 없다. 필자는 테스트를 여러 번 디버깅하여 (커밋되지 않은) 변경 사항이 데이터베이스에 표시되는 시점을 확인할 수 있지만 그 중 하나만 사라지는 경우를 확인할 수 있습니다.바닐라 JDBC 업데이트가 스프링 유닛 테스트에서 롤백되지 않음
내가 볼 수있는 유일한 차이점은 삽입이 원시 JDBC로 수행되고 두 번째 경우에는 Sping의 JdbcTemplate으로 수행된다는 것입니다. 그러나 둘 다 롤백 된 동일한 트랜잭션에 있지 않아야합니까?
여기 내 테스트 클래스의 :
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring/test-context.xml"})
@Rollback
@Transactional(transactionManager = "txManager")
public class MyDaoIntegrationTest {
@Autowired
private DataSource dataSource;
@Autowired
private MyDao myDao;
@Test
public void createMyObject_test() throws Exception {
MyObject myObject = new MyObject();
myDao.createMyObject(myObject, 123L);
}
}
내 시험의 context.xml은 다음과 같습니다
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="myDao" class="my.package.myDao">
<constructor-arg name="dataSource" ref="dataSource"/>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="url" value="${unit.test.db.url}"/>
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"/>
<property name="username" value="${unit.test.db.user}"/>
<property name="password" value="${unit.test.db.pass}"/>
</bean>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
약 (등 폐쇄 연결에 소음 제거) 보이는 테스트 할 수있는 방법 정도 :
public void createMyObject(MyObject vo, long refId) throws SQLException {
Connection cn = dataSource.getConnection();
PreparedStatement ps = cn.prepareStatement("insert into MY_OBJECT (COL1, COL, ...)) values (?,?,...)");
ps.setInt(1, vo.getCol1());
ps.setInt(2, vo.getCol2());
...
ps.executeUpdate();
MyObjectEventVO event = new MyObjectEventVO();
createMyObjectEvent(event);
}
public void createMyObjectEvent(MyObjectEventVO vo) throws DataAccessException {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
String updateSql =
"insert into MY_OBJECT_EVENT(COL1, COL2, ...) "
+ "values (?, ?, ...)";
Object[] params = {vo.getCol1(), vo.getCol2(), ... };
int[] types = {Types.INTEGER, Types.VARCHAR, ...};
jdbcTemplate.update(updateSql, params, types);
}
업데이트 createMyObjectEvent (이벤트)에 대한 호출을 주석 처리하여 하나의 삽입 만 발생하도록했습니다. 최종 결과는 동일합니다. 첫 번째 삽입은 롤백되지 않습니다. 따라서 첫 번째 삽입에 대한 트랜잭션에 문제가있는 것으로 보입니다.
업데이트 2 JdbcTemplate도 사용하도록 첫 번째 삽입을 리팩토링 한 다음 모든 것이 잘 작동합니다! 따라서 질문은 바닐라 JDBC 코드를 스프링 유닛 테스트에서 롤백하는 방법으로 표현할 수 있습니다.
createMyObjectEvent에 고유 한 트랜잭션이있을 수 있습니까? 예 : 이런 식으로 주석이 달린 myDao입니까? –
MyDao에 주석이 없습니다. 단위 테스트 외부의 모든 구성은 XML에서 제공됩니다. – inovaovao
두 번째 방법에서 새 JdbcTemplate을 사용하는 이유는 무엇입니까? – Nemesis