SSM_MyBatis
动态SQL元素和了JSTL或基于类似XML的文本处理器相似。在MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis采用功能强大的基于OGNL的表达式来淘汰其它大部分元素。
-
if
-
choose (when,otherwise)
-
trim (where,set)
-
foreach
1. 环境搭建
CREATE TABLE `blog`( `id` varchar(50) NOT NULL COMMENT ‘博客id‘, `title` varchar(100) NOT NULL COMMENT ‘博客标题‘, `author` varchar(30) NOT NULL COMMENT ‘博客作者‘, `create_time` datetime NOT NULL COMMENT ‘创建时间‘, `views` int(30) NOT NULL COMMENT ‘浏览量‘ )ENGINE=InnoDB DEFAULT CHARSET=utf8
实体类
@Data public class Blog { private String id; private String title; private String author; private Date createTime; //属性名字段名不一致 private int views; } //=============在配置文件中设置驼峰命名转换,将数据库经典命名"_"转换为驼峰命名 <setting name="mapUnderscoreToCamelCase" value="true" />
新建工具类
public class IDutils { public static String getId(){ //随机生成序列,清除"-" return UUID.randomUUID().toString().replaceAll(" -",""); } }
2. IF
<select id="queryBlogIF" parameterType="map" resultType="blog"> <!--此处1=1不正规,其它动态标签讲解--> select * from mybatis.blog where 1=1 <if test="title != nu11"> and title =#{title} </if> <if test="author != null"> and author = #{author} </if> </select>
测试
public void testqueryBlogIF{ SqlSession sqlSession = MybatisUtils.getSqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); HashMap map = new HashMap(); //如果不加参数则查询所有 map.put("tit1e","Java"); List<Blog> blogs = mapper.queryBlogIF(map); for(Blog blog : blogs) { System.out.printin(blog); } sqlSession.close(); }
3. Choose (when,otherwise)
<select id="queryBlogChoose" parameterType="map" resultType="blog"> <!--此处1=1不正规,其它动态标签讲解--> select * from mybatis.blog <!--如果一个子元素都不满足 where自动省略--> <where> <choose> <!--when只会实现一个,按先后顺序--> <when test="title != nu11"> title =#{title} </when> <when test="author != null"> <!--自动配置是否是第一个,是第一个自动去除AND--> and author = #{author} </when> <otherwise> and views = #{views} </otherwise> </choose> </where> </select>
4. Trim (where,set)
where元素只会在至少有一个子元素的条件返回SQL子句的情况下才去插入“WHERE"子句。
若语句的开头为"AND"或“OR", where元素也会将它们去除。
<select id="queryBlogWhere" parameterType="map" resultType="blog"> <!--此处1=1不正规,其它动态标签讲解--> select * from mybatis.blog <!--如果一个子元素都不满足 where自动省略--> <where> <if test="title != nu11"> title =#{title} </if> <if test="author != null"> <!--自动配置是否是第一个,是第一个自动去除AND--> and author = #{author} </if> </where> </select>
set元素会动态前置SET关键字,同时也会删掉无关的逗号
使用set,条件成立自动拼接"set",且自动删除多余","
<update id="updateBlog" parameterType="map"> update mybatis.blog <set> <if test="title != null"> title = #{title}, </if> <if test="author != null"> author = #{author} </if> </set> where id = #{id} </update>
trim
<trim prefix="SET" suffixoverrides=","> </trim> <!--参照文档学习-->
5. Foreach
select * from user where 1=1 and (id=1 or id=2 or id=3) ? <foreach item="id" index="index" collection="ids" open="(" separator= "or" close=")"> #{item} </foreach>
案例
<select id="queryBlogForeach" parameterType="map" resultType="blog"> select * from mybatis.blog <where> <!--遍历ids,每一项为id,以"and ("开头,以")"结尾,分隔符为"or"--> <foreach collection="ids" item="id" open="and (" close=")" separator="or"> id =#{id} </foreach> </where> </select>
HashMap map = new HashMap( ); ArrayList<Integer> ids = new ArrayList<Integer>(); ids.add(1); //..... map.put("ids",ids); List<Blog> blogs = mapper.queryBlogForeach(map); for (Blog blog : blogs) { System.out.printin(biog); }
6. SQL片段
有的时候,我们可能会将一些功能的部分抽取出来,方便复用!
使用SQL标签抽取公共的部分
在需要使用的地方使用Include标签引用即可
注意事项
-
最好基于单表来定义SQL片段
-
不要存在where标签
<sql id="if-title-author"> <if test="title != null"> title = #{title} </if> <if test="author != null"> author = #{author} </if> </sql> ? <select id="queryBlogIF" parameterType="map" resultType="blog"> select * from mybatis.blog <where> <include refid="if-title-author"></include> </where> </select>
建议: 现在Mysql中写出完整的SQL,再对应的去修改成为我们的动态SQL实现通用即可
13.缓存(了解)
查询 连接数据库 (占资源)
-
一次查询结果,暂存在一个可以直接取到的地方 内存-->缓存
-
再次查询相同数据时,直接走缓存,不用走数据库
-
什么是缓存[Cache ]?
-
存在内存中的临时数据。
-
将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。
-
-
为什么使用缓存?
-
减少和数据库的交互次数,减少系统开销,提高系统效率。
-
-
什么样的数据能使用缓存?
-
经常查询并且不经常改变的数据。【可以使用缓存】
-
1. MyBatis缓存
-
MyBatis包含一个非常强大的查询缓存特性,它可以非常方便地定制和配置缓存。缓存可以极大的提升查询效率。
-
MyBatis系统中默认定义了两级缓存 : 一级缓存和二级缓存
-
默认情况下,只有一级缓存开启(sqlSession级别的缓存,也称为本地缓存)。
-
二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
-
为了提高扩展性,MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存
-
2. 一级缓存
一级缓存也叫本地缓存: sqlSession
-
与数据库同一次会话期间查询到的数据会放在本地缓存中。
-
以后如果需要获取相同的数据,直接从缓存中拿,没必须再去查询数据库;
开启日志
映射语句文件中的所有select语句的结果将会被缓存。
映射语句文件中的所有insert、update和delete语句会刷新缓存。
缓存会使用最近最少使用算法(LRU,Least Recently Used)算法来清除不需要的缓存。
缓存不会定时进行刷新(也就是说,没有刷新间隔)。
缓存会保存列表或对象(无论查询方法返回哪种)的1024个引用。
缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
缓存失效情况 :
-
查询不同东西
-
增删改
-
查询不同的Mapper
-
手动清理 SqlSession.clearCache();
小结 : 一级缓存默认是开启的,只在一次SqlSession中有效,也就是拿到连接到关闭连接这个区间段
3. 二级缓存
-
二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存
-
基于namespace级别的缓存,一个名称空间,对应一个二级缓存;
-
工作机制
-
一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
-
如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的―数据被保存到二级缓存中;
-
新的会话查询信息,就可以从二级缓存中获取内容;
-
不同的mapper查出的数据会放在自己对应的缓存(map)中;
-
提示 : 二级缓存是事务性的。这意味着,当SqlSession完成并提交时,或是完成并回滚,但没有执行fushCache=true 的insert/delete/update语句时,缓存会获得更新。
步骤:
-
开启全局缓存
<setting name="cacheEnabled" value="true"/>
-
显示的开启二级缓存
<select id="queryUserById" resultType="user" useCache="true"> select * from user where id = #{id} </ select>
-
可以自定义参数
<chche eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
这个更高级的配置创建了一个FIFO缓存,每隔600秒刷新,最多可以存储结果对象或列表的512个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。
可用清除策略:
-
LRU一最近最少使用 : 移除最长时间不被使用的对象。(默认)
-
FIFO一先进先出 : 按对象进入缓存的顺序来移除它们。
-
SOFT一软引用 : 基于垃圾回收器状态和软引用规则移除对象。
-
WEAK一弱引用 : 更积极地基于垃圾收集器状态和弱引用规则移除对象。
-
-
注意 : 我们需要将实体类序列化!否则就会报错!
-
即实体类实现 Serializable接口
-
-
只要开启了二级缓存,在同一个Mapper下就有效
-
所有的数据都会先放在一级缓存中
-
只有当会话提交,或者关闭的时候,才会提交到二级缓冲中!
4. 自定义缓存-ehcache
Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存
-
导包
-
在mapper中指定使用我们的ehcache缓存实现!
<cache type="org.mybatis.caches.ehcache.EhcacheCache">
-
配置文件 ehcache.xml
Redis数据库来做缓存! K-V