本記事では、JavaベースのWebアプリケーション開発において、データベースアクセスを効率化するためのフレームワークであるMyBatisについて解説します。まず、MyBatisとは何かを理解しましょう。
MyBatisは、優れた永続化層(データを永続的に保存する層)のフレームワークです。アプリケーションのデータを一時的な状態(メモリ上)と永続的な状態(データベース)の間で変換する役割を担います。
JDBC(Java Database Connectivity)に比べて、より使いやすく、テンプレートが豊富であるため、開発のスピードアップにも貢献します。
永続層とは? 永続層とは、DAO層、サービス層、コントローラ層など、データの永続化処理を担うコードのブロックを指します。各層の役割は明確に分かれています。
なぜMyBatisを使うのか? 伝統的なJDBCは複雑なコードを書く必要がありました。MyBatisのようなフレームワークは、このプロセスを自動化し、開発者の手間を軽減します。SQL文とJavaコードを分離することで、保守性が向上し、学習曲線も緩やかになります。また、広く使われているため、情報も豊富です。
重要:技術に優劣はありません。優劣があるのは、プログラマーのスキルです。
実装の流れ:環境構築、依存関係の追加、コードの記述、テスト
手順:
- データベースの作成
- Mavenプロジェクトの新規作成
- srcディレクトリの削除(親プロジェクトとして扱う)
- 必要なライブラリの依存関係を追加(基本環境の構築完了)
- サブモジュールの作成とMyBatisの設定ファイルの記述
- コア設定ファイルの記述
- MyBatisの主要なコンポーネントの実装
MyBatisの実装手順:
-
ユーティリティクラスの作成 まず、SqlSessionFactoryを生成するためのユーティリティクラスを作成します。このクラスは、設定ファイルを読み込む必要があります。そのため、リソースディレクトリに設定ファイルを配置します。
MyBatisのアプリケーションは、SqlSessionFactoryのインスタンスを中心に構築されます。このファクトリからSqlSessionを取得でき、SQLコマンドを実行するためのすべてのメソッドが含まれています。
staticブロックは、クラスがロードされた時点で実行されるため、初期化エラーを防ぐことができます。
注意:SqlSessionFactoryを取得できれば、SqlSessionインスタンスを生成できます。まず、SqlSessionFactoryのスコープを広げるために、private static SqlSessionFactory factory; として宣言します。
package com.util;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.io.Resources;
import java.io.IOException;
import java.io.InputStream;
public class MyBatisUtil {
private static SqlSessionFactory factory;
static {
try {
String configPath = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(configPath);
// リソースを読み込み、使用可能なオブジェクトを作成します。(Connectionに似ています)
factory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession openSession() {
return factory.openSession();
}
}
- 設定ファイルの記述
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/your_database?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8"/>
<property name="username" value="your_username"/>
<property name="password" value="your_password"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/dao/UserMapper.xml"/>
</mappers>
</configuration>
- エンティティクラス(POJO)の作成
エンティティクラスは、privateなフィールド、コンストラクタ、getter/setterメソッドを持ちます。通常、pojoパッケージに配置します。
package com.pojo;
public class User {
private String userName;
private String password;
private String idNumber;
private String departmentInfo;
public User(String userName, String password, String idNumber, String departmentInfo) {
this.userName = userName;
this.password = password;
this.idNumber = idNumber;
this.departmentInfo = departmentInfo;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getIdNumber() {
return idNumber;
}
public void setIdNumber(String idNumber) {
this.idNumber = idNumber;
}
public String getDepartmentInfo() {
return departmentInfo;
}
public void setDepartmentInfo(String departmentInfo) {
this.departmentInfo = departmentInfo;
}
@Override
public String toString() {
return "User{" +
"userName='" + userName + ''' +
", password='" + password + ''' +
", idNumber='" + idNumber + ''' +
", departmentInfo='" + departmentInfo + ''' +
'}';
}
}
- Mapper(DAO)とMapper XMLの作成
DAOインターフェースはdaoパッケージに配置し、interface型で定義します。DAOはMapperと同義です。
設定ファイルを作成します。任意の場所に作成できますが、今回はリソースディレクトリに配置します。ファイル名はxxxxMapper.xmlとします。 このファイルの書き方: ヘッダにnamespaceを追加し、SQL文を使用するインターフェースを紐付けます。 mapper内のidは、元のメソッド名に相当します。 resultTypeは単一の結果を返し、resultMapはコレクションを返します。
注意:各mapper.xmlは、MyBatisの設定ファイルで登録する必要があります。
package com.dao;
import com.pojo.User;
import java.util.List;
public interface UserMapper {
List<User> selectAllUsers();
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dao.UserMapper">
<select id="selectAllUsers" resultType="com.pojo.User">
SELECT * FROM users;
</select>
</mapper>
これでテストに進む準備が整いました。以下のコードを使用してテストを実行します。
リソースのフィルタリング問題が発生する可能性があります。その場合は、上記のXMLファイルをリソースディレクトリの直下に移動してください。 最後に、JUnitを使用してテストします。testディレクトリ内に上記と同じパッケージを作成し、そこにxxxMapperTestクラスを作成します。SqlSessionオブジェクトを取得し、SQLを実行します。
package com.dao;
import com.pojo.User;
import com.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;
import java.util.List;
public class UserMapperTest {
@Test
public void testSelectAllUsers() {
// SqlSessionオブジェクトを取得
SqlSession session;
session = MyBatisUtil.openSession();
// 方法1:推奨。Mapperインターフェースを取得するため、キャストが不要で安全です。
UserMapper mapper = session.getMapper(UserMapper.class);
List<User> userList = mapper.selectAllUsers();
// 方法2:直接、インターフェース内の具体的なメソッドを使用する
// List<User> userList = session.selectList("com.dao.UserMapper.selectAllUsers");
for (User user : userList) {
System.out.println(user);
}
session.close();
}
}
テストが成功すれば、機能が正常に動作します。
mapperRegistryは、コア設定ファイル内でmappersを登録する場所です。 発生する可能性のある問題:
- 設定ファイルが登録されていない
- インターフェースの紐付けが誤っている
- メソッド名が一致しない
- 戻り値の型が一致しない
- Mavenのリソースエクスポートの問題
以下にプロジェクトのディレクトリ構造を示します。参考にしてください。
最後に、リソースのクローズを忘れないでください!