Skip to content

Commit 7f4ccce

Browse files
Solved http://code.google.com/p/mybatis/issues/detail?id=301 . The deferLoad method loads the property right away if it's available in the cache.
1 parent 6bf00fc commit 7f4ccce

File tree

11 files changed

+313
-1
lines changed

11 files changed

+313
-1
lines changed

src/main/java/org/apache/ibatis/executor/BaseExecutor.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,12 @@ public List query(MappedStatement ms, Object parameter, RowBounds rowBounds, Res
124124

125125
public void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key) {
126126
if (closed) throw new ExecutorException("Executor was closed.");
127-
deferredLoads.add(new DeferredLoad(ms, resultObject, property, key));
127+
DeferredLoad deferredLoad = new DeferredLoad(ms, resultObject, property, key);
128+
if (deferredLoad.canLoad()) {
129+
deferredLoad.load();
130+
} else {
131+
deferredLoads.add(new DeferredLoad(ms, resultObject, property, key));
132+
}
128133
}
129134

130135
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds) {
@@ -255,6 +260,9 @@ public DeferredLoad(MappedStatement mappedStatement, MetaObject resultObject, St
255260
this.key = key;
256261
}
257262

263+
public boolean canLoad() {
264+
return localCache.getObject(key) != null && localCache.getObject(key) != EXECUTION_PLACEHOLDER;
265+
}
258266
public void load() {
259267
Object value = null;
260268
List list = (List) localCache.getObject(key);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package org.apache.ibatis.submitted.deferload_common_property;
2+
3+
public class Child {
4+
private Integer id;
5+
private String name;
6+
private Father father;
7+
public Integer getId() {
8+
return id;
9+
}
10+
public void setId(Integer id) {
11+
this.id = id;
12+
}
13+
public String getName() {
14+
return name;
15+
}
16+
public void setName(String name) {
17+
this.name = name;
18+
}
19+
public Father getFather() {
20+
return father;
21+
}
22+
public void setFather(Father father) {
23+
this.father = father;
24+
}
25+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package org.apache.ibatis.submitted.deferload_common_property;
2+
3+
import java.util.List;
4+
5+
public interface ChildMapper {
6+
public List<Child> selectAll();
7+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<!DOCTYPE mapper
3+
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
4+
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5+
6+
<mapper namespace="org.apache.ibatis.submitted.deferload_common_property.ChildMapper">
7+
8+
<resultMap id="ChildMap" type="Child">
9+
<id property="id" column="id"/>
10+
<result property="name" column="name"/>
11+
<association property="father" column="father_id" select="org.apache.ibatis.submitted.deferload_common_property.FatherMapper.selectById"/>
12+
</resultMap>
13+
14+
15+
<select id="selectAll" resultMap="ChildMap">
16+
SELECT id, name, father_id
17+
FROM Child
18+
</select>
19+
</mapper>
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package org.apache.ibatis.submitted.deferload_common_property;
2+
3+
import static org.junit.Assert.*;
4+
5+
import java.io.Reader;
6+
import java.sql.Connection;
7+
import java.sql.DriverManager;
8+
import java.util.ArrayList;
9+
import java.util.List;
10+
11+
import org.apache.ibatis.io.Resources;
12+
import org.apache.ibatis.jdbc.ScriptRunner;
13+
import org.apache.ibatis.session.ResultContext;
14+
import org.apache.ibatis.session.ResultHandler;
15+
import org.apache.ibatis.session.SqlSession;
16+
import org.apache.ibatis.session.SqlSessionFactory;
17+
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
18+
import org.junit.BeforeClass;
19+
import org.junit.Test;
20+
21+
public class CommonPropertyDeferLoadError {
22+
23+
private static SqlSessionFactory sqlSessionFactory;
24+
private static SqlSessionFactory lazyLoadSqlSessionFactory;
25+
26+
@BeforeClass
27+
public static void initDatabase() throws Exception {
28+
Connection conn = null;
29+
30+
try {
31+
Class.forName("org.hsqldb.jdbcDriver");
32+
conn = DriverManager.getConnection("jdbc:hsqldb:mem:deferload_common_property", "sa",
33+
"");
34+
35+
Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/deferload_common_property/CreateDB.sql");
36+
37+
ScriptRunner runner = new ScriptRunner(conn);
38+
runner.setLogWriter(null);
39+
runner.setErrorLogWriter(null);
40+
runner.runScript(reader);
41+
conn.commit();
42+
reader.close();
43+
44+
reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/deferload_common_property/ibatisConfig.xml");
45+
sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
46+
reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/deferload_common_property/lazyLoadIbatisConfig.xml");
47+
lazyLoadSqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
48+
reader.close();
49+
} finally {
50+
if (conn != null) {
51+
conn.close();
52+
}
53+
}
54+
}
55+
56+
@Test
57+
public void testDeferLoadAfterResultHandler() {
58+
SqlSession sqlSession = sqlSessionFactory.openSession();
59+
try {
60+
class MyResultHandler implements ResultHandler {
61+
List<Child> children = new ArrayList<Child>();
62+
@Override
63+
public void handleResult(ResultContext context) {
64+
Child child = (Child)context.getResultObject();
65+
children.add(child);
66+
}
67+
};
68+
MyResultHandler myResultHandler = new MyResultHandler();
69+
sqlSession.select("org.apache.ibatis.submitted.deferload_common_property.ChildMapper.selectAll", myResultHandler);
70+
for (Child child: myResultHandler.children) {
71+
assertNotNull(child.getFather());
72+
}
73+
} finally {
74+
sqlSession.close();
75+
}
76+
}
77+
@Test
78+
public void testDeferLoadDuringResultHandler() {
79+
SqlSession sqlSession = sqlSessionFactory.openSession();
80+
try {
81+
class MyResultHandler implements ResultHandler {
82+
@Override
83+
public void handleResult(ResultContext context) {
84+
Child child = (Child)context.getResultObject();
85+
assertNotNull(child.getFather());
86+
}
87+
};
88+
sqlSession.select("org.apache.ibatis.submitted.deferload_common_property.ChildMapper.selectAll", new MyResultHandler());
89+
} finally {
90+
sqlSession.close();
91+
}
92+
}
93+
@Test
94+
public void testDeferLoadAfterResultHandlerWithLazyLoad() {
95+
SqlSession sqlSession = lazyLoadSqlSessionFactory.openSession();
96+
try {
97+
class MyResultHandler implements ResultHandler {
98+
List<Child> children = new ArrayList<Child>();
99+
@Override
100+
public void handleResult(ResultContext context) {
101+
Child child = (Child)context.getResultObject();
102+
children.add(child);
103+
}
104+
};
105+
MyResultHandler myResultHandler = new MyResultHandler();
106+
sqlSession.select("org.apache.ibatis.submitted.deferload_common_property.ChildMapper.selectAll", myResultHandler);
107+
for (Child child: myResultHandler.children) {
108+
assertNotNull(child.getFather());
109+
}
110+
} finally {
111+
sqlSession.close();
112+
}
113+
}
114+
@Test
115+
public void testDeferLoadDuringResultHandlerWithLazyLoad() {
116+
SqlSession sqlSession = lazyLoadSqlSessionFactory.openSession();
117+
try {
118+
class MyResultHandler implements ResultHandler {
119+
@Override
120+
public void handleResult(ResultContext context) {
121+
Child child = (Child)context.getResultObject();
122+
assertNotNull(child.getFather());
123+
}
124+
};
125+
sqlSession.select("org.apache.ibatis.submitted.deferload_common_property.ChildMapper.selectAll", new MyResultHandler());
126+
} finally {
127+
sqlSession.close();
128+
}
129+
}
130+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
create table Child (
2+
id int,
3+
name varchar(100),
4+
father_id int
5+
);
6+
create table Father (
7+
id int,
8+
name varchar(100)
9+
);
10+
11+
INSERT INTO Child (id, name, father_id)
12+
VALUES (1, 'John Smith jr', 1);
13+
INSERT INTO Child (id, name, father_id)
14+
VALUES (2, 'John Smith jr 2', 1);
15+
16+
INSERT INTO Father (id, name)
17+
VALUES (1, 'John Smith');
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package org.apache.ibatis.submitted.deferload_common_property;
2+
3+
public class Father {
4+
private Integer id;
5+
private String name;
6+
public Integer getId() {
7+
return id;
8+
}
9+
public void setId(Integer id) {
10+
this.id = id;
11+
}
12+
public String getName() {
13+
return name;
14+
}
15+
public void setName(String name) {
16+
this.name = name;
17+
}
18+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package org.apache.ibatis.submitted.deferload_common_property;
2+
3+
public interface FatherMapper {
4+
public Father selectById(Integer id);
5+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<!DOCTYPE mapper
3+
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
4+
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
5+
6+
<mapper namespace="org.apache.ibatis.submitted.deferload_common_property.FatherMapper">
7+
8+
<resultMap id="FatherMap" type="Father">
9+
<id property="id" column="id"/>
10+
<result property="name" column="name"/>
11+
</resultMap>
12+
13+
14+
<select id="selectById" resultMap="FatherMap" parameterType="int">
15+
SELECT id, name
16+
FROM Father
17+
WHERE id = #{id}
18+
</select>
19+
</mapper>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<!DOCTYPE configuration
3+
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
4+
"http://mybatis.org/dtd/mybatis-3-config.dtd">
5+
6+
<configuration>
7+
8+
<settings>
9+
<setting name="lazyLoadingEnabled" value="false"/>
10+
</settings>
11+
12+
<typeAliases>
13+
<typeAlias alias="Child" type="org.apache.ibatis.submitted.deferload_common_property.Child"/>
14+
<typeAlias alias="Father" type="org.apache.ibatis.submitted.deferload_common_property.Father"/>
15+
</typeAliases>
16+
17+
<environments default="test">
18+
<environment id="test">
19+
<transactionManager type="JDBC"></transactionManager>
20+
<dataSource type="UNPOOLED">
21+
<property name="driver" value="org.hsqldb.jdbcDriver"/>
22+
<property name="url" value="jdbc:hsqldb:mem:deferload_common_property"/>
23+
<property name="username" value="sa"/>
24+
</dataSource>
25+
</environment>
26+
</environments>
27+
28+
<mappers>
29+
<mapper resource="org/apache/ibatis/submitted/deferload_common_property/ChildMapper.xml"/>
30+
<mapper resource="org/apache/ibatis/submitted/deferload_common_property/FatherMapper.xml"/>
31+
</mappers>
32+
</configuration>

0 commit comments

Comments
 (0)