Skip to content

Commit 5428e1b

Browse files
committed
Fix for http://code.google.com/p/mybatis/issues/detail?id=30 - handle nested result maps with refcursors properly
1 parent 675c4c6 commit 5428e1b

File tree

7 files changed

+202
-0
lines changed

7 files changed

+202
-0
lines changed

src/main/java/org/apache/ibatis/mapping/MappedStatement.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,18 @@ public BoundSql getBoundSql(Object parameterObject) {
200200
if (parameterMappings == null || parameterMappings.size() <= 0) {
201201
boundSql = new BoundSql(configuration, boundSql.getSql(), parameterMap.getParameterMappings(), parameterObject);
202202
}
203+
204+
// check for nested result maps in parameter mappings (issue #30)
205+
for (ParameterMapping pm : boundSql.getParameterMappings()) {
206+
String rmId = pm.getResultMapId();
207+
if (rmId != null) {
208+
ResultMap rm = configuration.getResultMap(rmId);
209+
if (rm != null) {
210+
hasNestedResultMaps |= rm.hasNestedResultMaps();
211+
}
212+
}
213+
}
214+
203215
return boundSql;
204216
}
205217

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
3+
<!DOCTYPE configuration
4+
PUBLIC "-//ibatis.apache.org//DTD Config 3.0//EN"
5+
"http://ibatis.apache.org/dtd/ibatis-3-config.dtd">
6+
<configuration>
7+
8+
<environments default="development">
9+
<environment id="development">
10+
<transactionManager type="JDBC">
11+
<property name="" value=""/>
12+
</transactionManager>
13+
<dataSource type="UNPOOLED">
14+
<property name="driver" value="org.postgresql.Driver"/>
15+
<property name="url" value="jdbc:postgresql:mbtest"/>
16+
<property name="username" value="postgres"/>
17+
<property name="password" value="root"/>
18+
</dataSource>
19+
</environment>
20+
</environments>
21+
22+
<mappers>
23+
<mapper resource="org/apache/ibatis/submitted/refcursor/OrdersMapper.xml"/>
24+
</mappers>
25+
26+
</configuration>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package org.apache.ibatis.submitted.refcursor;
2+
3+
import java.util.List;
4+
5+
public class Order {
6+
private Integer orderId;
7+
private String customerName;
8+
private List<OrderDetail> detailLines;
9+
public Integer getOrderId() {
10+
return orderId;
11+
}
12+
public void setOrderId(Integer orderId) {
13+
this.orderId = orderId;
14+
}
15+
public String getCustomerName() {
16+
return customerName;
17+
}
18+
public void setCustomerName(String customerName) {
19+
this.customerName = customerName;
20+
}
21+
public List<OrderDetail> getDetailLines() {
22+
return detailLines;
23+
}
24+
public void setDetailLines(List<OrderDetail> detailLines) {
25+
this.detailLines = detailLines;
26+
}
27+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package org.apache.ibatis.submitted.refcursor;
2+
3+
public class OrderDetail {
4+
private Integer orderNumber;
5+
private Integer lineNumber;
6+
private Integer quantity;
7+
private String description;
8+
public Integer getLineNumber() {
9+
return lineNumber;
10+
}
11+
public void setLineNumber(Integer lineNumber) {
12+
this.lineNumber = lineNumber;
13+
}
14+
public Integer getQuantity() {
15+
return quantity;
16+
}
17+
public void setQuantity(Integer quantity) {
18+
this.quantity = quantity;
19+
}
20+
public String getDescription() {
21+
return description;
22+
}
23+
public void setDescription(String description) {
24+
this.description = description;
25+
}
26+
public Integer getOrderNumber() {
27+
return orderNumber;
28+
}
29+
public void setOrderNumber(Integer orderNumber) {
30+
this.orderNumber = orderNumber;
31+
}
32+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package org.apache.ibatis.submitted.refcursor;
2+
3+
import java.util.Map;
4+
5+
public interface OrdersMapper {
6+
void getOrder1(Map<String, Object> parameter);
7+
void getOrder2(Map<String, Object> parameter);
8+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN" "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
3+
<mapper namespace="org.apache.ibatis.submitted.refcursor.OrdersMapper">
4+
<resultMap type="org.apache.ibatis.submitted.refcursor.Order" id="OrderResult">
5+
<id property="orderId" column="ORDER_ID"/>
6+
<result property="customerName" column="CUST_NAME"/>
7+
<collection property="detailLines" ofType="org.apache.ibatis.submitted.refcursor.OrderDetail">
8+
<id property="lineNumber" column="LINE_NUMBER"/>
9+
<result property="quantity" column="QUANTITY"/>
10+
<result property="description" column="ITEM_DESCRIPTION"/>
11+
</collection>
12+
</resultMap>
13+
14+
<update id="getOrder1" parameterType="map" statementType="CALLABLE">
15+
{ #{order,jdbcType=OTHER,mode=OUT,resultMap=OrderResult,javaType=java.sql.ResultSet} =
16+
call mbtest.get_order(#{orderId,jdbcType=INTEGER,mode=IN}) }
17+
</update>
18+
19+
<update id="getOrder2" parameterType="map" statementType="CALLABLE">
20+
{ #{order,jdbcType=OTHER,mode=OUT,resultMap=org.apache.ibatis.submitted.refcursor.OrdersMapper.OrderResult,javaType=java.sql.ResultSet} =
21+
call mbtest.get_order(#{orderId,jdbcType=INTEGER,mode=IN}) }
22+
</update>
23+
</mapper>
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package org.apache.ibatis.submitted.refcursor;
2+
3+
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertNotNull;
5+
6+
import java.io.IOException;
7+
import java.io.Reader;
8+
import java.util.HashMap;
9+
import java.util.List;
10+
import java.util.Map;
11+
12+
import org.apache.ibatis.io.Resources;
13+
import org.apache.ibatis.session.SqlSession;
14+
import org.apache.ibatis.session.SqlSessionFactory;
15+
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
16+
import org.junit.Ignore;
17+
import org.junit.Test;
18+
19+
/**
20+
* This class contains tests for refcursors. The tests require a
21+
* local install of PostgreSQL and cannot be run as a part of the normal
22+
* MyBatis build. They must be run manually on a box with PostgreSQL
23+
* setup as described in setupdb.txt
24+
*
25+
* @author Jeff
26+
*
27+
*/
28+
public class RefCursorTest {
29+
@SuppressWarnings("unchecked")
30+
@Test
31+
@Ignore("See setupdb.txt for instructions on how to run this test")
32+
public void testRefCursor1() throws IOException {
33+
Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/refcursor/MapperConfig.xml");
34+
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
35+
SqlSession sqlSession = sqlSessionFactory.openSession();
36+
try {
37+
OrdersMapper mapper = sqlSession.getMapper(OrdersMapper.class);
38+
Map<String, Object> parameter = new HashMap<String, Object>();
39+
parameter.put("orderId", 1);
40+
mapper.getOrder1(parameter);
41+
42+
assertNotNull(parameter.get("order"));
43+
List<Order> orders = (List<Order>) parameter.get("order");
44+
assertEquals(1, orders.size());
45+
Order order = orders.get(0);
46+
assertEquals(3, order.getDetailLines().size());
47+
} finally {
48+
sqlSession.close();
49+
}
50+
}
51+
52+
@SuppressWarnings("unchecked")
53+
@Test
54+
@Ignore("See setupdb.txt for instructions on how to run this test")
55+
public void testRefCursor2() throws IOException {
56+
Reader reader = Resources.getResourceAsReader("org/apache/ibatis/submitted/refcursor/MapperConfig.xml");
57+
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
58+
SqlSession sqlSession = sqlSessionFactory.openSession();
59+
try {
60+
OrdersMapper mapper = sqlSession.getMapper(OrdersMapper.class);
61+
Map<String, Object> parameter = new HashMap<String, Object>();
62+
parameter.put("orderId", 1);
63+
mapper.getOrder2(parameter);
64+
65+
assertNotNull(parameter.get("order"));
66+
List<Order> orders = (List<Order>) parameter.get("order");
67+
assertEquals(1, orders.size());
68+
Order order = orders.get(0);
69+
assertEquals(3, order.getDetailLines().size());
70+
} finally {
71+
sqlSession.close();
72+
}
73+
}
74+
}

0 commit comments

Comments
 (0)