doma2でデータベース連携(Spring boot)

※アウトプット用メモですので他記事と被っている箇所があるかもしれません。悪しからず。

#Doma2とは
データベースアクセスに使います。特徴としては以下。
[公式(https://doma.readthedocs.io/en/stable/)](https://doma.readthedocs.io/en/stable/)によると

>Doma 2は、Java 8以降用のデータベースアクセスフレームワークです。Domaにはさまざまな長所があります。

>・注釈処理を使用してコンパイル時にソースコードを検証して生成します。
・データベース列をユーザー定義のJavaオブジェクトにマップします。
・「2-way SQL」と呼ばれるSQLテンプレートを使用します。
・java.time.LocalDate、 java.util.Optionalおよびjava.util.stream.StreamなどJava 8で導入されたクラスをサポート
・他のライブラリに依存しない

ほとんど翻訳のままですので少し日本語がおかしいかもしれません。。。


大きな利点としては以下の2点であるかと
・JRE 以外のライブラリへの依存が一切ない（依存性には敏感ですww)
・SQLをファイルですべて管理できる(疎結合ってやつですかね？）
これは自分が使ってみた意見ですが、SQLファイルで管理することで**過剰な共通化**を防ぐ利点があると思いました。
共通化のしすぎは逆にわかりにくくなることがあります。

##実装
公式にサンプルプロジェクトがありましたのでこちらがわかりやすいかと思います。
[公式サンプル](https://github.com/ko-aoki/springboot-doma.git)
主に必要な構成としては
・Dao  (Daoはデータベースアクセスのためのインタフェース)
・Entity  (テーブルを表現する（だけではないですが）クラス)
・SQLファイル  (クエリー）
になります。

DaoでCRUD処理をするメソッドを定義します。

```java:MstEmployeeDao.java

package com.example.dao;

import com.example.entity.MstEmployee;
import com.example.entity.UserEntity;
import org.seasar.doma.Dao;
import org.seasar.doma.Insert;
import org.seasar.doma.Select;
import org.seasar.doma.boot.ConfigAutowireable;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/** 従業員マスタのDaoインターフェース. */
@ConfigAutowireable
@Dao
public interface MstEmployeeDao {

  @Select
  List<MstEmployee> selectAll();

  @Select
  MstEmployee selectOne(String id);

  @Select
  UserEntity selectUser(String id);

  @Insert
  @Transactional
  int insert(MstEmployee mstEmployee);
}

```

このメソッドでやりたい問い合わせをSQLファイルにしてやろう。という使い方です。SQLファイルを配置する場所は`META-INF`の中に上記クラス内の`package com.example.dao;`と同じようにフォルダ階層を作成しかつ**ファイル名をメソッド名と同じ名前にします**(拡張子はsql)

サンプルプロジェクトのtreeを見るとわかりやすいと思います。

```:tree
├── pom.xml ... Maven設定ファイル
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── example
    │   │           ├── App.java  ... アプリケーション実行ファイル
    │   │           ├── SecurityConfig.java  ... セキュリティ設定ファイル
    │   │           ├── dao  ... Doma2のDAOクラス格納パッケージ
    │   │           │   ├── MstEmployeeDao.java
    │   │           │   ├── MstNewsDao.java
    │   │           │   └── MstRoleDao.java
    │   │           ├── dto
    │   │           │   └── NewsDto.java
    │   │           ├── entity  ... Doma2のEntityクラス格納パッケージ
    │   │           │   ├── AuditEntity.java
    │   │           │   ├── MstEmployee.java
    │   │           │   ├── MstNews.java
    │   │           │   ├── MstRole.java
    │   │           │   ├── UserEntity.java
    │   │           │   └── listener
    │   │           │       └── AuditListener.java
    │   │           ├── security  ... Spring Securityの認証機能
    │   │           │   ├── LoginUserDetails.java
    │   │           │   ├── LoginUserDetailsService.java
    │   │           │   └── UserInfo.java
    │   │           ├── service  ... サービスクラス格納パッケージ
    │   │           │   ├── NewsService.java
    │   │           │   └── NewsServiceImpl.java
    │   │           └── web ... Spring MVC コントローラクラス格納パッケージ
    │   │               ├── LoginController.java
    │   │               ├── NewsController.java
    │   │               ├── TopController.java
    │   │               └── manager
    │   │                   ├── NewsForm.java
    │   │                   ├── NewsManagerEditController.java
    │   │                   ├── NewsManagerListController.java
    │   │                   └── NewsManagerRegisterController.java
    │   └── resources
    │       ├── META-INF
    │       │   └── com
    │       │       └── example
    │       │           └── dao ... Doma2のSQLファイル格納パッケージ
    │       │               ├── MstEmployeeDao
    │       │               │   ├── selectAll.sql
    │       │               │   ├── selectOne.sql
    │       │               │   └── selectUser.sql
    │       │               ├── MstNewsDao
    │       │               │   ├── selectAll.sql
    │       │               │   ├── selectNewsDtoByCond.sql
    │       │               │   └── selectOneNewsDto.sql
    │       │               └── MstRoleDao
    │       │                   └── selectAll.sql
    │       ├── ValidationMessages.properties ... バリデーションチェックのメッセージ設定ファイル
    │       ├── application.yml ... アプリケーション設定ファイル
    │       ├── data.sql ... 起動時に実行するDDL文
    │       ├── messages.properties ... バリデーションチェックメッセージのFormプロパティ置換設定ファイル
    │       ├── schema.sql ... 起動時に実行するDML文
    │       ├── static ... 実行時にはコンテキストルート直下になる静的ファイル格納フォルダ
    │       │   ├── css
    │       │   │   └── lib ... CSSライブラリ格納フォルダ
    │       │   │       ├── bootstrap-theme.min.css
    │       │   │       └── bootstrap.min.css
    │       │   ├── fonts ... フォント格納フォルダ(Bootstrap)
    │       │   │   ├── glyphicons-halflings-regular.eot
    │       │   │   ├── glyphicons-halflings-regular.svg
    │       │   │   ├── glyphicons-halflings-regular.ttf
    │       │   │   ├── glyphicons-halflings-regular.woff
    │       │   │   └── glyphicons-halflings-regular.woff2
    │       │   ├── js
    │       │   │   └── lib ... JavaScriptライブラリ格納フォルダ
    │       │   │       └── bootstrap.min.js
    │       │   └── movie
    │       │       ├── sample
    │       │       │   └── nc144421.mp4
    │       │       └── thumbnail
    │       │           ├── nc144421.jpg
    │       │           └── nc144555.jpg
    │       └── templates ... Thymeleafテンプレート格納フォルダ
    │           ├── learning
    │           │   └── learning.html
    │           ├── loginForm.html
    │           ├── manager
    │           │   ├── managerLayout.html
    │           │   └── news
    │           │       ├── edit
    │           │       │   ├── newsEditComplete.html
    │           │       │   ├── newsEditConfirm.html
    │           │       │   └── newsEditInput.html
    │           │       ├── list
    │           │       │   └── newsList.html
    │           │       └── register
    │           │           ├── newsRegisterComplete.html
    │           │           ├── newsRegisterConfirm.html
    │           │           └── newsRegisterInput.html
    │           ├── news
    │           │   └── news.html
    │           └── top
    │               └── top.html
    └── test ... テストコード格納フォルダ
        └── java
            └── com
                └── example
                    └── service
                        └── NewsServiceImplTest.java

```

##パラメータの書き方
以下のようにsqlファイルを記述することでDaoクラスの変数とsqlファイルの変数をバインドすることができます。

```sql:selectOne

SELECT
	employee_id,
	employee_last_name,
	employee_first_name,
	role_id
FROM mst_employee
WHERE
  employee_id = /* id */'employee_id';

```


さらに、以下のように記述することで動的条件を表現できます。
if文とか、アノテーションが使えるんですね。

```sql:selectNewsDtoByCond.sql

select
  n.mst_news_id id,
  n.role_id role_id,
  r.role_name role_nm,
  n.subject subject,
  n.url url,
  n.version version
FROM
  mst_news n
INNER JOIN
  mst_role r
ON
  n.role_id = r.role_id
WHERE
/*%if @isNotEmpty(url) */
    n.url LIKE /* @prefix(url) */'http'
/*%end*/
/*%if @isNotEmpty(subject) */
AND
    n.subject LIKE /* @prefix(subject) */'今日'
/*%end*/
/*%if @isNotEmpty(roleId) */
AND
    n.role_id = /* roleId */'01'
/*%end*/
ORDER BY
  n.mst_news_id

```

Spring bootのデータベースアクセスではJPAを使っていましたが、こっちの方が標準みたいですね。