MyBatis Dynamic SQLを使ってみよう!
今回はMyBatis Dynamic SQLを使ってSQLを発行し、データを取得する実装を試してみました!
業務でバリバリ使うことになるかもなので、備忘録として残しておきます。
実装形式としてはSeasar2のS2JDBCに似ていて、複数のメソッドチェインを行うことで発行するSQLを作成しています。
実行準備
用意したテーブルはこんな感じでシンプルなものを用意しました。
データはテキトーに数件登録しておきます。
CREATE TABLE "MEMBER" (
"ID" NUMBER(8,0)
, "BLOOD" VARCHAR2(20 BYTE)
, "NAME" VARCHAR2(20 BYTE)
, "CORP" VARCHAR2(20 BYTE)
);
Entityもテーブル構成に合わせて作成します。
public class Member {
private Integer id;
private String name;
private String corp;
private String blood;
//getter・setterは省略
}
マッパーインターフェースは下記のように作成します。
今回は複数のデータをListに返却する想定で実装しています。
public interface MemberMapper {
@SelectProvider(type=SqlProviderAdapter.class, method="select")
@Results(id="memberResult", value={
@Result(column="ID", property="id"),
@Result(column="NAME", property="name"),
@Result(column="CORP", property="corp"),
@Result(column="BLOOD", property="blood"),
})
List<Member> selectMany(SelectStatementProvider selectStatement);
}
MyBatis Dynamic SQLと連携するためのサポートクラスを作成します。
取得するカラムやWHERE句の指定をするときなどに利用します。
public final class MemberDynamicSqlSupport {
public static final Member Member = new Member();
public static final SqlColumn <Integer> id = Member.id;
public static final SqlColumn <String> name = Member.name;
public static final SqlColumn <String> corp = Member.corp;
public static final SqlColumn <String> blood = Member.blood;
public static final class Member extends SqlTable {
public final SqlColumn <Integer> id = column("ID", JDBCType.INTEGER);
public final SqlColumn <String> name = column("NAME", JDBCType.VARCHAR);
public final SqlColumn <String> corp = column("CORP", JDBCType.VARCHAR);
public final SqlColumn <String> blood = column("BLOOD", JDBCType.VARCHAR);
public Member() {
super("Member");
}
}
}
SQL実行
上記で作成したクラスを使って実際にSQLを発行するクラスを実装してみましょう。
今回はjunitを使ってテストコードを実装してみます。
import static jp.co.stylez.support.MemberDynamicSqlSupport.*;
import static org.mybatis.dynamic.sql.SqlBuilder.isEqualTo;
import static org.mybatis.dynamic.sql.SqlBuilder.isLessThan;
import static org.mybatis.dynamic.sql.SqlBuilder.select;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MybatisConfig.class)
public class Main {
@Autowired
ApplicationContext context;
@Test
public void test() {
MemberMapper mapper = context.getBean(MemberMapper.class);
SelectStatementProvider selectStatement = select(Member.allColumns()).from(Member).where(id, isLessThan(10))
.and(corp, isEqualTo("stylez")).orderBy(id).build().render(RenderingStrategies.MYBATIS3);
List<Member> members = mapper.selectMany(selectStatement);
for (Member member : members) {
System.out.println("********************");
System.out.println("id:" + member.getId());
System.out.println("name:" + member.getName());
System.out.println("corp:" + member.getCorp());
System.out.println("blood:" + member.getBlood());
System.out.println("********************");
}
}
}
Configクラスは別途実装してDataSourceやMapperScan対象の設定をしておきます。
XML形式でも設定可能ですが、今回はJavaで設定しました。
(設定関連の解説は割愛します)
MapperScanで登録したMapperを取り出し、実際にSQLを実行しています。
実行結果は下記のようになります。
********************
id:1
name:hogehoge
corp:stylez
blood:B
********************
********************
id:2
name:test.taro
corp:stylez
blood:O
********************
********************
id:3
name:hiroya.endo
corp:stylez
blood:A
********************
指定した条件のデータが複数取得出来ていることが確認できました!
実際に使ってみて…
主にWHERE句の条件指定に関して非常に柔軟な実装が可能だと感じました。
コードの可読性としても非常に高く、コーティングもしやすいので使いやすい印象でした。
テーブル結合やサブクエリにも対応できるので、それもまた魅力の一つかと思いました。
Mapper.xmlを使用したSQLと使い分けることも可能なので、必要に応じて構成管理ができると思います。
これから使う方のよい参考になれば幸いです!
参考