メニューを閉じる

テクノデジタルグループ

メニューを開く

2018.04.20

プログラミング

Domaの好きなとこ3選

こんにちは、MTです。
今回は、JavaのDBアクセスライブラリ「Doma」の好きなところを3つ紹介させてください。

※実際にDomaを使用するための設定等は割愛させていただきます。

アジェンダ

  • ・Domaとは
  • ・好きなところ3選
    • ・2waySQLである
    • ・エンティティの項目に ValueObject が使える
    • ・Collect検索機能
  • ・最後に

Domaとは

Doma = Domain Oriented Database MApping Frameworkの略。
Java製のDBアクセスライブラリになります。(ORマッパーというよりは、Resultマッパー)

MyBatisのようにDaoとSQLファイルを用意して、クエリの発行結果をエンティティにマッピングするタイプのライブラリです。(なのでResultマッパー)
現在はバージョン2までで、現在バージョン3の製作が進んでいるところです。

好きなところ3選

2waySQLである

2waySQLが何なのかを説明しておくと、「素のままでも、アプリケーションからも使用することもできるSQL」を指します。
student デーブルから id を指定してレコードを取得する場合、アプリケーション側で作成するSQLは以下のようになります。

SELECT 
    /*%expand*/*
FROM
    student
WHERE
    id = /* id */0
;

%expand はDomaの機能で、エンティティの全項目を展開してくれるものです。

素のSQLとしては /* ~ */ で囲われた部分はコメント扱いになるので、DBクライアント等からそのままクエリを発行することが可能です。
また、アプリケーション(Doma)から発行されるクエリは

SELECT 
    id, first_name, last_name, ... // エンティティの項目が展開される
FROM
    student
WHERE
    id = ? // プレースホルダに置き換わる
;

となります。
このように、素のSQLとしても、アプリケーション用としても使用できるため開発効率は良いはずです。
※勿論、実際にアプリケーションから発行されるクエリの妥当性等はテストする必要があります。

エンティティの項目に ValueObject が使える

少し話は変わりますが、こんな経験はありませんか?

// 生徒エンティティ
@Entity
public class Student {
    private long id;
    private String firstName;
    private String lastName;
    private int age;
    // getter, setter は省略
}
// 生徒の情報を登録する処理
InputForm form = // 画面から入力された情報

Student student = new Student();
student.setId(form.getStudentId());
student.setFirstName(form.getStudentFirstName());
student.setLastName(form.getStudetnFirstName()); // lastName に firstName 入れてる。。。
student.setAge(form.getStudentAge());

studentDao.insert(student);

上記のプログラムでは firstNamelastName の型が同じ String なので、コンパイルエラーにはなりません。
人間からすれば違う項目であることは分かりますが、それは人間の話。
コンピュータ(コンパイラ)からすれば、どちらも String なので正しいとしか判断してくれません。
このように、異なる項目に設定してしまい、実行後のテーブルを確認して初めてミスに気付くパターン、経験ありませんか?

Domaは ValueObject が使用できるので、上記のようなミスを防ぐことができます。
上記の Student エンティティを、ValueObjectの項目に置き換えると以下のようになります。

@Entity
public class Student {
    private ID id;
    private FirstName firstName;
    private LastName lastName;
    private Age age;
    // getter, setter は省略
}

このように ValueObject を使用することで、間違った項目に値を設定した場合でもコンパイルエラーになります。

InputForm form = // 画面から入力された情報(InputFormもValueObjectの項目を保持していると想定)

Student student = new Student();
student.setId(form.getStudentId());
student.setFirstName(form.getStudentFirstName());
student.setLastName(form.getStudetnFirstName()); 
student.setAge(form.getStudentAge());

studentDao.insert(student);
型 Student のメソッド setLastName(LastName) は引数 (FirstName) に適用できません

項目の数だけ ValueObject を作成する必要がありますが、作成するコスト以上のメリット(型による恩恵)があると思っています。

Collect検索機能

Domaには「Collect検索」という機能が備わっています。
「Collect検索」とは

検索結果を java.util.Collector で処理したい場合は、コレクト検索を利用できます。

です。
Domaでは複数件検索の結果は、メソッドの戻り値を List<T> にします。

@Dao
public interface StudentDao {
    @Select
    List<Student> findAll();
}

こんな感じ。
この場合 StudentDao#findAllList<Student> しか返せませんが、
年齢でグルーピングした Map<Age, List<Student>> で受け取りたい場合はDaoの呼び出し元で Map への変換を行う必要があります。

Map<Age, List<Student>> studentMap 
    = studentDao.findAll().stream().collect(Collectors.groupingBy(Student::getAge));

単に Map で扱いたいだけなのに、わざわざ変換処理を噛ますのは面倒ですね。
そこで「Collect検索」機能です。

「Collect検索」機能は、Daoメソッドの引数に Collector を渡すことで任意の型で結果を受け取ることができるようになります。
まずDaoメソッド findAllCollector を受け取るようにします。

@Dao
public interface StudentDao {
    @Select(strategy = SelectType.COLLECT)
    <R> R findAll(final Collector<Student, ?, R> collector);
}

@Select(strategy = SelectType.COLLECT) の部分は「Collect検索」を使用する宣言だと思ってください。
findAll の戻り値は任意型にしたいので R 、引数には Collector<Student, ?, R> を受け取るようにします。
これで「Collect検索」を利用することができます。

Map<Age, List<Student>> studentMap = studentDao.findAll(Collectors.groupingBy(Student::getAge));

大分スッキリしました。
また、最初と同じく List<Student> で受け取りたい場合は List に変換する Collector を渡せばいいので

List<Student> studentList = studentDao.findAll(Collectors.toList());

こうなります。
Collector を作ってしまえば、様々な型で受け取ることができるため、柔軟性が高くなります。
「Collecto検索」素敵ですね。

最後に

他にも好きな点はあるのですが、今回は3点紹介させていただきました。
Domaは静的型付け言語のメリットを生かすことができるライブラリですので、是非使っていただきたいです。


【記事への感想募集中!】

記事への感想・ご意見がありましたら、ぜひフォームからご投稿ください!
  • こんな記事が読んでみたい、こんなことが知りたい、調べてほしい!という意見も募集中!
  • いただいた感想は今後の記事に活かしたいと思います!

感想フォームはこちら


【テクノデジタルではエンジニア/デザイナーを積極採用中です!】

下記項目に1つでも当てはまる方は是非、詳細ページへ!
  • 自分でアプリを作ってみたい
  • ITで世の中にワクワクを生み出したい
  • 使いやすさ、デザインにこだわったWebサイトを開発したい

採用情報の詳細はこちら


Qangaroo(カンガルー)

  • 徹底した見やすさと優れた操作性で、テストの「見える化」を実現。
  • テストの進捗が見える。開発がスマートに進む。
  • クラウド型テスト管理ツール『Qangaroo(カンガルー)』

【テクノデジタルのインフラサービス】

当社では、多数のサービスの開発実績を活かし、
アプリケーションのパフォーマンスを最大限に引き出すインフラ設計・構築を行います。
AWSなどへのクラウド移行、既存インフラの監視・運用保守も承りますので、ぜひご相談ください。
詳細は下記ページをご覧ください。

https://www.tcdigital.jp/infrastructure/

最近の記事