๋ฌธ์
JDBI ๊ณต์ ๋ฌธ์๋ ๊ฐ๋ฐ์๋ค์ด @CreateSqlObject ์ฃผ์์ด ์ด์ง์ ์ธ DAO์ ํธ๋์ญ์
์ง์์ ์ถ๊ฐํ๊ธฐ ์ํ ๋ฉ์ปค๋์ฆ์ด๋ผ๊ณ ๋ฏฟ๊ฒ ํฉ๋๋ค.
http://jdbi.org/#__createsqlobject
์ ํธํ๋ jdbi.onDemand
์์ฑ ๋ฉ์ปค๋์ฆ๊ณผ ํจ๊ป ์ฌ์ฉํ ๋ ์ํ ์ค๋ฅ๋ก ์ด์ด์ง ์ ์๋ ์ค์ ๋์์ ๋ํด ์ฝ๊ฐ ์คํด์ ์์ง๊ฐ ์๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ด ํผ๋์ ์ค๋ช ํ๋ ๋ช ๊ฐ์ง ๋ฉ์์ง๊ฐ ํฌ๋ผ์ ์์ต๋๋ค.
https://groups.google.com/forum/#!searchin/jdbi/CreateSqlObject %7 Csort:date/jdbi/FPI1l1OBLU0/slXj_8hJBwAJ
https://groups.google.com/forum/#!searchin/jdbi/CreateSqlObject %7 Csort:date/jdbi/b1rWVQ7JNAg/2R2c9okAAgAJ
์๊ตฌ
์ด ๋ฌธ์ ์ ๋ํ ์ต์์ ์๋ฃจ์
์ด ๋ฌด์์ธ์ง ํ์คํ์ง ์์ต๋๋ค. ์๊ฐ๋๋ ๋ช ๊ฐ์ง:
์ ๊ณ ํด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ์ฌ๊ธฐ์์ ๊ธฐ์ ์ ์ผ๋ก ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ์ด ์์ ๊ฒ์ผ๋ก ์๊ฐํ์ง๋ง ๊ธฐ์กด ๋์์ด 3.x ๋ฆด๋ฆฌ์ค ์ฃผ๊ธฐ์ ์ด๊ธฐ์ ๊ธฐ์ ์ ์ผ๋ก ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ์ ๋ง๋ค ๋งํผ ์ถฉ๋ถํ ์ข์ง ์๋ค๊ณ ์๊ฐํฉ๋๋ค. ๊ธฐ์กด ๋์์ ์์กดํ๊ฑฐ๋ ์ ์ฌ์ ์ผ๋ก ์์ ์ฃผ์ ๋ณ๊ฒฝ ์ฌํญ์ ์ฌ๊ธฐ์ ์ ๊ณตํ๋ ๋ฐ ๋์ํ์ง ์๋ ๊ฒฝ์ฐ ์ด ๋ฌธ์ ์ ํ๋๊ทธ๋ฅผ ์ง์ ํ์ญ์์ค.
@CreateSqlObject
๊ฐ ์จ๋๋งจ๋์์ ์ ์๋ํ์ง ์๋ _์ด์ _์ ๋ํ ์ปจํ
์คํธ:
@CreateSqlObject
๋ handle.attach(sqlObjectType)
๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌํ๋๋ฉฐ ์๋ SQL ๊ฐ์ฒด์ ์ง์ ํธ๋ค์ด ์์ต๋๋ค.๋ฐ๋ผ์ ์์ฑ๋ SQL ๊ฐ์ฒด์ ๋ํ ์ง์ ํธ๋ค์ SQL ๊ฐ์ฒด๊ฐ ๋ฐํ๋๊ธฐ ์ ์ ๋ซํ๋๋ค.
์์ ์ด๋ ๊ฒ๋ ํ์ ๋ ๊ฒ์ ์๋๋ฉฐ ํ์ฌ ๊ตฌํ๋ ๋ฐฉ์์ ๋๋ค.
๋๋ ์ฐ๋ฆฌ๊ฐ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ํธํ์ฑ์ ๊นจ์ผ ํ ๊ฒ์ด๋ผ๊ณ ํ์ ํ์ง ์์ต๋๋ค.
์ฃ์กํฉ๋๋ค. ์ ์ดํด๊ฐ ๋์ง ์์ต๋๋ค... onDemand ๋ฐ CreateSqlObject์ ๋ฌธ์ ๋ ์ ํํ ๋ฌด์์ ๋๊น? ๋๋ ๊ทธ๊ฒ์ ๋ํด ์๋ฌด๋ฐ ๋ฌธ์ ๊ฐ ์์๊ณ @qualidafial ์ ์ค๋ช ์ ๋ํ ๋ฌด์ธ๊ฐ๊ฐ ๋ด ๋ง์์ ๊ธฐ์ธ๊ฒ ๋ง๋ญ๋๋ค ...
fooProxy.usecase ์ ๋ํ ํธ์ถ์ ๋ํ ์ฐ๊ฒฐ์ด ํ๋ณด๋ฉ๋๋ค. Foo.usecase ๋ ํ์ฌ( usecase ์) ํธ๋ค์ ์ฐ๊ฒฐํ ํ ์ Bar ๋ฅผ ๋ฐํํ๋ createSqlObject ๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค. usecase ๊ฐ ๋ฐํ๋๋ฉด usecase ์ ํธ๋ค์ด ๋ซํ๋๋ค. ๋ฐํ๋ Bar ์ ๋น๋๊ธฐ์์ผ๋ก ์๋ฌด๊ฒ๋ ํ์ง ์๋ ํ ์ด๋ป๊ฒ bar ์ ํธ๋ค์ด ๋๋ฌด ์ผ์ฐ ๋ง๋ฃ๋ ์ ์์ต๋๊น? bar ์ ์๋ช ์ฃผ๊ธฐ์ ์ฌ์ฉ์ ํธ๋ค๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก Foo.usecase ์ ๋ณธ๋ฌธ์ผ๋ก ์ ํ๋ฉ๋๋ค.
JDBI ๋ด๋ถ์ ๋ํด ๋งํ ์๋ ์์ง๋ง ํ๋ก๋์ ์์ ๋ณธ ๋์์ ๋ํด์๋ ์ธ๊ธํ ์ ์์ต๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก ์ฐ๋ฆฌ์ ๋ฎ์ ํ๊ฒฝ์์๋ ๊ด์ฐฎ์์ต๋๋ค. ๊ทธ๋ฌ๋ ํ๋ก๋์ ์ ๋ก๋๊ฐ ์ฆ๊ฐํจ์ ๋ฐ๋ผ ์ ์ ํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ ธ๋์ ๋ํด SQL ๋ฌธ์ด ์คํ๋์ง ์๋ ๊ฒ์ ๊ณ์ ๋ณด๊ฒ ๋ฉ๋๋ค. ์๋ฅผ ๋ค์ด ์ฝ๊ธฐ ์ ์ฉ ์ ํ์ ๋ง์คํฐ ๋ ธ๋์ ๋๋ฌํ๊ณ ์ฝ์ ์ ์ฝ๊ธฐ ์ ์ฉ ๋ณต์ ๋ณธ์ ๋๋ฌํฉ๋๋ค. ๋ํ ์์ ๋์ค์ ์ฐ๊ฒฐ ๋ซํ ์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค.
๋ณธ์ง์ ์ผ๋ก @CreateSqlObject ๊ฐ ์ค๋ ๋ ์์ ๋ฌธ์ ๋ฅผ ๋ง๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ฝ๊ธฐ ์ ์ฉ ํ๋๊ทธ๊ฐ ๊ฒฝ์ ์์ฒญ์ ์ํด ๋ณ๊ฒฝ๋๋ ๊ฒฝ์ฐ์ ๋๋ค.
๋ฌธ์ ๋ฅผ "ํด๊ฒฐ"ํ๊ธฐ ์ํด @CreateSqlObject
์ ๋ชจ๋ ์ฌ์ฉ์ ์ ๊ฑฐํ๊ณ ๋ค์๊ณผ ๊ฐ์ด ๋๋์ต๋๋ค.
class FooDao
class BarDao
class CombinedDao extends FooDao, BarDao
๊ทธ๋ฐ ๋ค์ ์ฐ๋ฆฌ๋ jdbi.onDemand(CombinedDao)
๋ฅผ ์ฌ์ฉํ๊ณ ์ด๋ฅผ ํตํ ์ก์ธ์ค๋ง ์ฌ์ฉํฉ๋๋ค.
๊ทธ ํจํด์ผ๋ก ์ ํํ๋ฉด ์์์ง๋ ์์ง๋ง ์์ ์ธ๊ธํ ํ๋ก๋์
์ค๋ฅ๊ฐ ๋ชจ๋ ์ ๊ฑฐ๋์์ต๋๋ค.
์ ๋ณด๋ฅผ ์ํด, ์ ๋ชจ๋ ์ฝ๋๊ฐ ํ์ฌ ์ถ์ ํด๋์ค์ ํจ๊ป onDemand๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ JDBI 2๋ก ๋์๊ฐ ์๊ฐ์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ ๊ฐ ๋ง์กฑํ ๋ฐฉ์์ผ๋ก ์ฌ๊ตฌ์ฑํ๋ ๋ฐฉ๋ฒ์ ์์๋ผ ์ ์์ต๋๋ค!
์ ๋ ์์ SQL์ธ DAO ํด๋์ค์ ๋ํ ์ก์ธ์ค๋ฅผ ์ ๊ณตํ๊ธฐ ์ํด CreateSqlObject๋ฅผ ์ฌ์ฉํ์ฌ ํธ๋์ญ์ ์ผ๋ก ์ฃผ์์ด ๋ฌ๋ฆฐ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ๋ ผ๋ฆฌ๋ฅผ ํฌํจํ์ง๋ง SQL์ ํฌํจํ์ง ์๋ ์ถ์ ๊ตฌํ ํด๋์ค๊ฐ ์๋ ์๋น์ค ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝํฅ์ด ์์ต๋๋ค. ๋จ์ํ๋ ์:
์ํธ ์์ฉ
public interface AccountService {
void addAccount(Account account, User user);
}
๊ตฌํ
public abstract class AccountServiceJdbi implements AccountService {
<strong i="11">@Override</strong>
<strong i="12">@Transaction</strong>
public final void addAccount(@BindBean() Account account, User user) {
long accountId = accountDao().insertAccount(account);
accountDao().linkAccountToOwner(accountId, user.getId());
}
<strong i="13">@CreateSqlObject</strong>
abstract AccountDao accountDao();
}
(๋น์ ์ Dao๋ฅผ ์์ํ ์ ์์ต๋๋ค)
์ด๊ฒ์ ์ฌ๋ฌ DAO ๋ฉ์๋๋ฅผ ํตํ ํธ๋์ญ์ ์ ํ์ฉํ๋ฉด์ ๋ก์ง๊ณผ ๋ฐ์ดํฐ ์ก์ธ์ค๋ฅผ ์์ฃผ ํ๋ฅญํ๊ฒ ๋ถ๋ฆฌํฉ๋๋ค. ์๋น์ค์ ๋ํ ๋จ์ ํ ์คํธ๋ DAO ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ์ฌ ์์ฑํ๊ณ ์ดํดํ๊ธฐ ์ฝ์ต๋๋ค.
JDBI 3์์ ๋น์ทํ ์์ ์ ์๋ํ์ง๋ง ๋ด ์๋น์ค ํด๋์ค์ ๊ตฌํ์ด ๋ ผ๋ฆฌ๋ฅผ ํฌํจํ๋ ๊ธฐ๋ณธ ๋ฉ์๋๊ฐ ์๋ ์ธํฐํ์ด์ค์ฌ์ผ ํ๋ค๋ ๊ฒ์ ์๋ฏธํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๊ธฐ๋ณธ ๋ฉ์๋๋ ์ต์ข ์ ์ผ๋ก ๋ง๋ค ์ ์๊ธฐ ๋๋ฌธ์ ์ฝ๋๊ฐ ๊ฐ๊ฒฐํ์ง ์๊ณ ํด๋์ค๋ฅผ ์ฌ์ฉํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ํ ํต์ ๋ ฅ์ด ๋จ์ด์ง๋๋ค.
์ต์ข ํธ๋์ญ์ ๋ฉ์๋๋ฅผ ๊ฐ๋๋ก JDBI 3์์ ์ฝ๋๋ฅผ ๊ตฌ์ฑํ ์ ์๋ ๋ฐฉ๋ฒ์ด ์์ต๋๊น?
์ธํฐํ์ด์ค ๋ฉ์๋๋ฅผ final๋ก ์ ์ํ ๋ฐฉ๋ฒ์ด ์๋ค๋ ๊ฒ์ด ๋ง์ต๋๋ค.
๊ทธ๋ฌ๋ @SqlQuery
, @SqlUpdate
๋ฑ๊ณผ ๋๋ฑํ ์์ฒด SQL ๋ฉ์๋ ์ฃผ์์ ์ ์ํ๊ณ ํด๋น ์ฃผ์์ผ๋ก ๋ฉ์๋์ ๋ํ ์ ์ ๊ตฌํ์ โโ์ ๊ณตํ ์ ์์ต๋๋ค.
๊ทธ๋ฌ๋
@SqlQuery
,@SqlUpdate
๋ฑ๊ณผ ๋๋ฑํ ์์ฒด SQL ๋ฉ์๋ ์ฃผ์์ ์ ์ํ๊ณ ํด๋น ์ฃผ์์ผ๋ก ๋ฉ์๋์ ๋ํ ์ ์ ๊ตฌํ์ โโ์ ๊ณตํ ์ ์์ต๋๋ค.
๋ต๋ณ์ ๊ฐ์ฌ๋๋ฆฝ๋๋ค. ๊ทธ๊ฒ ์ด๋ป๊ฒ ๋์์ด ๋๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค. ์ฌ๋ฌ DAO์ ์ฟผ๋ฆฌ๋ฅผ ํฌํจํ๋ ๋์ผํ ํธ๋์ญ์ ์์ ์คํํ๋ ๋ฐ ๊ถ์ฅ๋๋ ๋ฐฉ๋ฒ์ ๋ฌด์์ ๋๊น?
์ฌ๋ฌ DAO์์ ์ฟผ๋ฆฌ๋ฅผ ์ํํ์ง๋ง ๋์ผํ ํธ๋์ญ์ ์์ ์คํํ๋ ๋ฐฉ๋ฒ์ ๋ฌด์์ ๋๊น?
๊ฐ์ธ์ ์ผ๋ก ๋๋ ๋ค์๊ณผ ๊ฐ์ ๊ฒ์ ์ฌ์ฉํฉ๋๋ค.
interface Dao1 {
@SqlQuery("...")
void query1();
}
interface Dao2 {
@SqlQuery("...")
void query2();
}
interface JdbiServiceImpl extends Service {
<strong i="8">@CreateSqlObject</strong>
Dao1 dao1();
<strong i="9">@CreateSqlObject</strong>
Dao2 dao2();
<strong i="10">@Transaction</strong>
<strong i="11">@Override</strong>
void businessCase() {
dao1().query1();
dao2().query2();
}
}
Service service = handle.attach(JdbiServiceImpl.class);
service.businessCase();
์ด๋ฐ ์์ผ๋ก ๋๋ฅผ ์ํด ์ ์๋ํฉ๋๋ค. @CreateSqlObject ๋ ๊ธฐ๋ณธ์ ์ผ๋ก getter/setter์ ์ํ ์คํ๋ง์ ์ข ์์ฑ ์ฃผ์ ๊ณผ ๊ฐ์ต๋๋ค. ๋ด ์คํ๋ง ์ปจํ ์คํธ์ onDemand ์ธ์คํด์ค๋ฅผ bean์ผ๋ก ๋์ด ์ผ๋ฐ ์๋น์ค์ ๋๊ฐ์ด ์๋ํ๋ฏ๋ก ํธ์ถ์๋ jdbi ๋๋ ๊ตฌํ ์ธํฐํ์ด์ค์ ๋ํด ์ ํ์๊ฐ ์์ต๋๋ค.
๋น์ ์ด ๋ณด๋ ๋ฐํจํด ๋ชจ์์ StockReductionCase๋ CreateSqlObject๋ฅผ ์ฌ์ฉํ ์ค์ฒฉ๋ jdbi "์ข ์์ฑ ์ฃผ์ "์ ์์ ๋๋ค. ์๋น์ค ๊ตฌํ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ด๋ถ์ ์์ฒด ์ข ์์ฑ์ด ์์ต๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ๊ทธ ์์ฒด๋ก ์๋น์ค์ ๋๋ค. ์๋น์ค(์ฌ์ฌ์ฉ ๋ถ๊ฐ๋ฅํ ์ต์์ ๋ ผ๋ฆฌ) ๋ด๋ถ์ Cases(์ฌ๋ฌ ์์น์ ํ์)์ ์ฟผ๋ฆฌ๋ฅผ ๋ ์ค ํ๋์ ๋ฃ์์ผ๋ก์จ ์ํ ์ข ์์ฑ์ ํผํ๊ธฐ ์ํด Service ๋์ Case๋ผ๊ณ ๋ถ๋ฆ ๋๋ค.
@CreateSqlObject
, ํนํ onDemand()
์ ๊ฒฐํฉํ ๋ ํธ๋์ญ์
๋ฒ์๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ์ง์ ํ๋ ๋ฐ ์ฑ๊ณตํ๋ค๋ ํผํฉ ๋ณด๊ณ ์๋ฅผ ๋ค์์ต๋๋ค.
๋์ผํ ํธ๋์ญ์
์์ ์ฌ๋ฌ SQL ๊ฐ์ฒด๋ฅผ ์คํํ๋ ๊ฐ์ฅ ํ์คํ ๋ฐฉ๋ฒ์ Handle.inTransaction()
๋๋ Jdbi.inTransaction()
๋ฅผ ํตํด ํธ๋์ญ์
์ ์คํํ๋ ๊ฒ์
๋๋ค. ์ฝ๋ฐฑ ๋ด์์ Handle.attach()
๋ฅผ ํตํด ์์ฑ๋ ๋ชจ๋ DAO๋ ํธ๋ค ํธ๋์ญ์
์ ์ผ๋ถ๊ฐ ๋ฉ๋๋ค.
jdbi.useTransaction(handle -> {
Dao1 dao1 = handle.attach(Dao1.class);
Dao2 dao2 = handle.attach(Dao2.class);
dao1.doStuff();
dao2.doMoreStuff();
});
๋ต๋ณ ๊ฐ์ฌํฉ๋๋ค
@qualidafial ์ด๊ฒ์ ๋ด๊ฐ ๊ฐ์ผ ํ ๊ธธ์ฒ๋ผ ๋ณด์ด์ง๋ง ์๋น์ค ํด๋์ค์ ๋ํ ๋จ์ ํ
์คํธ๋ฅผ ์์ฑํ๊ธฐ ์ด๋ ต๊ฒ ๋ง๋ญ๋๋ค. Daos ์์ฒด๋ฅผ ์ธ์คํด์คํํ๋ฏ๋ก ๋จ์ ํ
์คํธ๋ฅผ ๋ชจ์ Daos๋ก ๋์ฒดํ ์ ์์ต๋๋ค.
@RealMarnes ๋ ๊ฐ์ฌํฉ๋๋ค. ์ด๊ฒ์ ๋ด๊ฐ ์๋ํ ๊ฒ๊ณผ ๋น์ทํด ๋ณด์ด์ง๋ง ์ฌ์ ์ํ ์ ์๋ ๊ธฐ๋ณธ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ๋ ๊ฒ์ ์ข์ํ์ง ์์ต๋๋ค.
@qualidafial ์ฌ๋ฌ dao ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ์๋น์ค ๋ฉ์๋์ jdbi์ @Transaction
์ฃผ์์ ์ฌ์ฉํ ์ ์์์ ํ์ธํ๊ณ ์ถ์ต๋๋ค.
์ด ๊ฐ์ ์ด ๋ง๋ค๋ฉด ๊ณต์ ๋ฌธ์์ ์ผ๋ถ๋ก ์ ๋๋ก ๋ฌธ์ํ๋์ง ์์ ์ด ๋์์ ๋งค์ฐ ์ํํฉ๋๋ค. ๋ง์ ๊ฐ๋ฐ์๊ฐ Spring ์คํ์ ๋ํ ๊ฒฝํ์ด ์๊ณ @Transactional
์ฃผ์์ ์ฌ์ฉํ๋ ๊ฒ์ ์ฌ๋ฌ DAO์์ ํธ๋์ญ์
์ ์ง์ํ๋ ๋งค์ฐ ํ์ค์ ์ธ ๋ฐฉ๋ฒ์
๋๋ค.
@svlada @Transaction
์ฃผ์ _only_๋ SQL ๊ฐ์ฒด์ ๋ฉ์๋์์ ์๋ํฉ๋๋ค. "์๋น์ค ๋ฉ์๋"๋ผ๊ณ ๋งํ ๋ Jdbi์ ์ํฅ์ ๋ฐ์ง ์๋ ์ผ๋ถ ๊ฐ์ฒด(์: ์ฃผ์
๋ ํด๋์ค)์ ์ฃผ์์ ์ฌ์ฉํ๊ณ ์๋ค๋ ์ธ์์ ๋ฐ์์ต๋๋ค.
ํ ์คํธ ์ค์ํธ์ ์:
<strong i="9">@Test</strong>
public void testInsertAndFind() {
Foo foo = handle.attach(Foo.class);
Something s = foo.insertAndFind(1, "Stephane");
assertThat(s).isEqualTo(new Something(1, "Stephane"));
}
<strong i="10">@Test</strong>
public void testTransactionPropagates() {
Foo foo = dbRule.getJdbi().open().attach(Foo.class);
assertThatExceptionOfType(Exception.class)
.isThrownBy(() -> foo.insertAndFail(1, "Jeff"));
Something n = foo.createBar().findById(1);
assertThat(n).isNull();
}
public interface Foo {
<strong i="11">@CreateSqlObject</strong>
Bar createBar();
@SqlUpdate("insert into something (id, name) values (:id, :name)")
int insert(@Bind("id") int id, @Bind("name") String name);
<strong i="12">@Transaction</strong>
default Something insertAndFind(int id, String name) {
insert(id, name);
return createBar().findById(id);
}
<strong i="13">@Transaction</strong>
default Something insertAndFail(int id, String name) {
insert(id, name);
return createBar().explode();
}
}
public interface Bar {
@SqlQuery("select id, name from something where id = :id")
Something findById(@Bind("id") int id);
default Something explode() {
throw new RuntimeException();
}
}
๋ํ onDemand()
+ @CreateSqlObject
์ ๋ํด ๋ช
ํํ ํ๊ณ ์ถ์ต๋๋ค.
@CreateSqlObject
DAO๋ ์์ ์์ ๊ฐ์ด DAO๋ฅผ ๋ง๋ DAO์ ๋ด๋ถ ๋ฉ์๋์์๋ง ์ฌ์ฉํ ์ ์์ต๋๋ค.fooDao.createBar().findById()
๋ฅผ ํธ์ถํ๋ฉด ์ฐ๊ฒฐ์ด ๋ซํ๋ค๋ ์์ธ๊ฐ ๋ฐ์ํฉ๋๋ค.์ด์ ๋ํด ๋ค์ ํ ๋ฒ ๋๊ธ์ ๋ฌ์ ์ฃ์กํฉ๋๋ค. ๋น์ ์ ๋ก๋๋งต์ ์ด๊ฒ์ ๋์์ด ๋ ๊ฒ์ด ์์ต๋๊น?
๋๋ ์์ง๋ ์ถ์ ํด๋์ค์์ CreateSqlObject๋ฅผ ์ฌ์ฉํ ์ ์๋ค๋ ๊ฒ์ด ์ ๋ง ๊ทธ๋ฆฌ์์. ์ธํฐํ์ด์ค์์ ๋ชจ๋ ์์ ์ ์ํํด์ผ ํ๋ ๊ฒ์ ์ฌ์ ํ โโ์ ํ์ ์ ๋๋ค. ์ข ์ข "์๋น์ค" ์ ํ์ ๋ฉ์๋๋ฅผ ํธ๋์ญ์ ๋ฐฉ์์ผ๋ก ๋ง๋ค๊ณ ์ถ์ง๋ง, ์ด๋ ๋ด ์๋น์ค ํด๋์ค๋ ๊ธฐ๋ณธ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ์ธํฐํ์ด์ค์ฌ์ผ ํ๋ค๋ ๊ฒ์ ์๋ฏธํ๋ฉฐ ๊ด์ฌ์ฌ ๋ถ๋ฆฌ, ๊ตฌ์ฒด์ ์ธ ์ต์ข ๋ฉ์๋ ๋ฑ์ ๋ช ํ์ฑ์ ์๊ธฐ ์์ํฉ๋๋ค.
@tamslinn ์ถ์ ํด๋์ค ๋์ ์ธํฐํ์ด์ค์ ๋ํ ๋ฌธ์ ์ ๊ดํ ํ, ๊ฐ๊น์ด ์์ผ ๋ด์ ๊ทธ ๊ฒฐ์ ์์ ๋์์ค์ง ์์ ๊ฒ์ด๋ผ๊ณ ์์ ํ๊ฒ ๋งํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค. Jdbi3๋ ์ธํฐํ์ด์ค๋ง ์ง์ํ๋ jdk ํ๋ก์๋ฅผ ์ฌ์ฉํฉ๋๋ค.
๋๋ cglib ๋๋ ์ด ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ์ผ๋ถ์ ๊ตฌ์ถ๋ ๋ณ๋์ ๊ธฐ์ฌ ๋ชจ๋์ด ์ ํ ๋ฌธ์ ๊ฐ ๋์ง ์๋๋ค๊ณ ์๊ฐํ์ง๋ง ์ง๊ธ ๋น์ฅ์ ๋ฌธ์ ๊ฐ ๋์ง ์์ต๋๋ค.
sqlobject ๊ณต๋ฆฌ๊ฐ ๊ทธ๋ ๊ฒ ์ ํฉํ์ง ์์ ๊ฒฝ์ฐ ํญ์ ์๋น์ค๋ฅผ jdbi์ ์ํด ํฅ์๋์ง ์์ ์ผ๋ฐ ํด๋์ค๋ก ๋ฆฌํฉํ ๋งํ ์ ์์ง๋ง ๋์ ์ ์ฐฝํ API๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด ์ฃผ์
๋ Jdbi
์ธ์คํด์ค๋ฅผ ๊ฐ์ง ์ ์์ต๋๋ค.
์ฐ๋ฆฌ์ ํธ๋์ญ์ ์ง์, ์จ๋๋งจ๋ ๋ฑ ์ฌ์ด์ ํ๋์ ์๋ ์ฃผ์ ์ ๊ดํด์๋, ๋น๋ก ์ฐ๋ฆฌ๊ฐ ์์ง ์ ๋ง๋ก ๊ตฌ์ฒด์ ์ธ ๊ณํ์ ๊ฐ์ง๊ณ ์๋ค๊ณ ์๊ฐํ์ง ์์ง๋ง, ๊ทธ๊ฒ์ ์์ ์ ์ ์ ๋ ์ด์ ์ ๋ง์ถ๊ณ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ์ ๋๋ฌํ๊ณ ์์ต๋๋ค.
์
๋ฐ์ดํธํด์ฃผ์
์ ๋๋จํ ๊ฐ์ฌํฉ๋๋ค. ํ๋ก์์ ๋ํด ์์ ํ ์๋ฏธ๊ฐ ์์ต๋๋ค.
์ ์๊ฒ ํน์ ํ ์ ํ์ JDBI ํด๋์ค ์ธ๋ถ์์ ํธ๋์ญ์
์ ์์/์ข
๋ฃํ ์ ์๋ค๋ ๊ฒ์
๋๋ค.
( @svlada ๊ฐ ์ธ๊ธํ๋ฏ์ด ๋ค๋ฅธ ํ๋ ์์ํฌ์์๋ ๋ ๋์ ์์ค์์ @Transactional
๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์
๋๋ค)
JDBI์ ๋ํ ๋ค๋ฅธ ๋ชจ๋ ๊ฒ์ด ์ ๋ง ๋ง์์ ๋ญ๋๋ค. ๊ทธ๋์ ๊ณ์ ์ฌ์ฉํ ๊ฒ์
๋๋ค. ์๋ง๋ ์๋น์ค ํด๋์ค์ ๋ง์กฑํ๋ ๋์์ธ ํจํด์ ์๊ฐํด๋ผ ๊ฒ์
๋๋ค. :)
์ด์ ๋ํด ๋ค์ ํ ๋ฒ ๋๊ธ์ ๋ฌ์ ์ฃ์กํฉ๋๋ค. ๋น์ ์ ๋ก๋๋งต์ ์ด๊ฒ์ ๋์์ด ๋ ๊ฒ์ด ์์ต๋๊น?
์ ํ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ์ด๊ฒ์ ๋ถ๋ช ํ ํผ๋์ ์์ธ์ด๋ฉฐ ์ฐ๋ฆฌ๊ฐ ์์ ํ๊ณ ์ถ์ ๊ฒ์ ๋๋ค. ์ฐ๋ฆฌ๋ ์ง๋๋ฒ์ ์ฐ๋ฆฌ๊ฐ ํ์ง ์์๊ธฐ ๋๋ฌธ์ ์ด๋ฒ์๋ ๊ทธ๊ฒ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ๊ธฐ๋ฅผ ์ ๋ง๋ก ์ํฉ๋๋ค. :)
( @svlada ์์ ์ธ๊ธํ๋ฏ์ด ๋ค๋ฅธ ํ๋ ์์ํฌ์์๋ @Transactional ์ ๋ ๋์ ์์ค์์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ ๋๋ค)
์, ํ์ง๋ง ๋ด๊ฐ ์ดํดํ๋ ํ, ์ด๋ ๋ชจ๋ DI ํ๋ ์์ํฌ(์: Spring)์ AOP ํํฌ๋ฅผ ํตํด ์ํ๋ฉ๋๋ค. JDBI๊ฐ ๋ชจ๋ ์๋น์ค ๊ฐ์ฒด๋ฅผ "๋ํ"ํ์ง ์๊ธฐ ๋๋ฌธ์ ์ฐ๋ฆฌ๊ฐ ์ง์ ์์ฑํ์ง ์์ ๊ฐ์ฒด์ ๋ํด AOP์ ๊ฐ์ ์๋ฃจ์
์ ์ ๊ณตํ ๊ธฐํ๊ฐ ์์ต๋๋ค. ์ด์ cglib
๊ตฌํ์กฐ์ฐจ๋ daos ์์ฒด์์ @Transactional
๋ง ์ ์ ์์๊ณ ๋ณ๋์ ์๋น์ค ํด๋์ค์์๋ ์๋ํ์ง ์์์ ๊ฒ์
๋๋ค.
๋์์ด ๋๋ค๋ฉด ๋ ๋์ ์์ค์์ ํธ๋์ญ์
์ ํ์ฉํ๊ธฐ ์ํด ์๋ฅผ ๋ค์ด Spring ๋ฐ/๋๋ Guice AOP ๋ฐ์ธ๋ฉ์ ์ถ๊ฐํ๋ ๊ฒ์ ๊ณ ๋ คํ ์ ์์ต๋๋ค. ์ด๊ฒ์ core
์ ์ผ๋ถ๊ฐ ์๋๋ผ spring
ํ์ฅ์ ์ผ๋ถ์
๋๋ค. ์ด๊ฒ์ ํต์ฌ ๊ฐ๋ฐ์๋ค์ด ๋ฐ์ด๋์ ๊ฒ ๊ฐ์ง๋ ์์ง๋ง ๊ธฐ์ฌ๋ ํฌํจ์ ์ํด ์ง์งํ๊ฒ ๊ณ ๋ ค๋ ๊ฒ์
๋๋ค. "๋ ๊น๋ํ" ๋ฐฉ์์ผ๋ก ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์๊น์?
์ฐ๋ฆฌ๋ ์ฃผ๋ก ํธํ์ฑ์ ์ํด cglib
์์ Proxy
๋ก ์ ํํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค. Proxy
๋ ์ง์๋๋ jdk API์ธ ๋ฐ๋ฉด cglib
(๋๋ ๋ณด๋ค ๊ตฌ์ฒด์ ์ผ๋ก asm
) ๋ชจ๋ ์ฃผ์ ๋ฆด๋ฆฌ์ค(8, 9, 11, ...์ ์ค๋จ๋จ)์ ํจ๊ป ์ค๋จ๋๋ ๊ฒฝํฅ์ด ์์ผ๋ฉฐ ์ด๋ ์ ์ง ๊ด๋ฆฌ์ ํฐ ๊ณจ์นซ๊ฑฐ๋ฆฌ๊ฐ ๋ฉ๋๋ค.
์๋ง๋ https://github.com/jdbi/jdbi/pull/1252 ๊ฐ ๊ด๋ จ์ด ์์ต๋๊น?
์๋ ,
@stevenschlansker ์ ๋ณด ๊ฐ์ฌํฉ๋๋ค. ๋๋ ์ค์ ๋ก ํ์ฌ ํ๋ก์ ํธ์์ JDBI์ ํจ๊ป Spring์ ์ฌ์ฉํ์ง ์๊ณ ์์ผ๋ฉฐ, ๋น๊ต๋ฅผ ์ํด ์ธ๊ธํ ๊ฒ๋ฟ์
๋๋ค. ๋๋ AOP๋ฅผ ์์ ํ ์ดํดํฉ๋๋ค. ๊ทธ๋ฅ ๋ด๊ฐ ์ํ๋ ๋ฐฉ์์ผ๋ก ์ฝ๋๋ฅผ ๋ถํ ํ ์ ์๋ค๋ ๊ฒ์ ์๋ฏธํ๋ ๋ฐฉ๋ฒ์ ์ฐพ์ผ๋ ค๊ณ ๋
ธ๋ ฅํ๋ ๊ฒ๋ฟ์
๋๋ค cglib
์ด์ ํ์ํ ๋ ์๋น์ค ํด๋์ค๋ฅผ ๊ตฌ์ฑํ์ฌ ํธ๋์ญ์ ๋ด์์ ๊ตฌ์ฑํ ์ ์๋ค๊ณ ์๊ฐํฉ๋๋ค.
try (Handle handle = jdbi.open()) {
handle.useTransaction(h -> {
AccountService accountService = new AccountServiceImpl(h.attach(AccountDao.class));
accountService.addAccount(a, u);
});
}
์ด๊ฒ์ ๋ด๊ฐ Mock Dao๋ก ์๋น์ค๋ฅผ ๋จ์ ํ ์คํธํ๊ณ , ์๋น์ค ๋ฉ์๋๋ฅผ ์ต์ข ์ ์ผ๋ก ์ ์งํ๊ณ , ํธ๋์ญ์ ๊ด๋ฆฌ๋ฅผ ์ํ ์ธํฐํ์ด์ค์ ๊ธฐ๋ณธ ๋ฉ์๋์ ์์กดํ์ง ์๊ณ , ์๋น์ค ํด๋์ค ์ธ์คํด์คํ์ ์ถ๊ฐ ์ค๋ฒํค๋๊ฐ ํฐ ์ํฅ์ ๋ฏธ์น์ง ์์์ผ ํจ์ ์๋ฏธํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋ง์ง๋ง ์ฃผ์์ ์ฝ๋ ์์ ์ ๋ํ ๋น ๋ฅธ ์๋ต: try
๋ธ๋ก์ ๊ฑด๋๋ฐ๊ณ jdbi.useTransaction()
๋ฅผ ์ง์ ํธ์ถํ ์ ์์ต๋๋ค. ์ด ๋ฉ์๋๋ ์ฝ๋ฐฑ์ด ๋ฐํ๋ ๋ ์๋์ผ๋ก ๋ซํ๋ ์์ ํธ๋ค์ ํ ๋นํฉ๋๋ค.
์๋ ํ์ธ์ ์ฌ๋ฌ๋ถ, PR #1579๊ฐ ์์ต๋๋ค -- jdbi 3.10.0์์ CreateSqlObject์ onDemand๋ (๋ง์นจ๋ด) ์ ์๋ํด์ผ ํฉ๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
์ ํ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ์ด๊ฒ์ ๋ถ๋ช ํ ํผ๋์ ์์ธ์ด๋ฉฐ ์ฐ๋ฆฌ๊ฐ ์์ ํ๊ณ ์ถ์ ๊ฒ์ ๋๋ค. ์ฐ๋ฆฌ๋ ์ง๋๋ฒ์ ์ฐ๋ฆฌ๊ฐ ํ์ง ์์๊ธฐ ๋๋ฌธ์ ์ด๋ฒ์๋ ๊ทธ๊ฒ์ ์ฌ๋ฐ๋ฅด๊ฒ ์ฒ๋ฆฌํ๊ธฐ๋ฅผ ์ ๋ง๋ก ์ํฉ๋๋ค. :)
์, ํ์ง๋ง ๋ด๊ฐ ์ดํดํ๋ ํ, ์ด๋ ๋ชจ๋ DI ํ๋ ์์ํฌ(์: Spring)์ AOP ํํฌ๋ฅผ ํตํด ์ํ๋ฉ๋๋ค. JDBI๊ฐ ๋ชจ๋ ์๋น์ค ๊ฐ์ฒด๋ฅผ "๋ํ"ํ์ง ์๊ธฐ ๋๋ฌธ์ ์ฐ๋ฆฌ๊ฐ ์ง์ ์์ฑํ์ง ์์ ๊ฐ์ฒด์ ๋ํด AOP์ ๊ฐ์ ์๋ฃจ์ ์ ์ ๊ณตํ ๊ธฐํ๊ฐ ์์ต๋๋ค. ์ด์
cglib
๊ตฌํ์กฐ์ฐจ๋ daos ์์ฒด์์@Transactional
๋ง ์ ์ ์์๊ณ ๋ณ๋์ ์๋น์ค ํด๋์ค์์๋ ์๋ํ์ง ์์์ ๊ฒ์ ๋๋ค.๋์์ด ๋๋ค๋ฉด ๋ ๋์ ์์ค์์ ํธ๋์ญ์ ์ ํ์ฉํ๊ธฐ ์ํด ์๋ฅผ ๋ค์ด Spring ๋ฐ/๋๋ Guice AOP ๋ฐ์ธ๋ฉ์ ์ถ๊ฐํ๋ ๊ฒ์ ๊ณ ๋ คํ ์ ์์ต๋๋ค. ์ด๊ฒ์
core
์ ์ผ๋ถ๊ฐ ์๋๋ผspring
ํ์ฅ์ ์ผ๋ถ์ ๋๋ค. ์ด๊ฒ์ ํต์ฌ ๊ฐ๋ฐ์๋ค์ด ๋ฐ์ด๋์ ๊ฒ ๊ฐ์ง๋ ์์ง๋ง ๊ธฐ์ฌ๋ ํฌํจ์ ์ํด ์ง์งํ๊ฒ ๊ณ ๋ ค๋ ๊ฒ์ ๋๋ค. "๋ ๊น๋ํ" ๋ฐฉ์์ผ๋ก ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์๊น์?์ฐ๋ฆฌ๋ ์ฃผ๋ก ํธํ์ฑ์ ์ํด
cglib
์์Proxy
๋ก ์ ํํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค.Proxy
๋ ์ง์๋๋ jdk API์ธ ๋ฐ๋ฉดcglib
(๋๋ ๋ณด๋ค ๊ตฌ์ฒด์ ์ผ๋กasm
) ๋ชจ๋ ์ฃผ์ ๋ฆด๋ฆฌ์ค(8, 9, 11, ...์ ์ค๋จ๋จ)์ ํจ๊ป ์ค๋จ๋๋ ๊ฒฝํฅ์ด ์์ผ๋ฉฐ ์ด๋ ์ ์ง ๊ด๋ฆฌ์ ํฐ ๊ณจ์นซ๊ฑฐ๋ฆฌ๊ฐ ๋ฉ๋๋ค.