• 【Mybatis】使用结果嵌套方式完成一对多映射


    【一对多的重要意义】

    以公司与雇员为例,如果不用一对多,至少需要访问DB两次,一次按取公司的相关属性,第二次取公司下的雇员们,而采用一对多后,你会发现一次DB访问就够了。

    例程下载:https://files.cnblogs.com/files/heyang78/MybatisCli220527.rar?t=1653593808

    【目的】

    完成一个公司Company包含多个雇员Emp的一对多映射。

    【窍门】

    理清结果集与实体类的映射关系,分清哪些会分类汇总,哪些会进行组内聚合,进而理解MyBatis在背后帮了什么忙。 

    【建表充值部分】

    create table company(
        id number(10),
        name nvarchar2(20),
        primary key(id)
    );
    
    insert into company(id,name) values(1,'google');
    insert into company(id,name) values(2,'microsoft');
    
    create table emp(
        id number(10),
        cid number(10),
        name nvarchar2(20),
        primary key(id)
    );
    
    insert into emp(id,cid,name) values(1,1,'Andy');
    insert into emp(id,cid,name) values(2,1,'Bill');
    insert into emp(id,cid,name) values(3,2,'Cindy');
    insert into emp(id,cid,name) values(4,2,'Douglas');

    【实体类部分】

    Company类:

    package com.hy.entity;
    
    import java.util.List;
    
    public class Company {
        private long id;
        private String name;
        private List<Emp> emps;
    
        public String toString(){
            StringBuilder sb=new StringBuilder();
    
            sb.append("Company id="+id);
            sb.append(" name="+name);
    
            for(Emp emp:emps){
                sb.append(" emp="+emp.toString());
            }
    
            return sb.toString();
        }
    
        public long getId() {
            return id;
        }
    
        public void setId(long id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public List<Emp> getEmps() {
            return emps;
        }
    
        public void setEmps(List<Emp> emps) {
            this.emps = emps;
        }
    }

    Emp类:

    package com.hy.entity;
    
    public class Emp {
        private long id;
        private String name;
    
        public String toString(){
            return String.format("Emp id=%d name=%s",id,name);
        }
    
        public long getId() {
            return id;
        }
    
        public void setId(long id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }

    【Mapper接口】

    package com.hy.dao;
    
    import com.hy.entity.Company;
    import org.apache.ibatis.annotations.Mapper;
    
    @Mapper
    public interface CompanyMapper {
        Company fetchOne(long id);
    }

    【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.hy.dao.CompanyMapper">
        <select id="fetchOne" resultMap="map1">
            select c.id as cid,c.name as cname,e.id as eid,e.name as ename
            from company c,emp e
            where c.id=e.cid
            and c.id=#{id}
        </select>
    
        <resultMap id="map1" type="com.hy.entity.Company">
            <result column="cid" property="id"/>
            <result column="cname" property="name"/>
    
            <collection property="emps" ofType="com.hy.entity.Emp">
                <result column="eid" property="id"/>
                <result column="ename" property="name"/>
            </collection>
        </resultMap>
    </mapper>

    resultMap顾名思义是结果集的映射,当id=1时SQL语句是:

    select c.id as cid,c.name as cname,e.id as eid,e.name as ename
    from company c,emp e
    where c.id=e.cid
    and c.id=1

    而出来的结果集是:

    SQL> select c.id as cid,c.name as cname,e.id as eid,e.name as ename
      2  from company c,emp e
      3  where c.id=e.cid
      4  and c.id=1;
    
           CID CNAME                       EID ENAME
    ---------- -------------------- ---------- --------------------
             1 google                        1 Andy
             1 google                        2 Bill

    对照一下Map1里写的,cid给Company的id,cname给Company的name,EID给Emp的id,ename给Emp的name。

    对于这样两行的结果集怎么变成一个Company的实例的呢?

    我的理解是Mybatis背后 对于同等值就相当于进行group by分类汇总,而emps部分的处理相当于做了listagg组内聚合。

    【启动程序】

    package com.hy;
    
    import com.hy.dao.CompanyMapper;
    import com.hy.entity.Company;
    import com.hy.entity.Emp;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    import java.io.InputStream;
    import java.util.List;
    
    @SpringBootApplication
    public class MyApplication  implements CommandLineRunner {
        public static void main(String[] args) {
            SpringApplication.run(MyApplication.class, args);
        }
    
        @Override
        public void run(String... args) throws Exception {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory =
                    new SqlSessionFactoryBuilder().build(inputStream);
    
            try (SqlSession session = sqlSessionFactory.openSession()) {
                CompanyMapper mapper = session.getMapper(CompanyMapper.class);
    
                Company google= mapper.fetchOne(1);
                System.out.println(google);
    
                Company microsoft= mapper.fetchOne(2);
                System.out.println(microsoft);
            }
        }
    }

    【执行结果】

    Company id=1 name=google emp=Emp id=1 name=Andy emp=Emp id=2 name=Bill
    Company id=2 name=microsoft emp=Emp id=3 name=Cindy emp=Emp id=4 name=Douglas

    【参考文档】

    https://blog.csdn.net/qq_45173404/article/details/107672660

    END

  • 相关阅读:
    LayUI图片上传
    LayUI预设的正则
    SpringMVC
    避免IE执行AJAX时,返回JSON出现下载文件
    linux服务器无法显示tomcat详细错误信息
    User.java 实体类 带 数据库字段模板
    文字和图片放一起, 文字下沉的处理方法
    后台数据download成excel的方法(controller/action)
    table导出到excel的两种方法
    什么是脏读,不可重复读,幻读
  • 原文地址:https://www.cnblogs.com/heyang78/p/16316071.html
Copyright © 2020-2023  润新知