动态SQL

当需求是可能存在0到多个条件进行sql查询时,需要进行sql条件拼接。使用java过于繁琐,在mybatis有如下的解决方案。

1.使用if标签进行拼接

select * from table where 1=1

<if test=" name != null and name != ' '  ">

  and name=#{name}

</if>

 

2.使用where标签

在where标签内使用if标签,where可以自动处理if标签前面多余的and以及是否生成where。

但是不能将if标签后面的and截取掉!!!!!

select * from table

<where>  

  <if test=" name != null and name != ' '  ">

    name=#{name}

  </if>

  <if test=" age!= null and age!= ' '  ">

    and age=#{age}

  </if>

</where>

 

3.trim标签

trim标签有四个属性,prefix、suffix表示整体的前后添加指定字符串,prefixOverrides、suffixOverrides表示整体标签的前后去掉指定字符串。

select * from table

<trim prefix="where" suffixOverrides="and">

  <if test=" name != null and name != ' '  ">

    name=#{name} and

  </if>

  <if test=" age!= null and age!= ' '  ">

    age=#{age} and

  </if>

</trim>

 

4.choose when otherwise标签

类似switch

 

select * from table

<where>  

  <choose>

    <when test=" name != null and name != ' '  ">

      name=#{name}

    </when>

    <when test=" age!= null and age!= ' '  ">

      age=#{age}

    </when>

  </choose>

</where>

 

5.foreach标签

void insertMoreEmp(@param("emps")List<Emp>emps);

 

<insert id="insertMoreEmp">

  insert into emp values

  <foreach collection="emps" item="emp" separator=",">

    (null,#(emp.empName),#{emp.age},#{emp.gender},null)

  </foreach>

</insert>

注意:

当输入参数为List时,取参数需要用list,所以最好用注解标注参数名字

foreach标签有分隔符属性,在每个元素中间隔开

 

<delete id = "deleteMoreEmp">

  delete from emp where id in

  (

    <foreach collection="empIds" item="empId" separator=",">

      #{empId}

    </foreach>

  )

  <foreach collection="empIds" item="empId" separator="," open="(" close=")">

    #{empId}

  </foreach>

</delete>

 

<delete id = "deleteMoreEmp">

  delete from emp where

  <foreach collection="empIds" item="empId" separator="or">

    emp_id = #{empId}

  </foreach>

</delete>

 

6.sql标签

<sql id="empColumns">

  emp_id,emp_name,age,gender,dept_id

</sql>

 

<select id="func">

  select <include refid="empColumns"/> from emp

</select>

 

Mybatis的缓存

Mybatis的一级缓存

Mybatis的一级缓存为SqlSession级别的,即通过一个SqlSession查询的数据会被缓存

当使用同一个session查询同一条数据时会从缓存中获取

默认开启

 

一级缓存失效的情况:

不同的SqlSession

不同的数据

查询之间执行过增删改操作,会清空缓存

查询之间手动清空过缓存  sqlSession.clearCache();

 

Mybatis的二级缓存

Mybatis的二级缓存为SqlSessionFactory级别的,即通过同一个Factory创建的Session查询的结果会被缓存

使用相同Factory创建的Session查询数据会从缓存中获取

开启条件:

在核心配置文件中设置 cacheEnabled="true" ,默认为true

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

二级缓存必须在Session关闭或提交后有效

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

 

失效:

增删改操作

手动清除一级缓存不会影响二级

 

二级缓存的配置

1.eviction 缓存回收策略 默认LRU

LRU 最近最少使用

FIFO 队列

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

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

2.flushInterval 刷新间隔 单位为毫秒

默认为不设置,当语句调用时刷新

3.size 引用数目

代表缓存最多储存多少个对象

4.readOnly只读 默认false

当为true时会直接返回缓存中的对象,若进行修改则会导致下次的查询结果有问题,性能优势

false时会创建一个副本,修改不会对缓存中的内容产生影响,安全

 

Mybatis缓存查询的顺序

先查询二级缓存,没有命中再查询一级,没有命中则查询数据库。

 

整合第三方缓存EHCache

 

依赖

复制代码
<!-- 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>
复制代码

 

ehcache依赖于slf4j,slf4j是接口也叫做门面,logback-classic是该门面的实现

 

配置文件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:\dev\ehcache"/> <defaultCache maxElementsInMemory="1000"
            maxElementsOnDisk
="10000000"
            eternal
="false"
            overflowToDisk
="true" timeToIdleSeconds="120"
            timeToLiveSeconds
="120"
            diskExpiryThreadIntervalSeconds
="120" memoryStoreEvictionPolicy="LRU">
   </
defaultCache> </ehcache>
复制代码

 

设置二级缓存类型 

不设置时为内置的

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

 

Mybatis的逆向工程

正向工程:先创建Java实体类,由框架负责根据实体类生成数据库表。 Hibernate是支持正向工程的。

逆向工程:先创建数据库表,由框架负责根据数据库表,反向生成:

Java实体类
Mapper接口
Mapper映射文件

 

依赖

复制代码
<dependencies>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.7</version>
    </dependency> 
    <!-- junit测试 -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency> 
    <!-- log4j日志 -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>1.2.17</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.16</version>
    </dependency>
</dependencies>
<!-- 控制Maven在构建过程中相关配置 -->
<build>
    <!-- 构建过程中用到的插件 -->
    <plugins> 
        <!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 -->
        <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.0</version> <!-- 插件的依赖 -->
            <dependencies> <!-- 逆向工程的核心依赖 -->
                <dependency>
                    <groupId>org.mybatis.generator</groupId>
                    <artifactId>mybatis-generator-core</artifactId>
                    <version>1.3.2</version>
                </dependency> <!-- MySQL驱动 -->
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>8.0.16</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>
复制代码

 

创建逆向工程核心配置文件generatorConfig.xml

复制代码
<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE generatorConfiguration PUBLIC
        "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration> 
    <!-- targetRuntime: 执行生成的逆向工程的版本 MyBatis3Simple: 生成基本的CRUD(清新简洁版) MyBatis3: 生成带条件的CRUD(奢华尊享版) -->
    <context id="DB2Tables" targetRuntime="MyBatis3"> 
        <!-- 数据库的连接信息 -->
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/mybatis? serverTimezone=UTC" userId="root"
                        password="123456">
        <property name="nullCatalogMeansCurrent" value="true" />
    </
jdbcConnection> <!-- javaBean的生成策略--> <javaModelGenerator targetPackage="com.atguigu.mybatis.pojo" targetProject=".\src\main\java"> <property name="enableSubPackages" value="true"/> <property name="trimStrings" value="true"/> </javaModelGenerator> <!-- SQL映射文件的生成策略 --> <sqlMapGenerator targetPackage="com.atguigu.mybatis.mapper" targetProject=".\src\main\resources"> <property name="enableSubPackages" value="true"/> </sqlMapGenerator> <!-- Mapper接口的生成策略 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.atguigu.mybatis.mapper" targetProject=".\src\main\java"> <property name="enableSubPackages" value="true"/> </javaClientGenerator> <!-- 逆向分析的表 --> <!-- tableName设置为*号,可以对应所有表,此时不写domainObjectName -->
     <!-- domainObjectName属性指定生成出来的实体类的类名 --> <table tableName="t_emp" domainObjectName="Emp"/> <table tableName="t_dept" domainObjectName="Dept"/> </context> </generatorConfiguration>
复制代码

 

配置正确后,在数据库有对应表的情况下,点击插件generator就可以自动生成代码

 

分页插件

依赖

<dependency>
  <groupId>com.github.pagehelper</groupId>
  <artifactId>pagehelper</artifactId>
  <version>5.2.0</version>
</dependency>
 
<plugins>
  <!--设置分页插件-->
  <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>

 

分页拦截器

会自动拦截sql返回的结果,使结果返回的是对应页的结果。

 

查询前使用PageHelper.startPage(PageNum,PageSize)

该方法有返回值Page<Object> page

page中会自动保存后续查到的部分信息。

mapper查询结果的返回值也可以设置为page类型

 

查询后使用PageInfo<Emp> pageInfo = new PageInfo<>(list,导航分页页码数)

pageInfo数据更丰富更多。