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가 우선되기 때문에 특정 로드만 즉시 로드하고 싶은 경우는 설정을 무시할 수 있다.
최종 수정 : 2021-08-26