jdbi3์ spring-boot์ ํตํฉํ๊ณ ์ถ์ต๋๋ค. ๊ทธ๋ฌ๋ ์ธํฐ๋ท์์ ์ ์ฒด ๊ทธ๋ฆผ์ ์ป๊ธฐ ์ํด ํ์ํ ๋ชจ๋ ๋ถ๋ถ์ ์ฐพ๊ธฐ๋ ์ด๋ ต์ต๋๋ค.
jdbi3๋ก ์คํ๋ง ๋ถํธ ์ ํ๋ฆฌ์ผ์ด์
์ ์ค์ ํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ฃผ๋ github์ jdbi-examples-repository๋ฅผ ์ ๊ณตํ ๊ธฐํ๊ฐ ์์ต๋๊น?
์ ๋ง ๊ฐ์ฌํ๊ฒ ์ต๋๋ค. ์ ๋ง ๊ฐ์ฌํฉ๋๋ค.
/์
๊ฐ๋จํ ๊ฒฝ์ฐ์ Spring์ ํธ๋์ญ์
๊ธฐ๋ฅ๊ณผ์ ํตํฉ์ด ํ์ํ์ง ์๋ค๋ฉด Spring ๊ตฌ์ฑ์์ Jdbi
๋ฐ DAO๋ฅผ ์ด๊ธฐํํ๊ธฐ
<strong i="7">@Bean</strong>
public DataSource dataSource() {
// From Spring Boot's connection pool configuration;
}
<strong i="8">@Bean</strong>
public Jdbi createJdbi(DataSource dataSource) {
return Jdbi.create(dataSource);
}
<strong i="9">@Bean</strong>
public UserDao userDao(Jdbi jdbi) {
return jdbi.onDemand(UserDao.class);
}
@bastman ๋ , @alwins0n ์ #989์์ ๋ ๋์ Spring ์ง์์ ๊ธฐ์ฌํ๊ณ ์์ต๋๋ค. ์ง๊ธ๊น์ง ๊ทธ์ ์์ ์ ๊ฒํ ํ๊ณ Spring ํตํฉ์ ๋ ๋ช ํํ๊ฒ ๋ง๋๋์ง ๋๋ ์ฝ๊ฐ ๋ค๋ฅธ ๊ฒ์ ์๊ตฌํ๋์ง ์ฌ๋ถ์ ๋ํด ์๊ฒฌ์ ๋ง์ํ์๊ฒ ์ต๋๊น?
jdbi๋ฅผ ์คํ๋ง ๋ถํธ์ ํตํฉํ๋ ๊ฒ์ ๊ฐ๋จํฉ๋๋ค. @Configuration
ํด๋์ค์์ @Bean
์ฃผ์ ๋ฉ์๋๋ฅผ ์ค์ ํ์ฌ Jdbi ์ธ์คํด์ค๋ฅผ ๋ฐํํ๋ฉด ๋ฉ๋๋ค. @arteam์์ ๋ณผ ์ ์๋ฏ์ด
๋ด ์คํ๋ง PR์์ ์ํํ ๊ฒ์ฒ๋ผ ๋ ์ด๋ ค์ด ๊ฒ์ jdbi๋ฅผ ์คํ๋ง ํธ๋์ญ์ ๊ด๋ฆฌ์ ํตํฉํ๋ ๊ฒ์ ๋๋ค. ๊ทธ๊ฒ์ด ๋น์ ์ด ์ฐพ๊ณ ์๋ ๊ฒ์ด๋ผ๋ฉด ๋ฐ๋์ ํ์ธํด์ผํฉ๋๋ค.
๋ํ ์ด๊ฒ์ด ์น์ธ๋๋ฉด ์คํ๋ง ๋ถํธ(2)๋ฅผ ์ํ autoconfiguration/spring-boot-starter๋ฅผ ๋ง๋๋ ๊ฒ์ ๊ณ ๋ คํ๊ณ ์์ต๋๋ค. ๊ทธ๊ฒ์ด ๋น์ ์ด ์ฐพ๊ณ ์๋ ๊ฒ์ด๋ผ๋ฉด. (์์ ์ ์๋ํ๊ณ ์ถ๋ค๋ฉด ์ค์ ๋ก ์ข์ ์ฐ์ต์ ๋๋ค: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-develping-auto-configuration.html )
๋๋ ์๋ฌด๋ฐ ๋ฌธ์ ์์ด jdbi2.x์ ํจ๊ป ๋ค์ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. jdbi3.x๋ก ํ ์คํธํด ๋ณด์์ง๋ง ๋ฌธ์ ๋ ์์์ต๋๋ค. ์ด๊ฒ์ jdbi๋ฅผ ์ฌ์ฉํ๋ ๋์ ํธ๋์ญ์ ์ ๊ด๋ฆฌํ๊ธฐ ์ํด spring์ ์ป๋ ๋ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ฒ๋ผ ๋ณด์ ๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก ํ๋ก์๋ฅผ TransactionAwareDataSourceProxy๋ก ๋ํํ๊ณ ์ด๋ฅผ ์ฌ์ฉํ์ฌ Jdbi ์ธ์คํด์ค๋ฅผ ์์ฑํฉ๋๋ค. (์์ ๊ฐ ์ผ๊ด๋๋๋ก @arteam ์ ๋ต๋ณ์์ c/p'd๊ฐ ์์ต๋๋ค)
<strong i="8">@Bean</strong>
public DataSource dataSource() {
// From Spring Boot's connection pool configuration;
}
<strong i="9">@Bean</strong>
public TransactionAwareDataSourceProxy txDataSource(DataSource dataSource) {
return new TransactionAwareDataSourceProxy(dataSource);
}
<strong i="10">@Bean</strong>
public PlatformTransactionManager transactionManager(DataSource dataSource) {
//not sure if this is needed
return new DataSourceTransactionManager(dataSource);
}
<strong i="11">@Bean</strong>
public Jdbi createJdbi(TransactionAwareDataSourceProxy dataSource) {
//note that parameter is TransactionAwareDataSourceProxy instead of plain DataSource
return Jdbi.create(dataSource);
}
<strong i="12">@Bean</strong>
public UserDao userDao(Jdbi jdbi) {
return jdbi.onDemand(UserDao.class);
}
์ข์๋ฐ ์ด๋ฐ ํด๋์ค๊ฐ ์๋์ง ๋ชฐ๋๋ค์.
์์ ์ธ๊ธํ PR์ ๋ณผ ์ ์์ต๋๊น? jdbi์ ๊ธฐ๋ณธ์ด ๋๋ "ํธ๋์ญ์ ์ธ์" ์ฐ๊ฒฐ ํฉํ ๋ฆฌ์ ๊ด๋ จํ์ฌ ์ด๋ฏธ ์ ์์ด ์์์ต๋๋ค.
iirc ์ฐ๊ฒฐ๊ณผ ํธ๋ค์ด ๋๊ธฐํ ์ํ๊ฐ ์๋๋ผ๋ ๋ฌธ์ ๊ฐ ๋จ์ ์์ต๋๋ค. ๋ฐ๋ผ์ ์ด ds๋ ํธ๋์ญ์ ์ข ๋ฃ ์ ๋ซํ ์ฐ๊ฒฐ(ํธ๋์ญ์ ์ ๋ฐ์ธ๋ฉ๋จ)์ โโ๋ฐํํฉ๋๋ค. ๋ฐ๋ฉด ์ฌ์ฉ๋ ํธ๋ค์ ๋ซํ์ง ์๊ณ (์ฌ)์ฌ์ฉํ๋ ค๊ณ ์๋ํ ๋ ์์ธ๊ฐ ๋ฐ์ํฉ๋๋ค.
๊ทธ๋ฌ๋ ์ด๊ฒ์ ๊ทธ๋ค์ง ํฐ ๊ฑฐ๋๊ฐ ์๋๋ฉฐ ์คํ๋ ค ๋ชจ์๋ฆฌ ์ผ์ด์ค y์ด๋ฉฐ ๊ทํ์ ์๋ฃจ์ ์ ์ฌ์ฉ ์ฌ๋ก์ 99%์ ์ ํฉํฉ๋๋ค.
์์ปจ๋: ๊ทํ์ ์ ๊ทผ ๋ฐฉ์์์ ํธ๋์ญ์ ๊ด๋ฆฌ ๋ฆฌ์์ค๋ ์ฐ๊ฒฐ์ ๋๋ค. ๋ด PR์์ ๊ด๋ฆฌ ์์์ ํธ๋ค์ ๋๋ค.
stringtemplate4 ๋ฐ ๊ทธ๋ฃน ๊ฐ์ ธ์ค๊ธฐ์ ํจ๊ป jdbi3์ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ๊ด๋ จ๋ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ๋ด ๋ฌธ์ ๋ฅผ ์ฐธ์กฐํ์ญ์์ค https://github.com/jdbi/jdbi/issues/1052
์ด ๋ฌธ์ ์๋ ์คํ๋ง ๋ถํธ 2.0.0์์ jdbi3์ ์ฌ์ฉํ๊ธฐ ์ํด ์์ ํ ์๋ํ๋ repo ์ค์ผ๋ ํค์ ๋ํ ๋งํฌ๋ ํฌํจ๋์ด ์์ต๋๋ค.
Spring์ @Transactional ์ฃผ์์ผ๋ก @kaandok ์ ์๋ฃจ์ ์ ๊ตฌํํ ๋ ์ด๋ฆฐ ํธ๋์ญ์ ์ด ์์ ๋ ํธ๋ค์ ๋ซ๋ ๊ฒ์ผ๋ก ์ธํด ๋ค์๊ณผ ๊ฐ์ ์์ธ๊ฐ ๋ฐ์ํฉ๋๋ค. ์ด์ ๋ํ ๊ถ์ฅ/์ ์ฉ ๊ฐ๋ฅํ ์๋ฃจ์ ์ด ์์ต๋๊น?
"๋ถ์ ์ ํ ํธ๋์ญ์ ์ฒ๋ฆฌ๊ฐ ๊ฐ์ง๋์์ต๋๋ค. ์ด๋ ค ์๋ ํธ๋์ญ์ ์ด ์๋ ํธ๋ค์ด ๋ซํ์ต๋๋ค. ํธ๋ค์ ๋ซ๊ธฐ ์ ์ ํธ๋์ญ์ ์ ๋ช ์์ ์ผ๋ก ์ปค๋ฐํ๊ฑฐ๋ ๋กค๋ฐฑํด์ผ ํฉ๋๋ค. Jdbi๊ฐ ์ด ํธ๋์ญ์ ์ ์๋์ผ๋ก ๋กค๋ฐฑํ์ต๋๋ค."
@cengha ๋ฌธ์ ๋ฅผ ๋ณด์ฌ์ฃผ๋ ๋ช ๊ฐ์ง ์ฝ๋๋ฅผ ์ ๊ณตํ ์ ์์ต๋๊น?
์๋๋ ๊ตฌ์ฑ ํด๋์ค์ ๋๋ค.
<strong i="6">@Bean</strong>
public HikariDataSource hikariDataSource() {
HikariConfig dataSourceConfig = new HikariConfig();
dataSourceConfig.setDriverClassName(driverClassName);
dataSourceConfig.setJdbcUrl(jdbcUrl);
dataSourceConfig.setUsername(username);
dataSourceConfig.setPassword(password);
dataSourceConfig.setAutoCommit(true);
return new HikariDataSource(dataSourceConfig);
}
<strong i="7">@Bean</strong>
public TransactionAwareDataSourceProxy transactionAwareDataSourceProxy(HikariDataSource dataSource) {
return new TransactionAwareDataSourceProxy(dataSource);
}
<strong i="8">@Bean</strong>
public PlatformTransactionManager platformTransactionManager(HikariDataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
<strong i="9">@Bean</strong>
public Jdbi jdbi(TransactionAwareDataSourceProxy transactionAwareDataSourceProxy) {
Jdbi jdbi = Jdbi.create(transactionAwareDataSourceProxy);
jdbi.installPlugin(new SqlObjectPlugin());
return jdbi;
}
๋ค์์ ์๋น์ค ๊ณ์ธต์ ๋๋ค.
<strong i="13">@Override</strong>
<strong i="14">@Transactional</strong>
public Long createX(X x) {
Long aLong = XDao.insertX(x);
if(true) throw new RuntimeException();
return aLong;
}
์๋ ์ปค๋ฐ์ด false๋ก ์ค์ ๋๋ฉด ํธ๋์ญ์ ์ค๋ฅ๊ฐ ์ธ๊ธ๋์์ง๋ง true๋ก ์ค์ ํ๋ฉด ํธ๋์ญ์ ์ค๋ฅ๊ฐ ์์ง๋ง ์ด๋ฒ์๋ ๋กค๋ฐฑ์ด ์๋ํ์ง ์์ผ๋ฏ๋ก(๋ฐํ์ ์์ธ ํ) X ๊ฐ์ฒด๊ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ง๋ฉ๋๋ค. ๋๋ ๋ด 2.0.3, JDBI 3.0.0-beta2๋ฅผ ์ฌ์ฉํ๋ค.
๋ฌธ์ ํด๊ฒฐ๋จ. ์ด ์ค๋ ๋ ๊ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ๋ฐ์ดํธํ๊ณ ๋ชจ๋ ๊ฒ์ด ํด๊ฒฐ๋ ๊ฒ์ ํ์ธํ ํ ์ด์ ๋ฒ์ ์ JDBI๋ฅผ ์ฌ์ฉํ๊ณ ์์์ต๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
๋๋ ์๋ฌด๋ฐ ๋ฌธ์ ์์ด jdbi2.x์ ํจ๊ป ๋ค์ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. jdbi3.x๋ก ํ ์คํธํด ๋ณด์์ง๋ง ๋ฌธ์ ๋ ์์์ต๋๋ค. ์ด๊ฒ์ jdbi๋ฅผ ์ฌ์ฉํ๋ ๋์ ํธ๋์ญ์ ์ ๊ด๋ฆฌํ๊ธฐ ์ํด spring์ ์ป๋ ๋ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ฒ๋ผ ๋ณด์ ๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก ํ๋ก์๋ฅผ TransactionAwareDataSourceProxy๋ก ๋ํํ๊ณ ์ด๋ฅผ ์ฌ์ฉํ์ฌ Jdbi ์ธ์คํด์ค๋ฅผ ์์ฑํฉ๋๋ค. (์์ ๊ฐ ์ผ๊ด๋๋๋ก @arteam ์ ๋ต๋ณ์์ c/p'd๊ฐ ์์ต๋๋ค)