
2025-05-08
@Transactional์์ ์ฌ์ฉํ ํธ๋์ญ์
๋งค๋์ ๋ฅผ ๋ช
์์ ์ผ๋ก ์ง์ ํจ์ผ๋ก์จ ํผ์ ์ ๋ฐฉ์งํ ์ ์๋ค.TxConfig.java@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages ="com.example.demo.domain.repository",
transactionManagerRef = "jpaTransactionManager"
)
public class TxConfig {
@Autowired
private DataSource dataSource;
// MyBatis ๋๋ ๊ธฐ๋ณธ JDBC์ฉ ํธ๋์ญ์
๋งค๋์
@Bean(name = "dataSourceTransactionManager")
public DataSourceTransactionManager transactionManager2() {
return new DataSourceTransactionManager(dataSource);
}
// JPA์ฉ ํธ๋์ญ์
๋งค๋์
@Bean(name = "jpaTransactionManager")
public JpaTransactionManager jpaTransactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
transactionManager.setDataSource(dataSource);
return transactionManager;
}
}
JpaConfig.java@Configuration
@EntityScan(basePackages = {"com.example.demo.domain.entity"})
@EnableJpaRepositories(
basePackages = {"com.example.demo.domain.repository"},
transactionManagerRef = "jpaTransactionManager"
)
public class JpaConfig {
@Autowired
private DataSource dataSource;
@Bean
LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
factoryBean.setPackagesToScan("com.example.demo.domain.entity");
Map<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto", "update");
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
properties.put("hibernate.show_sql", true);
properties.put("hibernate.format_sql", true);
factoryBean.setJpaPropertyMap(properties);
return factoryBean;
}
// โ ๏ธ ์ค๋ฌด์์๋ dev ํ๊ฒฝ์์๋ง ๋์ํ๋๋ก @Profile("dev") ์ถ๊ฐ ๊ถ์ฅ
@Bean
public DataSourceInitializer dataSourceInitializer() {
DataSourceInitializer initializer = new DataSourceInitializer();
initializer.setDataSource(dataSource);
initializer.setDatabasePopulator(databasePopulator());
return initializer;
}
private DatabasePopulator databasePopulator() {
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
populator.addScript(new ClassPathResource("schema.sql"));
populator.addScript(new ClassPathResource("data.sql"));
return populator;
}
}
TxTestService.java@Service
@Slf4j
public class TxTestService {
@Autowired
private MemoMapper memoMapper;
@Transactional(rollbackFor = SQLException.class, transactionManager = "dataSourceTransactionManager")
public void addMemoTx(MemoDto dto) throws Exception {
log.info("MyBatis Insert ์คํ");
memoMapper.insert(dto);
throw new SQLException(); // ๋กค๋ฐฑ ํ
์คํธ์ฉ ์์ธ
}
@Autowired
private MemoRepository memoRepository;
@Transactional(rollbackFor = SQLException.class, transactionManager = "jpaTransactionManager")
public void addMemoTx2(MemoDto dto) throws Exception {
log.info("JPA Insert ์คํ");
Memo memo = new Memo();
memo.setId(dto.getId());
memo.setText(dto.getText());
memoRepository.save(memo);
throw new SQLException(); // ๋กค๋ฐฑ ํ
์คํธ์ฉ ์์ธ
}
}
TxTestServiceTest.java@SpringBootTest
class TxTestServiceTest {
@Autowired
private TxTestService txTestService;
@Test
void t2() throws Exception {
txTestService.addMemoTx(new MemoDto(1, "TEST1")); // MyBatis ํธ๋์ญ์
ํ
์คํธ
}
@Test
void t3() throws Exception {
txTestService.addMemoTx2(new MemoDto(1, "TEST1")); // JPA ํธ๋์ญ์
ํ
์คํธ
}
}
@Transactional(transactionManager = "...")๋ก ๋ช
์ ์ง์ ํ์@Profile("dev") ๋ฑ์ผ๋ก ๋ถ๋ฆฌํ๋ ๊ฒ์ด ์ค๋ฌด์ ์ ํฉ์ด๋ฒ ์ค์ต์ ํตํด ํ๋์ ํ๋ก์ ํธ์์ MyBatis์ JPA๋ฅผ ๋์์ ์ฌ์ฉํ ๋ ๋ฐ์ํ ์ ์๋ ํธ๋์ญ์ ์ถฉ๋ ๋ฌธ์ ๋ฅผ ์ฌ์ ์ ์๋ฐฉํ ์ ์์๋ค. ํธ๋์ญ์ ๋งค๋์ ๋ฅผ ๋ช ํํ ๊ตฌ๋ถํ๊ณ ํ ์คํธ๋ก ๊ฒ์ฆํ๋ ๊ณผ์ ์ ์ค๋ฌด์์๋ ๋งค์ฐ ์ ์ฉํ ๊ฒ์ด๋ค.