Open3
MyBatisのソースコードを読んだ時のメモ
ソースコードを読みたくなった背景
- MyBatis経由でSELECT文を実行した時に、マッピングするクラスにprivateでいいからセッターを生やしておく必要があると教わったので、ソースコード的に真なのか調べたくなった。
- InteliJの外部ライブラリでコードジャンプして読んでいく方向でソースコードを読んでいたが、いろんなクラスがあったりインタフェースの実装クラスがあり、どこに実装があるかぱっと見追えず、外部ライブラリでコードジャンプして読んでいくことに限界を感じた。なので、ライブラリ側でログをだして挙動を把握したいと思った。
MyBatisのソースコードを読んだ時の手順(準備編)
- ソースコードをcloneする
-
git checkout tags/mybatis-3.5.1
して3.5.1のタグに切り替える - InteliJで開く
- 準備をする(データベース側)
- MySQLのサンプルデータベースのsakilaをローカル環境で使えるようにする ※今回は
sakila
のActor
テーブルを使う
-
準備をする(MyBatis側)
- 公式ドキュメントに従って、必要な設定ファイルを配置していく
-
src/test/resources
配下にsample
フォルダを作成し、設定ファイルを追加する
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings> <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://127.0.0.1:3306/sakila"/> <property name="username" value="設定したユーザ名"/> <property name="password" value="設定したパスワード"/> </dataSource> </environment> </environments> <mappers> <mapper resource="sample/ActorMapper.xml"/> </mappers> </configuration>
-
src/test/resources
配下にsample
フォルダの配下に、マッパーのXMLを追加する
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="org.apache.ibatis.sample.mapper.ActorMapper"> <select id="selectActor" resultType="org.apache.ibatis.sample.entity.Actor"> SELECT actor_id, last_name, first_name FROM actor WHERE actor_id = #{id} </select> </mapper>
-
src/test/java
のsample
パッケージ配下にマッピングするクラスとマッパーのインタフェースを追加する
Actor.javapackage org.apache.ibatis.sample.entity; public class Actor { private int actorId; private String firstName; private String lastName; public Actor(int actorId, String firstName, String lastName) { System.out.println("引数ありのコンストラクタが呼ばれた " + actorId + ", " + firstName + ", " + lastName); this.actorId = actorId; this.firstName = firstName; this.lastName = lastName; } public Actor() { System.out.println("引数なしのコンストラクタが呼ばれた"); } public int getActorId() { return actorId; } public void setActorId(int actorId) { System.out.println("setActorIdが呼ばれた " + actorId); this.actorId = actorId; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { System.out.println("setFirstNameが呼ばれた " + firstName); this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { System.out.println("setLastNameが呼ばれた " + lastName); this.lastName = lastName; } @Override public String toString() { return firstName + " " + lastName + " (id: " + actorId + ")"; } }
ActorMapper.javapackage org.apache.ibatis.sample.mapper; import org.apache.ibatis.sample.entity.Actor; public interface ActorMapper { Actor selectActor(int id); }
-
src/test/java
配下にsample
パッケージを作り、テストを追加する
package org.apache.ibatis.sample; import org.apache.ibatis.io.Resources; import org.apache.ibatis.sample.entity.Actor; import org.apache.ibatis.sample.mapper.ActorMapper; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import org.junit.jupiter.api.Test; import java.io.IOException; import java.io.InputStream; public class SampleTest { @Test void クエリを実行する() throws IOException { // https://mybatis.org/mybatis-3/ja/getting-started.html String resource = "sample/mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); try (SqlSession session = sqlSessionFactory.openSession()) { Actor actor = session.selectOne("org.apache.ibatis.sample.mapper.ActorMapper.selectActor", 101); System.out.println("実行結果: " + actor.toString()); } } }
MyBatisのソースコードを読んだ時の手順(実行編)
- 自身で追加したテストコードを実行して、DBに接続できて取得したレコードの内容が出力されるかどうか確認する
- (期待通り動くことが確認できたら)コードジャンプ機能を使って、気になる部分に
System.out.println()
を仕込んで、どのインタフェースを実装しているクラスやその時点の変数の値を確認する。または、ブレイクポイントを張って、デバック実行する。