• mybatis


    动态SQL

    1. If标签

      		 <if test="字段名 条件判断">
                and 列名=#{字段名}
            if>
      		<if test="empno != null">
                and empno =#{empno}
            if>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2. where标签

    	<where>
            <if test="empno != null">
                and empno= #{empno}
            if>
            <if test="ename != null and ename != ''">
                and ename= #{ename}
            if>
        where>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    可去除 不正确的and 
    例如: where and ename= #{ename}
    会修正为: where  ename= #{ename}
    
    • 1
    • 2
    • 3

    3 . Set标签

    <update id="方法名" >
        update 表名
    	<set>
            <if test="ename != null and ename != '' ">
                , ename =#{ename}
            if>
            <if test="job != null and ename != '' ">
                , job =#{job}
            if>
          set>
      update>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    可去除 不正确的 ','
    例如: set , ename= #{ename}
    会修正为: set ename= #{ename}
    
    • 1
    • 2
    • 3

    4. Trim标签

     <trim prefix=" "where" prefixOverrides="and" suffix="" suffixOverrides="">
                <if test="deptno!= null">
                    DEPTNO = #{deptno}
                if>
                <if test="dname!= null and dname!='' ">
                    and DNAME=#{dname}
                if>
                <if test="loc != null and loc!=''">
                    and Loc =#{loc}
                if>
            trim>" prefixOverrides="and" suffix="" suffixOverrides="">
                <if test="deptno!= null">
                    DEPTNO = #{deptno}
                if>
                <if test="dname!= null and dname!='' ">
                    and DNAME=#{dname}
                if>
                <if test="loc != null and loc!=''">
                    and Loc =#{loc}
                if>
            trim>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    prefix : 前面填充内容 prefixOverrides 前面去除内容
    suffix :后面填充内容 suffixOverrides 后面去除内容
    where和set标签就是基于这个实现的

    5. Bind标签

    在这里插入图片描述

    用于模糊查询使用,也可以使用 concat(“%”,#{字段名},“%”)进行拼接

    6. Sql标签

    <sql id="empColumn">empno,ename,job,mgr,hiredate,sal,comm,deptnosql>
    <sql id="baseSelect">select <include refid="empColumn"/>from empsql>
    
    
    <select id="findByCondition" resultType="emp">
        <include refid="baseSelect">include>
      select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    通过 来引入上面定义的sql

    7. Foreach标签

    <foreach collection="list" separator="," open="(" close=")" item="deptno">
             #{deptno}
      foreach>
    
    • 1
    • 2
    • 3

    collection : 参数类型,可参考mybatis官网
    separator :分隔符
    open: 前缀
    close:后缀
    item : 元素名

    8.Choose标签

     <where>
            <choose>
                <when test="empno != null">
                    and empno= #{empno}
                when>
                <when test="ename != null and ename != ''">
                    and ename= #{ename}
                when>
                 <otherwise>      
                 otherwise>
              choose>
       where>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    相当于switch,满足一个就不会往下执行别的判断了,如果都不满足会走默认的

    MyBatis实现多表查询

    1. 关联查询
    • 手动处理映射关系resultMap
    <mapper namespace="com.xx.mapper.EmpMapper">
        <!--手动处理数据库查询字段和封装实体类属性之间的映射关系
        1 主键一般使用id属性
        2 当属性名和查询出的数据表字段名相同 可以不写映射关系
        -->
        <resultMap id="empMap" type="emp">
            <!--<id property="empno" column="empno"></id>-->
            <result property="name" column="ename"></result>
            <result property="job" column="job"></result>
            <result property="sal" column="sal"></result>
            <result property="hiredate" column="hiredate"></result>
            <result property="mgr" column="mgr"></result>
            <result property="comm" column="comm"></result>
            <result property="deptno" column="deptno"></result>
        </resultMap>
        <select id="findByEmpno" resultMap="empMap" >
            select * from emp where empno =#{empno}
        </select>
    </mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 一对一关联查询
    <mapper namespace="com.xxx.mapper.EmpMapper">
    
    
        <!--Emp findEmpJoinDeptByEmpno(int empno);-->
        <resultMap id="empJoinDept" type="emp">
            <!--设置emp本身的八个属性的映射关系-->
            <id property="empno" column="empno"></id>
            <result property="ename" column="ename"></result>
            <result property="job" column="job"></result>
            <result property="sal" column="sal"></result>
            <result property="hiredate" column="hiredate"></result>
            <result property="mgr" column="mgr"></result>
            <result property="comm" column="comm"></result>
            <result property="deptno" column="deptno"></result>
            <!--
            association 处理一对一
            封装一对一信息关系的标签
            property  emp类的属性名
            javaType  用哪个类的对象给属性赋值
            -->
            <association property="dept" javaType="dept">
                <id column="deptno" property="deptno"></id>
                <result column="dname" property="dname"></result>
                <result column="loc" property="loc"></result>
            </association>
    
        </resultMap>
    
        <select id="findEmpJoinDeptByEmpno" resultMap="empJoinDept" >
            select * from
            emp e
            left join dept  d
            on e.deptno =d.deptno
            where empno = #{empno}
        </select>
    
    
    </mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 一对多关联查询
    <mapper namespace="com.xxx.mapper.DeptMapper">
        <!--Dept findDeptJoinEmpsByDeptno(int deptno);-->
        <resultMap id="deptJoinEmps" type="dept">
            <id column="deptno" property="deptno"></id>
            <result column="dname" property="dname"></result>
            <result column="loc" property="loc"></result>
            <!--处理一对多关系的标签-->
            <collection property="empList" ofType="emp" >
                <!--设置emp本身的八个属性的映射关系-->
                <id property="empno" column="empno"></id>
                <result property="ename" column="ename"></result>
                <result property="job" column="job"></result>
                <result property="sal" column="sal"></result>
                <result property="hiredate" column="hiredate"></result>
                <result property="mgr" column="mgr"></result>
                <result property="comm" column="comm"></result>
                <result property="deptno" column="deptno"></result>
            </collection>
        </resultMap>
    
    
        <select id="findDeptJoinEmpsByDeptno" resultMap="deptJoinEmps">
            select * from dept d left join emp e on d.deptno =e.deptno where d.deptno =#{deptno}
        </select>
    
    
    </mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 多对多关联查询
    <mapper namespace="com.xxx.mapper.ProjectMapper">
    
        <!--Project findProjectJoinEmpsByPid(int pid);-->
        <resultMap id="projectJoinEmps" type="project">
            <id column="pid" property="pid"></id>
            <result column="pname" property="pname"></result>
            <result column="money" property="money"></result>
            <!--一对多 集合属性 collection-->
            <collection property="projectRecords" ofType="projectRecord">
                <id column="empno" property="empno"></id>
                <id column="pid" property="pid"></id>
                <!--一对一 -->
                <association property="emp" javaType="emp">
                    <id property="empno" column="empno"></id>
                    <result property="ename" column="ename"></result>
                    <result property="job" column="job"></result>
                    <result property="sal" column="sal"></result>
                    <result property="hiredate" column="hiredate"></result>
                    <result property="mgr" column="mgr"></result>
                    <result property="comm" column="comm"></result>
                    <result property="deptno" column="deptno"></result>
                </association>
            </collection>
    
        </resultMap>
    
        <select id="findProjectJoinEmpsByPid"  resultMap="projectJoinEmps">
            select * from
            project p
            left join projectrecord pr
            on p.pid = pr.pid
            left join emp e
            on e.empno = pr.empno
            where p.pid= #{pid}
        </select>
    
    </mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    1. 级联查询
      级联查询,顾名思义,就是利于数据库表间的外键关联关系进行自动的级联查询操作。使用MyBatis实现级联查询,除了实体类增加关联属性外,还需要在映射文件中进行配置。
    • 立即加载
    <mapper namespace="com.xxx.mapper.DeptMapper">
        <!--Dept findDeptByDeptno(int deptno);
        select="com.msb.mapper.EmpMapper.findEmpsByDeptno" 调用的另一个SQL语句
        javaType="list"  实体类的属性数据类型
        column="deptno"  给另一个SQL语句传入的参数列
        jdbcType="INTEGER" 参数对应JDBC的数据类型
        fetchType="eager"  加载方式 eager 积极加载  lazy延迟加载-->
        <resultMap id="deptJoinEmps" type="dept">
            <id property="deptno" column="deptno"></id>
            <result property="dname" column="dname"></result>
            <result property="loc" column="loc"></result>
    
            <collection property="empList"
                        select="com.msb.mapper.EmpMapper.findEmpsByDeptno"
                        javaType="list"
                        column="deptno"
                        jdbcType="INTEGER"
                        fetchType="eager"
            >
            </collection>
    
        </resultMap>
    
        <select id="findDeptByDeptno" resultMap="deptJoinEmps">
            select * from dept where deptno =#{deptno}
        </select>
    </mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 延迟加载
      第一步:全局开关:在sqlMapConfig.xml中打开延迟加载的开关。配置完成后所有的association和collection元素都生效
    <settings>
        <setting name="lazyLoadingEnabled" value="true"/>
        <setting name="aggressiveLazyLoading" value="true"/>
    settings>
    
    • 1
    • 2
    • 3
    • 4

    lazyLoadingEnabled:是否开启延迟加载。是Mybatis是否启用懒加载的全局开关。当开启时,所有关联对象都会延迟加载。特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态
    aggressiveLazyLoading:当开启时,任何方法的调用都会懒加载对象的所有属性。否则,每个属性会按需加载,
    第二步:分开关:指定的association和collection元素中配置fetchType属性。eager:表示立刻加载;lazy:表示延迟加载。将覆盖全局延迟设置。

    • 多表查询总结与扩展
      在这里插入图片描述
      在这里插入图片描述

    ResultType和ResultMap使用场景
    1)如果你做的是单表的查询并且封装的实体和数据库的字段一一对应 resultType
    2)如果实体封装的属性和数据库的字段不一致 resultMap
    3)使用N+1级联查询的时候 resultMap
    4)使用的是多表的连接查询 resultMap

    一对一关联映射的实现
    1)实例:学生和学生证、雇员和工牌
    2)数据库层次:主键关联或者外键关联(参看之前内容)
    3)MyBatis层次:在映射文件的设置双方均使用association即可,用法相同

    多对多映射的实现
    1)实例:学生和课程、用户和角色
    2)数据库层次:引入一个中间表将一个多对多转为两个一对多
    3)MyBatis层次
    方法1:在映射文件的设置双方均使用collection即可,不用引入中间类
    方法2:引入中间类和中间类的映射文件,按照两个一对多处理
    自关联映射
    1)实例:Emp表中的员工和上级。一般是一对多关联
    2)数据库层次:外键参考当前表的主键(比如mgr参考empno)
    3)MyBatis层次:按照一对多处理,但是增加的属性都写到一个实体类中,增加的映射也都写到一个映射文件中

    缓存

    1. 一级缓存
    一级存储是SqlSession上的缓存,默认开启,是一种内存型缓存,不要求实体类对象实现Serializable接口。(必须同一个SqlSession)
    缓存中的数据使用键值对形式存储数据
    namespace+sqlid+args+offset>>> hash值作为键,查询出的结果作为值
    在这里插入图片描述

    @Test
    public void testFindDeptByDetpno()   {
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        Emp emp = mapper.findByEmpno(7521);
        System.out.println(emp);
    
    
        // 中间发生了增删改或者是调用了SqlSession调用了commit,会自动清空缓存
        sqlSession.commit();// 增删改的时候调用
    
        EmpMapper mapper2 = sqlSession.getMapper(EmpMapper.class);
        Emp emp2 = mapper2.findByEmpno(7521);
        System.out.println(emp2);
    
        System.out.println(emp==emp2);
        System.out.println(mapper==mapper2);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    结果: emp == emp2 为true ,
    mapper == mapper2 为false

    2. 二级缓存
    二级缓存是以namespace为标记的缓存,可以是由一个SqlSessionFactory创建的SqlSession之间共享缓存数据。默认并不开启。下面的代码中创建了两个SqlSession,执行相同的SQL语句,尝试让第二个SqlSession使用第一个SqlSession查询后缓存的数据。要求实体类必须实现序列化接口
    在这里插入图片描述

    开启:

    1)全局开关:在mybatis.xml(核心)文件中的标签配置开启二级缓存

    <settings>
        <setting name="cacheEnabled" value="true"/>
    settings>
    
    • 1
    • 2
    • 3

    cacheEnabled的默认值就是true,所以这步的设置可以省略。

    2)分开关:在要开启二级缓存的mapper文件中开启缓存:

    <mapper namespace="com.xxx.mapper.EmployeeMapper">
        <cache/>
    mapper>
    
    • 1
    • 2
    • 3

    3)二级缓存未必完全使用内存,有可能占用硬盘存储,缓存中存储的JavaBean对象必须实现序列化接口,

    public class Emp implements  Serializable {  }
    
    • 1

    经过设置后,查询结果如图所示。发现第一个SqlSession会首先去二级缓存中查找,如果不存在,就查询数据库,在commit()或者close()的时候将数据放入到二级缓存。第二个SqlSession执行相同SQL语句查询时就直接从二级缓存中获取了。
    注意:
    1)MyBatis的二级缓存的缓存介质有多种多样,而并不一定是在内存中,所以需要对JavaBean对象实现序列化接口。
    2)二级缓存是以 namespace 为单位的,不同 namespace 下的操作互不影响
    3)加入Cache元素后,会对相应命名空间所有的select元素查询结果进行缓存,而其中的insert、update、delete在操作是会清空整个namespace的缓存。
    4)cache 有一些可选的属性 type, eviction, flushInterval, size, readOnly, blocking。
    在这里插入图片描述
    5)如果在加入Cache元素的前提下让个别select 元素不使用缓存,可以使用useCache属性,设置为false。useCache控制当前sql语句是否启用缓存 flushCache控制当前sql执行一次后是否刷新缓存

    <select id="findByEmpno" resultType="emp" useCache="true" flushCache="false">
    
    • 1

    3. 三方缓存
    分布式缓存框架:我们系统为了提高系统并发 和性能,一般对系统进行分布式部署(集群部署方式)不适用分布缓存, 缓存的数据在各个服务单独存储,不方便系统开发。所以要使用分布式缓存对缓存数据进行集中管理.ehcache,redis ,memcache缓存框架。
    Ehcache:是一种广泛使用的开源java分布式缓存。主要面向通用缓存,javaEE 和 轻量级容器。它具有内存和磁盘存储功能。被用于大型复杂分布式web application的
    这里的三方缓存是作为二级缓存使用的
    导入依赖的jar文件

    <dependency>
        <groupId>org.mybatis.cachesgroupId>
        <artifactId>mybatis-ehcacheartifactId>
        <version>1.0.2version>
    dependency>
    <dependency>
        <groupId>net.sf.ehcachegroupId>
        <artifactId>ehcacheartifactId>
        <version>2.10.1version>
    dependency>
    
    <dependency>
        <groupId>org.slf4jgroupId>
        <artifactId>slf4j-nopartifactId>
        <version>1.7.2version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    去各自的sql映射文件里,开启二级缓存,并把缓存类型指定为EhcacheCache

     <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
    
    • 1

    在资源目录下放置一个缓存配置文件,文件名为: ehcache.xml 内容如下

    
    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:noNamespaceSchemaLocation="ehcache.xsd"
             updateCheck="true" monitoring="autodetect"
             dynamicConfig="true">
    
        <diskStore path="D:\xxx\ehcache" />
        <defaultCache
                maxElementsInMemory="1000"
                maxElementsOnDisk="10000000"
                eternal="false"
                overflowToDisk="true"
                timeToIdleSeconds="120"
                timeToLiveSeconds="120"
                diskExpiryThreadIntervalSeconds="120"
                memoryStoreEvictionPolicy="LRU">
        defaultCache>
    
    
    ehcache>
    
            
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
  • 相关阅读:
    Python提示<_io.TextIOWrapper name=‘静夜思‘ mode=‘r‘ encoding=‘utf-8‘>解决方法 Python
    接口测试测什么?这篇文章告诉你
    前端与后端传递数据 — — JSON
    2022-11-05 mysql-派生表-解读
    紫光展锐荣评“5G技术创新力企业”,5G赋能千行百业
    x86平台运行arm64平台docker 镜像
    【iOS】JSONModel的基本使用
    2023年成都.NET线下技术沙龙活动即将到来!
    攻防世界Check
    python 应用之 request 请求调用
  • 原文地址:https://blog.csdn.net/ypqdcsdn/article/details/127675095