Java框架之MyBatis 07-动态SQL-缓存机制-逆向工程-分页插件
MyBatis
今天大年初一,你在学习!不学习做什么,斗地主...人都凑不齐。学习吧,学习使我快乐!除了诗和远方还有责任,我也想担当,我也想负责,可臣妾做不到啊,怎么办?你说怎么办,为啥人家能做到你做不到,因为人家比你多做了那么一点点。哪一点点?就那么一点点,只要你也多做那么一点点,不就做到了!...就那么一点点呀,我回顾SE去了。万丈高楼平地起,基础打的牢,怕什么狂风暴雨
MyBatis 动态SQL
MyBatis为了解决通过一些不确定性的条件进行SQL语句的拼接操作的问题, 提供了动态SQL. 具体来说,就是提供了一些标签 <if> <where> <trim> <set> <choose> <foreach> 等.写出可扩展SQL语句
MyBatis 采用功能强大的基于 OGNL 的表达式来简化操作
OGNL( Object Graph Navigation Language )对象图导航语言,这是一种强大的表达式语言,通过它可以非常方便的来操作对象属性。 类似于EL表达式,例:
访问对象属性: person.name
调用方法: person.getName()
调用静态属性/方法: @java.lang.Math@PI
调用构造方法: new com.bean.Person(‘admin’).name
运算符: +,-*,/,%
逻辑运算符: in,not in,>,>=,<,<=,==,!=
注意:xml中特殊符号如”,>,<等这些都需要使用转义字符
标签
1) <if>:用于完成简单的判断.只有一个属性 test 用于判断条件是否成立
2) <where>:在SQL语句中添加WHERE关键字, 作用:去掉 where 后面第一个条件前面的 and / or 。
<select id="getBook" resultType="main.beans.Book">
SELECT id,title,author,price
FROM books
<where>
<if test="id != null"> and id= #{id}</if>
<if test="title != null"> and title = #{title}</if>
</where>
</select>
3) <trim> : 可以在条件判断完的SQL语句的前后 添加内容 或者去掉指定的内容. 去掉第一个或最后一个
prefix: 添加前缀 prefixOverrides: 去掉前缀
suffix: 添加后缀 suffixOverrides: 去掉后缀
<delete id="deleteBook">
DELETE FROM books
<trim prefix="WHERE" suffixOverrides="and">
<if test="id != null">id = #{id} and</if>
<if test="title != null">itle = #{title} and</if>
</trim >
</delete>
4) <set> :在修改的操作中, 去掉SQL语句中多出的逗号,即在sql语句中最后句可能多出的逗号
<update id="updateBook">
UPDATE books
<set>
<if test="title != null">title = #{title},</if>
<if test="author != null">author = #{author},</if>
</set>
where id = #{id}
</update>
5) <sql> 标签是用于抽取可重用的sql片段,将使用频繁的SQL片段抽取出来,不仅仅只提取整条sql语句,字段也可以提取
id:指定被提取的 sql 片段唯一标识被引用
引用:在任何需要插入此 sql 片段的语句中使用 <include refid="id标识"></include> 引入即可
<sql id="bookFields">
id,title,author,price,sales,stock,img_path
</sql>
<insert id="insertBook" useGeneratedKeys="true" keyProperty="id">
INSERT INTO books (<include refid="bookFields"></include>)
VALUES(#{id},#{title},#{author},#{price},#{sales},#{stock},#{imgPath})
</insert>
6) <choose> <when> <otherwise> : 用于分支判断,最终只会满足其中的一个分支. 类似于 switch case 语句.
<select id="selectBookPrice" resultType="main.beans.Book">
SELECT <include refid="bookFields"></include>
FROM books
<where>
<choose>
<when test="id != null">id = #{id}</when>
<otherwise>price > #{price}</otherwise>
</choose>
</where>
</select>
7) <foreach>: 主要用于循环迭代
collection: 要迭代的集合
item: 当前从集合中迭代出的元素赋值的变量
open: 开始字符
close:结束字符
separator: 指定元素与元素之间的分隔符
index:
迭代的是List集合: index表示当前元素的下标
迭代的Map集合: index表示当前元素的 key
注意:此操作属于批量操作需在 properties 配置的 url 中添加 allowMultiQueries=true 开启批处理
<select id="getBooks" resultType="main.beans.Book">
SELECT <include refid="bookFields"></include>
FROM books where id in
<foreach collection="ids" item="id" separator="," open="(" close=")" >
#{id}
</foreach>
</select>
MyBatis 缓存机制
MyBatis 包含一个非常强大的查询缓存特性,它可以非常方便地配置和定制。缓存可以极大的提升查询效率
MyBatis系统中默认定义了两级缓存:一级缓存、二级缓存
默认情况下,只有一级缓存(SqlSession级别的缓存,也称为本地缓存)开启。
二级缓存需要手动开启和配置,他是基于namespace级别的缓存。为了提高扩展性。MyBatis定义了缓存接口Cache,支持第三方缓存。
一级缓存
1) 一级缓存(local cache), 即本地缓存, 作用域默认为sqlSession。每个sqlSession对象都有自己的一级缓存,相互独立不共享。当 Session flush 或 close 后, 该 Session 中的所有 Cache 将被清空。
2) 本地缓存不能被关闭, 但可以调用 clearCache() 来清空本地缓存, 或者改变缓存的作用域.
3) 在mybatis3.1之后, 可以配置本地缓存的作用域. 在 mybatis.xml 中配置
4) 一级缓存的工作机制,同一次会话期间只要查询过的数据都会保存在当前SqlSession的一个Map中
key: hashCode+查询的SqlId+编写的sql查询语句+参数
缓存机制:
基于相同sqlSession多次查询,每次查询都会先从缓存中获取数据,如果缓存中没获取到数据,则从数据库中获取数据,之后,将数据存放到一级缓存。
一级缓存的失效问题
1)不同的SqlSession对应不同的一级缓存
2)同一个SqlSession但是查询条件不同
3)同一个SqlSession两次查询期间执行了任何一次增删改操作
增删改操作,会默认清空缓存。
4)同一个SqlSession两次查询期间手动清空了缓存
总结:当同一 SqlSession 多次查询同一语句时,且中间未有增删改或手动刷新、关闭、清空 clearCache() 过缓存,便会直接从缓存中取数据。若开启了二级缓存则会先从二级缓存读取,若二级缓存里没有再去一级缓存读取,如果只想从一级缓存中读取可在对应 <select> 配置属性中设置 useCache="false" 来关闭当前二级缓存,注意增删改不涉及缓存机制
二级缓存
默认关闭,使用需要满足三个条件才被开启
二级缓存:namespace级别缓存(sqlSessionFacotry)级别的缓存,作用域更广但是需要在 sqlSessionFacotry 内的 sqlSession 提交或关闭以后才会生效。即才会将 sqlSession 中的缓存存到二级缓存中。
二级缓存使用的步骤:
① 全局配置文件中开启二级缓存<setting name="cacheEnabled" value="true"/>
② 在需要使用二级缓存的映射文件( <mapper> 配置文件)使用 cache 标签配置缓存<cache />
③ 注意:POJO需要实现 Serializable 接口
<cache> 标签属性
① eviction=“LRU”:缓存回收策略:默认的是 LRU。
LRU – 最近最少使用的:移除最长时间不被使用的对象。
FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
② flushInterval:刷新间隔,单位毫秒
默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
③ size:引用数目,正整数
代表缓存最多可以存储多少个对象,太大容易导致内存溢出
④ readOnly:只读,默认是 false。虽然设为true能提高效率但是为了安全,因此不需设置此项
⑤ type:引入缓存类库(第三方缓存)
其他相关属性设置
1) 全局setting的 cacheEnable:
配置二级缓存的开关,一级缓存一直是打开的。
2) select标签的 useCache 属性:
配置这个 select 是否使用二级缓存。一级缓存一直是使用的
3) sql标签的 flushCache 属性:
增删改默认 flushCache=true。sql执行以后,会同时清空一级和二级缓存。
查询默认 flushCache=false。
4) sqlSession.clearCache():只是用来清除一级缓存。
二级缓存机制
基于相同sqlSessionFactory下,多次查询,优先去二级缓存中获取数据,二级缓存获取不到数据,去一级缓存中获取数据,一级缓存中也获取不到数据,直接去数据库中查询数据。
查询后,将数据直接存放一级缓存,提交或关闭 sqlSession 时,才将一级缓存中的数据,缓存到二级缓存中。
EhCache第三方缓存
EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider
整合EhCache缓存的步骤:
① 导入ehcache包,以及整合包,日志包
ehcache-core-2.6.8.jar、mybatis-ehcache-1.0.3.jar
slf4j-api-1.6.1.jar、slf4j-log4j12-1.6.2.jar
② 编写 ehcache.xml 配置文件
③ 配置 cache 标签
<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>
第三方缓存的使用机制,同二级缓存一样也需要 setting 的 cacheEnable 设置为 true 并且实现序列化接口 Serializable
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
<!-- 磁盘保存路径 -->
<diskStore path="F:\code\mysql\ehcache" />
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000000"
eternal="false"
overflowToDisk="true"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
</defaultCache>
</ehcache>
MyBatis 逆向工程
MyBatis Generator: 简称MBG,是一个专门为MyBatis框架使用者定制的代码生成器,可以快速的根据表生成对应的映射文件,接口,以及bean类。支持基本的增删改查,以及QBC风格的条件查询。但是表连接、存储过程等这些复杂sql的定义需要我们手工编写
Mybatis使用逆向工程步骤
1.加入逆向工程相关的jar包.
mybatis-generator-core-1.3.2.jar
2.配置逆向工程的配置文件: mbg.xml ==> 生成的版本 、 javaBean、Mapper接口、映射文件的生成策略 、 分析的表 .
mbg.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.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/bookstore?allowMultiQueries=true"
userId="root"
password="12345">
</jdbcConnection>
<!-- javaBean的生成策略 bean的存放路径-->
<javaModelGenerator targetPackage="main.beans" targetProject=".\src">
<property name="enableSubPackages" value="true"/>
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- SQL映射文件的生成策略 mapper.xml文件路径-->
<sqlMapGenerator targetPackage="main.mapper" targetProject=".\conf">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!-- Mapper接口的生成策略 mapper接口路径-->
<javaClientGenerator type="XMLMAPPER" targetPackage="main.mapper" targetProject=".\src">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!-- 逆向分析的表 表名对应的javaBean名-->
<table tableName="books" domainObjectName="Book"></table>
<table tableName="users" domainObjectName="User"></table>
</context>
</generatorConfiguration>
3.执行生成代码.
@Test
public void testMbg() throws Exception {
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
File configFile = new File("mbg.xml");
ConfigurationParser cp = new ConfigurationParser(warnings);
Configuration config = cp.parseConfiguration(configFile);
DefaultShellCallback callback = new DefaultShellCallback(overwrite);
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config,callback, warnings);
myBatisGenerator.generate(null);
}
PageHelper 分页插件
PageHelper 是MyBatis中非常方便的第三方分页插件。内部提供了 PageHelper 和 PageInfo 两个非常强大的类库。
使用步骤
1) 导入相关包 pagehelper-5.0.0.jar 和 jsqlparser-0.9.5.jar
2) 在MyBatis全局配置文件中配置分页插件,注意标签位置不可乱序
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>
3) 使用:在查询出集合之前开启分页查询
Page<Book> page = PageHelper.startPage(3,2 );
List<Book> books = mapper.selectByExample(bookExample);
//查询出当前为第3页,每页显示2条的图书信息,其还可得到更多页码相关值
books.forEach((book -> System.out.println("book = " + book)));
PageInfo<Book> info = new PageInfo<>(books,3);
System.out.println("=============获取详细分页相关的信息=================");
System.out.println("当前页: " + info.getPageNum());
System.out.println("总页码: " + info.getPages());
System.out.println("总条数: " + info.getTotal());
System.out.println("每页显示的条数: " + info.getPageSize());
System.out.println("是否是第一页: " + info.isIsFirstPage());
System.out.println("是否是最后一页: " + info.isIsLastPage());
System.out.println("是否有上一页: " + info.isHasPreviousPage());
System.out.println("是否有下一页: " + info.isHasNextPage());
System.out.println("============分页逻辑===============");
int[] nums = info.getNavigatepageNums();
for (int num : nums) {
System.out.println("num = " + num);
}
Page对象
在查询之前通过PageHelper.startPage(页码,条数)设置分页信息,该方法返回Page对象
PageInfo对象
在查询完数据后,使用PageInfo对象封装查询结果,可以获取更详细的分页信息以及可以完成分页逻辑
SSM配置文件
Java框架之MyBatis 07-动态SQL-缓存机制-逆向工程-分页插件的更多相关文章
- java web(七): mybatis的动态sql和mybatis generator自动生成pojo类和映射文件
前言: MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据 不同条件拼接 SQL 语句的痛苦.例如拼接时要确保不能忘记添加必要的空格,还 ...
- Java框架之Mybatis(二)
本文主要介绍 Mybatis(一)之后剩下的内容: 1 mybatis 中 log4j的配置 2 dao层的开发(使用mapper代理的方式) 3 mybatis的配置详解 4 输入输出映射对应的类型 ...
- MyBatis的动态SQL详解
MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑,本文详解mybatis的动态sql,需要的朋友可以参考下 MyBatis 的一个强大的特性之一通常是它 ...
- mybatis中的.xml文件总结——mybatis的动态sql
resultMap resultType可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功. 如果sql查询字段名和pojo的属性名不一致,可以通过re ...
- MyBatis的动态SQL详解-各种标签使用
MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑. MyBatis中用于实现动态SQL的元素主要有: if choose(when,otherwise) ...
- 9、SpringBoot+Mybatis整合------动态sql
开发工具:STS 前言: mybatis框架中最具特色的便是sql语句中的自定义,而动态sql的使用又使整个框架更加灵活. 动态sql中的语法: where标签 if标签 trim标签 set标签 s ...
- Java-MyBatis:MyBatis 3 动态 SQL
ylbtech-Java-MyBatis:MyBatis 3 动态 SQL 1.返回顶部 1. 动态 SQL MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其它类似框架 ...
- MyBatis 示例-动态 SQL
MyBatis 的动态 SQL 包括以下几种元素: 详细的使用参考官网文档:http://www.mybatis.org/mybatis-3/zh/dynamic-sql.html 本章内容简单描述这 ...
- mybatis 使用动态SQL
RoleMapper.java public interface RoleMapper { public void add(Role role); public void update(Role ro ...
随机推荐
- linux 让出处理器
如我们已见到的, 忙等待强加了一个重负载给系统总体; 我们乐意找出一个更好的技术. 想到的第一个改变是明确地释放 CPU 当我们对其不感兴趣时. 这是通过调用调度函数而 实现地, 在 <linu ...
- C# 标准性能测试高级用法
本文告诉大家如何在项目使用性能测试测试自己写的方法 在 C# 标准性能测试 已经告诉大家如何使用 BenchmarkDotNet 测试性能,本文会告诉大家高级的用法. 建议是创建一个控制台项目用来做性 ...
- Vue+node.js实现一个简洁的个人博客系统
本项目是一个用vue和node以及mysql实现的一个简单的个人博客系统,整体逻辑比较简单.但是可以我们完整的了解一个项目从数据库到后端到前端的实现过程,适合不太懂这一块的朋友们拿来练手. 本项目所用 ...
- dotnet 将文件删除到回收站
默认删除文件的时候 File.Delete 是将文件永久删除,如果是一些文档,建议删除到回收站,这样用户可以自己还原 通过 SHFileOperation 可以将文件放在回收站 本文提供的方法暂时只能 ...
- dotnet 获取程序所在路径的方法
在 dotnet 有很多方法可以获取当前程序所在的路径,但是这些方法获取到的路径有一点不相同,特别是在工作路径不是当前的程序所在的路径的时候 通过下面几个方法都可以拿到程序所在的文件夹或程序文件 Ap ...
- 【hdu 1848】Fibonacci again and again
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s) ...
- jq 技巧汇总
1,jQuery方法$()实际上是拥有两个参数的 $('li','.firstEl').onclick(function(){.......}) 这里,第二个参数用来限制第一个参数给定的查找结果 ...
- 为什么我们要使用DTO
基础结构解释 UI-表现层-与控制器打交道(UI向Controller 传递数据时使用DTO(数据传输对象)) Service-应用服务层 Domain 领域对象 DTO 数据传输对象,一般只包含基础 ...
- 无法加载文件C:\Users\TANG\AppData\Roaming\npm\nrm.ps1,因为在此系统上禁止运行脚本
# 碰到问题解决过程 > 1. 刚在一个新的机器上装node环境时,要用一个nrm管理镜像源时.报了一个错,如图1 到类似于版本控制系统的系统. 像Git,SVN存储代码,它们存储的往往是源代码,不是二进制文 ...