最小構成でMyBatisを動作させる(pure Java)

普段noteでは自作迷路の投稿を主に行っていますが、本業はシステムエンジニアのアーシです。


noteというプラットフォーム、エンジニアを名乗る方は結構多いですが、技術記事というものはあまり投稿されていません。


今回はMyBatisを取り上げますが、2020年5月20日現在、note内でMyBatisの検索を行うとヒットする記事はたったの7件。(記事以外を含めると9件)

うち、MyBatisの中身について少しでも触れているのは2件と、とてもマイナーなジャンルになります。


MyBatis自体はJavaを利用したフレームワークを利用する場合は比較的メジャーなDBアクセス方式です。


そんなMyBatis、今回は最小構成でMyBatisを使う方法を紹介!

MyBatisとはどんなものか知りたい、試しに最小構成で使ってみたいという方はぜひ。


Springフレームワークもmavenも要りません。

pureJavaだけでmybatisによるDBアクセスがどこまでできるか、試してみましょう!


準備するもの

MyBatisを使用するにあたり、以下の物を準備します。

 ・開発環境
 ・データベース
 ・MyBatis


今回、開発環境はEclipseを使います。

バージョンによって大きな差はないはずですが、私のPCにインストールされているEclipseのバージョンは下記の通りです。(古い)

Version: Luna Service Release 2 (4.4.2)
Build id: 20150219-0600

【Eclipseのダウンロードはこちらから】
https://mergedoc.osdn.jp/


データベースはOracleが無償で提供しているOracle Database 18c Express Edition(XE)を使います。

【Oracle XEのダウンロードはこちらから】
https://www.oracle.com/jp/database/technologies/appdev/xe.html
(注)Oracleのアカウントを作成する必要があります!!


また、セットアップしたOracle XEのデータベースに対して、下記のSQLを発行し、今回使うテーブルを作成しておきます。

CREATE TABLE DUMMY_TABLE (
ID NUMBER(6),
NAME VARCHAR2(100)
);


MyBatisを使うためにはMyBatisのjarはもちろん必須です。

書いている時点では3.5.4が最も新しいMyBatisのば

【MyBatisのダウンロードはこちらから】
https://mybatis.org/mybatis-3/ja/getting-started.html


最小構成でMyBatisを実装する

ここから、最小構成でMyBatisを使用するための資産作りを行います。

Eclipseで新規Javaプロジェクトを作成し、JREはJava8を選択(もっと古くても可)、MyBatisのjarおよびOracleドライバのjarにビルドパスを通す、と最低限の設定をします。


今回行うMyBatisの最低限の構成では、下記のように6つのファイルを作成します。

xml資産:
 ・mybatis-config.xml
 ・DummyTableMapper.xml (★)

Java資産:
 ・DummyTableMapper.java (★)
 ・DummyTableBean.java
 ・DummyTableDao.java
 ・Main.java(Daoを起動するためだけに実装する。最小構成としては不要)


(★)をつけた2つのファイルは名前が同じ必要があるのが重要なポイントです。

それぞれのファイルの中身については各々の章で見ていきましょう。


xml資産の作成

 ・mybatis-config.xml

MyBatisを使う上で最も基本となる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="test">
   <environment id="test">
     <transactionManager type="JDBC"/>
     <dataSource type="POOLED">
       <property name="driver" value="oracle.jdbc.driver.OracleDriver"/>
       <property name="url" value="jdbc:oracle:thin:@sid:1521:xe"/>
       <property name="username" value="user"/>
       <property name="password" value="pass"/>
     </dataSource>
   </environment>
 </environments>
 <mappers>
   <mapper resource="resources/DummyTableMapper.xml"/>
 </mappers>
</configuration>

今回紹介する資産は基本的にコピペでOKですが、このファイルの下記4箇所は自分のOracleDBの状態に合わせて修正してください。

 「sid」:アクセスしたいOracleDBのスキーマ名
 「1521」:アクセスしたいOracleDBのポート番号
 「user」:アクセスしたいOracleDBのユーザ名
 「pass」:アクセスしたいOracleDBのパスワード


 ・DummyTableMapper.xml

DUMMY_TABLEにアクセスするO/Rマッピングを行うための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="resources.DummyTableMapper">
 <resultMap id="DummyTableBeanMap" type="bean.DummyTableBean">
   <result property="id" column="ID" />
   <result property="name" column="NAME" />
 </resultMap>
 <select id="selectAll" resultMap="DummyTableBeanMap">
   SELECT * FROM DUMMY_TABLE
 </select>
 <select id="selectById" resultMap="DummyTableBeanMap" parameterType="Integer">
   SELECT * FROM DUMMY_TABLE WHERE ID='${id}'
 </select>
 <select id="selectByCols" resultMap="DummyTableBeanMap" parameterType="bean.DummyTableBean">
   SELECT * FROM DUMMY_TABLE WHERE ID='${id}' AND NAME='${name}'
 </select>
 <insert id="insert" parameterType="bean.DummyTableBean">
   INSERT INTO DUMMY_TABLE VALUES ('${id}','${name}')
 </insert>
 <delete id="deleteAll">
   DELETE FROM DUMMY_TABLE
 </delete>
 <delete id="deleteById" parameterType="Integer">
   DELETE FROM DUMMY_TABLE WHERE ID='${id}'
 </delete>
</mapper>

今回は最小構成といいつつ、説明のため、6つのメソッドを用意しました。

後述のJavaファイルと並べて参照ください。

resultMapタグ内には、select結果を格納するための設定が記載されます。
typeにはJavaで作成するBean名を記載します。
resultタグ内のpropertyにはBean内の項目の名称、columnにはデータベースの項目の名称を記載します。

selectのメソッドは今回、「selectAll」「selectById」「selectByCols」の3種類を定義しています。
いずれも戻り値はresultMapで指定しているidが「DummyTableBeanMap」のresultMap、すなわち「bean.DummyTableBean」に格納されます。
「selectAll」では引数無しでDUMMY_TABLE全量を取得します。
「selectById」では、parameterTypeで指定した「Integer」型の項目を引数に、SQLを発行します。
${id}と書かれた箇所に引数で指定した値が代入されています。
「selectByCols」では、parameterTypeで指定した「bean.DummyTableBean」型の項目を引数に、SQLを発行します。
${id}および${name}と書かれた箇所に引数で指定した値が代入されています。

insertのメソッドは今回1つだけ定義しています。
selectと異なり、戻り値がないためresultMapの指定は不要、引数を表わすparameterTypeに「bean.DummyTableBean」を指定しています。
Beanの情報がDUMMY_TABLEに格納されます。

deleteのメソッドは今回、「deleteAll」「deleteById」の2つを定義しています。
selectとinsertのxml記述方法を理解していれば改めて説明する必要はありません。
答え合わせ・凡例を増やすために定義しています。


最後に補足をしておくと、SQLの末尾に終了を表わす「;」を入力していると、実行時にエラーになります。
注意しましょう。


Java資産の作成

 ・DummyTableMapper.java

DummyTableMapper.xmlとのインターフェースを記述します。

package resources;

import java.util.List;

import bean.DummyTableBean;

public interface DummyTableMapper {

	public List<DummyTableBean> selectAll();

	public List<DummyTableBean> selectById(int id);

	public List<DummyTableBean> selectByCols(DummyTableBean bean);

	public void insert(DummyTableBean bean);

	public void deleteAll();

	public void deleteById(int id);
}

DummyTableMapper.xmlで指定しているメソッド単位でメソッドを作成し、parameterTypeで指定している型を引数に、resultMapで指定している型を戻り値に指定します。

classではなく、interfaceとして作成します。


 ・DummyTableBean.java

DUMMY_TABLEの情報を格納するためのBeanです。

package bean;

public class DummyTableBean {

	int id;
	String name;

	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;
	}

	@Override
	public String toString() {
		return "DummyTableBean [id=" + id + ", name=" + name + "]";
	}
}

今回はidとnameの2項目しかないため、単純な作りになっています。


 ・DummyTableDao.java

DUMMY_TABLEへアクセスするためのDaoです。

package dao;

import java.io.InputStream;
import java.util.List;

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 resources.DummyTableMapper;
import bean.DummyTableBean;

public class DummyTableDao {
	DummyTableMapper mapper = null;

	public DummyTableDao() {
		try {
			// mybatis-configの格納先を記載
			String resource = "resources\\mybatis-config.xml";
			InputStream inputStream = Resources.getResourceAsStream(resource);
			// セッション取得
			SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
					.build(inputStream);
			// 今回はauto-commitをtrueとする
			SqlSession session = sqlSessionFactory.openSession(true);
			mapper = session.getMapper(DummyTableMapper.class);
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("Could not get session.");
		}

	}

	public List<DummyTableBean> selectAll() {
		return mapper.selectAll();
	}

	public List<DummyTableBean> selectById(int id) {
		return mapper.selectById(id);
	}

	public List<DummyTableBean> selectByCols(DummyTableBean bean) {
		return mapper.selectByCols(bean);
	}

	public void insert(DummyTableBean bean) {
		mapper.insert(bean);
	}

	public void deleteAll() {
		mapper.deleteAll();
	}

	public void deleteById(int id) {
		mapper.deleteById(id);
	}
}

コンストラクタでsqlsessionを利用したマッパーを作成している以外は、DummyTableMapperに単純にデータを渡しているのみです。

今回はトランザクション制御まで紹介するつもりはないため、sqlsession作成時にauto-commitをtrueにしています。


 ・Main.java

最後に、今回作成した資産を実行するためのMainクラスを作成しました。

実行方法はJUnitを使うなど、いくらでもやり方があるため、最小構成で実行するための一例と考えてください。

package main;

import java.util.ArrayList;
import java.util.List;

import bean.DummyTableBean;
import dao.DummyTableDao;

public class Main {

	public static void main(String[] args) {
		System.out.println("Start MyBatis");

		if (args.length == 0) {
			System.out.println("args.length=0");
			System.out.println("End MyBatis");
			return;
		}

		DummyTableDao dao = new DummyTableDao();
		List<DummyTableBean> beanList = new ArrayList<DummyTableBean>();

		if ("select".equals(args[0])) {
			if (args.length == 1) {
				beanList = dao.selectAll();
			} else if (args.length == 2) {
				beanList = dao.selectById(Integer.parseInt(args[1]));
			} else if (args.length == 3) {
				DummyTableBean inBean = new DummyTableBean();
				inBean.setId(Integer.parseInt(args[1]));
				inBean.setName(args[2]);
				beanList = dao.selectByCols(inBean);
			}
			for (DummyTableBean outBean : beanList) {
				System.out.println(outBean.toString());
			}
		} else if ("insert".equals(args[0])) {
			if (args.length == 3) {
				DummyTableBean inBean = new DummyTableBean();
				inBean.setId(Integer.parseInt(args[1]));
				inBean.setName(args[2]);
				dao.insert(inBean);
			}
		} else if ("delete".equals(args[0])) {
			if (args.length == 1) {
				dao.deleteAll();
			} else if (args.length == 2) {
				dao.deleteById(Integer.parseInt(args[1]));
			}
		} else {
			System.out.println("args[0]不正");
		}

		System.out.println("End MyBatis");
	}
}

テスト用なのでエラーハンドリングはまともにしていません。

これで、ほぼコピペでpureJavaを使用したMyBatisの動作が可能です。


参考までに、私のPCではMyBatisのjarおよびOracleドライバのjarしかビルドパスを通さず、MyBatisを使用したDBアクセスができています。

画像1


あとがき

今回、MyBatisの最小構成について書いたのは、私がMyBatisの動作を知りたくてちょっと使おうと思った時、かなりハマったからです。

MyBatisの公式ページの書き方が結構不親切というのはあるのですが、Qiitaを調べてみてもSpringフレームワークやmavenを使っているものがほとんどで、MyBatisを始めるための第一歩となる情報がありませんでした。


今回、この記事を基にMyBatisの最初の一歩を踏み出し、そこから少しずつ、Java+O/Rマッパーの世界に足を踏み入れる人が少しでも増えたらなと思います。


初めて書く技術系の記事ですので、

ここが分かりにくい、
ここはこっちが正しい、
こういうものも紹介して欲しい、

などありましたら是非コメントで教えてください。

サポートいただけますと幸いです。より多くの人に私の迷路を伝えられるようがんばります。