2012-03-06 3 views
0

У меня есть два класса:Круговые реверансы в Ibatis

class Apple { 
    Worm worm; 
} 

class Worm { 
    Apple apple; 
} 

Они хранятся в БД в 1: 1 моды:

table Apple(id, wormId) 
table Worm(id) 

Каждое яблоко имеет только один червь, и наоборот.

с из Ibatis я могу сделать это просто:

Worm worm = new Worm(); 
Apple apple = new Apple(); 
worm.setApple(apple); 
apple.setWorm(worm); 

Как я могу это сделать в 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> 

Итак, я хочу, чтобы быть в состоянии сделать:

Apple apple = foo.queryForObject("getApple", 42L); 
Worm = worm.getApple(); 
Apple appleAgain = apple.getWorm().getApple(); 
// apple == appleAgain here 

Вместо этого я получаю StackOverflowException потому, что распорки называет getWormByApple/getApple навсегда.

Я вижу только одно решение здесь:

class Apple { 
    void setWorm(Worm worm){ 
    this.worm = worm; 
    worm.setApple(this); 
    } 

... и удалить "свойство =" яблоко "" от Worm resultMap.

Но это отстой, потому что я должен был бы помнить, какие сеттеры обновляют аргумент, а с нет. Это также плохо, потому что может привести к бесконечному циклу, если сеттер Worm изменит аргумент.

Я также не хочу «исправлять» утечки iBatis с помощью моих классов моделей (т. Е. Я вообще не хочу прикасаться к моей модели).

Было бы неплохо иметь какой-то «постпроцессор»:

<resultMap id="Apple" type="Apple"> 
    <result property="id" column="id"/> 
    <result property="worm" select="getWormByApple"/> 
    <result property="worm.apple" postProcessor="appleToWormSetter"/> 
</resultMap> 

но нет какой-либо в Ibatis.

Как его решить? Thanks

ответ

0

MyBatis автоматически решает циклические ссылки. Попробуйте это:

<select id="x" resultMap="appleResult"> 
select apple.id, worm.id from apple join worm on apple.worm_id = worm.id 
</select> 

И два результата карты, как эти:

<resultMap id="appleResult" type="Apple"> 
    <id column="apple.id" property="id"/> 
    <association property="worm" resultMap="wormResult"> 
</resultMap> 
<resultMap id="wormResult" type="Worm"> 
    <id column="worm.id" property="id"/> 
    <association property="apple" resultMap="appleResult"> 
</resultMap> 

Обратите внимание, что в этом случае MyBatis обнаружит цикл и связать оба объекта вместе.