为了清晰而编辑02/07/17
我在工作中使用Mybatis 3.3,但我遇到了障碍。我很确定我的resultMapper存在问题,但我在查找相关教程/信息方面遇到了一些困难。
我有一个现有的Java模型,Mybatis映射器和表;而且我正在尝试编写一个尽可能多地重用的新模块。我现有的模型如下所示:
class Document {
Header header;
List<Detail> details;
}
我希望将模型与不同的Mybatis映射器一起使用,以在Details和Headers之间产生1-1关系(即details.size()始终为1)。
我目前只能获得1份文件。它拉出表中的第一个标题,并将每个文档的每个细节附加到它。这是我的结果地图和我正在处理的查询。查询返回正确的结果,但Mybatis错误地包装它们。
<resultMap id="header" type="Header">
<result property="id" column="ID" />
<result property="title" column="TITLE" />
</resultMap>
<resultMap id="detail" type="Detail">
<result property="id" column="ID" />
<result property="title" column="INFO" />
</resultMap>
<resultMap id="document" type="Document">
<association property="header" resultMap="header" />
<association property="details" resultMap="detail" />
</resultMap>
SELECT
HEADER.ID,
DETAIL.ID
FROM HEADER
JOIN DETAIL ON HEADER.ID = DETAIL.HEADER_ID
答案 0 :(得分:0)
在 resultMap 文档中,使用集合代替 association 获取属性详细信息。
编辑02-08-17:
根据您的编辑,使事情更清晰:轻微的模型更改将更符合您的需求:
class Document {
Header header;
Detail detail;
}
但是你想保留1个元素的List<Detail>
。
我想到了这一点。它只需要添加“虚拟属性”=&gt; getter和setter来包装列表。
public void setSingleDetail(Detail detail) {
this.details = Arrays.asList(detail);
}
public Detail getSingleDetail() {
return null == this.details ? null : this.details.iterator().next();
}
但这还不够,因为它只是覆盖了详细信息列表。
如果查看方法org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleRowValuesForNestedResultMap
。你会发现Mybatis不允许你想要的东西,它总是“分组”容器实体(如果你没有指定id属性,它将使用hash)。这也是需要getter的原因:与新行的值进行比较。
你想要做的是需要一个与Header关联的resultMap Detail(当然还有一个匹配结构的类),然后你得到一个结果/ Detail。
答案 1 :(得分:0)
要将行集映射到对象树,关键的是对象的标识。考虑这个例子:
header_id | detail_id
---------------------
1 | 1
1 | 2
有两种方法可以将此解析为对象树,Document
作为根实体。第一种方法是使一个实体具有标题和两个Detail
的集合。另一种方法是让两个Document
每个都有一个Detail
。这里的区别在于Document
对象的身份。您需要告诉mybatis哪个列是Document
实体的标识符。
出于您的目的,这应该是Detail
。
您需要更改查询和映射才能实现此目的。 主要目的是在此映射中将详细信息id指定为文档ID:
<resultMap id="document" type="Document">
<id column="detail_id"/>
<association property="header" resultMap="header" />
<association property="details" resultMap="detail"/>
</resultMap> modify the query
您需要更改查询,以便详细信息ID列具有唯一名称,例如
SELECT
HEADER.ID,
DETAIL.ID DETAIL_ID
FROM HEADER
JOIN DETAIL ON HEADER.ID = DETAIL.HEADER_ID
但这会破坏Detail
关联中其他列的映射。
要为resultMap
使用Detail
,您需要为详细信息表中的所有列添加相同的前缀,并在映射中指定:
<resultMap id="document" type="Document">
<id column="detail_id"/>
<association property="header" resultMap="header" />
<association property="details" resultMap="detail" prefix="DETAIL_"/>
</resultMap> modify the query
请注意,由于mybatis错误,前缀应为大写。