如何使用MyBatis 3.0.5创建双向映射?

时间:2011-10-16 15:18:44

标签: mybatis

假设我有两个域对象和一个映射器接口。

class Person {
    int id;
    List<Problem> problems = new ArrayList<Problem>();
}

class Problem {
    int id;
    Person person;
}

interface PersonMapper {
    public List<Person> selectAllPersons();
}

两个数据库表。

create table person (
    id integer not null generated always as identity constraint person_pk primary key,
)

create table problem (
    id integer not null generated always as identity constraint problem_pk primary key,
    person_id integer not null constraint problem_person_fk references person
)

我可以创建一个获取我想要的数据的映射文件。

<resultMap id="personMap" type="Person">
    <id column="person_id" property="id" />
    <collection column="problem_person_id" property="problems"
                javaType="ArrayList" ofType="Problem" resultMap="problemMap" />
</resultMap>

<resultMap id="problemMap" type="Problem">
    <id column="problem_id" property="id" />
    <!-- Adding an association here will cause a circular dependency -->
    <!-- The circular dependency results in a StackOverflowException -->
</resultMap>

<select id="selectAllPersons" resultMap="personMap">
    select
        person.id as person_id,
        problem.id as problem_id
    from person left outer join problem on person.id = problem.person_id
</select>

但是,由于MyBatis不进行双向映射,因此返回集合中的Problem个对象都不会正确设置其Person引用。

根据this issue,听起来我应该能够更新我的mapper接口并添加一个可以由调用类提供的自定义结果处理程序。

interface PersonMapper {
    public List<Person> selectAllPersons(ResultHandler handler);
}

class PersonResultHandler implements ResultHandler {
    @Override
    public void handleResult(ResultContext context) {
        System.out.println(context.getResultObject());
    }
}

class PersonDAO {
    // Get SqlSession sqlSession
    sqlSession.getMapper(PersonMapper.class).selectAllPersons(new PersonResultHandler());
}

但是,我handleResult的{​​{1}}方法永远不会被调用。我见过this example,但那里额外的绒毛课让人很难理解。任何人都可以给我一个使用映射器接口的自定义ResultHandler的简单示例吗?我正在使用MyBatis 3.0.5 +。

我还阅读了MyBatis邮件列表,并提出了一些使用缓存和延迟加载来解决循环依赖关系的建议,但我找不到任何有关如何执行此操作的示例。

1 个答案:

答案 0 :(得分:1)

您应该将方法声明替换为:

interface PersonMapper {
    public void selectAllPersons(ResultHandler handler);
}

并在List<Person>

中填充PersonResultHandler
class PersonResultHandler implements ResultHandler {

    List<Person> persons = new ArrayList<Person>();

    @Override
    public void handleResult(ResultContext context) {
        Object result = context.getResultObject();
        if (result instanceof Person) {
            Person person = (Person) result;
            for (Problem problem : person.getProblems()) {
                problem.setPerson(person);
            }
            persons.add(person);
        }
    }

    public List<Person> getPersons() {
        return persons;
    }
}