• Mybatis 小谈 (下篇)


    写在前面:分享技术,共同进步,有不足请见谅,相关意见可评论告知 ~

    编程路漫之远兮,运架构体之帷幄;
    劝君专注案前事,亦是杯酒敬苍生;

    多对一处理

    在这里插入图片描述

    测试环境搭建

    1. 导入lombok
      在这里插入图片描述

    2. 新建实体类 Teacher,Student

    3. 建立Mapper接口

    4. 建立Mapper.XML文件

    5. 在核心配置文件中绑定注册我们的Mapper接口或者文件!【方式很多,随心选】

    6. 测试查询是否能够成功!

    搭建图解

    在这里插入图片描述

    原始数据库SQL 操作:

    在这里插入图片描述

    按照查询嵌套处理

    解决两个内容无法连接的问题(即有一个属性为空)

    <!--
        思路:
            1. 查询所有的学生信息
            2. 根据查询出来的学生的tid,寻找对应的老师!  子查询
        -->
    
    <select id="getStudent" resultMap="StudentTeacher">
        select * from student
    </select>
    
    <resultMap id="StudentTeacher" type="Student">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <!--复杂的属性,我们需要单独处理 对象: association 集合: collection -->
        <association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
    </resultMap>
    
    <select id="getTeacher" resultType="Teacher">
        select * from teacher where id = #{id}
    </select>
    
    

    按照结果嵌套处理(推荐)

    <!--按照结果嵌套处理-->
    <select id="getStudent2" resultMap="StudentTeacher2">
        select s.id sid,s.name sname,t.name tname
        from student s,teacher t
        where s.tid = t.id;
    </select>
    
    <resultMap id="StudentTeacher2" type="Student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <association property="teacher" javaType="Teacher">
            <result property="name" column="tname"/>
        </association>
    </resultMap>
    

    回顾Mysql 多对一查询方式:

    • 子查询
    • 联表查询

    一对多处理

    前序:一对多关系一般都由多端维护系统关系

    环境搭建

    同上

    实体类

    @Data
    public class Student {
    
        private int id;
        private String name;
        private int tid;
    
    }
    
    
    @Data
    public class Teacher {
        private int id;
        private String name;
    
        //一个老师拥有多个学生
        private List<Student> students;
    }
    

    按照结果嵌套处理

        <!--按结果嵌套查询-->
        <select id="getTeacher" resultMap="TeacherStudent">
            select s.id sid, s.name sname, t.name tname,t.id tid
            from student s,teacher t
            where s.tid = t.id and t.id = #{tid}
        </select>
    
        <resultMap id="TeacherStudent" type="Teacher">
            <result property="id" column="tid"/>
            <result property="name" column="tname"/>
            <!--复杂的属性,我们需要单独处理 对象: association 集合: collection
            javaType="" 指定属性的类型!
            集合中的泛型信息,我们使用ofType获取
            -->
            <collection property="students" ofType="Student">
                <result property="id" column="sid"/>
                <result property="name" column="sname"/>
                <result property="tid" column="tid"/>
            </collection>
        </resultMap>
    

    按照查询嵌套处理

    <select id="getTeacher2" resultMap="TeacherStudent2">
        select * from mybatis.teacher where id = #{tid}
    </select>
    
    <resultMap id="TeacherStudent2" type="Teacher">
        <collection property="students" javaType="ArrayList" ofType="Student" select="getStudentByTeacherId" column="id"/>
    </resultMap>
    
    <select id="getStudentByTeacherId" resultType="Student">
        select * from mybatis.student where tid = #{tid}
    </select>
    

    小结

    1. 关联 - association 【多对一】
    2. 集合 - collection 【一对多】
    3. javaType & ofType
      1. JavaType 用来指定实体类中属性的类型
      2. ofType 用来指定映射到List或者集合中的 pojo类型,泛型中的约束类型!

    注意点

    • 保证SQL的可读性,尽量保证通俗易懂
    • 注意一对多和多对一中,属性名和字段的问题!
    • 如果问题不好排查错误,可以使用日志 , 建议使用 Log4j

    动态 SQL

    什么是动态SQL:动态SQL就是指根据不同的条件生成不同的SQL语句

    动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。



    if
    choose (when, otherwise)
    trim (where, set)
    foreach



    搭建环境

    CREATE TABLE `blog` (
      `id` varchar(50) NOT NULL COMMENT '博客id',
      `title` varchar(100) NOT NULL COMMENT '博客标题',
      `author` varchar(30) NOT NULL COMMENT '博客作者',
      `create_time` datetime NOT NULL COMMENT '创建时间',
      `views` int(30) NOT NULL COMMENT '浏览量'
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8
    
    

    创建一个基础工程

    1. 导包

    2. 编写配置文件

    3. 编写实体类

      @Data
      public class Blog {
          private int id;
          private String title;
          private String author;
          private Date createTime;
          private int views;
          
          
      }
      
    4. 编写实体类对应Mapper接口 和 Mapper.XML文件

    Tips:解决Idea拼写不符合规范问题(波浪线提示)

    @SuppressWarnings("all")
    

    编写随机ID工具类

    在这里插入图片描述
    配置数据库字段名与实体类中的兼容问题

    在这里插入图片描述
    利用驼峰式命名解决

    IF

    <select id="queryBlogIF" parameterType="map" resultType="blog">
        select * from mybatis.blog where 1=1
        <if test="title != null">
            and title = #{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </select>
    

    choose (when, otherwise)

        <select id="queryBlogChoose" parameterType="map" resultType="blog">
            select * from mybatis.blog
            <where>
                <choose>
                    <when test="title != null">
                        title = #{title}
                    </when>
                    <when test="author != null">
                        and author = #{author}
                    </when>
                    <otherwise>
                        and views = #{views}
                    </otherwise>
                </choose>
            </where>
        </select>
    

    类似于 switch....case

    trim (where,set)

    select * from mybatis.blog
    <where>
        <if test="title != null">
            title = #{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </where>
    
    <update id="updateBlog" parameterType="map">
        update mybatis.blog
        <set>
            <if test="title != null">
                title = #{title},
            </if>
            <if test="author != null">
                author = #{author}
            </if>
        </set>
        where id = #{id}
    </update>
    
    

    所谓的动态SQL,本质还是SQL语句 , 只是我们可以在SQL层面,去执行一个逻辑代码

    if

    where , set , choose ,when

    关于动态SQL的参考:
    官方文档
    文档
    博客

    Foreach

    遍历集合等

    select * from user where 1=1 and 
    
      <foreach item="id" collection="ids"
          open="(" separator="or" close=")">
            #{id}
      </foreach>
    
    (id=1 or id=2 or id=3)
    
    
    <!--
            select * from mybatis.blog where 1=1 and (id=1 or id = 2 or id=3)
    
            我们现在传递一个万能的map , 这map中可以存在一个集合!
    -->
    <select id="queryBlogForeach" parameterType="map" resultType="blog">
        select * from mybatis.blog
    
        <where>
            <foreach collection="ids" item="id" open="and (" close=")" separator="or">
                id = #{id}
            </foreach>
        </where>
    
    </select>
    
    

    动态SQL就是在拼接SQL语句,我们只要保证SQL的正确性,按照SQL的格式,去排列组合就可以了

    SQL片段

    功能的部分抽取出来,方便复用

    1. 使用SQL标签抽取公共的部分

      <sql id="if-title-author">
          <if test="title != null">
              title = #{title}
          </if>
          <if test="author != null">
              and author = #{author}
          </if>
      </sql>
      
    2. 在需要使用的地方使用Include标签引用即可

      <select id="queryBlogIF" parameterType="map" resultType="blog">
          select * from mybatis.blog
          <where>
              <include refid="if-title-author"></include>
          </where>
      </select>
      

    注意事项:

    • 最好基于单表来定义SQL片段!
    • 不要存在where标签

    缓存

    简介

    缓存 [ Cache ]

    存在内存中的临时数据,将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决高并发系统的性能问题。以减少和数据库的交互次数,减少系统开销,提高系统效率。

    Mybatis缓存

    系统定义两级缓存:一级缓存二级缓存

    • 默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存)

    • 二级缓存需要手动开启和配置,他是基于namespace级别的缓存。

    • 为了提高扩展性,MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存

    一级缓存

    又名本地缓存: SqlSession
    与数据库同一次会话期间查询到的数据会放在本地缓存中, 以后如果需要获取相同的数据,直接从缓存中拿,没必须再去查询数据库;

    测试步骤:

    1. 开启日志!
    2. 测试在一个Sesion中查询两次相同记录
    3. 查看日志输出

    在这里插入图片描述

    缓存失效的情况:

    1. 查询不同的东西

    2. 增删改操作,可能会改变原来的数据,所以必定会刷新缓存!
      3.手动清除缓存

    sqlSession.clearCache() 
    

    小结:一级缓存默认是开启的,只在一次SqlSession中有效,也就是拿到连接到关闭连接这个区间段!一级缓存就是一个Map。

    二级缓存

    • 二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存
    • 基于namespace级别的缓存,一个名称空间,对应一个二级缓存;
    • 工作机制
      • 一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
      • 如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中;
      • 新的会话查询信息,就可以从二级缓存中获取内容;
      • 不同的mapper查出的数据会放在自己对应的缓存(map)中;

    步骤:

    1. 开启全局缓存

      <!--显示的开启全局缓存-->
      <setting name="cacheEnabled" value="true"/>
      

    在这里插入图片描述

    1. 在要使用二级缓存的Mapper中开启

      <!--在当前Mapper.xml中使用二级缓存-->
      <cache/>
      

      也可以自定义参数

      <!--在当前Mapper.xml中使用二级缓存-->
      <cache  eviction="FIFO"
             flushInterval="60000"
             size="512"
             readOnly="true"/>
      

    在这里插入图片描述

    1. 测试

      1. 问题:我们需要将实体类序列化!否则就会报错!

        Caused by: java.io.NotSerializableException: com.kuang.pojo.User
        

    在这里插入图片描述

    小结:

    • 只要开启了二级缓存,在同一个Mapper下就有效
    • 所有的数据都会先放在一级缓存中;
    • 只有当会话提交,或者关闭的时候,才会提交到二级缓冲中!

    缓存原理

    在这里插入图片描述

    Redis数据库来做缓存 K-V

    常见异常及错误

    ①关于无法new java类错误

    现象:只有file,没有java class 如下图
    在这里插入图片描述

    解法:因为该不在可编译的目录下,可在 Project Structure 中进行设置
    在这里插入图片描述

    ②关于Test测试

    (1)下图情况
    在这里插入图片描述
    方法错误(即写的不是方法 eg: 少了方法的括号)

    (2)没有导入包 import org.junit.Test;

    ③关于数据库查询xml文件提示

    (1)波浪线为正常
    (2)里面包含的有些SQL语句是不加 ;
    在这里插入图片描述

    ④Mapper接口中未创建方法

    下图为在测试代码中
    在这里插入图片描述
    解法如下图:
    在这里插入图片描述

    ⑤resultType 与resultMap

    Caused by: org.apache.ibatis.type.TypeException: Could not resolve type alias 'Student'. Cause: java.lang.ClassNotFoundException: Cannot find class: Student

    原因:将resultMap写成了resultType,Type对应的是对象类,所以抛出ClassNotFoundException的异常,mybatis的结果是存放在resultMap中的。

    ⑥类找不到异常(*)

    Could not resolve type alias 'Student'. Cause: java.lang.ClassNotFoundException: Cannot find class: Student
    原因分析:找不到类替代的别名,在mybatis-config.xml,漏写typeAliases
    解决:
    在这里插入图片描述

    基于实战中学习,学习快乐中成长
    .
    时间会回答成长,成长会回答梦想

  • 相关阅读:
    leetcode——448.找到所有数组中消失的数字
    leetcode——268.缺失数字
    leetcode——680.验证回文字符串2
    leetcode——125.验证回文串
    leetcode——217.存在重复元素
    leetcode——189.旋转数组
    02-04 线性回归
    02-03 感知机对偶形式(鸢尾花分类)
    02-02 感知机原始形式(鸢尾花分类)
    02-01 感知机
  • 原文地址:https://www.cnblogs.com/lzhCreate/p/13501383.html
Copyright © 2020-2023  润新知