Mybatis笔记03 动态SQL,缓存,逆向工程,分页插件

动态SQL

MyBatis框架的动态SQL技术时一种根据特定条件动态拼接SQL语句的功能,它存在的意义是为了解决拼接SQL语句字符串时的痛点问题。

if标签

if标签可通过test属性的表达式进行判断,若表达式的结果为true,则标签中的内容会执行;否则标签的内容不会执行

DynamicSQLMapper.xml

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

测试

但是如果都不成立,此时就多了一个where

可以在SQL语句加一个1=1

但是查属性值都为空的Emp对象却查到了所有的Emp对象(有问题)

使用where标签

where标签

当where标签中有内容时会自动生成where关键字,并将内容前多余的and或or去掉

内容后的不会

当where标签中没有内容时,此时where标签没有任何效果

trim标签

prefix|suffix:将trim标签中内容前面或后面添加指定内容

prefixOverrides|suffixOverrides:将trim标签中内容前面或后面去掉指定内容

 若trim标签中没有内容,没有任何效果

choose,when,otherwise标签

相当于if...else if...else

当有when标签中有条件满足时就将标签中内容拼接到sql语句中,后面标签不再判断

传入的emp对象

new Emp(null, "GYQ", 15, "", "")

都不满足,将otherwise标签中内容拼接

传入的emp对象

new Emp(null, "", null, "", "")

foreach标签

批量删除

方式一:

方式二:

批量添加

collection:设置需要循环的数组或集合  item:表示数组或集合中的每一个数据

separator:循环体之间的分隔符  open:foreach标签所循环的所有内容的开始符

close:foreach标签所循环的所有内容的结束符

sql标签

设置SQL片段,引用SQL片段

MyBatis的缓存

一级缓存

一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问。默认开启

连续两次执行相同的查询

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

不同的SqlSession对应不同的一级缓存(获取另一个SqlSession,两者执行相同查询语句)

同一个SqlSession但是查询条件不同

同一个SqlSession两次查询期间执行了任何一次增删改操作

同一个SqlSession两次查询期间手动清空了缓存

二级缓存

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

二级缓存的开启条件

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

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

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

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

使二级缓存失效的清况

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

相关配置

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

MyBaits缓存查询的顺序

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

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

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

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

整合第三方缓存EHCache

使用第三方技术代替MyBatis的二级缓存

添加依赖

        <!--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>

slf4j:Simple Logging Facade for Java 简单日志门面(不是具体的日志解决方案,它只服务于各种各样的日志系统)

创建EHCache的配置文件ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
         updateCheck="false">
    <!--
       diskStore:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。参数解释如下:
       user.home – 用户主目录
       user.dir  – 用户当前工作目录
       java.io.tmpdir – 默认临时文件路径
     -->
    <diskStore path="D:\ideaworkspace\MyBatis\ehcache"/>
    <!--
       defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。
     -->
    <!--
      name:缓存名称。
      maxElementsInMemory:缓存最大数目
      maxElementsOnDisk:硬盘最大缓存个数。
      eternal:对象是否永久有效,一但设置了,timeout将不起作用。
      overflowToDisk:是否保存到磁盘,当系统当机时
      timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
      timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
      diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
      diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
      diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
      memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
      clearOnFlush:内存数量最大时是否清除。
      memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。
      FIFO,first in first out,这个是大家最熟的,先进先出。
      LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。
      LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
   -->
    <defaultCache
            eternal="false"
            maxElementsInMemory="10000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="259200"
            memoryStoreEvictionPolicy="LRU"/>
 
    <cache
            name="cloud_user"
            eternal="false"
            maxElementsInMemory="5000"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="1800"
            timeToLiveSeconds="1800"
            memoryStoreEvictionPolicy="LRU"/>
 
</ehcache>

设置二级缓存的类型

加入logback日志

存在

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

创建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>

测试:

MyBatis的逆向工程

正向工程:

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

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

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

创建逆向工程的步骤

添加依赖和插件

<dependencies>
        <!--MyBatis核心jar包-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>

        <!--Mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.27</version>
        </dependency>

        <!--Log4j日志-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <!--单元测试-->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </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>

                    <!-- 数据库连接池 -->
                    <dependency>
                        <groupId>com.mchange</groupId>
                        <artifactId>c3p0</artifactId>
                        <version>0.9.2</version>
                    </dependency>

                    <!-- MySQL驱动 -->
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>8.0.27</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>

创建jdbc.properties和log4j.xml

创建MyBatis的核心配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <properties resource="jdbc.properties"></properties>

    <!--设置MyBatis的全局配置-->
    <settings>
        <!--将下划线自动映射为驼峰,emp_name:empName-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <setting name="lazyLoadingEnabled" value="true"/>
    </settings>

    <typeAliases>
        <package name="com.gyq.mybatis.pojo"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <package name="com.gyq.mybatis.mapper"/>
    </mappers>

</configuration>

创建逆向工程的配置文件

文件名为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="MyBatis3Simple">
        <!-- 数据库的连接信息 -->
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/mybatis"
                        userId="root"
                        password="root">
        </jdbcConnection>
        <!-- javaBean的生成策略-->
        <javaModelGenerator targetPackage="com.gyq.mybatis.pojo" targetProject=".\src\main\java">
            <property name="enableSubPackages" value="true"/>
            <property name="trimStrings" value="true"/><!--去掉空格-->
        </javaModelGenerator>
        <!-- SQL映射文件的生成策略 -->
        <sqlMapGenerator targetPackage="com.gyq.mybatis.mapper"
                         targetProject=".\src\main\resources">
            <property name="enableSubPackages" value="true"/>
        </sqlMapGenerator>
        <!-- Mapper接口的生成策略 -->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.gyq.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>

双击

自动生成的代码

  👍

奢华版

将上面的配置文件更改  targetRuntime="MyBatis3",将刚才生成的删除后再次生成

在Emp类中生成无参,带参构造器和toString方法,用于测试

测试查询

测试修改

MyBatis的分页插件

使用步骤

添加依赖

        <!--分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.2.0</version>
        </dependency>

配置分页插件

在MyBatis的核心配置文件中配置插件

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

分页插件的使用

其中pageNum:3表示当前要查的是第3页的数据,pageSize表示每一页的数据条数

Page{count=true, pageNum=3, pageSize=4, startRow=8, endRow=12, total=21, pages=6, reasonable=false, pageSizeZero=false}[Emp{eid=11, empName='a', age=null, sex='null', email='null', did=null}, Emp{eid=12, empName='a', age=null, sex='null', email='null', did=null}, Emp{eid=13, empName='a', age=null, sex='null', email='null', did=null}, Emp{eid=14, empName='a', age=null, sex='null', email='null', did=null}]

navigatePages:3表示当前导航分页的数量,显示第三页时的相关信息

PageInfo{pageNum=3, pageSize=4, size=4, startRow=9, endRow=12, total=21, pages=6, list=Page{count=true, pageNum=3, pageSize=4, startRow=8, endRow=12, total=21, pages=6, reasonable=false, pageSizeZero=false}[Emp{eid=11, empName='a', age=null, sex='null', email='null', did=null}, Emp{eid=12, empName='a', age=null, sex='null', email='null', did=null}, Emp{eid=13, empName='a', age=null, sex='null', email='null', did=null}, Emp{eid=14, empName='a', age=null, sex='null', email='null', did=null}], prePage=2, nextPage=4, isFirstPage=false, isLastPage=false, hasPreviousPage=true, hasNextPage=true, navigatePages=3, navigateFirstPage=2, navigateLastPage=4, navigatepageNums=[2, 3, 4]}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值