MyBatis中高级多表查询(ResultMap、association、collection)详解

 更新时间:2024年11月27日 17:12:05   作者:雷神乐乐  
文章主要介绍了MyBatis中高级多表查询的四种方式:ResultMap、association、collection以及自连接查询,通过定义接口的抽象方法、编写mapper.xml和测试类,详细展示了如何根据复杂数据结构进行数据的装配和查询,感兴趣的朋友一起看看吧

一、ResultMap的使用

  • resultType:适用于装配数据时需要字段与属性一一对应(包含驼峰)
  • resultMap:适用于复杂数据结构。如果不指定里面的配置,其功能与resultType一致(自动对应);如果指定了里面的配置,会根据手动指定的列与属性的对应关系装配数据

(一)定义接口的抽象方法 

/**
* 查询每个员工的总工资
*/
List<Emp> empWithTotal();

(二)编写mapper.xml 

<!--高级查询-->
<resultMap id="empBaseMap" type="com.javatest.entity.Emp">
    <id property="empno" column="empno"></id>
    <result property="ename" column="ename"></result>
    <result property="job" column="job"></result>
    <result property="mgr" column="mgr"></result>
    <result property="hiredate" column="hiredate"></result>
    <result property="sal" column="sal"></result>
    <result property="comm" column="comm"></result>
    <result property="deptno" column="deptno"></result>
</resultMap>
<resultMap id="empWithTotal" extends="empBaseMap" type="com.javatest.entity.Emp">
    <result property="sal" column="totalSal"></result>
</resultMap>
<select id="empWithTotal" resultMap="empWithTotal">
    select *, (sal + ifnull(comm, 0)) totalSal
    from emp;
</select>

(三)测试类

@Test
public void testEmpWithTotal() {
    SqlSession sqlSession = MyBatisHelper.getSqlSession();
    EmpDao mapper = sqlSession.getMapper(EmpDao.class);
    List<Emp> empList = mapper.empWithTotal();
    System.out.println(JSON.toJSONString(empList));
    MyBatisHelper.backAndSaveSqlSession(sqlSession);
}
[{"deptno":20,"empno":7369,"ename":"SMITH","hiredate":"1980-12-17","job":"CLERK","mgr":7902,"sal":800.0},
{"comm":300.0,"deptno":30,"empno":7499,"ename":"ALLEN","hiredate":"1981-02-20","job":"SALESMAN","mgr":7698,"sal":1900.0},
{"comm":500.0,"deptno":30,"empno":7521,"ename":"WARD","hiredate":"1981-02-22","job":"SALESMAN","mgr":7698,"sal":1750.0},
{"deptno":20,"empno":7566,"ename":"JONES","hiredate":"1981-04-02","job":"MANAGER","mgr":7839,"sal":2975.0},
{"comm":1400.0,"deptno":30,"empno":7654,"ename":"MARTIN","hiredate":"1981-09-28","job":"SALESMAN","mgr":7698,"sal":2650.0},
{"deptno":30,"empno":7698,"ename":"BLAKE","hiredate":"1981-05-01","job":"MANAGER","mgr":7839,"sal":2850.0},
{"deptno":10,"empno":7782,"ename":"CLARK","hiredate":"1981-06-09","job":"MANAGER","mgr":7839,"sal":2450.0},
{"deptno":20,"empno":7788,"ename":"SCOTT","hiredate":"1987-04-19","job":"ANALYST","mgr":7566,"sal":3000.0},
{"deptno":10,"empno":7839,"ename":"KING","hiredate":"1981-11-17","job":"PRESIDENT","sal":5000.0},
{"comm":0.0,"deptno":30,"empno":7844,"ename":"TURNER","hiredate":"1981-09-08","job":"SALESMAN","mgr":7698,"sal":1500.0},
{"deptno":20,"empno":7876,"ename":"ADAMS","hiredate":"1987-05-23","job":"CLERK","mgr":7788,"sal":1100.0},
{"deptno":30,"empno":7900,"ename":"JAMES","hiredate":"1981-12-03","job":"CLERK","mgr":7698,"sal":950.0},
{"deptno":20,"empno":7902,"ename":"FORD","hiredate":"1981-12-03","job":"ANALYST","mgr":7566,"sal":3000.0},
{"deptno":10,"empno":7934,"ename":"MILLER","hiredate":"1982-01-23","job":"CLERK","mgr":7782,"sal":1300.0}]

        注意:这种方式改变了原有的sal属性的意思,开发中还是要使用DTO和VO来装配,这里简写。 

二、多表一对一查询——association

(一)定义接口的抽象方法 

/**
 * 查询每个员工对应的部门
 */
List<Emp> listEmpWithDept();

(二)编写mapper.xml 

<!--高级查询-->
<resultMap id="empBaseMap" type="com.javatest.entity.Emp">
    <id property="empno" column="empno"></id>
    <result property="ename" column="ename"></result>
    <result property="job" column="job"></result>
    <result property="mgr" column="mgr"></result>
    <result property="hiredate" column="hiredate"></result>
    <result property="sal" column="sal"></result>
    <result property="comm" column="comm"></result>
    <result property="deptno" column="deptno"></result>
</resultMap>
<resultMap id="listEmpWithDept" extends="empBaseMap" type="com.javatest.entity.Emp">
    <!--配置关联的对象-->
    <association property="dept" javaType="com.javatest.entity.Dept">
        <id property="deptno" column="deptno"></id>
        <result property="dname" column="dname"></result>
        <result property="loc" column="loc"></result>
    </association>
</resultMap>
<select id="listEmpWithDept" resultMap="listEmpWithDept">
    select *
    from dept d
             left join emp e on d.deptno = e.deptno
</select>

(三)测试类

@Test
public void testListEmpWithDept() {
    SqlSession sqlSession = MyBatisHelper.getSqlSession();
    EmpDao mapper = sqlSession.getMapper(EmpDao.class);
    List<Emp> empList = mapper.listEmpWithDept();
    System.out.println(JSON.toJSONString(empList));
    MyBatisHelper.backAndSaveSqlSession(sqlSession);
}

        注意:真实开发中,数据库对应的类属性,是和数据库字段一一对应的,如果需要改变,那么就要放在VO类中返回给前端,这里简写。

三、多表一对多查询——collection

(一)定义接口的抽象方法 

public interface DeptDao {
    /**
     * 查询每个部门对应的员工
     */
    List<Dept> listDeptWithEmps();
}

(二)编写mapper.xml 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.javatest.dao.DeptDao">
    <resultMap id="DeptBaseMap" type="com.javatest.entity.Dept">
        <result property="deptno" column="deptno"/>
        <result property="dname" column="dname"/>
        <result property="loc" column="loc"/>
    </resultMap>
    <!--一对多查询-->
    <resultMap id="listDeptWithEmps" extends="DeptBaseMap" type="com.javatest.entity.Dept">
        <!--配置关联的集合-->
        <collection property="emps" ofType="com.javatest.entity.Emp">
            <id property="empno" column="empno"></id>
            <result property="ename" column="ename"></result>
            <result property="job" column="job"></result>
            <result property="mgr" column="mgr"></result>
            <result property="hiredate" column="hiredate"></result>
            <result property="sal" column="sal"></result>
            <result property="comm" column="comm"></result>
            <result property="deptno" column="deptno"></result>
        </collection>
    </resultMap>
    <select id="listDeptWithEmps" resultMap="listDeptWithEmps">
        select *
        from dept d
                 left join emp e on d.deptno = e.deptno
    </select>
</mapper>
 

(三)测试类

@Test
public void testListDeptWithEmps(){
    SqlSession sqlSession = MyBatisHelper.getSqlSession();
    DeptDao mapper = sqlSession.getMapper(DeptDao.class);
    List<Dept> deptList = mapper.listDeptWithEmps();
    System.out.println(JSON.toJSONString(deptList));
    MyBatisHelper.backAndSaveSqlSession(sqlSession);
}

四、自连接查询——省市县区

(一)tb_area表

create table if not exists tb_area
(
    code  int          not null primary key,
    name  varchar(255) null,
    pcode int          null
);
INSERT INTO mydb.tb_area (code, name, pcode) VALUES (110000, '北京市', 0);
INSERT INTO mydb.tb_area (code, name, pcode) VALUES (110107, '石景山区', 110000);
INSERT INTO mydb.tb_area (code, name, pcode) VALUES (210000, '辽宁省', 0);
INSERT INTO mydb.tb_area (code, name, pcode) VALUES (210200, '大连市', 210000);
INSERT INTO mydb.tb_area (code, name, pcode) VALUES (210202, '中山区', 210200);
INSERT INTO mydb.tb_area (code, name, pcode) VALUES (210400, '抚顺市', 210000);
INSERT INTO mydb.tb_area (code, name, pcode) VALUES (210402, '新抚区', 210400);
INSERT INTO mydb.tb_area (code, name, pcode) VALUES (310000, '上海市', 0);
INSERT INTO mydb.tb_area (code, name, pcode) VALUES (310106, '静安区', 310000);
INSERT INTO mydb.tb_area (code, name, pcode) VALUES (310110, '杨浦区', 310000);

(二)TbArea实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class TbArea implements Serializable {
    private static final long serialVersionUID = 949170561403426696L;
    private Integer code;
    private String name;
    private Integer pcode;
    private List<TbArea> subArea;
}

(三)TbAreaDao接口

public interface TbAreaDao {
    /**
     * 查找省对应的市
     */
    List<TbArea> getCities();
    /**
     * 查找省对应的市,市对应的县区
     */
    List<TbArea> getAreas();
}

(四)TbArea.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.javatest.dao.TbAreaDao">
    <!--基础映射对象-->
    <resultMap id="tbArea" type="com.javatest.entity.TbArea">
        <id property="code" column="code"></id>
        <result property="name" column="name"></result>
        <result property="pcode" column="pcode"></result>
    </resultMap>
    <!--配置关联的集合:省-市-->
    <resultMap id="getCities" extends="tbArea" type="com.javatest.entity.TbArea">
        <collection property="subArea" ofType="com.javatest.entity.TbArea">
            <id property="code" column="cityCode"></id>
            <result property="name" column="cityName"></result>
            <result property="pcode" column="citypCode"></result>
        </collection>
    </resultMap>
    <!--配置关联的集合:省-市-县/区-->
    <resultMap id="getAreas" extends="tbArea" type="com.javatest.entity.TbArea">
        <collection property="subArea" ofType="com.javatest.entity.TbArea">
            <id property="code" column="cityCode"></id>
            <result property="name" column="cityName"></result>
            <result property="pcode" column="citypCode"></result>
            <collection property="subArea" ofType="com.javatest.entity.TbArea">
                <id property="code" column="areaCode"></id>
                <result property="name" column="areaName"></result>
                <result property="pcode" column="areapCode"></result>
            </collection>
        </collection>
    </resultMap>
    <!--获取省-市信息-->
    <select id="getCities" resultMap="getCities">
        select prov.*,
               city.code  as cityCode,
               city.name  as cityName,
               city.pcode as cityPcode
        from tb_area prov
                 left join tb_area city on prov.code = city.pcode
        where prov.pcode = 0
    </select>
    <!--获取省-市-县区信息-->
    <select id="getAreas" resultMap="getAreas">
        select prov.*,
               city.code  as cityCode,
               city.name  as cityName,
               city.pcode as cityPcode,
               area.code  as areaCode,
               area.name  as areaName,
               area.pcode as areaPcode
        from tb_area prov
                 left join tb_area city on prov.code = city.pcode
                 left join tb_area area on city.code = area.pcode
        where prov.pcode = 0
    </select>
</mapper>

sql查询结果:

获取省-市数据:

获取省-市-县区数据:

(五)测试类TbAreaTest

public class TbAreaTest {
    @Test
    public void testGetCities(){
        SqlSession sqlSession = MyBatisHelper.getSqlSession();
        TbAreaDao mapper = sqlSession.getMapper(TbAreaDao.class);
        List<TbArea> cities = mapper.getCities();
        System.out.println(JSON.toJSONString(cities));
        MyBatisHelper.backAndSaveSqlSession(sqlSession);
    }
    @Test
    public void testGetAreas(){
        SqlSession sqlSession = MyBatisHelper.getSqlSession();
        TbAreaDao mapper = sqlSession.getMapper(TbAreaDao.class);
        List<TbArea> areas = mapper.getAreas();
        System.out.println(JSON.toJSONString(areas));
        MyBatisHelper.backAndSaveSqlSession(sqlSession);
    }
}
testGetCities:获取省-市数据
[{"code":110000,"name":"北京市","pcode":0,"subArea":[{"code":110107,"name":"石景山区","pcode":110000}]},
{"code":210000,"name":"辽宁省","pcode":0,"subArea":[{"code":210400,"name":"抚顺市","pcode":210000},{"code":210200,"name":"大连市","pcode":210000}]},
{"code":310000,"name":"上海市","pcode":0,"subArea":[{"code":310110,"name":"杨浦区","pcode":310000},{"code":310106,"name":"静安区","pcode":310000}]}]
testGetAreas:获取省-市-县区数据
[{"code":110000,"name":"北京市","pcode":0,"subArea":[{"code":110107,"name":"石景山区","pcode":110000,"subArea":[]}]},
{"code":210000,"name":"辽宁省","pcode":0,"subArea":[{"code":210400,"name":"抚顺市","pcode":210000,"subArea":[{"code":210402,"name":"新抚区","pcode":210400}]},
{"code":210200,"name":"大连市","pcode":210000,"subArea":[{"code":210202,"name":"中山区","pcode":210200}]}]},
{"code":310000,"name":"上海市","pcode":0,"subArea":[{"code":310110,"name":"杨浦区","pcode":310000,"subArea":[]},{"code":310106,"name":"静安区","pcode":310000,"subArea":[]}]}]

到此这篇关于MyBatis中高级多表查询(ResultMap、association、collection)的文章就介绍到这了,更多相关MyBatis ResultMap、association、collection内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

最新评论