谷本 心 in せろ部屋

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

Bootiful SQL Templateという名前にしてMavenリポジトリで公開しました。

年末に作ったSqlTemplateですが、自分の仕事でも使いたいっていうか使ってるので、
ソースコードを多重管理しなくて済むよう、Mavenリポジトリで公開することにしました。


こんな指定で使えます。

    <dependencies>
        <dependency>
            <groupId>ninja.cero.bootiful-sqltemplate</groupId>
            <artifactId>bootiful-sqltemplate-core</artifactId>
            <version>1.0.1</version>
        </dependency>
        ...
    </dependencies>

ドメイン名は、ninja.cero-tにしようかと思ったんですが、
ハイフンとかアンダースコアとかをURLに入れるな勢が多いので、
ninja.ceroっていうちょっと語呂のよくないドメイン名になっています。


そんな話はどうでも良くて。


ドキュメントはこれから書いていきますが、
今すぐ試してくれるという方は、テストを見てもらうのが良いと思います。
https://github.com/cero-t/sqltemplate/blob/master/sqltemplate-core/src/test/


Spring Bootでの利用を前提としているので、まずはBean定義をします。
https://github.com/cero-t/sqltemplate/blob/master/sqltemplate-core/src/test/java/ninja/cero/sqltemplate/test/TestConfig.java

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

Spring BootじゃないSpringでも使えると思いますが、まったく試したことがありません。


呼び出し部分は、こんな感じ。
https://github.com/cero-t/sqltemplate/blob/master/sqltemplate-core/src/test/java/ninja/cero/sqltemplate/core/SqlTemplateTest.java

    @Test
    public void testForList_MapArg() {
        Map<String, Object> param = new HashMap<>();
        param.put("deptno", 30);
        param.put("job", "SALESMAN");

        List<Emp> result = template.forList("sql/selectByParam.sql", Emp.class, param);
        // 略
    }

    @Test
    public void testForList_MultiArg() {
        List<Emp> result = template.forList("sql/selectByArgs.sql", Emp.class, 30, "SALESMAN");
        // 略
    }

複数オブジェクトを返すforListと、単一オブジェクトを返すforObjectメソッドがあり、
パラメータに使える引数は「Map」「ValueObject」「可変長引数」の3種類です。


肝心のSQLテンプレートですが、バインド変数には :name か ? の好みのほうを使えます。
https://github.com/cero-t/sqltemplate/blob/master/sqltemplate-core/src/test/resources/sql/selectByParam.sql

SELECT
        *
    FROM
        emp
    WHERE
        deptno = :deptno
        AND job = :job
    ORDER BY
        empno

:name 形式のパラメータを使う場合、引数は「Map」か「ValueObject」になります。


https://github.com/cero-t/sqltemplate/blob/master/sqltemplate-core/src/test/resources/sql/selectByArgs.sql

SELECT
        *
    FROM
        emp
    WHERE
        deptno = ?
        AND job = ?
    ORDER BY
        empno

? をパラメータとして使う場合、引数は「可変長引数」になります。直感通りだと思います。


また、SQLファイルを事前処理するためのテンプレートエンジンとして
FreeMarkerを組み合わせて使うこともできます。
https://github.com/cero-t/sqltemplate/blob/master/sqltemplate-core/src/test/java/ninja/cero/sqltemplate/core/FreeMarkerTest.java

@SpringBootApplication
public class FreeMarkerConfig {
    @Bean
    SqlTemplate sqlTemplate(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
        return new SqlTemplate(jdbcTemplate, namedParameterJdbcTemplate, new FreeMarker());
    }
}


FreeMarkerを使ったテンプレートは、こんな書き方になります。
https://github.com/cero-t/sqltemplate/blob/master/sqltemplate-core/src/test/resources/ftl/selectByArgs.sql

SELECT
        *
    FROM
        emp
    WHERE
        1 = 1
<#if job??>
        AND job = :job
</#if>
<#if mgr??>
        AND mgr = :mgr
</#if>
<#if deptno??>
        AND deptno = :deptno
</#if>

FreeMarkerが先に事前処理をしてから、SQLテンプレートが解釈される形になります。


実装としては、ただのJdbcTemplateとNamedParameterJdbcTemplateのラッパーなので
たいした事はやっていません。
ただ、こんなシンプルなSQLテンプレートエンジンが欲しかったので、ひとまず形にしました。


SQLガ、イチバンヤー!