谷本 心 in せろ部屋

はてなダイアリーから引っ越してきました

SqlTemplateっていうJdbcTemplateのラッパーを作ってみました。

SQLが書きたいんや!」という想いのもと、
Spring Bootと組み合わせて簡単に使える、
JdbcTemplateのラッパーライブラリを勢いで作ってみました。


GitHubに置いています。
https://github.com/cero-t/sqltemplate


JdbcTemplate / NamedParameterJdbcTemplateをベースにして、
 1. SQLファイルが使えること
 2. Date and Time APIに対応すること
 3. publicフィールドに対応すること
 4. APIが今風であること
の4つを目的にして作りました。


それならMirageでいいんじゃね? という想いは消えませんが、
Spring標準機能のみを使うことによる、政治的な使いやすさを取りました。


作りましたって言っても、ただのラッパーですので
ソースコードはすっごく小さくて、空行とコメントを入れても600行ぐらいしかありません。
ジェバンニでなくとも一晩でやってくれるぐらいのサイズです。

利用イメージ

exampleのプロジェクトも作っておきました。
https://github.com/cero-t/sqltemplate/tree/master/sqltemplate-example


使う側のソースコードは、こんな感じになります。

@Component
public class SampleProcess {
    @Autowired
    SqlTemplate query;

    public void process() {
        List<Emp> emps = query.forList("sql/selectAll.sql", Emp.class);
        emps.forEach(e -> System.out.println(e.ename));

        Emp emp = query.forObject("sql/selectByEmpno.sql", Emp.class, 7839);
        System.out.println(emp.ename);

        Map<String, Object> condition = new HashMap<>();
        condition.put("deptno", 30);
        condition.put("job", "SALESMAN");
        emps = query.forList("sql/selectByCondition.sql", Emp.class, condition);
        emps.forEach(e -> System.out.println(e.ename));
    }
}

forObjectで1件検索、forListで複数件検索。
第一引数がSQLファイル名で、第二引数が戻り値の型、
第三引数以降がSQLにバインドするパラメータです。


ちなみにIntelliJを使っていると、ファイル名にカーソルをあわせて
Ctrl (Command) + クリックでSQLファイルを開けるのが嬉しいですね。


SQLファイルは、こんな感じになります。

select
    *
from
    emp
inner join dept
    on emp.deptno = dept.deptno
where
    dept.deptno = :deptno
    and emp.job = :job

第三引数に指定したMapやEntityの値を、SQLのパラメータとしてバインドします。
内部的にはNamedParameterJdbcTemplateに処理を委譲しているだけです。


名前を指定せずに ? を使うこともできます。

select
    *
from
    emp
where
    empno = ?

第三引数以降に指定した任意の数の基本型(String、Date、Number)をバインドします。
こちらは内部的にJdbcTemplateに委譲しているだけです。

使い方

使うための設定は一つだけ。
@Configurationアノテーションをつけたクラスに
SqlTemplateを返すメソッドを作り、@Beanアノテーションをつけます。

@Bean
SqlTemplate sqlTemplate(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
    return new SqlTemplate(jdbcTemplate, namedParameterJdbcTemplate);
}

この初期化の仕方は [twitter:@making] がpullリクエストで教えてくれました。
ありがとう!


ちなみにSqlTemplateのコンストラクタの第三引数には、
SQLファイルを読み込む際のテンプレートエンジンを指定することができます。
たとえばここで2-way SQLパーサーを指定すれば、
2-way SQLにも対応できるというスンポーです。


現時点でもFreeMarkerを使うことができるようにしているんですが、
一度も動作確認してないので、動くかどうか分かりません。てへぺろ

いまあるAPI一覧

用意したメソッドの一覧は、以下になります。

<T> T forObject(String fileName, Class<T> clazz, Object... args)
<T> T forObject(String fileName, Class<T> clazz, Map<String, Object> params)
<T> T forObject(String fileName, Class<T> clazz, Object entity)

<T> List<T> forList(String fileName, Class<T> clazz, Object... args)
<T> List<T> forList(String fileName, Class<T> clazz, Map<String, Object> params)
<T> List<T> forList(String fileName, Class<T> clazz, Object entity)

int update(String fileName, Map<String, Object> params)
int update(String fileName, Object entity)
int update(String fileName, Object... args)

戻り値をMapにする「forMap」とか
実案件では欠かせない「batchUpdate」は、まだ作っていません。
委譲するだけなので、作っちゃえばいいんですけどね。

制限事項的なやつ

とりあえずコンセプト実証した程度なので、色々できません。
 1. 上に書いた通り、forMapとbatchUpdateがありません。
 2. JSR-310を使っているので、Java8でしか動きません。
 3. publicフィールドのないgetter/setterベースのJavaBeansは使えません。
 4. パッケージ名が変です。
 5. mvnリポジトリに置いてないです。
 6. README.mdちゃんと書け。


ひとまずは「こんなコンセプトでサクッとできたよ! 」っていう位置づけです。
ご自由に参考にしてください!