데이터베이스 업데이트 중 하나가 실패 할 때 스프링 JDBC를 사용하는 스프링 트랜잭션 관리가 제대로 작동하는지 테스트하고 싶다.에러시 스프링 트랜잭션 관리가 작동하지 않는다
나는 콩을 구성하는 봄 선언적인 트랜잭션 관리를 사용public void createWithContactInfo(String username, String name, Date dob,
String contactName, String contactPhone, String contactEmail) {
try {
String sqlStmt = "INSERT INTO person (username, name, dob) VALUES (?, ?, ?)";
jdbcTemplateObject.update(sqlStmt, "paul", "Paul", dob);
sqlStmt = "INSERT INTO contact_info(username, customer_name, contact_name, contact_phone, contact_email) VALUES (?, ?, ?, ?, ?)";
jdbcTemplateObject.update(sqlStmt, username, name, contactName,
contactPhone, contactEmail);
} catch (DataAccessException e) {
e.printStackTrace();
}
}
사람과 contact_info : 내 테스트 코드에서 다음
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="createWithContactInfo"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="createOperation"
expression="execution(* com.example.db.CustomerJDBCTemplate.createWithContactInfo(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="createOperation" />
</aop:config>
<!-- Initialization for data source -->
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/Customer" />
<property name="username" value="myusername"/>
<property name="password" value="12345"/>
<property name="initialSize" value="10"/>
</bean>
<!-- Definition for customerJDBCTemplate bean -->
<bean id="customerJDBCTemplate" class="com.example.db.CustomerJDBCTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
을, 내가 가진 : 다음 나의 두 DB 테이블을 갱신하는 코드입니다
public class JdbcTest {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
CustomerDAO dao = (CustomerDAO) ctx.getBean("customerJDBCTemplate");
Date dob = new Date(90, 9, 10);
dao.createWithContactInfo("m9087", "Sam", dob, "David", "123456", "[email protected]");
}
}
주 프로그램을 실행 한 후에 나는 Duplicate entry 'm9087' for key 'PRIMARY'
이라는 예외가 있습니다. 이는 m9087
이 이미 contact_info 테이블에 존재하므로 예상됩니다. 하지만 트랜잭션에서 두 번째 DB 삽입이 실패한 이후로 나는 첫 번째 jdbcTemplateObject.update(sqlStmt, "paul", "Paul", dob);
이 트랜잭션에서 커밋되지 않을 것이라고 생각했습니다. 그러나 나는 person
테이블을 확인하고이 username=paul
유효 항목을 반환
SELECT * FROM person WHERE username='paul';
이 첫 번째 DB 삽입 두 번째 DB 인서트 키 예외를 중복으로 인해 실패에도 불구하고 성공을 의미합니다.
DB 작업 중 하나라도 실패하면 트랜잭션이 롤백되어야하며 커밋되지 않습니다. 그러나이 경우 중복 키 예외로 인해 두 번째 DB 업데이트가 실패하더라도 첫 번째 DB 삽입이 계속 성공했습니다. 트랜잭션 관리의 잘못된 동작이 아닙니까? 내 설정이 트랜잭션 관리에서 올바 릅니까?
고마워. 이 문제가 해결되었고 첫 번째 DB 삽입이 실패 할 때 첫 번째 DB 삽입이 커밋되지 않습니다. 나는 실제로 Spring Transaction Example : http://www.tutorialspring.com/spring/declarative_management.htm을 따라 갔고 그 예제에서는 예외를 잡기 위해 try catch를 사용한다. 그러나이 예제에서는 'try' 블록에 예외가 발생하기 때문에 시나리오가 다릅니다. – tonga