I have two classes:
class Apple {
Worm worm;
}
class Worm {
Apple apple;
}
They are stored in db in 1:1 fashion:
table Apple(id, wormId)
table Worm(id)
Each apple has only one worm and vice versa.
With out of iBatis I can do it simply:
Worm worm = new Worm();
Apple apple = new Apple();
worm.setApple(apple);
apple.setWorm(worm);
How can I do it in ibatis?
<resultMap id="Apple" type="Apple">
<result property="id" column="id"/>
<result property="worm" column="id" select="getWormByApple"/>
</resultMap>
<resultMap id="Worm" type="Worm">
<result property="id" column="id"/>
<result property="apple" column="id" select="getAppleByWorm"/>
</resultMap>
<select id="getApple" resultMap="Apple" parameterClass="java.lang.Long">
SELECT * FROM Apples where id=#value#
</select>
<select id="getWormByApple" resultMap="Worm" parameterClass="java.lang.Long">
SELECT * FROM Worms where appleId=#value#
</select>
So, I want to be able to do:
Apple apple = foo.queryForObject("getApple", 42L);
Worm = worm.getApple();
Apple appleAgain = apple.getWorm().getApple();
// apple == appleAgain here
Instead, I get StackOverFlowException because struts calls getWormByApple / getApple forever.
I see only one solution here:
class Apple {
void setWorm(Worm worm){
this.worm = worm;
worm.setApple(this);
}
...and remove "property="apple"" from Worm resultMap.
But it sucks because I would have to remember which setters update argument and with is not. It also bad because may lead to infinite loop in case when Worm's setter would change argument.
I also do not want to "fix" iBatis leaks with my model classes (i.e. I do not want to touch my model beans at all).
It would be nice to have some kind of "post processor":
<resultMap id="Apple" type="Apple">
<result property="id" column="id"/>
<result property="worm" select="getWormByApple"/>
<result property="worm.apple" postProcessor="appleToWormSetter"/>
</resultMap>
but there is no any in iBatis.
How can I solve it? Thanks