1. 序章

MyBatis は、Javaアプリケーションでのデータベースアクセスの実装を簡素化するオープンソースの永続化フレームワークです。 カスタムSQL、ストアドプロシージャ、およびさまざまなタイプのマッピング関係のサポートを提供します。

簡単に言えば、JDBCとHibernateの代替手段です。

2. Mavenの依存関係

MyBatisを利用するには、 pom.xml:に依存関係を追加する必要があります。

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.4</version>
</dependency>

依存関係の最新バージョンはここにあります。

3. Java API

3.1. SQLSessionFactory

SQLSessionFactory は、すべてのMyBatisアプリケーションのコアクラスです。 このクラスは、構成XMLファイルをロードする SQLSessionFactoryBuilder’ s builder()メソッドを使用してインスタンス化されます。

String resource = "mybatis-config.xml";
InputStream inputStream Resources.getResourceAsStream(resource);
SQLSessionFactory sqlSessionFactory
  = new SqlSessionFactoryBuilder().build(inputStream);

Java構成ファイルには、データソース定義、トランザクションマネージャーの詳細、エンティティ間の関係を定義するマッパーのリストなどの設定が含まれ、これらを一緒に使用してSQLSessionFactoryインスタンスを構築します。

public static SqlSessionFactory buildqlSessionFactory() {
    DataSource dataSource 
      = new PooledDataSource(DRIVER, URL, USERNAME, PASSWORD);

    Environment environment 
      = new Environment("Development", new JdbcTransactionFactory(), dataSource);
        
    Configuration configuration = new Configuration(environment);
    configuration.addMapper(PersonMapper.class);
    // ...

    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    return builder.build(configuration);
}

3.2. SQLSession

SQLSession には、データベース操作の実行、マッパーの取得、およびトランザクションの管理のためのメソッドが含まれています。 SQLSessionFactoryクラスからインスタンス化できます。 このクラスのインスタンスはスレッドセーフではありません。

データベース操作を実行した後、セッションを閉じる必要があります。 SqlSessionAutoCloseableインターフェースを実装しているため、try-with-resourcesブロックを使用できます。

try(SqlSession session = sqlSessionFactory.openSession()) {
    // do work
}

4. マッパー

マッパーは、メソッドを対応するSQLステートメントにマップするJavaインターフェースです。 MyBatisは、データベース操作を定義するための注釈を提供します。

public interface PersonMapper {

    @Insert("Insert into person(name) values (#{name})")
    public Integer save(Person person);

    // ...

    @Select(
      "Select personId, name from Person where personId=#{personId}")
    @Results(value = {
      @Result(property = "personId", column = "personId"),
      @Result(property="name", column = "name"),
      @Result(property = "addresses", javaType = List.class,
        column = "personId", many=@Many(select = "getAddresses"))
    })
    public Person getPersonById(Integer personId);

    // ...
}

5. MyBatisアノテーション

MyBatisが提供する主な注釈のいくつかを見てみましょう。

  • @ Insert、@ Select、@ Update、@ Delete – これらのアノテーションは、アノテーション付きメソッドを呼び出すことによって実行されるSQLステートメントを表します。
    @Insert("Insert into person(name) values (#{name})")
    public Integer save(Person person);
    
    @Update("Update Person set name= #{name} where personId=#{personId}")
    public void updatePerson(Person person);
    
    @Delete("Delete from Person where personId=#{personId}")
    public void deletePersonById(Integer personId);
    
    @Select("SELECT person.personId, person.name FROM person 
      WHERE person.personId = #{personId}")
    Person getPerson(Integer personId);
  • @Results –データベース列がJavaクラス属性にマップされる方法の詳細を含む結果マッピングのリストです。
    @Select("Select personId, name from Person where personId=#{personId}")
    @Results(value = {
      @Result(property = "personId", column = "personId")
        // ...   
    })
    public Person getPersonById(Integer personId);
  • @結果 –それはの単一のインスタンスを表します結果から取得した結果のリストから @結果。 これには、データベース列からJava Beanプロパティへのマッピング、プロパティのJavaタイプ、および他のJavaオブジェクトとの関連付けなどの詳細が含まれます。
    @Results(value = {
      @Result(property = "personId", column = "personId"),
      @Result(property="name", column = "name"),
      @Result(property = "addresses", javaType =List.class) 
        // ... 
    })
    public Person getPersonById(Integer personId);
  • @Many –1つのオブジェクトから他のオブジェクトのコレクションへのマッピングを指定します。
    @Results(value ={
      @Result(property = "addresses", javaType = List.class, 
        column = "personId",
        many=@Many(select = "getAddresses"))
    })

    ここで、 getAddresses は、Addressテーブルにクエリを実行してAddressのコレクションを返すメソッドです。

    @Select("select addressId, streetAddress, personId from address 
      where personId=#{personId}")
    public Address getAddresses(Integer personId);

    @Many アノテーションと同様に、オブジェクト間の1対1のマッピング関係を指定する@Oneアノテーションがあります。

  • @MapKey – これは、レコードのリストをvalue属性で定義されたキーを持つレコードのMapに変換するために使用されます。
    @Select("select * from Person")
    @MapKey("personId")
    Map<Integer, Person> getAllPerson();
  • @Options – このアノテーションは、定義するさまざまなスイッチと構成を指定するため、他のステートメントで定義する代わりに、@Optionsで定義できます。
    @Insert("Insert into address (streetAddress, personId) 
      values(#{streetAddress}, #{personId})")
    @Options(useGeneratedKeys = false, flushCache=true)
    public Integer saveAddress(Address address);

6. 動的SQL

動的SQLは、MyBatisが提供する非常に強力な機能です。 これにより、複雑なSQLを正確に構造化できます。

従来のJDBCコードでは、SQLステートメントを記述し、それらをスペースの正確さで連結し、適切な場所にコンマを配置する必要があります。 これは非常にエラーが発生しやすく、大きなSQLステートメントの場合はデバッグが非常に困難です。

アプリケーションで動的SQLを使用する方法を見てみましょう。

@SelectProvider(type=MyBatisUtil.class, method="getPersonByName")
public Person getPersonByName(String name);

ここでは、最終的なSQLを実際に構築および生成するクラスとメソッド名を指定しました。

public class MyBatisUtil {
 
    // ...
 
    public String getPersonByName(String name){
        return new SQL() {{
            SELECT("*");
            FROM("person");
            WHERE("name like #{name} || '%'");
        }}.toString();
    }
}

動的SQLは、すべてのSQL構造をクラスとして提供します。 SELECT WHEREなど。 これにより、WHERE句の生成を動的に変更できます。

7. ストアドプロシージャのサポート

@Selectアノテーションを使用してストアドプロシージャを実行することもできます。 ここでは、ストアドプロシージャの名前とパラメータリストを渡し、そのプロシージャに明示的なCallを使用する必要があります。

@Select(value= "{CALL getPersonByProc(#{personId,
  mode=IN, jdbcType=INTEGER})}")
@Options(statementType = StatementType.CALLABLE)
public Person getPersonByProc(Integer personId);

8. 結論

このクイックチュートリアルでは、MyBatisが提供するさまざまな機能と、データベース向けアプリケーションの開発を容易にする方法について説明しました。 また、ライブラリによって提供されるさまざまな注釈も確認しました。

この記事の完全なコードは、GitHubから入手できます。