• 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

  • 相关阅读:
    Nginx 413 Request Entity Too Large
    Docker 搭建一个多端同步网盘-Nextcloud
    FTP主动模式(PORT)与被动模式(PASV)
    Linux安装与使用FTP服务-vsftpd
    Mac FTP工具推荐-Transmit
    Nginx配置动静分离
    Nginx解决跨域问题(CORS)
    CentOS 7 之找回失落的ifconfig
    CentOS 7 之安装篇
    深入研究MiniMVC之后续篇
  • 原文地址:https://www.cnblogs.com/AmyZheng/p/9374126.html
Copyright © 2020-2023  润新知