telcontar4
Aug 18th, 2004, 02:26 PM
I have seen a lot of good discussion around unit testing Hibernate-based DAOs when using lazy loading (for example: http://sourceforge.net/forum/forum.php?thread_id=1030706&forum_id=250340). I wondered if anyone had encountered the same issues when using iBatis and has a similar solution?
DETAILS
----------
Spring 1.0.2, iBatis 2.0.5
I have a class that extends Spring's SqlMapClientDaoSupport and has the following method:
public Order loadOrder(String orderId) throws DataAccessException {
return (Order) getSqlMapClientTemplate().queryForObject("loadOrder", orderId);
}
The Order class includes a java.util.List property for line items. The relevant extracts from the SQL Map file are as follows:
<sqlMap>
<resultMap id="orderMap" class="domain.Order">
<result property="id" column="row_id"/>
...lots of other scalar fields...
<result property="lineItems" column="row_id" select="findLineItemsByOrderId"/>
</resultMap>
<resultMap id="orderItemMap" class="domain.OrderLineItem">
<result property="id" column="row_id"/>
...lots of other scalar fields...
</resultMap>
<select id="loadOrder" resultMap="orderMap">
SELECT
row_id,
...other columns...
FROM
order
WHERE
row_id = #value#
</select>
<select id="findLineItemsByOrderId" parameterClass="java.lang.String"
resultMap="orderItemMap">
SELECT
row_id,
...other columns...
FROM
order_item
WHERE
order_id = #value#
</select>
</sqlMap>
Now, this all works fine when I run the web application: I see all Order and Line Item fields. In my JUnit class, I have the following code (DbUnit stuff omitted):
protected DriverManagerDataSource m_dataSource; //Actually initialized in superclass
protected SqlMapClient m_sqlMapClient; // Actually initialized in superclass
private OrderDao m_dao;
protected void setUp() throws Exception {
m_dataSource = new SingleConnectionDataSource();
m_dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
m_dataSource.setUrl("jdbc:hsqldb:db-location");
m_dataSource.setUsername("sa");
m_dataSource.setPassword("");
m_sqlMapClient = SqlMapClientBuilder.buildSqlMapClient(...);
m_dao = new SqlMapOrderDao();
m_dao.setDataSource(m_dataSource);
m_dao.setSqlMapClient(m_sqlMapClient);
}
public void testLoadOrder() {
Order order = m_dao.loadOrder(orderId);
System.out.println(order); // Exception is thrown here!
...assertions omitted for brevity...
}
When I first attempt to read the value of the line items List property, I get the following stack trace:
java.lang.NullPointerException
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelega te.endTransaction(SqlMapExecutorDelegate.java:465)
at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.en dTransaction(SqlMapSessionImpl.java:134)
at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.end Transaction(SqlMapClientImpl.java:107)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelega te.autoEndTransaction(SqlMapExecutorDelegate.java: 515)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelega te.queryForList(SqlMapExecutorDelegate.java:381)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelega te.queryForList(SqlMapExecutorDelegate.java:359)
at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.qu eryForList(SqlMapSessionImpl.java:90)
at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.que ryForList(SqlMapClientImpl.java:65)
at com.ibatis.sqlmap.engine.mapping.result.loader.Res ultLoader.getResult(ResultLoader.java:65)
at com.ibatis.sqlmap.engine.mapping.result.loader.Laz yResultLoader.loadObject(LazyResultLoader.java:94)
at com.ibatis.sqlmap.engine.mapping.result.loader.Laz yResultLoader.invoke(LazyResultLoader.java:77)
at $Proxy0.hashCode(Unknown Source)
at java.util.HashMap.hash(HashMap.java:261)
at java.util.HashMap.containsKey(HashMap.java:339)
at java.util.HashSet.contains(HashSet.java:180)
at org.apache.commons.lang.builder.ReflectionToString Builder.isRegistered(ReflectionToStringBuilder.jav a:141)
at org.apache.commons.lang.builder.ToStringStyle.appe ndInternal(ToStringStyle.java:340)
at org.apache.commons.lang.builder.ToStringStyle.appe nd(ToStringStyle.java:314)
at org.apache.commons.lang.builder.ToStringBuilder.ap pend(ToStringBuilder.java:872)
at domain.Order.toString(Order.java:361)
...etc. etc....
If I disable lazy-loading, the unit test runs just fine.
DETAILS
----------
Spring 1.0.2, iBatis 2.0.5
I have a class that extends Spring's SqlMapClientDaoSupport and has the following method:
public Order loadOrder(String orderId) throws DataAccessException {
return (Order) getSqlMapClientTemplate().queryForObject("loadOrder", orderId);
}
The Order class includes a java.util.List property for line items. The relevant extracts from the SQL Map file are as follows:
<sqlMap>
<resultMap id="orderMap" class="domain.Order">
<result property="id" column="row_id"/>
...lots of other scalar fields...
<result property="lineItems" column="row_id" select="findLineItemsByOrderId"/>
</resultMap>
<resultMap id="orderItemMap" class="domain.OrderLineItem">
<result property="id" column="row_id"/>
...lots of other scalar fields...
</resultMap>
<select id="loadOrder" resultMap="orderMap">
SELECT
row_id,
...other columns...
FROM
order
WHERE
row_id = #value#
</select>
<select id="findLineItemsByOrderId" parameterClass="java.lang.String"
resultMap="orderItemMap">
SELECT
row_id,
...other columns...
FROM
order_item
WHERE
order_id = #value#
</select>
</sqlMap>
Now, this all works fine when I run the web application: I see all Order and Line Item fields. In my JUnit class, I have the following code (DbUnit stuff omitted):
protected DriverManagerDataSource m_dataSource; //Actually initialized in superclass
protected SqlMapClient m_sqlMapClient; // Actually initialized in superclass
private OrderDao m_dao;
protected void setUp() throws Exception {
m_dataSource = new SingleConnectionDataSource();
m_dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
m_dataSource.setUrl("jdbc:hsqldb:db-location");
m_dataSource.setUsername("sa");
m_dataSource.setPassword("");
m_sqlMapClient = SqlMapClientBuilder.buildSqlMapClient(...);
m_dao = new SqlMapOrderDao();
m_dao.setDataSource(m_dataSource);
m_dao.setSqlMapClient(m_sqlMapClient);
}
public void testLoadOrder() {
Order order = m_dao.loadOrder(orderId);
System.out.println(order); // Exception is thrown here!
...assertions omitted for brevity...
}
When I first attempt to read the value of the line items List property, I get the following stack trace:
java.lang.NullPointerException
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelega te.endTransaction(SqlMapExecutorDelegate.java:465)
at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.en dTransaction(SqlMapSessionImpl.java:134)
at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.end Transaction(SqlMapClientImpl.java:107)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelega te.autoEndTransaction(SqlMapExecutorDelegate.java: 515)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelega te.queryForList(SqlMapExecutorDelegate.java:381)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelega te.queryForList(SqlMapExecutorDelegate.java:359)
at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.qu eryForList(SqlMapSessionImpl.java:90)
at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.que ryForList(SqlMapClientImpl.java:65)
at com.ibatis.sqlmap.engine.mapping.result.loader.Res ultLoader.getResult(ResultLoader.java:65)
at com.ibatis.sqlmap.engine.mapping.result.loader.Laz yResultLoader.loadObject(LazyResultLoader.java:94)
at com.ibatis.sqlmap.engine.mapping.result.loader.Laz yResultLoader.invoke(LazyResultLoader.java:77)
at $Proxy0.hashCode(Unknown Source)
at java.util.HashMap.hash(HashMap.java:261)
at java.util.HashMap.containsKey(HashMap.java:339)
at java.util.HashSet.contains(HashSet.java:180)
at org.apache.commons.lang.builder.ReflectionToString Builder.isRegistered(ReflectionToStringBuilder.jav a:141)
at org.apache.commons.lang.builder.ToStringStyle.appe ndInternal(ToStringStyle.java:340)
at org.apache.commons.lang.builder.ToStringStyle.appe nd(ToStringStyle.java:314)
at org.apache.commons.lang.builder.ToStringBuilder.ap pend(ToStringBuilder.java:872)
at domain.Order.toString(Order.java:361)
...etc. etc....
If I disable lazy-loading, the unit test runs just fine.