새소식

반응형
Java/Spring

DataSoruce TransactionManager 설정(commit, rollback)

  • -
반응형

환경 : Spring Boot 6, HikariDataSource 사용

 

데이터베이스 Insert 및 Update 하는 과정에서 예외가 발생된다면 해당 과정들의 데이터를 다시

rollback 해야 하는 상황이 나타난다.

 

이러한 과정에서 예외가 발생하지 않았을 때 최종적으로 Insert 및 Update 를 하고

예외가 발생했을 때 rollback 하기 위해선 Spring 에서 제공하는 Transaction 기술을 사용해야한다.

자세한 내용은 Spring 공식문서에 나와있다.

 

https://docs.spring.io/spring-framework/reference/data-access/transaction/strategies.html

 

Understanding the Spring Framework Transaction Abstraction :: Spring Framework

You can also easily use Hibernate local transactions, as shown in the following examples. In this case, you need to define a Hibernate LocalSessionFactoryBean, which your application code can use to obtain Hibernate Session instances. The DataSource bean d

docs.spring.io

 

 

Transaction 을 처리하기 위해선 TransactionManager 를 사용한다.

TransactionManager 인터페이스를 실제로 들어가보면 비어있으며, TransactionManager 를 상속받은

PlatformTransactionManager 인터페이스를 사용하라고 공식문서에 나와있다.

PlatformTransactionManager 는 트랜잭션 관리 추상화 클래스이다.

 

PlatformTransactionManager 인터페이스를 구현하는 메서드는 총 3가지이다.

  • Transaction 을 가지고 오는 getTransaction()
  • DB 처리에 예외가 없고 모두 성공했다면 commit()
  • 예외 발생 시 rollback 을 위한 rollback()
public interface PlatformTransactionManager extends TransactionManager { TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException; void commit(TransactionStatus status) throws TransactionException; void rollback(TransactionStatus status) throws TransactionException; }

 

 

 

여기서 우리는 DataSource 를 이용하여 Transaction 을 처리한다.

PlatformTransactionManager 인터페이스를 구현한 구현체인 DataSourceTransactionManager 클래스를 이용한다.

 

@SuppressWarnings("serial") public class DataSourceTransactionManager extends AbstractPlatformTransactionManager implements ResourceTransactionManager, InitializingBean { @Nullable private DataSource dataSource; public DataSourceTransactionManager() { setNestedTransactionAllowed(true); } public DataSourceTransactionManager(DataSource dataSource) { this(); setDataSource(dataSource); afterPropertiesSet(); } ... }

 

 

위 DataSouraceTransactionManager 를 Bean 등록하여 사용해보자.

 

공식문서에서는 xml 에 bean 등록해서 사용하는 방법이 나와있다.

 

 

설정한 DataSource 를 DataSourceTransactionManager 에 설정하여 Bean 등록을 한다.

 

 

본인은 HikariDataSource 를 사용했으며, 설정은 아래와 같다.

@Configuration @MapperScan(basePackages = "com.league.mapper") public class DBConfig { @Bean @ConfigurationProperties(prefix = "spring.datasource.hikari") public HikariConfig hikariConfig() { return new HikariConfig(); } @Bean public HikariDataSource dataSource() { return new HikariDataSource(hikariConfig()); } @Bean public SqlSessionFactory sqlSessionFactory() throws Exception { SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); bean.setDataSource(dataSource()); bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:com/league/mapper/**/*.xml")); return bean.getObject(); } @Bean public SqlSessionTemplate sqlSession() throws Exception { return new SqlSessionTemplate(sqlSessionFactory()); } @Bean public DataSourceTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } }

 

 

DataSourceTransactionManager 에 dataSource 를 파라미터로 넘겨 Bean 등록을 한다.

추가한 내용은 아래와 같다.

@Bean public DataSourceTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); }

 

 

이제 설정한 TransactionManager 를 사용하기 위해 Service 단에 PlatformTransactionManager 를

주입받아 사용해보자. 본인은 @Autowired 를 사용하지 않고 생성자 주입방식으로 주입했다.

 

@Service public class LeagueService { private final SqlSessionTemplate sqlSession; private final PlatformTransactionManager tm; public LeagueService(SqlSessionTemplate sqlSession, PlatformTransactionManager tm) { this.sqlSession = sqlSession; this.tm = tm; } .... }

 

 

등록한 PlatformTransactionManager 를 사용해보자

getTransaction(new DefaultTransactionDefinition()) 을 통해서 현재 Transaction 을 가져온다.

DB  Transaction 에 예외가 발생하지 않았을경우 성공이라고 보고 commit 을 한다.

Exception 부분에 예외 발생 시 rollback 을 위한 Transaction rollback() 를 통해 rollback 한다.

public void authTest() { LeagueMapper mapper = sqlSession.getMapper(LeagueMapper.class); TransactionStatus ts = tm.getTransaction(new DefaultTransactionDefinition()); try { HashMap<String, Object> map = new HashMap<String, Object>(); map.put("user_name", "obo2"); map.put("user_pw", "1234"); map.put("role", "MAMBER"); mapper.insertTest(map); map.clear(); map.put("user_name", null); map.put("user_pw", "1234"); map.put("role", "MANAGER"); mapper.insertTest(map); tm.commit(ts); System.out.println("commit 완료"); } catch (Exception e) { tm.rollback(ts); System.out.println("rollback 완료"); e.printStackTrace(); } }

 

 

 

반응형

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.