2017年度 Java 永続化フレームワークについての考察(4) jOOQ

#前ポスト
- [2017年度 Java 永続化フレームワークについての考察(1)](http://qiita.com/shiroma_yuki/items/8d434862bba072bff264)
- [2017年度 Java 永続化フレームワークについての考察(2) Doma2](http://qiita.com/shiroma_yuki/items/d0e3b319626f4278fc6f)
- [2017年度 Java 永続化フレームワークについての推測(3) Reladomo](https://qiita.com/shiroma_yuki/items/1e3d83202afa6cf5dbef)

#前置き
隙間時間を利用して書いているので精度の甘い箇所があれば、ご指摘いただけると幸いです。
まずEOLであるものは除外。
有償の機能については検討対象に含むが、実際に使用はしません、懐の問題で。
「まぁ、たぶん明記されてなくてもPostgreならいけるだろ」ぐらいの間抜けな理由で使用DBはPostgreに固定。

#環境
- PostgreSQL 9.6.3
- [jOOQ 3.10.1](https://www.jooq.org/download/)
- Java 64bit 8u144
- なんかmavenもgitも繋がらないので手動DL、もろもろ直るかも

#テーブル構成
![employeeテーブルからpostテーブルにID紐づけ](https://qiita-image-store.s3.amazonaws.com/0/48666/ec265f75-ad54-4f56-a5f8-2b460723047a.png)

#所感
- しこたまわかりやすい、DSLでIDEからサポートされる外付け知識感はともかく、生成されるソース群と方法が直感的
- Record&lt;C1, C2, C3, ...&gt;みたいなカラムの数だけ型パラメータを持つ行クラスが居る
- 上記の型パラメータで制限されるため、コーディング段階で型セーフに取り扱うことができる

#サンプル
##単テーブル検索
###全件検索
```Main.java
DSLContext create = DSL.using(connection, SQLDialect.POSTGRES_9_4);

create.insertInto(Employee.EMPLOYEE).values(BigDecimal.ZERO, "太郎", "John", "山田").execute();
create.insertInto(Employee.EMPLOYEE).values(BigDecimal.ONE,  "次郎", "Smith", "佐藤").execute();

Result<Record> result = create.select().from(Employee.EMPLOYEE).fetch();

for (Record record : result) {
    System.out.println(
        record.get(Employee.EMPLOYEE.FIRST_NAME)
        + " "
        + record.get(Employee.EMPLOYEE.MIDDLE_NAME)
        + " "
        + record.get(Employee.EMPLOYEE.LAST_NAME));
}
```
###主キー検索
```Main.java
Result<Record> result = create.select()
        .from(Employee.EMPLOYEE)
        .where(Employee.EMPLOYEE.ID.eq(BigDecimal.ONE.intValue()))
        .fetch();
}
```
###Stream使う
```Main.java
create.select()
        .from(Employee.EMPLOYEE)
        .where(Employee.EMPLOYEE.ID.eq(BigDecimal.ONE.intValue()))
        .fetch()
        .stream()
        .forEach(record -> {
                System.out.println(
                        record.get(Employee.EMPLOYEE.FIRST_NAME)
                        + " "
                        + record.get(Employee.EMPLOYEE.MIDDLE_NAME)
                        + " "
                        + record.get(Employee.EMPLOYEE.LAST_NAME));});
```

##テーブル結合
```Main.java
create.insertInto(Post.POST).columns(Post.POST.ID, Post.POST.EMPLOYEE_ID, Post.POST.NAME)
        .values((short)0, 0, "代表")
        .values((short)1, 0, "取締役")
        .values((short)2, 1, "ヒラ").execute();

create.select()
        .from(Employee.EMPLOYEE)
        .join(Post.POST)
        .on(Employee.EMPLOYEE.ID.eq(Post.POST.EMPLOYEE_ID))
        .where(Employee.EMPLOYEE.ID.eq(BigDecimal.ZERO.intValue()))
        .fetch()
        .stream()
        .forEach(record -> {
                System.out.println(
                        record.get(Post.POST.NAME)
                        + " "
                        + record.get(Employee.EMPLOYEE.FIRST_NAME)
                        + " "
                        + record.get(Employee.EMPLOYEE.MIDDLE_NAME)
                        + " "
                        + record.get(Employee.EMPLOYEE.LAST_NAME));});
```

##トランザクション処理
```Main.java
create.transaction(t -> {
    DSLContext ctx = DSL.using(t);
    ctx.insertInto(Employee.EMPLOYEE).values(BigDecimal.valueOf(2L), "f", "m", "l").execute();
    ctx.select().from(Employee.EMPLOYEE).fetch();
});
```

#要点
- DB2Codeな生成形式
- DSLによる型セーフな記述サポート
- テーブル結合時に専用のエンティティを用意する面倒がない
- 楽 is 楽
- OracleとかSQL Serverは商用ライセンスです

#ハマったポイント
特になし、使用感は非常にやさしい

#後ポスト
今はまだない

#参考記事
- [The jOOQ User Manual. Multiple Pages](https://www.jooq.org/doc/3.10/manual/)