您的位置:首页 > 其它

mybatis入门教程(九)------mybatis缓存

2016-06-14 20:45 337 查看
9. Mybatis 缓存
9.1 Mybatis的一级缓存
9.1.1  数据表准备
9.1.2  User实体类准备
9.1.3 UserMapper.java
9.1.4 UserMapper.xml
9.1.5 测试
9.1.6 测试结果
9.2  Mybatis的二级缓存
9.2.1 没有开启Mybatis二级缓存之前,测试
9.2.2 User.java
9.2.3 Mybatis 配置文件
9.2.4 Mybatis二级缓存测试
9.2.5 测试结果
9.3 总结


9. Mybatis 缓存

   正如大多数持久层框架一样,MyBatis 同样提供了一级缓存和二级缓存的支持
1. 一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空。
2. 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。
3. 对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。


9.1 Mybatis的一级缓存


9.1.1  数据表准备

/*用户表*/
drop table if exists user;
create table user(
id int primary key auto_increment,
username varchar(50) unique,
password varchar(100),
nickname varchar(50),
salt varchar(100),
locked boolean
)engine=InnqDB default charset=utf8;



9.1.2  User实体类准备

package com.mscncn.batis.model;

public class User {
private int id;
private int age;
private String userName;
private String userAddress;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserAddress() {
return userAddress;
}
public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}

}



9.1.3 UserMapper.java

public interface UserMapper {
public User getUserById(int id);
}



9.1.4 UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?> 
<!DOCTYPE mapper 
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 
<!-- 这里namespace必须是PostsMapper接口的路径,不然要运行的时候要报错 “is not known to the MapperRegistry”--> 
<mapper namespace="com.mscncn.batis.mapper.UserMapper"> 
    <!-- 这儿的resultType是配置在mybatis-config.xml中得别名 -->
    <select id="getUserById" parameterType="int" resultType="User">
    		select * from user where id=#{id}
    </select>
</mapper>



9.1.5 测试

@Test 
    public void testgetUserById() { 
       SqlSession sqlSession = sqlSessionFactory.openSession(); 
       try { 
    	   		UserMapper mapper = sqlSession.getMapper(UserMapper.class); 
    	   		//注意,重写User的toString方法
    	   		User u1=mapper.getUserById(1);
    	   		System.out.println(u1);
    	   		User u2=mapper.getUserById(1);
    	   		System.out.println(u2);
           sqlSession.commit();//这里一定要提交,不然数据进不去数据库中 
       } finally { 
           sqlSession.close(); 
       } 
    }



9.1.6 测试结果





   从以上结果中可以看出,两次调用getUserById方法,但是只有一次查询数据库的过程,这种现象产生的原因就是mybatis的一级缓存,并且一级缓存是默认开启的。

9.2  Mybatis的二级缓存


9.2.1 没有开启Mybatis二级缓存之前,测试

 @Test 
    public void testCache2() { 
       SqlSession sqlSession = sqlSessionFactory.openSession(); 
       SqlSession sqlSession2 = sqlSessionFactory.openSession(); 
       try { 
    	   		UserMapper mapper = sqlSession.getMapper(UserMapper.class); 
    	   		UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class); 
    	   		//注意,重写User的toString方法
    	   		User u1=mapper.getUserById(1);
    	   		System.out.println(u1);
    	   		User u2=mapper2.getUserById(1);
    	   		System.out.println(u2);
           sqlSession.commit();//这里一定要提交,不然数据进不去数据库中 
       } finally { 
           sqlSession.close(); 
       } 
    }


  测试结果:





  两个session,分别查询id为1 的 User ,那么mybatis与数据库交互了两次,这样说明mybatis现在没有开启二级缓存,需要我们手动的开启。


9.2.2 User.java

    实体类实现可序列化接口:

public class User implements Serializable {...}


    如果实体类不实现可序列化接口,使用二级缓存,那么会报下列异常:

org.apache.ibatis.cache.CacheException: Error serializing object.  Cause: java.io.NotSerializableException:


   


9.2.3 Mybatis 配置文件

    默认配置:

<settings>
<setting name="cacheEnabled" value="true"/>
</settings>


 必须开启缓存配置,才能使用mybatis的二级缓存,不然不能使用


9.2.4 Mybatis二级缓存测试

@Test 
    public void testCache2() { 
    	SqlSession sqlSession = sqlSessionFactory.openSession(); 
        SqlSession sqlSession2 = sqlSessionFactory.openSession(); 
        try { 
     	   		UserMapper mapper = sqlSession.getMapper(UserMapper.class); 
     	   		UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class); 
     	   		//注意,重写User的toString方法
     	   		User u1=mapper.getUserById(1);
     	   		sqlSession.commit();
     	   		System.out.println(u1);
     	   		User u2=mapper2.getUserById(1);
     	   		System.out.println(u2);
            sqlSession.commit();//这里一定要提交,不然数据进不去数据库中 
        } finally { 
            sqlSession.close(); 
        } 
    }


   这儿需要注意,必须使用的是两个不同的session,并且第一个session必须提交才能使用二级缓存(二级缓存必须提交前面的session,现在还没有找到原因)


9.2.5 测试结果





9.3 总结

  mybatis 一级缓存:默认开启

  1. 必须同一个session,如果session对象已经close()过了就不能用了

  2. 查询条件必须一致

  3. 没有执行过session.cleanCache();清理缓存

  4. 没有执行过增删改操作(这些操作都会清理缓存) 

 mybatis 二级缓存: 

mybatis-config.xml 中默认配置
  <settings> 
        <setting name="cacheEnabled" value="true" /> 
  </settings>


 必须手动开启在Mapper.xml中添加

 <cache/> 有默认的参数值
<cache />

<?xml version="1.0" encoding="UTF-8" ?> 
<!DOCTYPE mapper 
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> 
<!-- 这里namespace必须是PostsMapper接口的路径,不然要运行的时候要报错 “is not known to the MapperRegistry”--> 
<mapper namespace="com.mscncn.batis.mapper.UserMapper"> 
<cache />
    <!-- 这儿的resultType是配置在mybatis-config.xml中得别名 -->
    <select id="getUserById" parameterType="int" resultType="User">
    		select * from user where id=#{id}
    </select>
</mapper>


1. 映射语句文件中的所有select语句将会被缓存。 

2. 映射语句文件中的所有insert,update和delete语句会刷新缓存。 

3. 缓存会使用Least Recently Used(LRU,最近最少使用的)算法来收回。 

4. 缓存会根据指定的时间间隔来刷新。 

5. 缓存会存储1024个对象

<cache 

eviction="FIFO"  //回收策略为先进先出

flushInterval="60000" //自动刷新时间60s

size="512" //最多缓存512个引用对象

readOnly="true"/> //只读

转载地址:http://my.oschina.net/KingPan/blog/280167?fromerr=TYEA5Ryh
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: