背景
在开发工程中经常会遇到一对多数据的情况,在查询公司信息列表信息时,需要把多个公司的标签也显示在列表中。这时我们就可以通过mybatis构建上述需求中的数据信息。
需求
一对多查询通常涉及到两个实体类,一个是一方实体类,一个是多方实体类。例如,一个公司可以拥有多个标签,那么公司就是一方实体类,标签就是多方实体类。
在查询公司列表信息时,除公司基本信息外,也要返回公司的多个标签信息
第一种实现
使用sql中的关联查询出全部数据,然后在使用collection标签对返回值进行格式化操作。部分代码如下:
<!-- 映射结果集 SerCompanyVO -->
<resultMap id="resultMap" type="SerCompanyVO">
<id column="company_id" property="companyId" jdbcType="INTEGER" />
<result column="company_name" property="companyName" jdbcType="VARCHAR" />
<result column="company_code" property="companyCode" jdbcType="VARCHAR" />
<result column="company_msg" property="companyMsg" jdbcType="VARCHAR" />
<result column="company_crdt" property="companyCrdt" jdbcType="VARCHAR" />
</resultMap>
<!-- 一对多查询 join 结果集 -->
<resultMap id="tagResultMap" type="SerCompanyVO" extends="resultMap">
<collection property="list" ofType="SerCompanyTagVO">
<id column="tag_id" property="tagId" jdbcType="INTEGER" />
<result column="tag_name" property="tagName" jdbcType="VARCHAR" />
<result column="tag_msg" property="tagMsg" jdbcType="VARCHAR" />
</collection>
</resultMap>
<!-- 一对多查询 join 语句-->
<select id="selectSerCompanyListTagJoin" resultMap="tagResultMap">
SELECT c.company_id,c.company_name, company_code, company_msg, company_crdt,
t.tag_id,t.tag_msg,t.tag_name FROM ser_company c
LEFT JOIN ser_company_tag t ON c.company_id = t.company_id
</select>
通过 selectSerCompanyListTagJoin 查询到公司信息及关联的公司标签信息。然后使用tagResultMap将结果集映射到SerCompanyVO实体类中。其中list 是 SerCompanyVO实体类中的标签类的集合。在接口调用后返回如下数据:
第二种实现
使用一个接口查询出主表数据,然后通过association标签进行二次子查询,在将关联数据返回。具体代码如下:
<!-- 映射结果集 SerCompanyVO -->
<resultMap id="resultMap" type="SerCompanyVO">
<id column="company_id" property="companyId" jdbcType="INTEGER" />
<result column="company_name" property="companyName" jdbcType="VARCHAR" />
<result column="company_code" property="companyCode" jdbcType="VARCHAR" />
<result column="company_msg" property="companyMsg" jdbcType="VARCHAR" />
<result column="company_crdt" property="companyCrdt" jdbcType="VARCHAR" />
</resultMap>
<!-- 映射结果集 SerCompanyTagVO -->
<resultMap id="serCompanyTagResultMap" type="SerCompanyTagVO">
<id column="tag_id" property="tagId" jdbcType="INTEGER" />
<result column="tag_name" property="tagName" jdbcType="VARCHAR" />
<result column="tag_msg" property="tagMsg" jdbcType="VARCHAR" />
<result column="company_id" property="companyId" jdbcType="INTEGER" />
</resultMap>
<!-- 一对多查询 asso 结果集 -->
<resultMap id="assoResultMap" type="com.study.model.SerCompanyVO" extends="resultMap">
<association property="list" column="company_id" select="getSerCompanyTag"/>
</resultMap>
<!-- 一对多查询 asso方式 子表查询 -->
<select id="selectSerCompanyListTagAsso" resultMap="assoResultMap">
select company_id,company_name, company_code, company_msg, company_crdt from ser_company
</select>
<!-- 一对多查询 asso方式 主表查询 -->
<select id="getSerCompanyTag" resultMap="serCompanyTagResultMap" parameterType="int">
select t.company_id,t.tag_id,t.tag_msg,t.tag_name from ser_company_tag t where t.company_id=#{companyId}
</select>
首先调用selectSerCompanyListTagAsso查询出主表信息,在返回结果集时,通过association调用设置好的select子查询进行二次查询。这里为getSerCompanyTag接口。然后在重组在结果集中。结果如下:
总结
第二种方式不太使用适用于列表查询接口中,主表返回多少条数据,子查询就会进行多少次查询。比较浪费数据库资源,所以推荐使用第一种方式进行查询。
第一种方式中必要时请使用inner join关联,这里仅为示例一对多返回。
实体类源码
@Alias("SerCompanyTagVO")
public class SerCompanyTagVO {
private int tagId;
private String tagName;
private String tagMsg;
private int companyId;
public int getTagId() {
return tagId;
}
public void setTagId(int tagId) {
this.tagId = tagId;
}
public String getTagName() {
return tagName;
}
public void setTagName(String tagName) {
this.tagName = tagName;
}
public String getTagMsg() {
return tagMsg;
}
public void setTagMsg(String tagMsg) {
this.tagMsg = tagMsg;
}
public int getCompanyId() {
return companyId;
}
public void setCompanyId(int companyId) {
this.companyId = companyId;
}
}
@Alias("SerCompanyVO")
public class SerCompanyVO {
private int companyId;
private String companyName;
private String companyCode;
private String companyMsg;
private String companyCrdt;
private List<SerCompanyTagVO> list;
private SerCompanyTagVO serCompanyTagVO;
public int getCompanyId() {
return companyId;
}
public void setCompanyId(int companyId) {
this.companyId = companyId;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public String getCompanyCode() {
return companyCode;
}
public void setCompanyCode(String companyCode) {
this.companyCode = companyCode;
}
public String getCompanyMsg() {
return companyMsg;
}
public void setCompanyMsg(String companyMsg) {
this.companyMsg = companyMsg;
}
public String getCompanyCrdt() {
return companyCrdt;
}
public void setCompanyCrdt(String companyCrdt) {
this.companyCrdt = companyCrdt;
}
public List<SerCompanyTagVO> getList() {
return list;
}
public void setList(List<SerCompanyTagVO> list) {
this.list = list;
}
public SerCompanyTagVO getSerCompanyTagVO() {
return serCompanyTagVO;
}
public void setSerCompanyTagVO(SerCompanyTagVO serCompanyTagVO) {
this.serCompanyTagVO = serCompanyTagVO;
}
}
dao层源码
@Mapper
public interface SerCompanyMapper {
/**
* 一对多查询公司信息 包含公司标签 join 方式
* @return
*/
List<SerCompanyVO> selectSerCompanyListTagJoin();
/**
* 一对多查询公司信息 包含公司标签 asso 方式
* @return
*/
List<SerCompanyVO> selectSerCompanyListTagAsso();
/**
* 一对多查询公司信息 包含公司标签 asso 方式
* @param companyId
* @return
*/
SerCompanyTagVO getSerCompanyTag(int companyId);
}
写在最后
开源是一种美德,尽早加入开源社区,共建美好生态!