ibatis-user-java mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ingmar Lötzsch <iloetz...@asci-systemhaus.de>
Subject execution of nested result maps depends on number of mapped properties?
Date Thu, 23 Oct 2008 09:10:07 GMT
Hello,

I found a behaviour in iBATIS, what I don't unterstand. Dependend on the
list of properties selected in a statement joining 3 tables the
execution of a nested result map results in an instantiation or not.

iBATIS: 2.3.4.726
Spring: 2.5.2

I have 3 tables (I omit the unnecessary properties):

--- tables ---

CREATE TABLE vertragszeitart
(
	id int NOT NULL,
	PRIMARY KEY (id)
);

CREATE TABLE dienstart
(
	id int NOT NULL,
	vertragszeitartid int NOT NULL,
	PRIMARY KEY (id),
	FOREIGN KEY (vertragszeitartid) REFERENCES vertragszeitart (id)
);

CREATE TABLE artikel
(
	id int NOT NULL,
	nummer text NOT NULL,
	dienstartid int,
	PRIMARY KEY (id),
	FOREIGN KEY (dienstartid) REFERENCES dienstart (id)
);

INSERT INTO vertragszeitart (id) VALUES (1);
INSERT INTO dienstart(id, vertragszeitartid) VALUES (1, 1);
INSERT INTO artikel (id, nummer, dienstartid) VALUES (1, 'Art. 1', 1);

--- domain classes ---

class Artikel:

package test;

public class Artikel
{
	private int id;
	private String nummer;
	private Dienstart dienstart;
	public int getId()
	{
		return this.id;
	}
	public void setId(int id)
	{
		this.id = id;
	}
	public String getNummer()
	{
		return this.nummer;
	}
	public void setNummer(String nummer)
	{
		this.nummer = nummer;
	}
	public Dienstart getDienstart()
	{
		return this.dienstart;
	}
	public void setDienstart(Dienstart dienstart)
	{
		this.dienstart = dienstart;
	}
}

class Dienstart:

package test;

public class Dienstart
{
	private int id;
	private Vertragszeitart vertragszeitart;
	public int getId()
	{
		return this.id;
	}
	public void setId(int id)
	{
		this.id = id;
	}
	public Vertragszeitart getVertragszeitart()
	{
		return this.vertragszeitart;
	}
	public void setVertragszeitart(Vertragszeitart vertragszeitart)
	{
		this.vertragszeitart = vertragszeitart;
	}
}
	
class Vertragszeitart:

package test;

public class Vertragszeitart
{
	private int id;
	public int getId()
	{
		return this.id;
	}
	public void setId(int id)
	{
		this.id = id;
	}
}

Now I want to load the artikel with ID 1. 1st approach is using the
select-Element with id "selectTest1":

--- test.xml ---

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd" >
<sqlMap namespace="test" >

<resultMap id="resultVertragszeitart" class="test.Vertragszeitart" >
  <result column="da_vertragszeitartid" property="id" jdbcType="INTEGER" />
</resultMap>
	
<resultMap id="resultDienstart1" class="test.Dienstart" >
  <result column="da_id" jdbcType="INTEGER" property="id" />
  <result property="vertragszeitart"
resultMap="test.resultVertragszeitart"/>
</resultMap>
	
<resultMap id="resultArtikel1" class="test.Artikel" >
  <result column="ar_id" property="id" jdbcType="INTEGER" />
  <result property="dienstart" resultMap="test.resultDienstart1"/>
</resultMap>

<select id="selectTest1" parameterClass="int" resultMap="resultArtikel1" >
	SELECT
		ar.id AS ar_id,
		da.id AS da_id,
		da.vertragszeitartid AS da_vertragszeitartid
	FROM artikel AS ar
	INNER JOIN dienstart AS da ON da.id = ar.dienstartid
	WHERE ar.id = #value#
</select>
</sqlMap>

--- DAO ---

class IbatisTestDAO:

package test;

import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;

public class IbatisTestDAO
extends SqlMapClientDaoSupport
{
	public IbatisTestDAO()
	{
		super();
	}

	public Artikel selectTest1(Integer id)
	{
		Artikel artikel = (Artikel)
getSqlMapClientTemplate().queryForObject("test.selectTest1", id);
		return artikel;
	}
}

-----------------------------

OK, this works. Calling the selectTest1() method returns an instance of
Artikel which contains the ID 1 and an instance of Dienstart, and the
latter contains an instance of Vertragszeitart.

Now I omit one property: the dienstart.id.

Add some elements:

--- test.xml ---

<resultMap id="resultDienstart2" class="test.Dienstart" >
  <result property="vertragszeitart"
resultMap="test.resultVertragszeitart"/>
</resultMap>
	
<resultMap id="resultArtikel2" class="test.Artikel" >
  <result column="ar_id" property="id" jdbcType="INTEGER" />
  <result property="dienstart" resultMap="test.resultDienstart2"/>
</resultMap>
	
<select id="selectTest2" parameterClass="int" resultMap="resultArtikel2" >
	SELECT
		ar.id AS ar_id,
		da.vertragszeitartid AS da_vertragszeitartid
	FROM artikel AS ar
	INNER JOIN dienstart AS da ON da.id = ar.dienstartid
	WHERE ar.id = #value#
</select>
</sqlMap>

--- IbatisTestDAO ---

	public Artikel selectTest2(Integer id)
	{
		Artikel artikel = (Artikel)
getSqlMapClientTemplate().queryForObject("test.selectTest2", id);
		return artikel;
	}

---------------------------

What happens now? Calling IbatisTestDAO.selectTest2() returns an
instance of Artikel, containing the ID 1, but not containing an instance
of Dienstart, although the selected record of artikel contains the value
1 for the column dienstartid.

Of course I searched the sources of iBATIS classes and followed the
execution of code in ResultMap with the debugger. Somewhere during the
call of applyNestedResultMap() in line 380 is decided to not instantiate
the nested object.

Maybe this is related to the comment in line 446:
"//JIRA 375 "Provide a way for not creating items from nested ResultMaps
when the items contain only null values"

Can anybody explain this behaviour?

Thanks a lot!

Ingmar

Mime
View raw message