Java高开发Java 杂谈Java

MyBatis缓存和注解

2019-06-03  本文已影响10人  48730ba83b2d

Mybatis缓存和注解

学习目标

1、mybatis缓存

2、mybatis注解

学习内容

1、mybatis缓存

如何提高查询的效率?

缓存技术:第一次查询到的数据缓存到内存中,后续再次进行相同的查询时,可以直接存内存中取数据。

mybatis缓存解决方案:

一级缓存:

一级缓存默认开启的,基于SqlSession级别的缓存,每一个sqlsession之间是相互独立的。

当SqlSession执行:关闭、更新操作(增删改)、清空缓存操作时:会清空缓存;

MyBatis缓存和注解

示例:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> @Test
 public void test1(){
 SqlSession session= SessionFactory.getSession();
 //接口绑定
 EmpDao dao= session.getMapper(EmpDao.class);
 List<Emp> list=dao.queryAll();
 System.out.println(list);
 List<Emp> list2=dao.queryAll();
 System.out.println(list2);
 session.close();
 }
</pre>

二级缓存:

基于Application级别的缓存。操作:对应到每一个mapper(文件)

MyBatis缓存和注解

实现二级缓存步骤:

1、开启二级缓存

二级缓存默认不开启,需要在全局配置文件中开启:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> <!--开启二级缓存-->
 <setting name="cacheEnabled" value="true"/>
</pre>

2、在对应的mapper文件中设置:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> <cache/>
</pre>

基本上就是这样。这个简单语句的效果如下:

详细设置如下:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> <cache 
 eviction="FIFO"
 flushInterval="60000"
 size="512"
 readOnly="true"/>
 ​
</pre>

1、eviction:清除策略

可用的清除策略有:

2、flushInterval(刷新间隔)属性可以被设置为任意的正整数,设置的值应该是一个以毫秒为单位的合理时间量。 默认情况是不设置,也就是没有刷新间隔,缓存仅仅会在调用语句时刷新。

3、size(引用数目)属性可以被设置为任意正整数,要注意欲缓存对象的大小和运行环境中可用的内存资源。默认值是 1024。

4、readOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。这就提供了可观的性能提升。而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false。

提示 二级缓存是事务性的。这意味着,当 SqlSession 完成并提交时,或是完成并回滚,但没有执行 flushCache=true 的 insert/delete/update 语句时,缓存会获得更新。

3、需要缓存的实体类要实现序列化接口

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">实体类 implements Serializable 
</pre>

4、测试

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> @Test
 public void test1(){
 SqlSession session= SessionFactory.getSession();
 //接口绑定
 EmpDao dao= session.getMapper(EmpDao.class);
 //一次
 List<Emp> list=dao.queryAll();
 System.out.println(list);
 session.close(); //提交事务
 session= SessionFactory.getSession();
 //接口绑定
 dao= session.getMapper(EmpDao.class);
 List<Emp> list2=dao.queryAll();
 System.out.println(list2);
 //session.clearCache();//清空缓存
 session.close();
 }
</pre>

注意:

只能对单表进行缓存。

在不同的标签上可以设置是否使用缓存:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><select ... flushCache="false" useCache="true"/>
<insert ... flushCache="true"/>
<update ... flushCache="true"/>
<delete ... flushCache="true"/>
</pre>

自定义二级缓存:

1、创建缓存类需要实现cache接口

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public interface Cache {
 String getId();
 int getSize();
 void putObject(Object key, Object value);
 Object getObject(Object key);
 boolean hasKey(Object key);
 Object removeObject(Object key);
 void clear();
}
</pre>

2、设置

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><cache type="com.domain.something.MyCustomCache"/>
</pre>

基于ehcache实现二级缓存:

echache:

EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider.

是java范围内使用最广泛的缓存。同时它也支持分布式缓存。也提供了磁盘,内存的缓存存储

操作步骤:

1、引入依赖

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> <!--引入ehcache依赖-->
 <dependency>
 <groupId>org.mybatis.caches</groupId>
 <artifactId>mybatis-ehcache</artifactId>
 <version>1.0.3</version>
 </dependency>
</pre>

2、设置:ehcache.xml

放到resources根目录下:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><ehcache>
 <diskStore path="F:cache_test" />
 <defaultCache eternal="false"
 maxElementsInMemory="10000"
 timeToIdleSeconds="20"
 timeToLiveSeconds="20"
 overflowToDisk="true"
 diskExpiryThreadIntervalSeconds="20"
 memoryStoreEvictionPolicy="LRU" />
</ehcache>
</pre>

属性说明如下:

3、设置cache标签:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
</pre>

源码查看 :

MyBatis缓存和注解

测试(略)

2、mybatis注解

常用注解:

说明:这四个注解分别代表将会被执行的 SQL 语句。它们用字符串数组(或单个字符串)作为参数。如果传递的是字符串数组,字符串之间先会被填充一个空格再连接成单个完整的字符串。这有效避免了以 Java 代码构建 SQL 语句时的“丢失空格”的问题。然而,你也可以提前手动连接好字符串。属性有:value,填入的值是用来组成单个 SQL 语句的字符串数组

结果映射的列表,包含了一个特别结果列如何被映射到属性或字段的详情。属性有:value, id。value 属性是 Result 注解的数组。这个 id 的属性是结果映射的名称./

在列和属性或字段之间的单独结果映射。属性有:id, column, javaType, jdbcType, typeHandler, one, many。id 属性是一个布尔值,来标识应该被用于比较(和在 XML 映射中的<id>相似)的属性。one 属性是单独的联系,和 <association> 相似,而 many 属性是对集合而言的,和<collection>相似。它们这样命名是为了避免名称冲突

复杂类型的单独属性值映射。属性有:select,已映射语句(也就是映射器方法)的全限定名,它可以加载合适类型的实例。fetchType会覆盖全局的配置参数 lazyLoadingEnabled。

注意 联合映射在注解 API中是不支持的。这是因为 Java 注解的限制,不允许循环引用

映射到复杂类型的集合属性。属性有:select,已映射语句(也就是映射器方法)的全限定名,它可以加载合适类型的实例的集合,fetchType 会覆盖全局的配置参数 lazyLoadingEnabled。

注意联合映射在注解 API中是不支持的。这是因为 Java 注解的限制,不允许循环引用

这是一个用在返回值为 Map 的方法上的注解。它能够将存放对象的 List 转化为 key 值为对象的某一属性的 Map。属性有: value,填入的是对象的属性名,作为 Map 的 key 值

为给定的命名空间(比如类)配置缓存。属性有:implemetation, eviction, flushInterval, size, readWrite, blocking 和properties

示例:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">public interface DeptAnnoDao {
 @Insert("insert into .... ")
 int insert(Dept dept);
 @Select("select * from dept")
 @Results(id="dept1", value = {
 @Result(id = true, column = "deptno", property = "deptno") ,
 @Result(column = "dname", property = "dname"),
 @Result(column = "deptno", property = "emps"),
 })
 List<Dept> query();
 @Update("update dept set name ... where id=...")
 int update(Dept dept);
}
</pre>

动态构建SQL:

官网示例:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName")
List<User> getUsersByName(String name);
class UserSqlBuilder {
 public static String buildGetUsersByName(final String name) {
 return new SQL(){{
 SELECT("*");
 FROM("users");
 if (name != null) {
 WHERE("name like #{value} || '%'");
 }
 ORDER_BY("id");
 }}.toString();
 }
}
</pre>

多参数使用

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName")
List<User> getUsersByName(
 @Param("name") String name, @Param("orderByColumn") String orderByColumn);
class UserSqlBuilder {
 // If not use @Param, you should be define same arguments with mapper method
 public static String buildGetUsersByName(
 final String name, final String orderByColumn) {
 return new SQL(){{
 SELECT("*");
 FROM("users");
 WHERE("name like #{name} || '%'");
 ORDER_BY(orderByColumn);
 }}.toString();
 }
 // If use @Param, you can define only arguments to be used
 public static String buildGetUsersByName(@Param("orderByColumn") final String orderByColumn) {
 return new SQL(){{
 SELECT("*");
 FROM("users");
 WHERE("name like #{name} || '%'");
 ORDER_BY(orderByColumn);
 }}.toString();
 }
}
</pre>

注意:

mybatis的注解和xml文件各有优劣,可以在项目过程中结合情况使用。

总结

1、mybatis缓存:(一级缓存和二级缓存,基于第三方框架实现二级缓存)

2、mybatis注解

上一篇下一篇

猜你喜欢

热点阅读