MyBatis | 検索結果を任意のJavaオブジェクトにマッピング | 関連オブジェクトのロードを遅延させる
ソースコード
sample_mapper.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="sample.mybatis">
<resultMap type="sample.mybatis.Foo" id="fooResultMap">
<id property="id" column="id" />
<association property="bar" column="{key1=bar_key1,key2=bar_key2}" select="selectBar"
fetchType="lazy" /> <!-- fetchTypeをlazyに設定 -->
</resultMap>
<select id="selectFoo" resultMap="fooResultMap">
select * from foo_table
</select>
<select id="selectBar" resultType="sample.mybatis.Bar">
select *
from bar_table
where key1 = #{key1}
and key2 = #{key2}
</select>
</mapper>
Foo.java
package sample.mybatis;
public class Foo {
private int id;
public Bar bar;
public void method() {
System.out.println("Foo.method() is called");
}
}
Main.java
package sample.mybatis;
import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class Main {
public static void main(String[] args) throws Exception {
try (InputStream in = Main.class.getResourceAsStream("/mybatis-config.xml")) {
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
try (SqlSession session = factory.openSession()) {
System.out.println("@selectList()");
List<Foo> result = session.selectList("sample.mybatis.selectFoo");
System.out.println("@result.get(0)");
Foo foo = result.get(0);
System.out.println("** foo.class = " + foo.getClass() + " **");
System.out.println("@foo.bar 1");
System.out.println("<< foo.bar = " + foo.bar + " >>");
System.out.println("@foo.method()");
foo.method();
System.out.println("@foo.bar 2");
System.out.println("<< foo.bar = " + foo.bar + " >>");
}
}
}
}
実行結果
@selectList()
[DEBUG] s.m.selectFoo - ==> Preparing: select * from foo_table
[DEBUG] s.m.selectFoo - ==> Parameters:
[DEBUG] s.m.selectFoo - <== Total: 3
@result.get(0)
** foo.class = class sample.mybatis.Foo_$$_jvst80f_0 **
@foo.bar 1
<< foo.bar = null >>
@foo.method()
[DEBUG] s.m.selectBar - ==> Preparing: select * from bar_table where key1 = ? and key2 = ?
[DEBUG] s.m.selectBar - ==> Parameters: 1(Integer), fuga(String)
[DEBUG] s.m.selectBar - <== Total: 1
Foo.method() is called
@foo.bar 2
<< foo.bar = Bar [key1=1, key2=fuga] >>
説明
<association>のfetchType属性にlazyを設定すると、関連オブジェクトのロードを遅延できる。- デフォルトは即時ロード(eager)である。
- 遅延ロードが設定されたクラスのインスタンスは、MyBatisによって生成されたプロキシになる(class sample.mybatis.Foo _ $$ _ jvst80f_0)。
- 遅延ロードでない場合は、通常のインスタンスが渡される。
- 遅延ロードが実行されるタイミングは、プロキシ内のいずれかのメソッドが実行されたときのようである。
- フィールドを読み取ったときではないため、メソッド実行前に参照するとnullになる。通常は直接見せるものではないと思うが、参考として覚えておく。
デフォルト設定を遅延ロードにしたい場合は、ルート設定でlazyLoadingEnabledを設定する方法がある。
mybatis-config.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>
<settings>
<setting name="lazyLoadingEnabled" value="true"/> <!-- trueにする。 -->
</settings>
...
</configuration>
- この場合でも
<association>タグのfetchTypeが優先されるため、特定のロードだけ即時ロードにしたい場合は設定を上書きできる。