MyBatis 初級: JavaとDBをもっと仲良しに!

docs

以前の記事で、Javaとデータベース(DB)を連携させる基本的な方法を学びましたね。

JDBCでデータベースを操作してみよう! | ToolDocs

でも、もっとスマートに、もっと楽にDB操作をしたいと思いませんか?そんなときに役立つのが、今回ご紹介するMyBatisです。MyBatisは、SQLをJavaコードから分離して管理できるフレームワークで、DB操作のコードをすっきりさせ、開発効率をぐんとアップさせてくれます。


MyBatisってなあに?

MyBatisは、Javaオブジェクトとデータベースのレコードをマッピング(紐付け)するためのフレームワークです。これだけ聞くと難しく感じるかもしれませんが、要は**「Javaで書いたプログラムとデータベースの間を取り持ってくれる通訳さん」**みたいなものです。

通常、JavaでDBを操作するにはJDBC(Java DataBase Connectivity)を使いますが、JDBCだとSQL文をJavaコードの中に直接書くことが多く、SQLの変更があるたびにJavaコードを修正・コンパイルする必要がありました。MyBatisを使えば、SQL文をXMLファイルなどに外出しできるので、SQLの修正がJavaコードに影響を与えなくなり、開発がとってもスムーズになります。


MyBatisを始める準備

MyBatisを使うためには、いくつか準備が必要です。今回は、簡単なサンプルを通してMyBatisの基本的な使い方を見ていきましょう。

1. 必要なライブラリの追加

まずは、MyBatisを使うためのライブラリをプロジェクトに追加します。Mavenを使っているなら、pom.xmlに以下の依存関係を追加してください。

XML

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.5.7</version>
</dependency>
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.28</version>
</dependency>

mysql-connector-javaはMySQLを使う場合の例です。他のDBを使う場合は、それぞれのDB用のJDBCドライバーを追加してください。

2. データベースの準備

MyBatisで操作するデータベースを用意しましょう。今回はusersというテーブルを使います。

SQL

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL
);

INSERT INTO users (name, email) VALUES ('Taro Yamada', 'taro@example.com');
INSERT INTO users (name, email) VALUES ('Hanako Suzuki', 'hanako@example.com');

MyBatisの基本的な使い方

MyBatisを使うには、主に以下の要素が必要になります。

  1. 設定ファイル(mybatis-config.xml: データベース接続情報などを定義します。
  2. マッパーインターフェース: SQLとJavaのメソッドを紐付けます。
  3. マッパーXMLファイル: 実行するSQL文を定義します。
  4. データクラス(DTO/VO): データベースのテーブルと対応するJavaのクラスです。

順番に見ていきましょう。

1. 設定ファイル (mybatis-config.xml)

MyBatisがデータベースに接続するための情報を設定します。src/main/resourcesディレクトリに作成しましょう。

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>
  <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_name?serverTimezone=JST"/>
        <property name="username" value="your_username"/>
        <property name="password" value="your_password"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="mappers/UserMapper.xml"/>
  </mappers>
</configuration>

ポイント:

  • urlyour_database_nameusernamepasswordは自分の環境に合わせて書き換えてください。
  • <mappers>タグで、後述するマッパーXMLファイルを指定します。

2. データクラス (User.java)

usersテーブルに対応するJavaのクラスを作成します。

Java

// src/main/java/com/example/model/User.java
package com.example.model;

public class User {
    private int id;
    private String name;
    private String email;

    // コンストラクタ
    public User() {
    }

    public User(int id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }

    // ゲッターとセッター
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Override
    public String toString() {
        return "User{" +
               "id=" + id +
               ", name='" + name + '\'' +
               ", email='" + email + '\'' +
               '}';
    }
}

3. マッパーインターフェース (UserMapper.java)

SQLと関連付けるJavaのインターフェースです。

Java

// src/main/java/com/example/mapper/UserMapper.java
package com.example.mapper;

import com.example.model.User;
import java.util.List;

public interface UserMapper {
    User selectUserById(int id);
    List<User> selectAllUsers();
    void insertUser(User user);
    void updateUser(User user);
    void deleteUser(int id);
}

4. マッパーXMLファイル (UserMapper.xml)

SQL文を定義するXMLファイルです。src/main/resources/mappersディレクトリに作成しましょう。

XML

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
  <select id="selectUserById" resultType="com.example.model.User">
    SELECT id, name, email FROM users WHERE id = #{id}
  </select>

  <select id="selectAllUsers" resultType="com.example.model.User">
    SELECT id, name, email FROM users
  </select>

  <insert id="insertUser" parameterType="com.example.model.User" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO users (name, email) VALUES (#{name}, #{email})
  </insert>

  <update id="updateUser" parameterType="com.example.model.User">
    UPDATE users SET name = #{name}, email = #{email} WHERE id = #{id}
  </update>

  <delete id="deleteUser" parameterType="int">
    DELETE FROM users WHERE id = #{id}
  </delete>
</mapper>

ポイント:

  • namespaceには、対応するマッパーインターフェースの完全修飾名を指定します。
  • <select><insert><update><delete>タグでSQL文を記述します。
  • id属性はマッパーインターフェースのメソッド名と一致させます。
  • resultTypeには、SQLの結果をマッピングするJavaクラスの完全修飾名を指定します。
  • parameterTypeには、SQLに渡す引数の型を指定します。
  • #{propertyName}のように書くことで、JavaオブジェクトのプロパティをSQLのプレースホルダーとして利用できます。MyBatisが自動的にプリペアドステートメントを使ってくれるので、SQLインジェクション対策もバッチリです!

MyBatisでDB操作をやってみよう!

では、実際にMyBatisを使ってDB操作をしてみましょう。

Java

// src/main/java/com/example/Main.java
package com.example;

import com.example.mapper.UserMapper;
import com.example.model.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.Reader;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        SqlSession sqlSession = null;
        try {
            // mybatis-config.xmlを読み込む
            Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);

            // SqlSessionをオープン
            sqlSession = sqlSessionFactory.openSession();

            // マッパーインターフェースのインスタンスを取得
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

            // 1. 全ユーザー取得
            System.out.println("--- 全ユーザー取得 ---");
            List<User> users = userMapper.selectAllUsers();
            users.forEach(System.out::println);
            // 実行結果例:
            // User{id=1, name='Taro Yamada', email='taro@example.com'}
            // User{id=2, name='Hanako Suzuki', email='hanako@example.com'}

            // 2. IDでユーザーを検索
            System.out.println("\n--- ID:1 のユーザー検索 ---");
            User user = userMapper.selectUserById(1);
            System.out.println(user);
            // 実行結果例:
            // User{id=1, name='Taro Yamada', email='taro@example.com'}

            // 3. ユーザーを新規追加
            System.out.println("\n--- ユーザーを新規追加 ---");
            User newUser = new User();
            newUser.setName("Jiro Sato");
            newUser.setEmail("jiro@example.com");
            userMapper.insertUser(newUser);
            sqlSession.commit(); // 変更をコミット
            System.out.println("追加後のユーザーID: " + newUser.getId());
            // 実行結果例:
            // 追加後のユーザーID: 3 (自動採番されたID)

            System.out.println("--- 追加後の全ユーザー ---");
            users = userMapper.selectAllUsers();
            users.forEach(System.out::println);
            // 実行結果例:
            // User{id=1, name='Taro Yamada', email='taro@example.com'}
            // User{id=2, name='Hanako Suzuki', email='hanako@example.com'}
            // User{id=3, name='Jiro Sato', email='jiro@example.com'}

            // 4. ユーザー情報を更新
            System.out.println("\n--- ユーザー情報を更新 (ID:3) ---");
            User updateUser = userMapper.selectUserById(newUser.getId());
            if (updateUser != null) {
                updateUser.setName("Jiro Tanaka");
                updateUser.setEmail("jiro.tanaka@example.com");
                userMapper.updateUser(updateUser);
                sqlSession.commit();
                System.out.println("更新後のユーザー: " + userMapper.selectUserById(newUser.getId()));
            }
            // 実行結果例:
            // 更新後のユーザー: User{id=3, name='Jiro Tanaka', email='jiro.tanaka@example.com'}

            System.out.println("--- 更新後の全ユーザー ---");
            users = userMapper.selectAllUsers();
            users.forEach(System.out::println);
            // 実行結果例:
            // User{id=1, name='Taro Yamada', email='taro@example.com'}
            // User{id=2, name='Hanako Suzuki', email='hanako@example.com'}
            // User{id=3, name='Jiro Tanaka', email='jiro.tanaka@example.com'}


            // 5. ユーザーを削除
            System.out.println("\n--- ユーザーを削除 (ID:3) ---");
            userMapper.deleteUser(newUser.getId());
            sqlSession.commit();
            System.out.println("削除後の全ユーザー:");
            users = userMapper.selectAllUsers();
            users.forEach(System.out::println);
            // 実行結果例:
            // User{id=1, name='Taro Yamada', email='taro@example.com'}
            // User{id=2, name='Hanako Suzuki', email='hanako@example.com'}

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (sqlSession != null) {
                sqlSession.close(); // SqlSessionをクローズする
            }
        }
    }
}

まとめ

お疲れ様でした!今回はMyBatisの基本的な使い方を学びました。MyBatisを使うことで、JavaコードからSQLを分離し、DB操作をより効率的かつ安全に行えるようになることが実感できたのではないでしょうか。

MyBatisは、他にも動的SQL(条件によってSQLを動的に生成する機能)やキャッシュ機能など、便利な機能がたくさんあります。今回紹介した内容はMyBatisのほんの入り口に過ぎません。ぜひ、今回学んだことを活かして、MyBatisをさらに深く探求してみてください。

次の記事では、MyBatisの動的SQLについて深掘りしていく予定です。お楽しみに!


前回の記事:JUnit徹底活用!テストの質を高める上級テクニック | ToolDocs

MyBatisの公式ドキュメント

コメント

タイトルとURLをコピーしました