MyBatis详细使用示例(下)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: MyBatis详细使用示例

分步查询

DeptMapper.xml(部门)

<resultMap id="deptEmpMapOne" type="Dept">
      <id property="did" column="did"></id>
      <result property="deptName" column="dept_name"></result>
      <collection property="emps" select="com.atguigu.mybatis.mapper.EmpMapper.getEmpByDeptTwo" column="did" fetchType="lazy"></collection>
 </resultMap>
 <!--Dept getDeptById(@Param("did") int did);-->
 <select id="getDeptById" resultMap="deptEmpMapOne">
    select * from t_dept d where d.did=#{did}
 </select>


EmpMapper.xml(员工)

<!--List<Emp> getEmpByDeptTwo(@Param("did") String did);-->
    <select id="getEmpByDeptTwo" resultType="Emp">
        select * from t_emp where did=#{did}
    </select>


动态SQL


if

<!--List<Emp> getEmpListByMoreTJ(Emp emp);--> 
<select id="getEmpListByMoreTJ" resultType="Emp"> 
   select * from t_emp where 1=1 
   <if test="ename != '' and ename != null"> 
      and ename = #{ename} 
   </if> 
   <if test="age != '' and age != null"> 
      and age = #{age} 
   </if> 
   <if test="sex != '' and sex != null"> 
      and sex = #{sex} 
   </if> 
</select>


判断数字是否等于0,0通过mapper会转换为 ‘’ 空串,所以if应该这样判断参数是否为0

<if test="sex != null and sex == ''"> 
      and sex = #{sex} 
   </if> 
   <!--
   错误用法
   <if test="sex == 0"> 
   -->


注:判断 Integer 和 Long 时, == ‘’ 和 ==0作用是相同的


判断 Integer是否有值

<where>
            <if test="labelType != null or labelType == 0">
                tb.label_type = #{labelType}
            </if>
            <if test="bookId != null or bookId == 0">
                AND tlr.book_id = #{bookId}
            </if>
        </where>


where

<select id="getEmpListByMoreTJ2" resultType="Emp"> 
  select * from t_emp 
  <where> 
  <if test="ename != '' and ename != null"> 
    ename = #{ename} 
  </if> 
  <if test="age != '' and age != null"> 
    and age = #{age} 
  </if> 
  <if test="sex != '' and sex != null"> 
    and sex = #{sex} 
  </if> 
  </where> 
</select>


where 和 if 一般结合使用:

若where标签中的if条件都不满足,则where标签没有任何功能,即不会添加where关键字


若where标签中的if条件满足,则where标签会自动添加where关键字,并将条件最前方多余的and去掉


注意:where标签不能去掉条件最后多余的and


trim

<select id="getEmpListByMoreTJ" resultType="Emp"> 
  select * from t_emp 
  <trim prefix="where" suffixOverrides="and"> 
  <if test="ename != '' and ename != null"> 
    ename = #{ename} and 
  </if> 
  <if test="age != '' and age != null"> 
    age = #{age} and 
  </if> 
  <if test="sex != '' and sex != null">
    sex = #{sex} 
  </if> 
  </trim> 
</select>


trim用于去掉或添加标签中的内容


常用属性:

prefix:在trim标签中的内容的前面添加某些内容

prefixOverrides:在trim标签中的内容的前面去掉某些内容

suffix:在trim标签中的内容的后面添加某些内容

suffixOverrides:在trim标签中的内容的后面去掉某些内容


choose、when、otherwise

choose、when、otherwise相当于if…else if…else

<!--List<Emp> getEmpListByChoose(Emp emp);--> 
<select id="getEmpListByChoose" resultType="Emp"> 
select <include refid="empColumns"></include> from t_emp 
  <where> 
  <choose> 
    <when test="ename != '' and ename != null"> 
    ename = #{ename} 
    </when> 
    <when test="age != '' and age != null"> 
    age = #{age} 
    </when> 
    <when test="sex != '' and sex != null"> 
    sex = #{sex} 
    </when> 
    <when test="email != '' and email != null"> 
    email = #{email} 
    </when>
    <otherwise>
    id = 1
    </otherwise>
  </choose> 
  </where> 
</select>


foreach

插入多个

<!--int insertMoreEmp(@Param("emps") List<Emp> emps);--> 
<insert id="insertMoreEmp"> 
  insert into t_emp values 
  <foreach collection="emps" item="emp" separator=","> 
  (null,#{emp.ename},#{emp.age},#{emp.sex},#{emp.email},null) 
  </foreach> 
</insert>


删除多条

<!--int deleteMoreByArray(@Param("eids") int[] eids);--> 
<delete id="deleteMoreByArray"> 
  delete from t_emp where
  <foreach collection="eids" item="eid" separator="or"> 
  eid = #{eid} 
  </foreach>
</delete>
<!--int deleteMoreByArray(@Param("eids") int[] eids);--> 
<delete id="deleteMoreByArray"> 
  delete from t_emp where eid in 
  <foreach collection="eids" item="eid" separator="," open="(" close=")"> 
  #{eid} 
  </foreach> 
</delete>


属性:

collection:设置要循环的数组或集合

item:表示集合或数组中的每一个数据

separator:设置循环体之间的分隔符

open:设置foreach标签中的内容的开始符

close:设置foreach标签中的内容的结束符


SQL片段

<sql id="empColumns"> eid,ename,age,sex,did </sql> 
select <include refid="empColumns"></include> from t_emp


MyBatis的缓存


MyBatis的一级缓存

一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就

会从缓存中直接获取,不会从数据库重新访问

使一级缓存失效的四种情况:

1) 不同的SqlSession对应不同的一级缓存
2) 同一个SqlSession但是查询条件不同
3) 同一个SqlSession两次查询期间执行了任何一次增删改操作
4) 同一个SqlSession两次查询期间手动清空了缓存


MyBatis的二级缓存

二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取


二级缓存开启的条件:

a>在核心配置文件中,设置全局配置属性cacheEnabled=“true”,默认为true,不需要设置

b>在映射文件中设置标签<cache />

c>二级缓存必须在SqlSession关闭或提交之后有效

d>查询的数据所转换的实体类类型必须实现序列化的接口

使二级缓存失效的情况:

两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效


二级缓存的相关配置

在 mapper 配置文件中添加的 cache 标签可以设置一些属性:


eviction属性:缓存回收策略

LRU(Least Recently Used) – 最近最少使用的:移除最长时间不被使用的对象。

FIFO(First in First out) – 先进先出:按对象进入缓存的顺序来移除它们。

SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。

WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

默认的是 LRU。

flushInterval属性:刷新间隔,单位毫秒

默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新

size属性:引用数目,正整数

代表缓存最多可以存储多少个对象,太大容易导致内存溢出

readOnly属性:只读,true/false

true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。

false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。

MyBatis缓存查询的顺序

先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用。

如果二级缓存没有命中,再查询一级缓存

如果一级缓存也没有命中,则查询数据库

SqlSession关闭之后,一级缓存中的数据会写入二级缓存

整合第三方缓存EHCache


a>添加依赖

<!-- Mybatis EHCache整合包 --> 
<dependency> 
  <groupId>org.mybatis.caches</groupId> 
  <artifactId>mybatis-ehcache</artifactId> 
  <version>1.2.1</version> 
</dependency> 
<!-- slf4j日志门面的一个具体实现 --> 
<dependency> 
  <groupId>ch.qos.logback</groupId> 
  <artifactId>logback-classic</artifactId> 
  <version>1.2.3</version> 
</dependency>


b>各jar包功能

1673335462950.jpg

c>创建EHCache的配置文件ehcache.xml

<?xml version="1.0" encoding="utf-8" ?> 
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> 
  <!-- 磁盘保存路径 --> 
  <diskStore path="D:\atguigu\ehcache"/>
  <defaultCache 
  maxElementsInMemory="1000" 
  maxElementsOnDisk="10000000" 
  eternal="false" 
  overflowToDisk="true" 
  timeToIdleSeconds="120" 
  timeToLiveSeconds="120" 
  diskExpiryThreadIntervalSeconds="120" 
  memoryStoreEvictionPolicy="LRU"> 
  </defaultCache> 
</ehcache>


d>xxxMapper.xml设置二级缓存的类型

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

e>加入logback日志


存在SLF4J时,作为简易日志的log4j将失效,此时我们需要借助SLF4J的具体实现logback来打印日志。


创建logback的配置文件logback.xml

<?xml version="1.0" encoding="UTF-8"?> 
<configuration debug="true"> 
  <!-- 指定日志输出的位置 --> 
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
  <encoder> 
  <!-- 日志输出的格式 --> 
  <!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体内容、换行 -->
   <pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern> 
  </encoder> 
  </appender> 
  <!-- 设置全局日志级别。日志级别按顺序分别是:DEBUG、INFO、WARN、ERROR --> <!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 --> 
  <root level="DEBUG"> 
  <!-- 指定打印日志的appender,这里通过“STDOUT”引用了前面配置的appender --> 
  <appender-ref ref="STDOUT" /> 
  </root> <!-- 根据特殊需求指定局部日志级别 --> 
  <logger name="com.atguigu.crowd.mapper" level="DEBUG"/> 
</configuration>
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
SQL XML 算法
Mybatis框架详解+示例
Mybatis框架详解+示例
Mybatis框架详解+示例
|
SQL 存储 Java
Mybatis多表查询分析+示例(一对多、多对多)
Mybatis多表查询分析+示例(一对多、多对多)
Mybatis多表查询分析+示例(一对多、多对多)
|
SQL 测试技术 数据库
spring springmvc mybatis maven 项目整合示例-导航页面
spring原理 实践解析-简单的helloworld   spring原理案例-基本项目搭建 01 spring framework 下载 官网下载spring jar包 spring原理案例-基本项目搭建 02 spring jar包详解 spring jar包的用途 spring原理案例-基本...
2697 0
|
SQL Java 数据库连接
MyBatis 多参数综合查询的动态 SQL 实现示例
List findQualityDataOfAppDtoByDeptNoAndAoneProductId( @Param("deptNo") Long deptNo, @Param("aonePr...
1046 0