在Mybatis的开发中,经常遇到某个表是一个主表的一部分,对应Java的对象概念就是一个Pojo类是另一个Pojo的一部分。这儿讨论的是一对多的关系的关联的嵌套结果配置。
假设:有一个DsBase.mapper.xml,用于对 t_ds_base表(数据源主表)的配置,DsTech.mapper.xml对就ds_tech表(数据源技术信息表)的配置。
Sql如下:
CREATE TABLE t_ds_base
(
ds_id varchar(64) NOT NULL, -- 代理主键
ds_name_en varchar(100), -- 数据源英文标识
ds_name_cn varchar(100), -- 数据源中文标识
ds_desc varchar(500), -- 数据源描述
ds_reg_date date, -- 数据源注册日期
ds_modify_date date, -- 数据源修改日期
ds_valid_sign numeric, -- 数据源有效性标识
CONSTRAINT pk_t_ds_base PRIMARY KEY (ds_id)
)
CREATE TABLE t_ds_tech
(
ds_tech_id varchar(64) NOT NULL, -- 代理主键,数据源技术信息ID
ds_id varchar(64), -- 代理主键
tech_label_en varchar(100), -- 数据源技术信息英文标签
tech_label_cn varchar(100), -- 数据源技术信息中文标签
tech_label_value varchar(100), -- 数据源技术信息标签值
create_date date, -- 创建日期
modify_date date, -- 修改日期
valid_sign numeric, -- 有效性标识
CONSTRAINT pk_t_ds_tech PRIMARY KEY (ds_tech_id),
CONSTRAINT fk_t_ds_tec_reference_t_ds_bas FOREIGN KEY (ds_id)
REFERENCES t_ds_base (ds_id) MATCH SIMPLE
ON UPDATE RESTRICT ON DELETE RESTRICT
)
对应的java对象如下:
public class DsBase {
private String dsId;
private String dsNameEn;
private String dsNameCn;
private String dsDesc;
private Date dsRegDate;
private Date dsModifyDate;
private Integer dsValidSign;
/** 数据源的技术信息 */
private List<DsTech> dsTechList;
//省略getter,setter方法
}
public class DsTech {
private String dsTechId;
private String dsId;
private String techLabelEn;
private String techLabelCn;
private String techLabelValue;
private Date createDate;
private Date modifyDate;
private Integer validSign;
}
目标:我们以一条语句连接语句把DsBase的内容查出,也就是实现下面这条查询语句。
select base.ds_id,base.ds_name_en,base.ds_name_cn,base.ds_desc,base.ds_reg_date,base.ds_modify_date,base.ds_valid_sign,
tech.ds_tech_id,tech.ds_id as t_ds_id,tech.tech_label_en,tech.tech_label_cn,tech.tech_label_value,tech.create_date,tech.modify_date,tech.valid_sign
from T_DS_BASE base left join T_DS_TECH tech on (base.ds_id = tech.ds_id)
问题的关键也就在Mybatis的关联查询的配置,详细的内容可以参考 Mybatis 的 Mapper XML 文件。
配置如下:
DsBase.mapper.xml部分配置
<resultMap id="SelectAllEntity" type="DsBase">
<id property="dsId" column="ds_id"/>
<result property="dsId" column="ds_id" jdbcType="VARCHAR" javaType="String" />
<result property="dsNameEn" column="ds_name_en" jdbcType="VARCHAR" javaType="String" />
<result property="dsNameCn" column="ds_name_cn" jdbcType="VARCHAR" javaType="String" />
<result property="dsDesc" column="ds_desc" jdbcType="VARCHAR" javaType="String" />
<result property="dsRegDate" column="ds_reg_date" jdbcType="DATE" javaType="Date" />
<result property="dsModifyDate" column="ds_modify_date" jdbcType="DATE" javaType="Date" />
<result property="dsValidSign" column="ds_valid_sign" jdbcType="NUMERIC" javaType="Integer" />
<collection property="dsTechList" ofType="DsTech" column="t_ds_id"resultMap="com.cds.datacontrol.dscontrol.dao.DsTechDao.SelectAllTech"></collection>
</resultMap>
关键点也就在上面标注为红色的部分,collection配置的两个属性备注:
1.resultMap的内容为带有namespace的全名Id引用,不带上namespace默认是在当前文件查找。这也就是为什么不同文件的Id可以重复。
2.column的内容说明了以那个字段进行集合归类,也就是List里的对象都有这个特征。在两个表中有同一个字段时,至少要给出一个别名,如上面的sql中标红的。
DsTech.mapper.xml部分配置
<mapper namespace="com.cds.datacontrol.dscontrol.dao.DsTechDao">
<resultMap id="SelectAllTech" type="DsTech">
<id property="dsTechId" column="ds_tech_id"/>
<result property="dsTechId" column="ds_tech_id" jdbcType="VARCHAR" javaType="String" />
<result property="dsId" column="t_ds_id" jdbcType="VARCHAR" javaType="String" />
<result property="techLabelEn" column="tech_label_en" jdbcType="VARCHAR" javaType="String" />
<result property="techLabelCn" column="tech_label_cn" jdbcType="VARCHAR" javaType="String" />
<result property="techLabelValue" column="tech_label_value" jdbcType="VARCHAR" javaType="String" />
<result property="createDate" column="create_date" jdbcType="DATE" javaType="Date" />
<result property="modifyDate" column="modify_date" jdbcType="DATE" javaType="Date" />
<result property="validSign" column="valid_sign" jdbcType="NUMERIC" javaType="Integer" />
</resultMap>
...
</mapper>