transactionUpdateTest를 통해서 테스트코드에 트랜잭션을 적용하려고 한다.
격리레벨은 read committed로 설정하고 sqlRegistrySchema.sql에서 읽어온 정보를 db에 빌드하고
db변수에 registry를 담은 후에
map 객체에 sql1, sql2, sql3.. 이런 식으로 담고 변경중에 에러가 터지면 롤백처리를 한다.
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
for(Map.Entry<String, String> entry : sqlmap.entrySet()) {
updateSql(entry.getKey(), entry.getValue());
}
}
});
updateSql메서드를 호출하고 맵에 있는 정보를 꺼내서 전달하면 변경이 되는 로직이다. 중간에 에러가 터지면
롤백한다.
정확히 이해가 안가는 부분은 doInTransactionWithoutResult메서드의 status를 스프링이 전달해준다고 하는데
어떤 식으로 전달이 되는지 모르겠다.
public class EmbeddedDbSqlRegistryTest extends AbstractUpdatableSqlRegistryTest {
EmbeddedDatabase db;
@Override
protected UpdatableSqlRegistry createUpdatableSqlRegistry() {
db = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:sql/sqlRegistrySchema.sql")
.build();
EmbeddedDbSqlRegistry embeddedDbSqlRegistry = new EmbeddedDbSqlRegistry();
embeddedDbSqlRegistry.setDataSource(db);
return embeddedDbSqlRegistry;
}
@AfterEach
public void tearDown() {
db.shutdown();
}
@Test
public void transactionUpdate(){
checkFind("SQL1", "SQL2", "SQL3");
Map<String, String> sqlmap = new HashMap<>();
sqlmap.put("KEY1", "Modified1");
sqlmap.put("KEY9999!@#$", "Modified9999");
try{
sqlRegistry.updateSql(sqlmap);
fail();
}catch(SqlUpdateFailureException e){
checkFind("SQL1", "SQL2", "SQL3");
}
}
}
public class EmbeddedDbSqlRegistry implements UpdatableSqlRegistry {
JdbcTemplate jdbc;
TransactionTemplate transactionTemplate;
public void setDataSource(DataSource dataSource) {
jdbc = new JdbcTemplate(dataSource);
transactionTemplate = new TransactionTemplate(
new DataSourceTransactionManager(dataSource));
transactionTemplate.setIsolationLevel(TransactionTemplate.ISOLATION_READ_COMMITTED);
}
public void registerSql(String key, String sql) {
jdbc.update("insert into sqlmap(key_, sql_) values(?,?)", key, sql);
}
public String findSql(String key) throws SqlNotFoundException {
try {
return jdbc.queryForObject("select sql_ from sqlmap where key_ = ?", String.class, key);
}
catch(EmptyResultDataAccessException e) {
throw new SqlNotFoundException(key + "에 해당하는 SQL을 찾을 수 없습니다", e);
}
}
public void updateSql(String key, String sql) throws SqlUpdateFailureException {
int affected = jdbc.update("update sqlmap set sql_ = ? where key_ = ?" , sql, key);
if (affected == 0) {
throw new SqlUpdateFailureException(key + "에 해당하는 SQL을 찾을 수 없습니다");
}
}
public void updateSql(final Map<String, String> sqlmap) throws SqlUpdateFailureException {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
for(Map.Entry<String, String> entry : sqlmap.entrySet()) {
updateSql(entry.getKey(), entry.getValue());
}
}
});
}
}
'WEB > SPRING' 카테고리의 다른 글
토비2 1.2 ioc/di를 위한 빈 설정 메타정보 작성 (0) | 2024.03.06 |
---|---|
토비의 스프링 7.6 스프링 3.1의 DI (1) | 2024.02.27 |
토비의 스프링 7.5 DI를 이용해 다양한 구현 방법 적용하기 (0) | 2024.02.16 |
토비 스프링 7.2 인터페이스의 분리와 자기참조 빈 (0) | 2024.02.15 |
토비의 스프링 7.1 SQL과 DAO의 분리 (0) | 2024.02.13 |