MyBatisによるデータベース操作の基本ガイド

MyBatisの概要

MyBatisはJavaベースの優れた永続化フレームワークで、以下の特徴を持っています:

  • データベース接続プールを介して接続リソースを初期化する
  • SQL文をXML設定ファイルに分離する
  • リフレクションやインテロスペクションなどの低レベル技術を使用し、エンティティとテーブル間のプロパティとフィールドを自動的にマッピングする

フレームワークの説明

MyBatisはJavaの優れた永続層フレームワークであり、内部的にJDBCをカプセル化しています。開発者はSQL文そのものに集中すればよく、ドライバのロード、接続の作成、Statementの生成など複雑な処理を気にする必要がありません。MyBatisはXMLまたはアノテーションの方法で実行する各種Statementを設定し、JavaオブジェクトとStatement内のSQL動的パラメータをマッピングして最終的なSQL文を生成します。フレームワークはSQLを実行し、結果をJavaオブジェクトとして返却します。ORM思想を採用してエンティティとデータベースのマッピング問題を解決し、JDBCをカプセル化してAPIの低レベルアクセス詳細を隠蔽し、JDBC APIに直接対応することなくデータベースの永続化操作を完了できます。

実装手順

依存関係の追加

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.26</version>
</dependency>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.6</version>
</dependency>

ユーザーテーブルの作成

CREATE TABLE USERS( id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT, user_name VARCHAR(32) not null, password VARCHAR(32) not null )

ユーザークラスの作成

package com.example.model;

/**
 * ユーザー情報エンティティ
 */
public class UserInfo {
    private Integer userId;
    private String username;
    private String userPassword;

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getUserPassword() {
        return userPassword;
    }

    public void setUserPassword(String userPassword) {
        this.userPassword = userPassword;
    }

    @Override
    public String toString() {
        return "UserInfo{" +
                "userId=" + userId +
                ", username='" + username + '\'' +
                ", userPassword='" + userPassword + '\'' +
                '}';
    }
}

マッピングファイルの作成 (UserMapper.xml)

resourcesディレクトリ配下に新しいフォルダを作成します

<?xml version="1.0" encoding="UTF-8" ?>

<mapper namespace="userOperations">
    <!-- 結果セットをマッピングする型 -->
    <select id="fetchAllUsers" resultType="com.example.model.UserInfo">
        select * from users
    </select>
</mapper>

userOperations名前空間のfetchAllUsersメソッドを実行し、結果をUserInfo型にマッピングします

コア設定ファイル

<?xml version="1.0" encoding="UTF-8" ?>

<configuration>
    <!-- データソース環境 -->
    <environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/sample_db"/>
                <property name="username" value="admin"/>
                <property name="password" value="password123"/>
            </dataSource>
        </environment>
    </environments>
    <!-- マッピングファイルの読み込み -->
    <mappers>
        <mapper resource="mappings/UserMapper.xml"/>
    </mappers>
</configuration>

テストコードの作成

検索操作:

@Test
public void retrieveAllUsers() throws IOException {
    // コア設定ファイルを取得
    InputStream configStream = Resources.getResourceAsStream("mybatis-config.xml");
    // SqlSessionファクトリを構築
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(configStream);
    // SqlSessionインスタンスを取得
    SqlSession session = factory.openSession();
    // 操作を実行
    List<UserInfo> userList = session.selectList("userOperations.fetchAllUsers");
    // 結果出力
    System.out.println(userList);
    session.close();
}

挿入操作:

<!-- 挿入処理 -->
<insert id="addNewUser" parameterType="com.example.model.UserInfo">
    insert into users values(#{userId},#{username},#{userPassword})
</insert>
@Test
public void createUser() throws IOException {
    InputStream configStream = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(configStream);
    SqlSession session = factory.openSession();
    
    UserInfo newUser = new UserInfo();
    newUser.setUsername("tanaka");
    newUser.setUserPassword("secret999");
    
    int insertResult = session.insert("userOperations.addNewUser", newUser);
    session.commit(); // MyBatisはデフォルトで自動コミットしない
    System.out.println("挿入件数: " + insertResult);
    session.close();
}

更新操作:

<!-- 更新処理 -->
<update id="modifyUser" parameterType="com.example.model.UserInfo">
    update users set password=#{userPassword} where user_name=#{username}
</update>
@Test
public void updateUser() throws IOException {
    InputStream configStream = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(configStream);
    SqlSession session = factory.openSession();
    
    UserInfo updatedUser = new UserInfo();
    updatedUser.setUsername("tanaka");
    updatedUser.setUserPassword("newpass789");
    
    int updateCount = session.update("userOperations.modifyUser", updatedUser);
    session.commit();
    System.out.println("更新件数: " + updateCount);
    session.close();
}

削除操作:

<!-- 削除処理 -->
<delete id="removeUser" parameterType="com.example.model.UserInfo">
    delete from users where user_name=#{username}
</delete>
@Test
public void deleteUser() throws IOException {
    InputStream configStream = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(configStream);
    SqlSession session = factory.openSession();
    
    UserInfo targetUser = new UserInfo();
    targetUser.setUsername("tanaka");
    
    int deleteCount = session.delete("userOperations.removeUser", targetUser);
    session.commit();
    System.out.println("削除件数: " + deleteCount);
    session.close();
}

IDによる削除も可能です:

<!-- IDによる削除 -->
<delete id="removeById" parameterType="java.lang.Integer">
    delete from users where id=#{id}
</delete>

このように、SQL文が必要とするパラメータ型に応じてparameterTypeを適切に設定できます。

主な設定項目

データベース環境設定

複数環境設定をサポートしています。

トランザクションマネージャータイプには2種類あります:

  • JDBC:JDBCのコミット・ロールバック設定を直接使用し、データソースから得られる接続に依存してトランザクションスコープを管理します。
  • MANAGED:ほとんど何も行いません。接続のコミットやロールバックを行わず、コンテナにトランザクションライフサイクル全体を管理させます(例:JEEアプリケーションサーバのコンテキスト)。デフォルトでは接続をクローズしますが、一部のコンテナでは望ましくないため、closeConnectionプロパティをfalseに設定してデフォルトのクローズ動作を防ぐ必要があります。

データソースタイプには3種類あります:

  • UNPOOLED:このデータソース実装は要求ごとに接続を開閉します。
  • POOLED:このデータソース実装は「プール」概念を利用してJDBC接続オブジェクトを組織化します(JDBCではPOOLEDを使用)。
  • JNDI:EJBやアプリケーションサーバのようなコンテナ内で使用するための実装です。コンテナがデータソースを一元管理または外部設定し、JNDIコンテキスト参照を配置できます。

mapperタグ

マッピングの読み込みに使用され、以下の方法があります:

  • クラスパスに対するリソース参照
  • 完全修飾リソースロケータ(URL)
  • マッピングインターフェース実装クラスの完全修飾クラス名
  • パッケージ内のすべてのマッピングインターフェース実装を登録

propertiesタグ

単独で抽出して責任を明確化します。

typeAliasesタグ

エイリアス設定に使用されます。

<typeAliases>
    <typeAlias type="com.example.model.UserInfo" alias="userInfo"/>
</typeAliases>

SqlSessionFactory構築

// コア設定ファイルを取得
InputStream configStream = Resources.getResourceAsStream("mybatis-config.xml");
// SqlSessionファクトリを構築
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(configStream);
// SqlSessionインスタンスを取得
SqlSession session = factory.openSession();
メソッド 説明
openSession() デフォルトでトランザクションを開きますが、自動コミットされません。つまり手動でのコミットが必要です。
openSession(boolean autoCommit) 引数は自動コミットの有無です。trueに設定すると、手動でトランザクションをコミットする必要はありません。

SqlSessionインスタンスオブジェクトを使用して単一オブジェクトを照会できます。

MyBatisのプロキシ開発

Mapperインターフェース開発方法では、Mapperインターフェースを作成し、MyBatisフレームワークがインターフェース定義に基づいて動的プロキシオブジェクトを作成します。

以下の規約に従う必要があります:

  • Mapper.xmlファイルのnamespaceはMapperインターフェースの完全修飾名と一致する
  • Mapperインターフェースのメソッド名はMapper.xmlで定義された各statementのidと一致する
  • Mapperインターフェースメソッドの入力パラメータ型はmapper.xmlで定義された各SQLのparameterType型と一致する
  • Mapperインターフェースメソッドの戻り値型はmapper.xmlで定義された各SQLのresultType型と一致する

テストコード

public static void main(String[] args) throws IOException {
    InputStream configStream = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(configStream);
    SqlSession session = factory.openSession();

    UserMapper userMapper = session.getMapper(UserMapper.class);
    List<UserInfo> userList = userMapper.fetchAllUsers();
    System.out.println(userList);
}

タグ: MyBatis Java database JDBC ORM

5月17日 16:05 投稿