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

#前ポスト
- [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)
- [2017年度 Java 永続化フレームワークについての考察(4) jOOQ](https://qiita.com/shiroma_yuki/items/1f64cac07afc745579a5)
- [2017年度 Java 永続化フレームワークについての考察(5) Iciql](https://qiita.com/shiroma_yuki/items/42e2cf97076c964e8629)

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

#環境
- PostgreSQL 9.6.3
- [Ebean 11.5.1](http://ebean-orm.github.io/)
- Java 64bit 8u144
- 片端からproxy設定したらついにmavenが動いた、やったぜ

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


#対応範囲
|ORM|Transaction|Data Model|DSL|
|:-:|:---------:|:--------:|:-:|
|○|○|×|○|
○:対応
×:非対応

#所感
- エンティティの自動生成がないのツラい
- 使用感はほぼJPA実装、JPA依存だしね
    - ただしセッションレス、エンティティはトランザクション範囲内でキャッシュされるもよう
- 設定の少なさ、わかりやすさは凄い
- [Doma2でも使われていた注釈処理が使用されている](http://qiita.com/shiroma_yuki/items/d0e3b319626f4278fc6f)
    - が、enhance(※コンパイル済みコード拡張ぐらいの意味でとらえてますが)の有無ぐらいでしかまだ見たことない
    - あんまり恩恵を感じないなぁ、とはなります

#サンプル
##単テーブル検索
###全件検索
```Main.java
EbeanServer server = Ebean.getServer("example");
server.beginTransaction();
server.find(Employee.class).findList().stream().forEach(e -> {
    System.out.println(e.id + ":" + e.first_name + " " + e.middle_name + " " + e.last_name);
});
server.endTransaction();
```

###主キー検索
```Main.java
// ノーマルなヤツ
server.find(Employee.class).where().eq("id", Long.valueOf(1)).findList().stream().forEach(e -> {
    System.out.println(e.id + ":" + e.first_name + " " + e.middle_name + " " + e.last_name);
});

// 型セーフなヤツ
server.find(Employee.class).where().idEq(Long.valueOf(1)).findList().stream().forEach(e -> {
    System.out.println(e.id + ":" + e.first_name + " " + e.middle_name + " " + e.last_name);
});

// 型セーフクエリビーンを使うヤツ
new QEmployee().id.eq(Long.valueOf(1)).findList().stream().forEach(e -> {
    System.out.println(e.id + ":" + e.first_name + " " + e.middle_name + " " + e.last_name);
});
```

##テーブル結合
```Main.java
server.find(Employee.class).findList().stream().forEach(e -> {
    System.out.format("%1s:%2s %3s %4s\n", e.id, e.first_name, e.middle_name, e.last_name);
    e.posts.stream().forEach(p -> {
        System.out.format("\t%1s: %2s, %3s\n", p.id, p.employee_id, p.name);
    });
});
```
```Employee.java
@Entity
@Table(name="employee")
public class Employee extends Model {
    @Id
    @GeneratedValue(strategy= GenerationType.SEQUENCE)
    public long id;
    public String first_name;
    public String middle_name;
    public String last_name;

    @OneToMany(mappedBy = "employee")
    public List<Post> posts;
}
```
```Post.java
@Entity
@Table(name="post")
public class Post {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    public long id;
    public long employee_id;
    public String name;

    @ManyToOne(optional=false)
    public Employee employee;
}
```

#要点
- ほぼJPA実装なのでJPA慣れしている開発者なら使いやすく、また記述が簡便になる
    - 翻ってJPA慣れは必要
- SpringやPlayに対応しているため、当該フレームワークを使用する際には検討の価値がある
- n+1問題についてもSQL発行時に最適化するとのこと、これについては後に確認

#ハマったポイント
- cleanして実行したら「Bean class XXXXX is not enhanced?」とか怒られる
    - 本家見たら「Documentation/Setup/Enhanced」ってしっかり書いてありますがな……
    - maven plugin入れてclean, ビルド, enhance, 実行で解決

#後ポスト
まだない。

#参考記事
- [Ebean ORM - Java/Kotlin/JVM](http://ebean-orm.github.io/)
- [20170708 Ebeanのご紹介(O/Rマッパー勉強会 in 大都会)](https://www.slideshare.net/kunst1080/20170708-ebeanor-in)