MyBatis(二)-CURD (ResultMap 一对一,一对多)

打印 上一主题 下一主题

主题 895|帖子 895|积分 2685

1、insert 标签

1.1 获取SqlSessionFactory 对象的通用方法

方便后面分测试;
  1. //获取SqlSessionFactory 对象的通用方法
  2. public SqlSessionFactory getSqlSessionFactory() throws IOException {
  3.     InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
  4.     return new SqlSessionFactoryBuilder().build(inputStream);
  5. }
复制代码
1.2 属性说明

属性名说明idnamespace指定接口中的方法名parameterType指定接口方法入参类型,可写可不写(mybatis可用根据接口方法,自动推断类型)useGeneratedKeyinsert标签的属性,告诉mybatis,执行插入操作,需要返回自增的主键keyColumn自增主键的 字段名(可以不写,一张表只用能有一个自增主键)keyPropert指定返回的自增主键值,交给入参实体的哪个属性保存注意:增删改操作,和select查询标签最大的区别是:返回只有影响行数,所有没有resultType属性,而查询必须有resultType;
1.3 SQL
  1. <insert id="insertAnime" useGeneratedKeys="true" keyColumn="id" keyProperty="id" >
  2.     insert into `animes`(
  3.         `cid`,
  4.         `name`
  5.     )values(
  6.         #{cid},
  7.         #{name}
  8.     )
  9. </insert>
复制代码
1.4 测试

注意:mybatis 默认对增删改操作,事务不自动提交(自动提交是关闭的);
需要开启自动提交或这是手动提交
开启自动提交openSession(true);手动提交sqlSession.commit();
  1. @Test
  2. public void testMybatisMapperC() throws IOException {
  3.     //获取SqlSession对象
  4.     // SqlSession sqlSession = getSqlSessionFactory().openSession();
  5.     //方式2:创建SqlSession对象时,指定事务自动提交-true,默认false
  6.     SqlSession sqlSession = getSqlSessionFactory().openSession(true);
  7.     //获取mapper接口的代理实现对象
  8.     AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
  9.     System.out.println(animeMapper); //org.apache.ibatis.binding.MapperProxy@224edc67
  10.     //模拟从前端获取参数,封装请求实体
  11.     Anime animeForm = new Anime();
  12.     animeForm.setCid(1);
  13.     animeForm.setName("蜡笔小新");
  14.     //执行添加动漫
  15.     int row = animeMapper.insertAnime(animeForm);
  16.     //mybatis 默认对增删改操作,事务是不自动提交(自动提交是关闭的)
  17.     //方式1:手动提交
  18.     //sqlSession.commit();
  19.     System.out.println(String.format("----------执行添加动漫,影响行数:%d--------", row));
  20.    
  21.     //获取自增主键
  22.     System.out.println(String.format("----------执行添加动漫,新增的自增id:%d--------", animeForm.getId()));
  23.    
  24. }
复制代码
2、update 标签

2.1 SQL
  1. <update id="updateAnimeById">
  2.     update `animes` set
  3.         `cid` = #{cid},
  4.         `name` = #{name}
  5.     where `id` = #{id}
  6. </update>
复制代码
2.2 测试
  1. @Test
  2. public void testMybatisMapperU() throws IOException {
  3.     SqlSession sqlSession = getSqlSessionFactory().openSession(true);
  4.     AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
  5.     //模拟从前端获取参数,封装请求实体
  6.     Anime animeForm = new Anime();
  7.     animeForm.setId(648);
  8.     animeForm.setCid(1);
  9.     animeForm.setName("蜡笔小新5");
  10.     //执行修改动漫
  11.     int row = animeMapper.updateAnimeById(animeForm);
  12.     System.out.println(String.format("----------执行修改动漫,影响行数:%d--------", row));
  13. }
复制代码
3、delete 标签

3.1 SQL
  1. <delete id="deleteAnimeById">
  2.     delete from `animes`
  3.     where `id` =  #{animeId}
  4. </delete>
复制代码
3.2 测试
  1. @Test
  2. public void testMybatisMapperD() throws IOException {
  3.     SqlSession sqlSession = getSqlSessionFactory().openSession(true);
  4.     AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
  5.     //模拟从前端获取参数,封装请求实体
  6.     Anime animeForm = new Anime();
  7.     animeForm.setId(648);
  8.     //执行删除动漫
  9.     int row = animeMapper.deleteAnimeById(animeForm.getId());
  10.     System.out.println(String.format("----------执行删除动漫,影响行数:%d--------", row));
  11. }
复制代码
4、select 标签

4.1  属性说明

属性名说明id对应就是namespace指定接口中的查询方法名parameterType指定接口方法入参类型可写可不写(建议不写)resultType指定接口返回的目标类型(建议使用全类名,也可以使用别名)

  • #{id}:这就告诉 MyBatis 创建一个预处理语句(PreparedStatement)参数,在 JDBC 中,这样的一个参数在 SQL 中会由一个“?”来标识,并被传递到一个新的预处理语句中;
  • 如果接口只有一个参数参数名可以随便写,建议跟形参名保持一致
4.2 一个参数

4.2.1 SQL

接口只有一个参数,参数名,可以随便写,建议跟形参名保持一致;
  1. <select id="selectAnimeById" resultType="com.kgc.mybatis.bean.Anime">
  2.     select `id`,
  3.     `cid`,
  4.     `name`
  5.     from `animes`
  6.     where `id` = #{animeId}
  7. </select>
复制代码
4.2.2 测试
  1. @Test
  2. public void testMybatisMapperSelectParams1() throws IOException{
  3.     SqlSession sqlSession = getSqlSessionFactory().openSession();
  4.     AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
  5.     //调用mapper接口,根据动漫编号查询动漫信息
  6.     Anime anime = animeMapper.selectAnimeById(101);
  7.     System.out.println(String.format("1.一个参数 根据动漫编号:%d,查询动漫详情%s",anime.getId(),anime));
  8. }
复制代码
4.3 两个参数

多个参数,没有自定义参数别名时可以使用

  • 形参名
  • 内置参数 0,1,...
  • 内置参数 param1,param2,...
自定义参数别名@Param("自定义参数名")时可以使用:

  • 自定义参数名
  • 内置参数  param1,param2,...
4.3.1 SQL

4.3.1.1 没有自定义参数别名:
  1. Anime selectAnimeByNameAndCid(String animeName,Integer animeId);
复制代码
  1. <select id="selectAnimeByNameAndCid" resultType="com.kgc.mybatis.bean.Anime">
  2.     select `id`,
  3.     `cid`,
  4.     `name`
  5.      from `animes`
  6.     where `name` = #{animeName}
  7.     and `cid` = #{animeId}
  8. </select>
复制代码
4.3.1.2 自定义参数别名
  1. Anime selectAnimeByNameAndCid(@Param("animeName") String animeName,@Param("animeId") Integer animeId);
复制代码
  1. Anime selectAnimeByNameAndCid(@Param("animeName") String animeName,@Param("animeId") Integer animeId);<select id="selectAnimeByNameAndCid" resultType="com.kgc.mybatis.bean.Anime">
  2.     select `id`,
  3.     `cid`,
  4.     `name`
  5.      from `animes`
  6.     where `name` = #{animeName}
  7.     and `cid` = #{animeId}
  8. </select>
复制代码
自定义了参数名,如果使用#{0},#{1}会报错
Cause: org.apache.ibatis.binding.BindingException: Parameter '0' not found. Available parameters are [animeId, animeName, param1, param2]
4.3.2 测试
  1. @Test
  2. public void testMybatisMapperSelectParams2() throws IOException{
  3.     SqlSession sqlSession = getSqlSessionFactory().openSession();
  4.     AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
  5.     //通过动漫名称和分类编号查询动漫信息
  6.     Anime anime = animeMapper.selectAnimeByNameAndCid("完美世界",3);
  7.     System.out.println(String.format("2.两个参数 根据动漫编号:%d,查询动漫详情%s",anime.getId(),anime));
  8. }
复制代码
4.4 实体参数

不自定义参数别名:

  • 必须 只写 属性名 cid  author
自定义参数别名:

  • 使用   别名.属性名
  • 使用   param1.属性名
4.4.1 SQL

4.4.1.1  不自定义参数别名
  1. Anime selectAnimeByAnime(Anime animeForm);
复制代码
  1. <select id="selectAnimeByAnime" resultType="com.kgc.mybatis.bean.Anime">
  2.     select `id`,
  3.     `cid`,
  4.     `name`
  5.     from `animes`
  6.         where `cid` = #{cid}
  7.     and `author` = #{author}
  8. </select>
复制代码
4.4.1.2  自定义参数别名
  1. Anime selectAnimeByAnime(@Param("animeForm") Anime animeForm);
复制代码
  1. <select id="selectAnimeByAnime" resultType="com.kgc.mybatis.bean.Anime">
  2.     select `id`,
  3.     `cid`,
  4.     `name`
  5.     from `animes`
  6.      where `cid` = #{param1.cid}
  7.      and `author` = #{param1.author}
  8. </select>
复制代码
4.4.2 测试
  1. @Test
  2. public void testMybatisMapperSelectParams3() throws IOException{
  3.     SqlSession sqlSession = getSqlSessionFactory().openSession();
  4.     AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
  5.     //通过动漫分类编号和作者查询动漫信息
  6.     Anime animeForm = new Anime();
  7.     animeForm.setCid(1);
  8.     animeForm.setAuthor("三少");
  9.     Anime anime = animeMapper.selectAnimeByAnime(animeForm);
  10.     System.out.println(String.format("3.实体参数 根据动漫编号:%d,查询动漫详情%s",anime.getId(),anime));
  11. }
复制代码
4.5  Map集合参数


  • 通过Map 的 **键值 **获取参数
4.5.1 SQL
  1. <select id="selectAnimeByActorAndCid" resultType="com.kgc.mybatis.bean.Anime">
  2.     select `id`,
  3.     `cid`,
  4.     `name`
  5.      from `animes`
  6.     where `cid` = #{cid}
  7.     and `actor` = #{actor}
  8. </select>
复制代码
4.5.2 测试
  1. @Test
  2. public void testMybatisMapperSelectParams4() throws IOException{
  3.     SqlSession sqlSession = getSqlSessionFactory().openSession();
  4.     AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
  5.     //通过动漫分类编号和主角查询动漫信息
  6.     Map<String,Object> queryMap = new HashMap<>();
  7.     queryMap.put("cid","2");
  8.     queryMap.put("actor","路飞");
  9.     Anime anime = animeMapper.selectAnimeByActorAndCid(queryMap);
  10.     System.out.println(String.format("4.集合参数 根据动漫编号:%d,查询动漫详情%s",anime.getId(),anime));
  11. }
复制代码
4.6  #{}  和 ${} 的区别

#{}:

  • 类似于PreparedStatement
  • 可以获取普通参数,自定义参数,实体参数,集合参数等;
  • 底层使用的是?占位符,会进行预编译处理,可以防止SQL注入问题,安全性高;
  • 不可以进行表达式运算
${}:

  • 类似于Statement
  • 正常情况下,跟#{}获取参数的写法没有区别;
  • 区别:不能随意获取参数不能使用内置参数必须起别名;
  • 底层是字符串拼接,不是占位符,不安全,当#{}解决不了,就必须使用${};
  • 可以使用,动态表名,动态列名,表达式运算等
建议:MyBatis的SQL映射文件中,能优先使用#{},就必须使用,除非特殊情况,必须使用字符串拼接,才可以使用${};
4.6.1 SQL

使用动态表名查询动漫;
  1.     <select id="selectProduceAndCid" resultType="com.kgc.mybatis.bean.Anime">
  2.         select `id`,
  3.                 `cid`,
  4.                 `name`
  5.         from    ${tableName}
  6.         where  `produce` = #{produce}
  7.         and `cid` = #{cid}
  8. </select>
复制代码
4.6.2 测试
  1. @Test
  2. public void testMybatisMapperSelectParams5() throws IOException{
  3.     SqlSession sqlSession = getSqlSessionFactory().openSession();
  4.     AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
  5.     Anime anime = animeMapper.selectProduceAndCid("腾讯动漫", 2, "animes");
  6.     System.out.println(String.format("4.集合参数 根据动漫编号:%d,查询动漫详情%s",anime.getId(),anime));
  7. }
复制代码
4.7 查询多条数据

查询多条数据, resultType 属性值还是实体类
resultType="com.kgc.mybatis.bean.Anime"
Mybatis会自己走 返回集合的方法自动将数据放到集合中
  1. //var1 select标签的id属性的值
  2. <E> List<E> selectList(String var1);
  3. //var2 为接口方法的参数
  4. <E> List<E> selectList(String var1, Object var2);
  5. //var3 为分页对象
  6. <E> List<E> selectList(String var1, Object var2, RowBounds var3);
复制代码
4.7.1 SQL
  1. <select id="selectAnimeListByCid" resultType="com.kgc.mybatis.bean.Anime">
  2.     select `id`,
  3.     `cid`,
  4.     `name`
  5.     from   `animes`
  6.     where  `cid` = #{cid}
  7. </select>
复制代码
4.7.2 测试
  1. @Test
  2. public void testMyBatisMapperSelectResults() throws  IOException {
  3.     SqlSession sqlSession = getSqlSessionFactory().openSession();
  4.     AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
  5.         //根据动漫分类编号查询动漫
  6.     List<Anime> animeList = animeMapper.selectAnimeListByCid(3);
  7.     for (Anime anime : animeList) {
  8.         System.out.println(anime);
  9.     }
  10. }
复制代码
4.8 模糊查询

使用 #{} 建议使用 concat('%',#{name},'%');
使用 ${name}  必须给参数起别名
4.8.1 SQL

4.8.1.1 使用 #{name}
  1. <select id="selectAnimeListByName" resultType="com.kgc.mybatis.bean.Anime">
  2.     select `id`,
  3.     `cid`,
  4.     `name`
  5.     from   `animes`
  6.    
  7.     where  name like concat('%',#{name},'%')
  8. </select>
复制代码
4.8.1.2 使用${name}
  1. <select id="selectAnimeListByName" resultType="com.kgc.mybatis.bean.Anime">
  2.     select `id`,
  3.     `cid`,
  4.     `name`
  5.     from   `animes`
  6.     where  name like '%${name}%'
  7. </select>
复制代码
使用${name} 如果不取别名, 取不到参数;
There is no getter for property named 'name' in 'class java.lang.String'
4.8.2 测试
  1. @Test
  2. public void testMyBatisMapperSelectResults2() throws  IOException {
  3.     SqlSession sqlSession = getSqlSessionFactory().openSession();
  4.     AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
  5.     //根据动漫名称 模糊 查询动漫列表
  6.     List<Anime> animeList = animeMapper.selectAnimeListByName("魁");
  7.     for (Anime anime : animeList) {
  8.         System.out.println(anime);
  9.     }
  10. }
复制代码
4.9 分页查询


  • 方法一:调用接口的时候,计算好分页起始行,SQL中直接获取参数((pageNo - 1)*pageSize),实现分页;
  • 方法二:使用 limit ${(pageNo - 1)*pageSize},#{pageSize} (不建议使用)
  • 方法三:使用select的子标签bind自定义属性,
4.9.1 SQL
  1. <select id="selectAnimeListByProduce" resultType="com.kgc.mybatis.bean.Anime">
  2.     <bind name="pageIndex" value="((pageNo - 1)*pageSize)"/>
  3.     select `id`,
  4.     `cid`
  5.     from   `animes`
  6.     where  `produce` like concat('',#{produce},'%')
  7.    
  8.    
  9.    
  10.     limit #{pageIndex},#{pageSize}
  11. </select>
复制代码
4.9.2 测试
  1. @Test
  2. public void testSelectAnimeListByProduce() throws IOException {
  3.     SqlSession sqlSession = getSqlSessionFactory().openSession();
  4.     AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
  5.     //模拟获取分页参数
  6.     Integer pageNo = 1;
  7.     Integer pageSize = 3;
  8.     //调用mapper接口,模糊查询,查询分页列表
  9.     //方法一:调用接口的时候,计算好分页起始行,SQL中直接获取参数,实现分页
  10.     //方法二:使用 limit ${(pageNo - 1)*pageSize},#{pageSize}
  11.     //方法三:使用select的子标签bind,<bind name="pageIndex" value="((pageNo - 1)*pageSize)"/>
  12.     List<Anime> animeList = animeMapper.selectAnimeListByProduce("爱奇艺",pageNo,pageSize);
  13.     animeList.forEach(System.out::println);
  14. }
复制代码
4.10 返回Map集合

4.10.1 列名作为key,数值作为value


  • 以动漫详情为例模拟返回map集合,将列名作为key,数值作为value;
  • 实际开发中,查询结果集,是单条记录,且没有实体对应,比如:数据统计,只有统计结果,没有统计实体;
5.10.1.1 SQL

Map,方法的返回类型是Map,key是String类型,value是Object类型,因为每个字段有不同的类型
resultType="java.util.HashMap",因为将数据映射到map中;
  1. <select id="selectAnimeMapById" resultType="java.util.HashMap">
  2.     select  `id`,
  3.     `cid`,
  4.     `name`
  5.     from   `animes`
  6.     where  `id` = #{id}
  7. </select>
复制代码
4.10.1.1  测试
  1. @Test
  2. public  void testSelectAnimeByMapById() throws IOException {
  3.     SqlSession sqlSession = getSqlSessionFactory().openSession();
  4.     AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
  5.     Map<String, Object> animeMap = animeMapper.selectAnimeMapById(301);
  6.     System.out.println(animeMap);
  7.     Object actor = animeMap.get("actor");
  8.     System.out.println("actor==>"+actor);
  9. }
复制代码
4.10.2主键key,实体为value


  • 以动漫详情为例模拟返回map集合,将数据主键列值作为key,整条数据作为value
  • 实际开发中返回多条记录,并需要根据key,快速遍历,比如分组查询;
4.10.2.1 SQL

因为它不知道你要将哪个属性作为map的key值,所以需要@MapKey("id")指定一个实体的属性作为map的key值;
  1. //以动漫详情为例模拟返回map集合,将数据主键列值作为key,整条数据作为value
  2. @MapKey("id")   //这里的MapKey 是实体的一个属性
  3. Map<Integer,Anime> selectAnimeMapByCid(Integer cid);
复制代码
resultType="com.kgc.mybatis.bean.Anime",虽然返回的结果是map,但是数据是映射到Anime动漫实体中;
  1. <select id="selectAnimeListByCid" resultType="com.kgc.mybatis.bean.Anime">
  2.     select `id`,
  3.     `cid`,
  4.     `name`
  5.     from   `animes`
  6.     where  `cid` = #{cid}
  7. </select>
复制代码
4.10.2.2 测试
  1. @Test
  2. public void  testSelectAnimeMapByCid() throws IOException {
  3.     SqlSession sqlSession = getSqlSessionFactory().openSession();
  4.     AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
  5.     Map<Integer, Anime> animeMap = animeMapper.selectAnimeMapByCid(3);
  6.     System.out.println(animeMap);
  7.     Anime anime = animeMap.get(301);
  8.     System.out.println(anime);
  9. }
复制代码
5、ResultMap 结果集映射

5.1 列名 和 属性名 不匹配


  • 可以取别名,查询出来的列名,取别名,跟实体的属性名一致
  • 自定义resultMap映射
5.1.1 SQL

resultMap的参数说明idresultMap唯一idtype返回值类型autoMapping是否开启自动映射resultMap自定义标签内指定的列才会映射,如果查询的结果列,不在自定义映射标签中,但是满足自动映射的条件(列名和实体属性名一致),    仍然会自动映射;
除非指定resultMap标签的autoMapping属性为falseautoMapping="false"),没有自定义映射的其他字段才不会自动映射
  1. <select id="selectAnimeByResultMap" resultMap="animeResultMap">
  2.     select `id`,
  3.     `cid`,
  4.     `name`,
  5.     `author`,
  6.     `actor`,
  7.     `produce`,
  8.     `create_date` `crateTime`
  9.     from   `animes`
  10.     where  `id` = #{id}
  11. </select>
  12. <resultMap id="animeResultMap" type="com.kgc.mybatis.bean.Anime" autoMapping="false">
  13.    
  14.     <id column="id" property="id"></id>
  15.    
  16.     <result column="cid" property="cid"></result>
  17.     <result column="name" property="name"></result>
  18.     <result column="crateTime" property="createDate"></result>
  19. </resultMap>
复制代码
5.1.2 测试
  1. @Test
  2. public void  testSelectAnimeByResultMap() throws IOException {
  3.     SqlSession sqlSession = getSqlSessionFactory().openSession();
  4.     AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
  5.     //使用自定义映射,查询动漫详情,解决列名和属性名不同意的映射
  6.     Anime anime = animeMapper.selectAnimeByResultMap(301);
  7.     System.out.println(anime);
  8. }
复制代码
5.2 级联映射

实体属性,级联映射;
5.2.1 一对一

级联映射只适合一对一;
要求:查询动漫Anime,并且查询出动漫的 实体属性category 的信息;
一个动漫  对  一个动漫分类
5.2.1.1 实体

动漫实体Anime
  1. public class Anime {
  2.     //动漫编号
  3.     private Integer id;
  4.     //分类编号
  5.     private  Integer cid;
  6.     //名称
  7.     private  String name;
  8.         ......
  9.     //分类详情实体,一对一  (也可以定义分类名称冗余到实体中也可以解决)
  10.     private Category category;
  11. }
复制代码
分类实体Category
  1. public class Category {
  2.     //分类编号
  3.     private  Integer id;
  4.     //分类名称
  5.     private  String name;
  6. }
复制代码
5.2.1.2 SQL
  1. [/code][table][tr]参数说明[/tr][tr][td]column="cid"[/td][td]连表查询出来的字段[/td][/tr][tr][td]property="category.id"[/td][td]实体属性 的属性[/td][/tr][/table]先通过[b]连表查询[/b],将动漫信息和分类信息查询出来,[b]再根据字段[/b],[b]一 一 映射[/b];
  2. [code]<resultMap id="animeResultMapCascade" type="com.kgc.mybatis.bean.Anime" >
  3.    
  4.     <id column="id" property="id"></id>
  5.    
  6.     <result column="cid" property="cid"></result>
  7.     <result column="name" property="name"></result>
  8.     <result column="author" property="author"></result>
  9.     <result column="create_date" property="createDate"></result>
  10.    
  11.     <result column="cid" property="category.id"></result>
  12.     <result column="cname" property="category.name"></result>
  13. </resultMap>
复制代码
5.2.1.3 测试
  1. @Test
  2. public void  testSelectAnimeByResultMapCascade() throws IOException {
  3.     SqlSession sqlSession = getSqlSessionFactory().openSession();
  4.     AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
  5.     //级联映射,动漫实体内部,分类实体属性的 级联映射
  6.     Anime anime = animeMapper.selectAnimeByResultMapCascade(301);
  7.     System.out.println(anime);
  8.     //Anime(id=301,
  9.     //                cid=3,
  10.     //                name=完美世界,
  11.     //        ......
  12.     //                category=Category(id=3, name=科幻)
  13.     //      )
  14. }
复制代码
5.3 关联映射 (高级映射)

实体属性,关联映射;
5.3.1 association 一对一

要求:查询动漫Anime,并且查询出动漫的 实体属性category 的信息 ;
一个动漫  对  一个动漫分类
5.3.1 实体

动漫实体Anime
  1. public class Anime {
  2.     //动漫编号
  3.     private Integer id;
  4.     //分类编号
  5.     private  Integer cid;
  6.     //名称
  7.     private  String name;
  8.         ......
  9.     //分类详情实体,一对一  
  10.     private Category category;
  11. }
复制代码
分类实体Category
  1. public class Category {
  2.     //分类编号
  3.     private  Integer id;
  4.     //分类名称
  5.     private  String name;
  6. }
复制代码
5.3.2 SQL

先通过连表查询,查询出动漫信息,和动漫分类信息;
再通过association标签,对动漫的 实体属性 category 进行赋值
  1.     select a.`id`,    a.`cid`,    a.`name`,    a.`author`,    a.`actor`,    a.`produce`,    a.`create_date`,    c.`name` 'cname'    from   `animes` a,`category` c    where  a.`cid` = c.`id`    and a.`id` = #{id}<resultMap id="animeResultMapCascade" type="com.kgc.mybatis.bean.Anime" >
  2.    
  3.     <id column="id" property="id"></id>
  4.    
  5.     <result column="cid" property="cid"></result>
  6.     <result column="name" property="name"></result>
  7.     <result column="author" property="author"></result>
  8.     <result column="create_date" property="createDate"></result>
  9.    
  10.     <result column="cid" property="category.id"></result>
  11.     <result column="cname" property="category.name"></result>
  12. </resultMap>                    
复制代码
5.3.3 测试
  1. @Test
  2. public void  testSelectAnimeByResultMapAssociation() throws IOException {
  3.     SqlSession sqlSession = getSqlSessionFactory().openSession();
  4.     AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
  5.     Anime anime = animeMapper.selectAnimeByResultMapAssociation(301);
  6.     System.out.println(anime);
  7.     //Anime(id=301,
  8.     //                cid=3,
  9.     //                name=完美世界,
  10.     //        ......
  11.     //                category=Category(id=3, name=科幻)
  12.     //      )
  13. }
复制代码
5.3.2  collection 一对多

要求:查询分类Category,并且查询出分类下的动漫集合属性 animes   信息
一个动漫分类  对  多个动漫
5.3.1 实体

分类实体Category
  1. public class Category {
  2.     //分类编号
  3.     private  Integer id;
  4.     //分类名称
  5.     private  String name;
  6.     //当前 分类下的 动漫集合
  7.     private List<Anime> animes;
  8. }
复制代码
动漫实体Anime
  1. public class Anime {
  2.     //动漫编号
  3.     private Integer id;
  4.     //分类编号
  5.     private  Integer cid;
  6.     //名称
  7.     private  String name;
  8.         ......
  9. }
复制代码
5.3.2 SQL

先通过连表查询,查询出动漫分类信息,和动漫信息;
再通过collection标签,对动漫分类的 集合属性 animes 进行赋值
  1.     select c.`id`,    c.`name`,    a.`id` 'aid',    a.`cid`,    a.`name` 'aname',    a.`author`,    a.`actor`,    a.`create_date`,    a.`produce`    from   `category` c,`animes` a    where  c.`id` = a.`cid`    and c.`id` = #{id}<resultMap id="animeResultMapCascade" type="com.kgc.mybatis.bean.Anime" >
  2.    
  3.     <id column="id" property="id"></id>
  4.    
  5.     <result column="cid" property="cid"></result>
  6.     <result column="name" property="name"></result>
  7.     <result column="author" property="author"></result>
  8.     <result column="create_date" property="createDate"></result>
  9.    
  10.     <result column="cid" property="category.id"></result>
  11.     <result column="cname" property="category.name"></result>
  12. </resultMap>                                    
复制代码
5.3.3 测试
  1. @Test
  2. public void  testSelectCategoryByResultMapCollection() throws IOException {
  3.     SqlSession sqlSession = getSqlSessionFactory().openSession();
  4.     CategoryMapper categoryMapper = sqlSession.getMapper(CategoryMapper.class);
  5.     //查询动漫分类详情,内部集合类型 映射
  6.     Category category = categoryMapper.selectCategoryByResultMapCollection(3);
  7.     System.out.println(category);
  8.     //Category(id=3,
  9.     //                   name=科幻,
  10.     //                   animes=[Anime(id=301, cid=3, name=完美世界, ...),
  11.     //                 Anime(id=649, cid=3, name=蜡笔小新, ...)
  12.     //                 ]
  13.     //         )
  14. }
复制代码
5.4  嵌套select, 延迟加载 和 分步查询


  • 开启延迟加载,默认false,需要支持延迟,改为true;



  • 按需加载 ,是否全部加载,

    • (前提必须是言辞加载是打开的,而且是自定义映射,配合高级嵌套select查询);
    • 3.4.1及之前的版本中默认为true,全部加载(任意一方法的调用都会加载该对象的所有延迟加载属性);
    • 只有改为false,才会分步加载,需要调用该方法时,才进行 延迟加载属性;


5.4.1 association 一对一

要求:查询动漫Anime,并且查询出动漫的 实体属性category 的信息 ;
一个动漫  对  一个动漫分类
5.4.1.1 实体

跟 关联映射  association 一对一 的实体一样;
5.4.1.2 SQL
  1. [/code][table][tr]参数说明[/tr][tr][td]property[/td][td]实体的属性[/td][/tr][tr][td]select[/td][td]指定嵌套的select语句的唯一标识[/td][/tr][tr][td]column[/td][td]指定嵌套的sleect语句执行需要的参数,多参数JSON格式{key1=col1,key2=col2}[/td][/tr][tr][td]fetchType[/td][td]是否适配系统延迟加载,默认是lazy,如果需要局部关闭延迟加载,改为eager[/td][/tr][/table]先通过[b]id查询动漫Anime[/b],再通过动漫的[b]cid,去查询 动漫分类[/b];
  2. AnimeMapper.xml
  3. [code]<select id="selectAnimeByResultMap" resultMap="animeResultMap">
  4.     select `id`,
  5.     `cid`,
  6.     `name`,
  7.     `author`,
  8.     `actor`,
  9.     `produce`,
  10.     `create_date` `crateTime`
  11.     from   `animes`
  12.     where  `id` = #{id}
  13. </select>
  14. <resultMap id="animeResultMap" type="com.kgc.mybatis.bean.Anime" autoMapping="false">
  15.    
  16.     <id column="id" property="id"></id>
  17.    
  18.     <result column="cid" property="cid"></result>
  19.     <result column="name" property="name"></result>
  20.     <result column="crateTime" property="createDate"></result>
  21. </resultMap>                           
复制代码
CategoryMapper.xml
  1. <select id="selectCategoryById" resultType="com.kgc.mybatis.bean.Category">
  2.     select `id`,
  3.     `name`
  4.     from `category`
  5.     where `id`= #{id}
  6. </select>
复制代码
5.4.1.3 测试
  1. @Test
  2. public void  testSelectAnimeByResultMapAssociationLazyLoadingStep() throws IOException {
  3.     SqlSession sqlSession = getSqlSessionFactory().openSession();
  4.     AnimeMapper animeMapper = sqlSession.getMapper(AnimeMapper.class);
  5.    
  6.     //高级映射,内部实体一对一 ,使用嵌套select 延迟加载和分布查询
  7.     Anime anime = animeMapper.selectAnimeByResultMapAssociationLazyLoadingStep(301);
  8.     System.out.println("如果只使用动漫的信息,不使用加载 动漫分类的SQL");
  9.     System.out.println(anime.getName());
  10.     System.out.println("=============================================");
  11.     System.out.println("动漫的分类名称:"+anime.getCategory().getName());
  12. }
复制代码
开启延迟加载和按需加载

关闭延迟加载和按需加载,或者局部关闭延迟加载

5.4.2 collection 一对多

要求:查询分类Category,并且查询出分类下的动漫集合属性 animes   信息
一个动漫分类  对  多个动漫
5.4.2.1 实体

跟 关联映射  collection 一对多 的实体一样;
5.4.2.2 SQL

先通过id查询分类Category,再通过动漫的id,去查询cid等于id的动漫
CategoryMapper.xml
  1. <select id="selectCategoryById" resultType="com.kgc.mybatis.bean.Category">
  2.     select `id`,
  3.     `name`
  4.     from `category`
  5.     where `id`= #{id}
  6. </select>                    
复制代码
AnimeMapper.xml
  1. <select id="selectAnimeMapByCid" resultType="com.kgc.mybatis.bean.Anime">
  2.     select `id`,
  3.     `cid`,
  4.     `name`,
  5.     `author`,
  6.     `actor`,
  7.     `produce`,
  8.     `create_date`
  9.     from   `animes`
  10.     where  `cid` = #{cid}
  11. </select>
复制代码
5.4.2.3 测试
  1. @Test
  2. public void testSelectCategoryByResultMapCollectionAssociationLazyLoadingStep() throws IOException {
  3.     SqlSession sqlSession = getSqlSessionFactory().openSession();
  4.     CategoryMapper categoryMapper = sqlSession.getMapper(CategoryMapper.class);
  5.     Category category = categoryMapper.selectCategoryByResultMapCollectionAssociationLazyLoadingStep(1);
  6.     System.out.println("分类名称:"+category.getName());
  7.     System.out.println("=============================================");
  8.     System.out.println("该分类下的动漫:"+category.getAnimes());
  9. }
复制代码
开启延迟加载和按需加载

关闭延迟加载和按需加载,或者局部关闭延迟加载


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

怀念夏天

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表