MyBatis学习(三)

一对一查询

1、一个角色只能属于一部动漫,下面是通过查询角色信息,关联查询所属动漫信息的案例来学习mybaits中的一对一关系映射。

2、通过resultType实现查询角色信息,关联查询所属动漫信息,使用resultType测试案例

  • 建表sql
    --自增长生成主键
    DROP TABLE IF EXISTS t_role;
    
    CREATE TABLE t_role(
        id INT(5) NOT NULL AUTO_INCREMENT COMMENT '角色id',
        role_name VARCHAR(150) COMMENT '角色姓名',
        note VARCHAR(150) COMMENT '角色备注',
        comic_id INT(5) NOT NULL COMMENT'动漫id',
        PRIMARY KEY (id),
        FOREIGN KEY(comic_id) REFERENCES t_comic(id)    
    );
    
    
    INSERT INTO t_role( role_name, note, comic_id) VALUES ("Saber","fate stay night",1);
    INSERT INTO t_role( role_name, note, comic_id) VALUES ("鸣人","火影忍者",2);
    INSERT INTO t_role( role_name, note, comic_id) VALUES ("佐助","火影忍者",2);
    INSERT INTO t_role( role_name, note, comic_id) VALUES ("赤丸","火影忍者",2);
    INSERT INTO t_role( role_name, note, comic_id) VALUES ("兜","火影忍者",2);
    INSERT INTO t_role( role_name, note, comic_id) VALUES ("鹿丸","火影忍者",2);
    INSERT INTO t_role( role_name, note, comic_id) VALUES ("萨博","海贼王",3);
    
    
    --uuid生成主键
    DROP TABLE IF EXISTS t_role;
    
    CREATE TABLE t_role(
        id VARCHAR(36) NOT NULL COMMENT '角色id' ,
        role_name VARCHAR(150) COMMENT '角色姓名',
        note VARCHAR(150) COMMENT '角色备注',
        comic_id INT(5) NOT NULL COMMENT'动漫id',
        PRIMARY KEY (id),
        FOREIGN KEY(comic_id) REFERENCES t_comic(id)    
    );
    
    
    
    INSERT INTO t_role( role_name, note, comic_id) VALUES ("Saber","fate stay night",1);
    INSERT INTO t_role( role_name, note, comic_id) VALUES ("鸣人","火影忍者",2);
    INSERT INTO t_role( role_name, note, comic_id) VALUES ("佐助","火影忍者",2);
    INSERT INTO t_role( role_name, note, comic_id) VALUES ("赤丸","火影忍者",2);
    INSERT INTO t_role( role_name, note, comic_id) VALUES ("兜","火影忍者",2);
    INSERT INTO t_role( role_name, note, comic_id) VALUES ("鹿丸","火影忍者",2);
    INSERT INTO t_role( role_name, note, comic_id) VALUES ("萨博","海贼王",3);
    
    
    --comic表
    
    DROP TABLE IF EXISTS t_comic;
    
    CREATE TABLE t_comic(
        id INT(5) NOT NULL AUTO_INCREMENT COMMENT '动漫id',
        comic_name VARCHAR(150) COMMENT '动漫名称' ,
        remark VARCHAR(150) COMMENT '动漫备注',
        PRIMARY KEY (id)
    );
    
    INSERT  INTO  t_comic(comic_name)  VALUES ( 'fate stay night');
    INSERT  INTO  t_comic(comic_name)  VALUES ( '火影忍者');
    INSERT  INTO  t_comic(comic_name)  VALUES ( '海贼王');

    角色表中comic_id 外键对应的是动漫表中的主键,一个角色只能属于一部动漫,角色到动漫是一对一的关系。

  • 查询sql
    SELECT t_role.id , t_role.role_name AS roleName, t_role.comic_id AS comicId, t_role.note, t_comic.comic_name AS comicName, t_comic.remark FROM t_role , t_comic WHERE t_role.comic_id = t_comic.id 

    使用resultType得保证字段名和列名保持一致,如果不一致需要使用别名的方式来完成映射

  • POJO类

    角色类:

    package ecut.association.po;
    
    import java.io.Serializable;
    
    public class Role implements Serializable {
    
        private static final long serialVersionUID = -4663460700843152533L;
    
        private Integer id;
    
        private String roleName;
    
        private String note;
        
        private Integer comicId;
    
        private Comic comic;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getRoleName() {
            return roleName;
        }
    
        public void setRoleName(String roleName) {
            this.roleName = roleName;
        }
    
        public String getNote() {
            return note;
        }
    
        public void setNote(String note) {
            this.note = note;
        }
    
        public Integer getComicId() {
            return comicId;
        }
    
        public void setComicId(Integer comicId) {
            this.comicId = comicId;
        }
    
        public Comic getComic() {
            return comic;
        }
    
        public void setComic(Comic comic) {
            this.comic = comic;
        }
    
        @Override
        public String toString() {
            String s = "
    "+"角色信息:id =" + id + ",roleName =" + roleName + ", note = " + note+", comicId = " + comicId;
            s=s+";"+"动漫信息:"+"id="+comic.getId()+",comicName="+comic.getComicName()+",remark="+comic.getRemark();
            return s;
        }
    
    }

    RoleComic类:

    package ecut.association.po;
    
    public class RoleComic extends Role {
    
        private static final long serialVersionUID = -6089413956387774208L;
    
        private String comicName;
    
        private String remark;
    
        public String getComicName() {
            return comicName;
        }
    
        public void setComicName(String comicName) {
            this.comicName = comicName;
        }
    
        public String getRemark() {
            return remark;
        }
    
        public void setRemark(String remark) {
            this.remark = remark;
        }
    
        @Override
        public String toString() {
            String s = "
    "+"角色信息:id =" + getId() + ",roleName =" + getRoleName() + ", note = " + getNote()+", comicId = " + getComicId();
            s=s+";"+"动漫信息:"+"comicName="+comicName+",remark="+remark;
            return s;
        }
    }

    将上边sql查询的结果映射到pojo中,pojo中必须包括所有查询列名。原始的Role.java不能映射全部字段,需要新创建的pojo。创建 一个pojo继承包括查询字段较多的po类。

  • 映射文件
    <?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">
      
      <!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离 
              注意:使用mapper代理方法开发,namespace有特殊重要的作用-->
      <mapper namespace="ecut.association.mapper.RoleMapperComic">
     
          <sql id="base">
          t_role.id , t_role.role_name AS roleName, t_role.comic_id AS comicId, t_role.note, t_comic.comic_name AS comicName, t_comic.remark  
          </sql>
          
          
        <!-- 查询角色关联查询动漫信息,使用resultType -->
          <select id="findRoleComicsByResultType" resultType="RoleComic">
              SELECT 
              <include refid="base"/>
              FROM t_role , t_comic 
              <where>
               t_role.comic_id = t_comic.id
              </where>
          </select>
      
          
      </mapper>

    通过取别名的方式使其字段名和属性名保持一致

  • 接口
    package ecut.association.mapper;
    
    import java.util.List;
    
    import ecut.association.po.Role;
    import ecut.association.po.RoleComic;
    
    public interface RoleMapperComic {
        
        //查询角色信息,关联查询所属动漫信息,使用resultType
        public List<RoleComic>  findRoleComicsByResultType() throws Exception ;
        
    }

    mapper.java接口中的方法名和mapper.xml中statement的id一致

    mapper.java接口中的方法输入参数类型和mapper.xml中statement的parameterType指定的类型一致

    mapper.java接口中的方法返回值类型和mapper.xml中statement的resultType指定的类型一致

  • 测试类
    package ecut.association.test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    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.junit.Before;
    import org.junit.Test;
    
    import ecut.association.mapper.RoleMapperComic;
    import ecut.association.po.Role;
    import ecut.association.po.RoleComic;
    
    public class ComicMapperTest {
        
        private SqlSessionFactory factory;
    
        
        @Before
        public  void init() throws IOException {
            String resource = "ecut/association/mybaits-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactoryBuilder builer =new SqlSessionFactoryBuilder();
            factory = builer.build(inputStream);
        }
        
        @Test
        public void testFindRoleComicsByResultType() throws Exception {
            SqlSession session = factory.openSession();
            RoleMapperComic  mapper =  session.getMapper(RoleMapperComic.class);
            List<RoleComic> roleComics = mapper.findRoleComicsByResultType();
            System.out.println(roleComics);
        }
    
    }

3、通过resultMap实现查询角色信息,关联查询所属动漫信息,使用resultType测试案例

  • 在Role中添加Comic属性

    动漫类:

    package ecut.association.po;
    
    import java.io.Serializable;
    
    public class Comic implements Serializable {
    
        private static final long serialVersionUID = -3674954993814032572L;
        
        private Integer id;
        
        private String comicName;
        
        private String remark;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getComicName() {
            return comicName;
        }
    
        public void setComicName(String comicName) {
            this.comicName = comicName;
        }
    
        public String getRemark() {
            return remark;
        }
    
        public void setRemark(String remark) {
            this.remark = remark;
        }
    
    }

    角色类:

    package ecut.association.po;
    
    import java.io.Serializable;
    
    public class Role implements Serializable {
    
        private static final long serialVersionUID = -4663460700843152533L;
    
        private Integer id;
    
        private String roleName;
    
        private String note;
        
        private Integer comicId;
    
        private Comic comic;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getRoleName() {
            return roleName;
        }
    
        public void setRoleName(String roleName) {
            this.roleName = roleName;
        }
    
        public String getNote() {
            return note;
        }
    
        public void setNote(String note) {
            this.note = note;
        }
    
        public Integer getComicId() {
            return comicId;
        }
    
        public void setComicId(Integer comicId) {
            this.comicId = comicId;
        }
    
        public Comic getComic() {
            return comic;
        }
    
        public void setComic(Comic comic) {
            this.comic = comic;
        }
    
        @Override
        public String toString() {
            String s = "
    "+"角色信息:id =" + id + ",roleName =" + roleName + ", note = " + note+", comicId = " + comicId;
            s=s+";"+"动漫信息:"+"id="+comic.getId()+",comicName="+comic.getComicName()+",remark="+comic.getRemark();
            return s;
        }
    
    }

    使用resultMap将查询结果中的角色信息映射到Role对象中,在Role类中添加Comic属性,将关联查询出来的动漫信息映射到角色对象中的comic属性中。

  • 映射文件
    <?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">
      
      <!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离 
              注意:使用mapper代理方法开发,namespace有特殊重要的作用-->
      <mapper namespace="ecut.association.mapper.RoleMapperComic">
          <!-- 用户查询关联动漫的resultMap
        将整个查询的结果映射到中ecut.association.po.Role
         -->
          <resultMap type="Role" id="RoleComicResultMap">
              <!-- 配置映射的角色信息 -->
            <!-- id:指定查询列中的唯 一标识,角色信息的中的唯 一标识,如果有多个列组成唯一标识,配置多个id
                column:角色信息的唯 一标识 列
                property:角色信息的唯 一标识 列所映射到Role中哪个属性
              -->
              <id column="id" property="id"/>
              <result column="role_name" property="roleName"/>
              <result column="comic_id" property="comicId"/>
              <result column="note" property="note"/>
              <!-- 配置映射的关联的动漫信息 -->
            <!-- association:用于映射关联查询单个对象的信息
            property:要将关联查询的动漫信息映射到Role中哪个属性
             -->
              <association property="comic" javaType="Comic">
                  <!-- id:关联查询动漫的唯 一标识
                column:指定唯 一标识动漫信息的列
                javaType:映射到Comic的哪个属性
                 -->
                <id column="comic_id" property="id"/>
                  <result column="comic_name" property="comicName"/>
                  <result column="remark" property="remark"/> 
             </association>
          </resultMap>
          
          
          <!-- 查询角色关联查询动漫信息 ,使用resultMap-->
          <select id="findRoleComicsByResultMap" resultMap="RoleComicResultMap">
              SELECT 
              t_role.*,t_comic.id AS comic_id , t_comic.comic_name , t_comic.remark
              FROM t_role , t_comic 
              <where>
               t_role.comic_id = t_comic.id
              </where>
          </select>
          
      </mapper>

    使用association标签映射关联查询单个对象的信息,其中property是要将关联查询的动漫信息映射到Role中哪个属性,javaType是属性对应的POJO类

  • 接口类
    package ecut.association.mapper;
    
    import java.util.List;
    
    import ecut.association.po.Role;
    import ecut.association.po.RoleComic;
    
    public interface RoleMapperComic {
        
    
        //查询角色信息,关联查询所属动漫信息,使用resultMap
        public List<Role>  findRoleComicsByResultMap() throws Exception ;
        
    }
  • 测试类
    package ecut.association.test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    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.junit.Before;
    import org.junit.Test;
    
    import ecut.association.mapper.RoleMapperComic;
    import ecut.association.po.Role;
    import ecut.association.po.RoleComic;
    
    public class ComicMapperTest {
        
        private SqlSessionFactory factory;
    
        
        @Before
        public  void init() throws IOException {
            String resource = "ecut/association/mybaits-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactoryBuilder builer =new SqlSessionFactoryBuilder();
            factory = builer.build(inputStream);
        }
        
        
        @Test
        public void testFindRoleComicsByResultMap() throws Exception {
            SqlSession session = factory.openSession();
            RoleMapperComic  mapper =  session.getMapper(RoleMapperComic.class);
            List<Role> roleComics = mapper.findRoleComicsByResultMap();
            System.out.println(roleComics);
        }
    
    }

4、两种方式实现一对一总结

  • resultType:使用resultType实现较为简单,如果pojo中没有包括查询出来的列名,需要增加列名对应的属性,即可完成映射。如果没有查询结果的特殊要求建议使用resultType。
  • resultMap:需要单独定义resultMap,实现有点麻烦,如果对查询结果有特殊的要求,使用resultMap可以完成将关联查询映射pojo的属性中。
  • resultMap可以实现延迟加载,resultType无法实现延迟加载。

一对多查询

1、一个动漫有多个角色,下面是通过查询动漫信息,关联查询角色信息的案例来学习mybaits中的一对多关系映射。

2、使用resultMap测试案例

  • sql语句
    SELECT * from t_comic ,t_role WHERE   t_role.comic_id = t_comic.id 
  • POJO类
    package ecut.association.po;
    
    import java.io.Serializable;
    import java.util.List;
    
    public class Comic implements Serializable {
    
        private static final long serialVersionUID = -3674954993814032572L;
        
        private Integer id;
        
        private String comicName;
        
        private String remark;
        
        private List<Role> roles;
        
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getComicName() {
            return comicName;
        }
    
        public void setComicName(String comicName) {
            this.comicName = comicName;
        }
    
        public String getRemark() {
            return remark;
        }
    
        public void setRemark(String remark) {
            this.remark = remark;
        }
    
        public List<Role> getRoles() {
            return roles;
        }
    
        public void setRoles(List<Role> roles) {
            this.roles = roles;
        }
        
    }

    在Comic类中添加List角色属性

  • 映射文件
    <?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">
      
      <!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离 
              注意:使用mapper代理方法开发,namespace有特殊重要的作用-->
      <mapper namespace="ecut.association.mapper.RoleMapperComic">
    
          <resultMap type="Comic" id="ComicResultMap">
              <id column="id" property="id"/>
              <result column="comic_name" property="comicName"/>
              <result column="remark" property="remark"/>
          </resultMap>
          
          <!-- 动漫明细信息
            一个动漫关联查询出了多歌角色,要使用collection进行映射
            collection:对关联查询到多条记录映射到集合对象中
            property:将关联查询到多条记录映射到ecut.association.po.Comic哪个属性
            ofType:指定映射到list集合属性中pojo的类型
             -->
          <resultMap type="Comic" extends="ComicResultMap" id="ComicsResultMap">
            <!-- 使用extends继承,不用在中配置动漫信息的映射 -->
              <collection property="roles" ofType="Role">
                  <!-- id:角色唯 一标识
                 property:要将角色的唯 一标识 映射到Role类的哪个属性
                   -->
                  <id column="role_id" property="id"/>
                  <result column="role_name" property="roleName"/>
                  <result column="comic_id" property="comicId"/>
                  <result column="note" property="note"/>
              </collection>
          </resultMap>
          
          <!--查询动漫信息。关联查询动漫中的角色,使用resultMap-->
          <select id="findComics" resultMap="ComicsResultMap">
              SELECT 
              t_comic.*,t_role.id AS role_id, t_role.role_name,  t_role.note ,t_role.comic_id 
              FROM t_comic, t_role
              <where>
               t_role.comic_id = t_comic.id
              </where>
          </select>
    
      </mapper>

    collection:对关联查询到多条记录映射到集合对象中,可以在resultMap中使用extends继承可以减少配置

  • 接口类

    package ecut.association.mapper;
    
    import java.util.List;
    
    import ecut.association.po.Comic;
    import ecut.association.po.Role;
    import ecut.association.po.RoleComic;
    
    public interface RoleMapperComic {
        
        //查询动漫信息。关联查询动漫中的角色
        public List<Comic> findComics() throws Exception ;
        
    }
  • 测试类
    package ecut.association.test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    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.junit.Before;
    import org.junit.Test;
    
    import ecut.association.mapper.RoleMapperComic;
    import ecut.association.po.Comic;
    import ecut.association.po.Role;
    import ecut.association.po.RoleComic;
    
    public class ComicMapperTest {
        
        private SqlSessionFactory factory;
    
        
        @Before
        public  void init() throws IOException {
            String resource = "ecut/association/mybaits-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactoryBuilder builer =new SqlSessionFactoryBuilder();
            factory = builer.build(inputStream);
        }
        
    
        @Test
        public void testFindComics() throws Exception {
            SqlSession session = factory.openSession();
            RoleMapperComic  mapper =  session.getMapper(RoleMapperComic.class);
            List<Comic> comics = mapper.findComics();
            for(Comic c : comics){
                String s = "动漫信息:id="+c.getId()+",comicName="+c.getComicName()+",remark="+c.getRemark();
                System.out.println(s);
                for(Role r:c.getRoles()){
                    System.out.println("角色信息:id =" + r.getId() + ",roleName =" + r.getRoleName() + ", note = " + r.getNote()+", comicId = " + r.getComicId());
                }
                System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~"); } } }

3、小结

  • mybatis使用resultMap的collection对关联查询的多条记录映射到一个list集合属性中。
  •  使用resultType实现:将角色映射到动漫中的roles中,需要自己处理,使用双重循环遍历,去掉重复记录,将角色信息放在roles中。

多对多查询
1、一个动漫有多个角色,一个角色只有一个配音演员,因此动漫到配音演员是一对多

  一个配音演员可以配多个角色,一个角色只能属于一部动漫,因此配音演员到动漫是一对多

 综上所述动漫和配音演员是多对多的关系,下面是通过查询动漫信息,关联查询动漫中的角色及配音演员信息的案例来学习mybaits的多对多查询

2、多对多测试案例

  • 建表sql语句
    --dubber表
    DROP TABLE IF EXISTS t_dubber;
    
    CREATE TABLE t_dubber(
        id INT(5) NOT NULL AUTO_INCREMENT COMMENT '配音演员id',
        dubber_name VARCHAR(150) COMMENT '配音演员姓名',
        role_id INT(5) NOT NULL COMMENT'角色id',
        PRIMARY KEY (id),
        FOREIGN KEY(role_id) REFERENCES t_role(id)    
    );
    
    INSERT INTO t_dubber( dubber_name, role_id) VALUES ("川澄绫子",1);
    INSERT INTO t_dubber( dubber_name, role_id) VALUES ("竹内顺子",2);
    INSERT INTO t_dubber( dubber_name, role_id) VALUES ("杉山纪彰",3);
    INSERT INTO t_dubber( dubber_name, role_id) VALUES ("竹内顺子",4);
    INSERT INTO t_dubber( dubber_name, role_id) VALUES ("神奈延年",5);
    INSERT INTO t_dubber( dubber_name, role_id) VALUES ("神奈延年",6);
    INSERT INTO t_dubber( dubber_name, role_id) VALUES ("竹内顺子",7);

    配音演员中有角色id是外键对应角色表中的id,一个配音演员可以配多个角色,比如竹内顺子,一个动漫可以有多个配音演员比如火影忍者

  • 查询sql
    SELECT t_comic.*,t_role.id AS role_id, t_role.role_name, t_role.note ,t_role.comic_id ,t_dubber.id AS dubber_id , t_dubber.dubber_name ,t_dubber.role_id AS dubber_role_id FROM t_comic, t_role,t_dubber WHERE t_role.id = t_dubber.role_id AND t_role.comic_id = t_comic.id 
  • POJO类

    角色类

    package ecut.association.po;
    
    import java.io.Serializable;
    
    public class Role implements Serializable {
    
        private static final long serialVersionUID = -4663460700843152533L;
    
        private Integer id;
    
        private String roleName;
    
        private String note;
        
        private Integer comicId;
    
        private Comic comic;
        
        private Dubber dubber;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getRoleName() {
            return roleName;
        }
    
        public void setRoleName(String roleName) {
            this.roleName = roleName;
        }
    
        public String getNote() {
            return note;
        }
    
        public void setNote(String note) {
            this.note = note;
        }
    
        public Integer getComicId() {
            return comicId;
        }
    
        public void setComicId(Integer comicId) {
            this.comicId = comicId;
        }
    
        public Comic getComic() {
            return comic;
        }
    
        public void setComic(Comic comic) {
            this.comic = comic;
        }
        
        
        public Dubber getDubber() {
            return dubber;
        }
    
        public void setDubber(Dubber dubber) {
            this.dubber = dubber;
        }
    
        @Override
        public String toString() {
            String s = "
    "+"角色信息:id =" + id + ",roleName =" + roleName + ", note = " + note+", comicId = " + comicId;
            s=s+";"+"动漫信息:"+"id="+comic.getId()+",comicName="+comic.getComicName()+",remark="+comic.getRemark();
            return s;
        }
    
    }

    配音演员类:

    package ecut.association.po;
    
    import java.io.Serializable;
    
    public class Dubber implements Serializable{
    
        private static final long serialVersionUID = -7436845097720592214L;
        
        private Integer id;
        
        private String dubberName;
        
        private Integer roleId;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getDubberName() {
            return dubberName;
        }
    
        public void setDubberName(String dubberName) {
            this.dubberName = dubberName;
        }
    
        public Integer getRoleId() {
            return roleId;
        }
    
        public void setRoleId(Integer roleId) {
            this.roleId = roleId;
        }
        
        
        
    }
  • 映射文件
    <?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">
      
      <!-- namespace命名空间,作用就是对sql进行分类化管理,理解sql隔离 
              注意:使用mapper代理方法开发,namespace有特殊重要的作用-->
      <mapper namespace="ecut.association.mapper.RoleMapperComic">
    
          <resultMap type="Comic" id="ComicDubberResultMap">
              <id column="id" property="id"/>
              <result column="comic_name" property="comicName"/>
              <result column="remark" property="remark"/>
              <collection property="roles" ofType="Role">
                  <!-- id:角色唯 一标识
                 property:要将角色的唯 一标识 映射到Role类的哪个属性
                   -->
                  <id column="role_id" property="id"/>
                  <result column="role_name" property="roleName"/>
                  <result column="comic_id" property="comicId"/>
                  <result column="note" property="note"/>
                  <association property="dubber" javaType="Dubber">
                    <id column="dubber_id" property="id"/>
                      <result column="dubber_name" property="dubberName"/>
                      <result column="dubber_role_id" property="roleId"/> 
                 </association>
              </collection>
          </resultMap>
          
          
          <!--查询动漫信息。关联查询动漫中的角色的配音演员信息,使用resultMap-->
          <select id="findComicsAndDubber" resultMap="ComicDubberResultMap">
              SELECT 
            t_comic.*,t_role.id AS role_id, t_role.role_name,  t_role.note ,t_role.comic_id ,t_dubber.id AS dubber_id , t_dubber.dubber_name ,t_dubber.role_id  AS dubber_role_id FROM t_comic, t_role,t_dubber
              <where>
               t_role.id = t_dubber.role_id  AND t_role.comic_id = t_comic.id
              </where>
          </select>
          
      </mapper>

    将动漫信息映射到Comic中。

    在Comic类中添加角色列表属性List<Role> roles,将动漫角色映射到roles中

    Role中添加Dubber属性,将角色所对应的配音演员映射到dubber中

  • 接口类
    package ecut.association.mapper;
    
    import java.util.List;
    
    import ecut.association.po.Comic;
    import ecut.association.po.Role;
    import ecut.association.po.RoleComic;
    
    public interface RoleMapperComic {
        
        //查询动漫信息。关联查询动漫中的角色及配音演员信息
        public List<Comic> findComicsAndDubber() throws Exception ;
        
    }
  • 测试类
    package ecut.association.test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    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.junit.Before;
    import org.junit.Test;
    
    import ecut.association.mapper.RoleMapperComic;
    import ecut.association.po.Comic;
    import ecut.association.po.Role;
    import ecut.association.po.RoleComic;
    
    public class ComicMapperTest {
        
        private SqlSessionFactory factory;
    
        
        @Before
        public  void init() throws IOException {
            String resource = "ecut/association/mybaits-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactoryBuilder builer =new SqlSessionFactoryBuilder();
            factory = builer.build(inputStream);
        }
    
        @Test
        public void testFindComicsAndDubber() throws Exception {
            SqlSession session = factory.openSession();
            RoleMapperComic  mapper =  session.getMapper(RoleMapperComic.class);
            List<Comic> comics = mapper.findComicsAndDubber();
            for(Comic c : comics){
                String s = "动漫信息:id="+c.getId()+",comicName="+c.getComicName()+",remark="+c.getRemark();
                System.out.println(s);
                for(Role r:c.getRoles()){
                    System.out.println("角色信息:id =" + r.getId() + ",roleName =" + r.getRoleName() + ", note = " + r.getNote()+", comicId = " + r.getComicId());
                    System.out.println("配音演员信息:id =" + r.getDubber().getId()+ ",dubberName =" + r.getDubber().getDubberName() + ", roleId = " + r.getDubber().getRoleId());
                }
                System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~");
            }
        }
    
    }

3、总结

  • 一对多是多对多的特例
  • 使用resultMap是针对那些对查询结果映射有特殊要求的功能,,比如特殊要求映射成list中包括 多个list。

resultType 和 resultMap总结

1、resultType

  • 作用:将查询结果按照sql列名pojo属性名一致性映射到pojo中。
  • 场合:常见一些明细记录的展示,比如用户购买商品明细,将关联查询信息全部展示在页面时,此时可直接使用resultType将每一条记录映射到pojo中,在前端页面遍历list(list中是pojo)即可。

2、resultMap:

  • 使用association和collection完成一对一和一对多高级映射(对结果有特殊的映射要求)。
  • association:

    作用: 将关联查询信息映射到一个pojo对象中。

    场合:为了方便查询关联信息可以使用association将关联订单信息映射为用户对象的pojo属性中,比如:查询角色及关联动漫信息。

       使用resultType无法将查询结果映射到pojo对象的pojo属性中,根据对结果集查询遍历的需要选择使用resultType还是resultMap。

  • collection:

    作用:将关联查询信息映射到一个list集合中。

    场合:为了方便查询遍历关联信息可以使用collection将关联信息映射到list集合中,如果使用resultType无法将查询结果映射到list集合中。

转载请于明显处标明出处

https://www.cnblogs.com/AmyZheng/p/9374126.html

原文地址:https://www.cnblogs.com/AmyZheng/p/9374126.html