1
문서와 일치하지 않는 이상한 동작이 나타납니다. 이것은 내가하고있는 일이다. Test 클래스에서 DB에 행을 생성 한 다음 @Transactional Service (REQUIRES_NEW로 표시된)를 호출하여 RunTimeException을 던지는 @Transactional Service를 호출한다. 나는 내 시험에서 내 기록을 볼 것으로 기대하지만, 나는 그렇지 않다. 아이디어?REQUIRES_NEW를 사용하여 전달을 수행하면 아웃 바운드 트랜잭션도 롤백됩니다. 왜?
내 테스트 클래스 :
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:**/jdbc-beans.xml","classpath:**/jdbc-infrastructure.xml","classpath:**/jdbc-infrastructure-test.xml" })
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public class TransactionalTest {
@Autowired
FeedManagerOne feedManagerOne;
@Test
public void test_propagation_REQUIRES_to_REQUIRES_NEW() {
Feed anotherFeed = new Feed("AnotherRSS", "http://www.anotherfeedlink.com", true);
assertFalse(feedManagerOne.exists(anotherFeed)); // EVALUATES TO FALSE
try {
feedManagerOne.createFeed(anotherFeed, true);
} catch (RuntimeException e) {
e.printStackTrace();
}
// EVALUATES TO FALSE. WRONG! IT SHOULD BE TRUE.
assertTrue(feedManagerOne.exists(anotherFeed));
}
}
서비스 하나 :
@Service
public class FeedManagerOne {
@Autowired
FeedManagerTwo feedManagerTwo;
@Autowired
JdbcTemplate jdbcTemplate;
@Transactional(readOnly = true)
public boolean exists(Feed feed) {
String query = "SELECT COUNT(*) FROM feed WHERE name = ? AND url = ? AND is_active = ?";
int total = jdbcTemplate.queryForInt(query, feed.getName(), feed.getUrl(), feed.isActive());
boolean found = (total == 1);
return found;
}
@Transactional
public boolean createFeed(Feed feed, boolean invokeFeedManagerTwo) {
String query = "INSERT INTO feed (name, url, is_active) values (?, ?, ?)";
int rowsChanged = jdbcTemplate.update(query, feed.getName(), feed.getUrl(), feed.isActive());
boolean created = (rowsChanged == 1);
// WHEN THE THE FOLLOWING METHOD THROWS A RUNTIME EXCEPTION,
// THE JUST CREATED RECORD WILL BE LOST FROM THE DB (SEE TEST)
feedManagerTwo.throwRuntimeExceptionFromRequiresNew();
return created;
}
}
서비스 두
@Service
public class FeedManagerTwo {
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED)
public void throwRuntimeExceptionFromRequiresNew() {
if (true) {
throw new RuntimeException("From REQUIRES_NEW");
}
}
}