やりたいこと
MyBatisのMapperをJakartaEEのCDIに登録したい。
課題
JakartaEEのCDIとOSSのMyBatisを併用する場合、Springのように@Mapperアノテーションを記述するだけではDIに登録できないらしいです。そのため、DIに登録するための記述を追加する必要があります。
前提
ビジネスロジック層はJakartaEEのCDI(4.1.0)、インテグレーション層はMyBatis(3.5.17)、ビルドツールはmavenを使用します。
MapperをDIに登録する手順
①pom.xmlを修正する
②mybatis-config.xmlを作成する
③②で作成したmybatis-config.xmlを読み込んだSqlSessionをCDIに登録する
④ServiceクラスでSqlSessionをインジェクションする
流れとしては、mybatis-config.xmlにMapperを登録し、それを読み込んだSqlSessionをCDIに登録し、登録したSqlSessionをインジェクトすることでMapperを使うことができるという感じです。
①pom.xmlを修正する
pom.xmlにCDI-API、MyBatis、MyBatis-CDIを追加します。
(バージョンは適宜調整してください。)
<!-- CDI API -->
<dependency>
<groupId>jakarta.enterprise</groupId>
<artifactId>jakarta.enterprise.cdi-api</artifactId>
<version>4.1.0</version>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.17</version>
</dependency>
<!-- MyBatis-CDI -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-cdi</artifactId>
<version>2.1.0</version>
</dependency>
②mybatis-config.xmlを作成する
DBへの接続情報や、Mapperの情報を記載したmybatis-config.xmlを作成し、src/main/resources配下に配置します。
以下、mybatis-config.xmlの例でございます。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--DB接続先情報-->
<environments default="test">
<environment id="test">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="org.postgresql.Driver" />
<property name="url" value="接続先URL" />
<property name="username" value="ユーザー名" />
<property name="password" value="パスワード" />
</dataSource>
</environment>
</environments>
<!--以下にMapper情報を登録-->
<!--本例では、mybatis-config.xmlと同じディレクトリに配置したmapper.xmlを登録しています-->
<mappers>
<mapper resource="./mapper.xml" />
</mappers>
</configuration>
以下のような記述で直接Mapperを登録することも可能です。
<mappers>
<mapper class="Mapperの相対パス" />
</mappers>
③②で作成したmybatis-config.xmlを読み込んだSqlSessionをCDIに登録する
mybatis-config.xmlを読み込んだSqlSessionをCDIに登録することで、MapperもCDI経由で呼び出すことができるようになります。
方法としては、SqlSessionFactory型を戻り値とするメソッドを用意し、mybatis-config.xmlを読み込ませたうえでSqlSessionFactoryBuilderクラスを用いてSqlSessionFactoryを生成/returnすることでSqlSessionをCDIに登録します。
例)SqlSessionFactoryProducer.java
package com.example.util;
import java.io.IOException;
import java.io.InputStream;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.inject.Produces;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.mybatis.cdi.SessionFactoryProvider;
//@Dependentで本クラスをCDI登録
@Dependent
public class SqlSessionFactoryProducer {
//@SessionFactoryProviderとして本メソッドを登録
@Produces
@ApplicationScoped
@SessionFactoryProvider
//SqlSessionFactoryを戻り値型に指定
public SqlSessionFactory produceFactory() throws IOException{
//mybatis-config.xmlを読み込んだInputStreamを生成
InputStream fileStream = Resources.getResourceAsStream("mybatis-config.xml");
//上記InputStreamを読み込んだSqlSessionFactoryBuilderを生成/returnすることで
//SqlSessionをApplicationスコープでCDI登録
return new SqlSessionFactoryBuilder().build(fileStream);
}
}
④ServiceクラスでSqlSessionをインジェクションする
最後に、③で登録したSqlSessionをインジェクトしてMapperを取得/利用します。
//SqlSessionをインジェクション
@Inject
private SqlSession sqlSession;
//SqlSessionからMapperを取得するprivateメソッド
private SampleMapper sampleMapper() {
return sqlSession.getMapper(SampleMapper.class);
}
//上記privateメソッドを用いてMapperを取得/利用
public List<SampleDto> getList(){
return sampleMapper().getList();
}
ソースコード
上記サンプルコードはGithubにコミットしています。
参考にさせていただいた記事