Skip to content

Commit 13d9aa8

Browse files
Patch applied for http://code.google.com/p/mybatis/issues/detail?id=179 did not support non fully qualified namespaces. Since MyBatis does not require namespaces to match mapper's class, this patch is applied so that changes made to correct bug 179 also supports any valid namespaces.
1 parent 4fd39b7 commit 13d9aa8

File tree

7 files changed

+222
-2
lines changed

7 files changed

+222
-2
lines changed

src/main/java/org/apache/ibatis/builder/xml/XMLMapperBuilder.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ private void sqlElement(List<XNode> list) throws Exception {
209209
private void bufferStatementNodes(List<XNode> list) {
210210
String currentNamespace = builderAssistant.getCurrentNamespace();
211211
configuration.addStatementNodes(currentNamespace, list);
212+
configuration.addResource(currentNamespace, resource);
212213
}
213214

214215
private ResultMapping buildResultMappingFromContext(XNode context, Class<?> resultType, ArrayList<ResultFlag> flags) throws Exception {

src/main/java/org/apache/ibatis/session/Configuration.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ public class Configuration {
7474

7575
/** A map holds statement nodes for a namespace. */
7676
protected final ConcurrentMap<String, List<XNode>> statementNodesToParse = new ConcurrentHashMap<String, List<XNode>>();
77+
/** A map holds a resource for a namespace. */
78+
protected final Map<String, String> resourceMap = new HashMap<String, String>();
7779
/**
7880
* A map holds cache-ref relationship. The key is the namespace that
7981
* references a cache bound to another namespace and the value is the
@@ -412,6 +414,10 @@ public void addStatementNodes(String namespace, List<XNode> nodes) {
412414
statementNodesToParse.put(namespace, nodes);
413415
}
414416

417+
public void addResource(String namespace, String resource) {
418+
resourceMap.put(namespace, resource);
419+
}
420+
415421
public void addCacheRef(String namespace, String referencedNamespace) {
416422
cacheRefMap.put(namespace, referencedNamespace);
417423
}
@@ -432,7 +438,12 @@ public void buildAllStatements() {
432438

433439
protected void buildStatementsFromId(String id) {
434440
final String namespace = extractNamespace(id);
435-
buildStatementsForNamespace(namespace);
441+
if (namespace == null) {
442+
// the id is a short name. process all statements.
443+
buildAllStatements();
444+
} else {
445+
buildStatementsForNamespace(namespace);
446+
}
436447
}
437448

438449
/**
@@ -456,7 +467,7 @@ protected void buildStatementsForNamespace(String namespace) {
456467
if (namespace != null) {
457468
final List<XNode> list = statementNodesToParse.get(namespace);
458469
if (list != null) {
459-
final String resource = namespace.replace('.', '/') + ".xml";
470+
final String resource = resourceMap.get(namespace);
460471
final MapperBuilderAssistant builderAssistant = new MapperBuilderAssistant(this, resource);
461472
builderAssistant.setCurrentNamespace(namespace);
462473
// Set a cache reference if one is bound to this namespace.
@@ -469,6 +480,7 @@ else if(cacheRefMap.containsKey(namespace)) {
469480
parseStatementNodes(builderAssistant, list);
470481
// Remove the processed nodes and resource from the cache.
471482
statementNodesToParse.remove(namespace);
483+
resourceMap.remove(namespace);
472484
}
473485
}
474486
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
3+
<!DOCTYPE configuration
4+
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
5+
"http://mybatis.org/dtd/mybatis-3-config.dtd">
6+
7+
<configuration>
8+
9+
<environments default="development">
10+
<environment id="development">
11+
<transactionManager type="JDBC">
12+
<property name="" value=""/>
13+
</transactionManager>
14+
<dataSource type="UNPOOLED">
15+
<property name="driver" value="org.hsqldb.jdbcDriver"/>
16+
<property name="url" value="jdbc:hsqldb:mem:xmlextref"/>
17+
<property name="username" value="sa"/>
18+
</dataSource>
19+
</environment>
20+
</environments>
21+
22+
<mappers>
23+
<mapper resource="org/apache/ibatis/submitted/xml_external_ref/NonFullyQualifiedNamespacePersonMapper.xml"/>
24+
<mapper resource="org/apache/ibatis/submitted/xml_external_ref/NonFullyQualifiedNamespacePetMapper.xml"/>
25+
</mappers>
26+
27+
</configuration>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
3+
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
4+
<mapper namespace="person namespace">
5+
<cache-ref namespace="pet namespace" />
6+
<resultMap type="org.apache.ibatis.submitted.xml_external_ref.Person"
7+
id="personResult">
8+
<id property="id" column="person_id" />
9+
<result property="name" column="person_name" />
10+
</resultMap>
11+
<resultMap type="org.apache.ibatis.submitted.xml_external_ref.Person"
12+
id="resultWithPets" extends="personResult">
13+
<collection property="pets"
14+
ofType="org.apache.ibatis.submitted.xml_external_ref.Pet" resultMap="pet namespace.petResult" />
15+
</resultMap>
16+
<sql id="personColumnList">
17+
person_id, person_name
18+
</sql>
19+
<!-- Referencing a sql fragment in another file -->
20+
<select id="select" parameterType="java.lang.Integer" resultMap="resultWithPets">
21+
SELECT
22+
<include refid="personColumnList" />
23+
,
24+
<include refid="pet namespace.petColumnList" />
25+
FROM person, pet
26+
WHERE person_id = #{id}
27+
AND person_id = owner_id
28+
ORDER
29+
BY pet_id
30+
</select>
31+
<!-- Referencing a sql fragment and a result map in another file -->
32+
<select id="selectPet" parameterType="java.lang.Integer"
33+
resultMap="pet namespace.petResult">
34+
SELECT
35+
<include refid="pet namespace.petColumnList" />
36+
FROM pet
37+
WHERE pet_id = #{id}
38+
</select>
39+
</mapper>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
3+
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
4+
<mapper namespace="pet namespace">
5+
<cache />
6+
<resultMap type="org.apache.ibatis.submitted.xml_external_ref.Pet"
7+
id="petResult">
8+
<id property="id" column="pet_id" />
9+
<result property="ownerId" column="owner_id" />
10+
<result property="name" column="pet_name" />
11+
</resultMap>
12+
<resultMap type="org.apache.ibatis.submitted.xml_external_ref.Pet"
13+
id="resultWithOwner" extends="petResult">
14+
<association property="owner"
15+
javaType="org.apache.ibatis.submitted.xml_external_ref.Person"
16+
resultMap="person namespace.personResult" />
17+
</resultMap>
18+
<sql id="petColumnList">
19+
pet_id, owner_id, pet_name
20+
</sql>
21+
<select id="select" parameterType="java.lang.Integer" resultMap="resultWithOwner">
22+
SELECT
23+
<include refid="petColumnList" />
24+
,
25+
<include refid="person namespace.personColumnList" />
26+
FROM pet, person where person_id = owner_id
27+
AND pet_id = #{id}
28+
</select>
29+
</mapper>
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package org.apache.ibatis.submitted.xml_external_ref;
2+
3+
import static org.junit.Assert.*;
4+
5+
import java.io.IOException;
6+
import java.io.Reader;
7+
import java.sql.Connection;
8+
import java.sql.SQLException;
9+
10+
import org.apache.ibatis.io.Resources;
11+
import org.apache.ibatis.jdbc.ScriptRunner;
12+
import org.apache.ibatis.mapping.MappedStatement;
13+
import org.apache.ibatis.session.Configuration;
14+
import org.apache.ibatis.session.SqlSession;
15+
import org.apache.ibatis.session.SqlSessionFactory;
16+
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
17+
import org.junit.Test;
18+
19+
public class NonFullyQualifiedNamespaceTest {
20+
@Test
21+
public void testCrossReferenceXmlConfig() throws Exception {
22+
Reader configReader = Resources
23+
.getResourceAsReader("org/apache/ibatis/submitted/xml_external_ref/NonFullyQualifiedNamespaceConfig.xml");
24+
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configReader);
25+
configReader.close();
26+
27+
Configuration configuration = sqlSessionFactory.getConfiguration();
28+
29+
MappedStatement selectPerson = configuration.getMappedStatement("person namespace.select");
30+
assertEquals(
31+
"org/apache/ibatis/submitted/xml_external_ref/NonFullyQualifiedNamespacePersonMapper.xml",
32+
selectPerson.getResource());
33+
34+
Connection conn = configuration.getEnvironment().getDataSource().getConnection();
35+
initDb(conn);
36+
37+
SqlSession sqlSession = sqlSessionFactory.openSession();
38+
try {
39+
Person person = (Person) sqlSession.selectOne("person namespace.select", 1);
40+
assertEquals((Integer)1, person.getId());
41+
assertEquals(2, person.getPets().size());
42+
assertEquals((Integer)2, person.getPets().get(1).getId());
43+
44+
Pet pet = (Pet) sqlSession.selectOne("person namespace.selectPet", 1);
45+
assertEquals(Integer.valueOf(1), pet.getId());
46+
47+
Pet pet2 = (Pet) sqlSession.selectOne("pet namespace.select", 3);
48+
assertEquals((Integer)3, pet2.getId());
49+
assertEquals((Integer)2, pet2.getOwner().getId());
50+
}
51+
finally {
52+
sqlSession.close();
53+
}
54+
}
55+
56+
private static void initDb(Connection conn) throws IOException, SQLException {
57+
try {
58+
Reader scriptReader = Resources
59+
.getResourceAsReader("org/apache/ibatis/submitted/xml_external_ref/CreateDB.sql");
60+
ScriptRunner runner = new ScriptRunner(conn);
61+
runner.setLogWriter(null);
62+
runner.setErrorLogWriter(null);
63+
runner.runScript(scriptReader);
64+
conn.commit();
65+
scriptReader.close();
66+
}
67+
finally {
68+
if (conn != null) {
69+
conn.close();
70+
}
71+
}
72+
}
73+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package org.apache.ibatis.submitted.xml_external_ref;
2+
3+
import static org.junit.Assert.*;
4+
5+
import java.io.IOException;
6+
import java.io.Reader;
7+
8+
import org.apache.ibatis.io.Resources;
9+
import org.apache.ibatis.mapping.MappedStatement;
10+
import org.apache.ibatis.session.Configuration;
11+
import org.apache.ibatis.session.SqlSessionFactory;
12+
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
13+
import org.junit.Test;
14+
15+
public class ShortNameTest {
16+
@Test
17+
public void getStatementByShortName() throws Exception {
18+
Configuration configuration = getConfiguration();
19+
// statement can be referenced by its short name.
20+
MappedStatement selectPet = configuration.getMappedStatement("selectPet");
21+
assertNotNull(selectPet);
22+
}
23+
24+
@Test(expected = IllegalArgumentException.class)
25+
public void ambiguousShortNameShouldFail() throws Exception {
26+
Configuration configuration = getConfiguration();
27+
// ambiguous short name should throw an exception.
28+
MappedStatement ambiguousStatement = configuration.getMappedStatement("select");
29+
fail("If there are multiple statements with the same name, an exception should be thrown.");
30+
}
31+
32+
private Configuration getConfiguration() throws IOException {
33+
Reader configReader = Resources
34+
.getResourceAsReader("org/apache/ibatis/submitted/xml_external_ref/MapperConfig.xml");
35+
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configReader);
36+
configReader.close();
37+
return sqlSessionFactory.getConfiguration();
38+
}
39+
}

0 commit comments

Comments
 (0)