LoginSignup
0
0

More than 1 year has passed since last update.

MyBatisをNoXMLで使う

Last updated at Posted at 2021-11-03

目的

MyBatisは通常XMLで各種定義を行いますが、XMLを使わないことも可能です。

手順

SqlSessionFactoryの取得

CDI+JNDIの場合

Java EEサーバ上で動かす場合はJNDIルックアップと組み合わせます。JNDI定義は例えば次の記事が参考になります。

    @Resource(lookup = "jdbc/********") // JNDI名
    private DataSource dataSource;

    @Produces
    public SqlSessionFactory produceSQLSessionFactory() {
        var config = new Configuration();
        config.addMappers("package.to.mappers"); // Mapperクラスが存在するパッケージ
        config.setEnvironment(new Environment("development", new JdbcTransactionFactory(), dataSource));
        config.setLocalCacheScope(LocalCacheScope.STATEMENT); // キャッシュなし
        config.setMapUnderscoreToCamelCase(true); // SNAKEをCAMELに
        var sqlSessionFactory = new SqlSessionFactoryBuilder().build(config);

        return sqlSessionFactory;
    }

手動で生成する場合

JUnitやスタンドアロンアプリでCDI+JNDIが使えない場合。ただしPGPoolingDataSourceはdeprecatedなので、正式に使う場合はHikari CPなどを挟むとよいでしょう。

    public static SqlSessionFactory getSqlSessionFactory() throws Exception {
        //(注)PGPoolingDataSourceの使用は現在推奨されていない
        var dataSource = new PGPoolingDataSource();
        dataSource.setURL("jdbc:postgresql://localhost:5432/********");
        dataSource.setUser("postgres");
        dataSource.setPassword("********");
        dataSource.setProperty("options", "-c lock_timeout=10000");

        var config = new Configuration();
        config.addMappers("package.to.mappers"); // Mapperクラスが存在するパッケージ
        config.setEnvironment(new Environment("development", new JdbcTransactionFactory(), (DataSource) dataSource));
        config.setLocalCacheScope(LocalCacheScope.STATEMENT); // キャッシュなし
        config.setMapUnderscoreToCamelCase(true); // SNAKEをCAMELに

        return new SqlSessionFactoryBuilder().build(config);
    }

Mapperクラスの作成

好みの分かれるところですが、SQLはアノテーションで指定できます。Spring Dataを真似して次のようなリポジトリクラス(マッパー)を用意します。このクラスは先ほどaddMappers()で指定したパッケージに配置します。

package package.to.mappers;

import java.util.Optional;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.apache.ibatis.cursor.Cursor;

public interface SampleRepository {

    @Select("SELECT id,xxx,yyy_at FROM samples")
    public Cursor<Sample> findAll();

    @Select("SELECT id,xxx,yyy FROM users WHERE id=#{id}")
    public Optional<Sample> findById(int id);

    @Insert("INSERT INTO samples (xxx,yyy) VALUES (#{xxx},#{yyy})")
    public void create(Sample sample);

    @Update("UPDATE samples SET xxx=#{xxx},yyy=#{yyy} WHERE id=#{id}")
    public void update(Sample sample);

    @Delete("DELETE FROM samples WHERE ID=#{id}")
    public void delete(User user);

    @Delete("DELETE FROM samples WHERE ID=#{id}")
    public void deleteById(int id);

}

対応するエンティティクラスも用意しておきます。

import lombok.Data;

@Data
public class Sample {

    private int id;
    private String xxx;
    private String yyy;

}

使い方

次のようにリポジトリ(マッパー)クラスを取得し、エンティティの出し入れをします。

    @Inject
    private SqlSessionFactory sqlSessionFactory;

    public void createSample() {
        try (var session = sqlSessionFactory.openSession()) {
            var sampleRepository = session.getMapper(SampleRepository.class);
            var sample = new Sample();
            sample.setXxx("aaa");
            sample.setYyy("bbb");
            sampleRepository.create(sample);
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

メリット

  • どこでどのSQLを使っているか一目瞭然
  • XMLファイルに悩まされなくてよい
  • チーム開発で競合しにくい

デメリット

  • アノテーションは改行できないので、SQLが長くなると読みづらくなる
  • 素直にSpring Data使えばという気になってくる
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0