Java
ORM
永続化
Speedment

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

前ポスト

前置き

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

環境

テーブル構成

employeeテーブルからpostテーブルにID紐づけ

対応範囲

ORM Transaction Data Model DSL
×

○:対応
×:非対応

所感

  • maven環境が整ってないと手の出しようがなかったけれど、環境が整ったらさっくりできた
  • Stream操作がDB操作と一体化しているので慣れが必要
  • 生成されるコードが大分ある、どれがどれかと把握するのに少し手間取るぐらい
  • 公式に「JOIN:flatMap()」と記載があるのだけれど、Java Magazinでいわく、LazyFetchでPreFetchは実装予定とのこと

サンプル

単テーブル検索

全件検索

Main.java
OrmSpeedmentApplication app = new OrmSpeedmentApplicationBuilder().withPassword("pass").build();
app.getOrThrow(EmployeeManager.class).stream().forEach(Main::sysout);
app.stop();
Main#sysout(Employee).java
public static void sysout(Employee e) {
    System.out.format("%1s: %2s, %3s, %4s\n", e.getId(), e.getFirstName(), e.getMiddleName(), e.getLastName());
}

主キー検索

Main.java
app.getOrThrow(EmployeeManager.class).stream()
    .filter(Employee.ID.equal(BigDecimal.ONE))
    .forEach(Main::sysout);

テーブル結合

Main.java
app.getOrThrow(EmployeeManager.class)
        .stream()
        .peek(Main::sysout)
        .flatMap(e -> app.getOrThrow(PostManager.class).stream().filter(Post.EMPLOYEE_ID.equal(e.getId())))
        .forEach(Main::sysout);

// トランザクション使う版
app.getOrThrow(TransactionComponent.class).createTransactionHandler().createAndAccept(tx -> {
            app.getOrThrow(EmployeeManager.class)
                    .stream()
                    .peek(Main::sysout)
                    .flatMap(e -> {
                        return app.getOrThrow(PostManager.class)
                                .stream()
                                .filter(Post.EMPLOYEE_ID.equal(e.getId()));
                    })
                    .forEach(Main::sysout);
            tx.rollback();
        });
Main#sysout(Post).java
public static void sysout(Post p) {
    System.out.format("\t%1s: %2s, %3s\n", p.getId(), p.getEmployeeId(), p.getName());
}

要点

  • Sreamの操作がResultSetの操作に直結している
    • つまりStreamの終端操作段階で操作の最適化が実行される
    • 現段階ではテーブル結合の際に別Streamから操作する都合上LazyFetchしかできないと思われる
      • ……そもそもこれは結合していない気がする、もっと正しい作法があるのかしら
  • JavaMagazineに載るぐらいには注目株
  • このStreamを安易にreturnしたり引数にしたりしてはならない、絶対にだ
  • Stream操作毎にSQLに関連付けされているイメージなので少し習熟が必要
  • パフォーマンスについては上記の件もあるため少々不安が残る、要調査

ハマったポイント

  • トランザクション使おうと思ったらQuick Startではいきなり「txHandler.createAndAccept(tx -> {」とかなってた
    • txHandlerはどこから来たんだよ、となり少し探す羽目に

後ポスト

まだない。

参考記事