LoginSignup
2
2

MyBatisのSQLをJavaコードに記載して動的SQLのカバレッジも測定しちゃおうよ!!

Last updated at Posted at 2023-06-17

MyBatis=XMLのイメージの方も多いと思いますが、「アノテーション」と「任意のJavaクラスのメソッド」にSQLを記載することができます(つまりXML書かなくてもMyBatisを使ってDBアクセスすることができます)。あまり知られていないかもしれないですが、「任意のJavaクラスのメソッド」を使用して動的SQLを記載すると、カバレッジ測定ツールと連動してSQLの生成ロジックに対するテストの充足性を確認することもできちゃいます。

JavaコードにSQLを記載したMapper

以下は、静的SQLを「アノテーション」に、動的SQLを「メソッド」に記載するしたMapperインタフェースになります。

package com.example.demo;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.SelectProvider;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Objects;

// language=sql
@Mapper
public interface PersonMapper {

  // アノテーションにSQLを指定する
  @Select("""
      SELECT
        id
        ,name
        ,address
        ,age
        ,memo
      FROM
        person
      WHERE
        id = #{id}
      """)
  Person selectOne(int id);

  // 任意のクラスのメソッドにSQLを指定する
  // language=sql
  class SelectByCriteriaSqlProvider {
    public static StringBuilder provideSql(PersonCriteria criteria) {
      StringBuilder sb = new StringBuilder("""
          SELECT
            id
            ,name
            ,address
            ,age
            ,memo
          FROM
            person
          WHERE 1 = 1
          """);
      if (StringUtils.hasLength(criteria.name)) {
        sb.append("""
            AND name = #{name}
            """);
      }
      if (StringUtils.hasLength(criteria.address)) {
        sb.append("""
            AND address = #{address}
            """);
      }
      if (Objects.nonNull(criteria.age)) {
        sb.append("""
            AND age = #{age}
            """);
      }
      return sb;
    }
  }
  @SelectProvider(SelectByCriteriaSqlProvider.class) // メソッド名をprovideSqlするとmethod属性は省略できる
  List<Person> selectByCriteria(PersonCriteria criteria);

}

カバレッジの確認

ageに条件を指定したテストのみ実行した時のカバレッジはこんな感じになります。nameとaddressを指定したテストが不足していることがわかります!!

image.png

参考:Personクラス

package com.example.demo;

public record Person(int id, String name, String address, Integer age, String memo) {
}

参考:PersonCriteriaクラス

package com.example.demo;

public class PersonCriteria {
  public String name;
  public String address;
  public Integer age;
}

まとめ

複雑なマッピングを行おうとするとXMLでしかサポートしていないケースはありますが、自動マッピングとアノテーションを使ったマッピングでも多くのパターンをサポートできると思います。データベースへアクセスする処理を分散させたくない場合やSQLの生成ロジックのカバレッジを取得したい場合は、JavaコードにSQLを記載する方法の採用を検討してみると良いと思います。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2