我有三个表:grandparent
,parent
和child
。模型非常简单:祖父母有很多父母,父母有很多孩子。并且,我想在一个grandparent
对象中检索它们的聚合。
这是我对这些表的DDL:
CREATE TABLE grandparent (
id BIGINT NOT NULL,
name VARCHAR(32) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE parent (
id BIGINT NOT NULL,
name VARCHAR(32) NOT NULL,
grandparent_id BIGINT NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE child (
id BIGINT NOT NULL,
name VARCHAR(32) NOT NULL,
parent_id BIGINT NOT NULL,
PRIMARY KEY (id)
);
而且,这是我的MyBatis映射器文件:
<mapper namespace="me.predatorray.mybatis.GrandparentMapper">
<!-- grandparent -->
<resultMap id="grandparentResultMap" type="me.predatorray.mybatis.Grandparent">
<constructor>
<idArg column="grandparent.id" javaType="long" jdbcType="BIGINT"/>
<arg column="grandparent.name" javaType="java.lang.String" jdbcType="VARCHAR"/>
</constructor>
<collection property="parents" column="parent.id" notNullColumn="parent.id"
javaType="java.util.ArrayList" ofType="me.predatorray.mybatis.Parent">
<constructor>
<idArg column="parent.id" javaType="long" jdbcType="BIGINT"/>
<arg column="parent.name" javaType="java.lang.String" jdbcType="VARCHAR"/>
</constructor>
<collection property="children" column="child.id" notNullColumn="child.id"
javaType="java.util.ArrayList" ofType="me.predatorray.mybatis.Child">
<constructor>
<idArg column="child.id" javaType="long" jdbcType="BIGINT"/>
<arg column="child.name" javaType="java.lang.String" jdbcType="VARCHAR"/>
</constructor>
</collection>
</collection>
</resultMap>
<select id="findGrandparentById" parameterType="long" resultMap="grandparentResultMap">
SELECT * FROM grandparent
LEFT JOIN parent ON grandparent.id = parent.grandparent_id
LEFT JOIN child ON parent.id = child.parent_id
WHERE grandparent.id = #{id, jdbcType=BIGINT};
</select>
</mapper>
而且,这是我的实体类:
public class Grandparent {
private Long id;
private String name;
private Collection<Parent> parents;
public Grandparent(Long id, String name) {
this.id = id;
this.name = name;
this.parents = new ArrayList<Parent>();
}
public void setParents(Collection<Parent> parents) {
this.parents = parents;
}
...getters
}
public class Parent {
private Long id;
private String name;
private Collection<Child> children;
public Parent(Long id, String name) {
this.id = id;
this.name = name;
this.children = new ArrayList<Child>();
}
public void setChildren(Collection<Child> children) {
this.children = children;
}
...getters
}
public class Child {
private Long id;
private String name;
public Child(Long id, String name) {
this.id = id;
this.name = name;
}
...getters
}
但是,我的映射器似乎有问题。返回的祖父对象不是我所期望的。祖父母中有重复的父母。例如,鉴于以下情况,
INSERT INTO grandparent (id, name) VALUES (3, 'Daisy');
INSERT INTO parent (id, name, grandparent_id) VALUES (2, 'Elizabeth', 3);
INSERT INTO child (id, name, parent_id) VALUES (1, 'Frieda', 2);
INSERT INTO parent (id, name, grandparent_id) VALUES (3, 'Grace', 3);
INSERT INTO child (id, name, parent_id) VALUES (2, 'Helen', 3);
INSERT INTO child (id, name, parent_id) VALUES (3, 'Ivy', 3);
INSERT INTO parent (id, name, grandparent_id) VALUES (4, 'Jack', 3);
findGrandparentById(3)
会返回像
Daisy (Grandparent)
Elizabeth (Parent)
Frieda (Child)
Grace (Parent)
Helen (Child)
Grace (Parent)
(C)Ivy (Child)
Jack (Parent)
&#34;恩&#34;谁有两个孩子在#34; Daisy&#34;中重复两次。那么,问题是什么?
给所有列命名后(例如,grandparent.id AS gid,parent.id AS pid等),问题就解决了。我只是想知道这可能是mybatis的错误吗?
答案 0 :(得分:0)
问题是你的查询。尝试在SQL客户端中运行它 - 它将为Ivy和Helen返回单独的行。 MyBatis忠实地反映了这一点。
我怀疑您想要的结果不太可能通过简单的查询来检索。您需要根据需要读取父表和子表,或者可能将完整的模型读入内存并从那里开始工作。
稍微OT:你真的需要三张桌子吗?该模型看起来像一个表,其中一个可选的parentId字段指向直接父级。