6.1 MyBatis_缓存及MyBatis整合ehcache

本文详细介绍了MyBatis的缓存机制,包括一级缓存和二级缓存的工作原理及使用方法,并通过示例代码展示了如何配置和利用缓存提高数据库访问效率。

1.目录结构


导入必要的jar包并使用mysql数据库创建表

2.代码

Employee.java

package com.bean;

import java.io.Serializable;

public class Employee implements Serializable{
	private Integer id;
	private String lastName;
	private String email;
	private String gender;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getLastName() {
		return lastName;
	}
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getGender() {
		return gender;
	}
	public void setGender(String gender) {
		this.gender = gender;
	}
	
	public Employee(Integer id, String lastName, String email, String gender) {
		super();
		this.id = id;
		this.lastName = lastName;
		this.email = email;
		this.gender = gender;
	}
	public Employee() {};
	
	@Override
	public String toString() {
		return "Employee [id=" + id + ", lastName=" + lastName + ", email=" + email + ", gender=" + gender + "]";
	}

	

}

EmployeeMapper.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:名称空间,指定接口的全类名
		id: 唯一标识符
		resultType:返回的对象类型  
	  如果数据库的某些字段与对象的属性不相同,可以把数据库的这些字段取别名(如数据库字段 last_name与对象属性lastName不一致)
 --> 
 <mapper namespace="com.dao.EmployeeMapper">
 
 	<cache type="org.mybatis.caches.ehcache.EhcacheCache"><property name="employee" value=""/></cache>
 	
 	<!-- 可引用缓存:namespace:指定和哪个名称空间下的缓存一样,如下是指Employee使用的缓存和Dempartment的缓存一样-->
 	<!-- <cache-ref namespace="com.bean.Department"/> -->
 	
 	    <!-- cache   缓存开启
         eviction 缓存回售策略
                LRU 最近最少使用的,移除最长时间不被使用的(默认)
                FIFO 先进先出
                SOFT 软引用
                WEAK 弱引用
         flushInterval 缓存刷新间隔
                 缓存清空时间,默认不清空,设置毫秒值
         readOnly 缓存是否只读
                 true  mybatis只从缓存中毒数据,不会修改数据
                 false  mybatis认为缓存中的数据会被修改,会用序列化和反序列化技术克隆一份给用户,安全,速度慢
         size  缓存存放多少元素
         type  指定自定义缓存的全类名
     -->
  <!-- <cache ></cache>  -->
 	 
   <!-- 11.抽取可重用的sql片段,方便后面引用 
   			1.sql抽取,经常将要查询的列名,或者插入用的列名抽取出来方便引用
   			2.insert来引用已经抽取的
   			3,include还可以自定义一些property,sql标签内部就能使用自定义的属性
   				include-property:取值的正确方式${prop}:	id,last_name,email,gender,#{testColumn}
   				#{不能使用这种方式}
   
   -->
	<sql id="insertColumn">
		<if test="_databaseId=='mysql'">
			id,last_name,email,gender
		</if>
		<if test="_databaseId=='oracle'">
			id,last_name,email,department_id
		</if>
	</sql>
	
	<insert id="addEmployeeBysql" databaseId="mysql">
		insert into tbl_employee(
			<!-- 引用外部定义的sql -->
			<include refid="insertColumn" ></include>
		) 
		values (#{id},#{lastName},#{email},#{gender})
	</insert>
	
	<select id="getEmployeeById" resultType="com.bean.Employee" databaseId="mysql" 
		useCache="true" >
		select * from tbl_employee where id=#{id}
	</select>
   		 
</mapper>

EmployeeMapper.java

package com.dao;

import java.util.List;

import org.apache.ibatis.annotations.Param;

import com.bean.Employee;

public interface EmployeeMapper {
	
	
	//11.测试sql可重复片段
	public void addEmployeeBysql(Employee employee);
	
	//测试缓存cache
	public Employee getEmployeeById(Integer id);
}


testMybatis.java
package com.test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import com.bean.Employee;
import com.dao.EmployeeMapper;

public class testMybatis{
	
	private SqlSessionFactory getSqlSessionFactory() throws IOException {
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory SqlSessionFactory =new SqlSessionFactoryBuilder().build(inputStream);
		return SqlSessionFactory;
	}
	
	@Test
	public void testSQL() throws IOException {
		SqlSessionFactory ssf=getSqlSessionFactory();
		SqlSession ss=ssf.openSession();
		try {
			EmployeeMapper mapper=ss.getMapper(EmployeeMapper.class);
			
			Employee emp1=mapper.getEmployeeById(38);
			System.out.println(emp1);
			
		/* 一级缓存失效的四种情况:
		 * 1.SqlSession不同,Cache会失效
			SqlSession ss2=ssf.openSession();
			EmployeeMapper mapper2=ss2.getMapper(EmployeeMapper.class);
			
			Employee emp2=mapper2.getEmployeeById(38);
			System.out.println(emp2);*/
			
		/*2.sqlSession相同,查询条件相同,但两次查询之间执行了增删改操作
			mapper.addEmployeeBysql(new Employee(null,"yiwen","yiwen@qq.com","1"));*/
			
		/*3.SqlSession相同,查询条件不同
			Employee emp3=mapper.getEmployeeById(41);
			System.out.println(emp3);*/
			
		/*4.sqlSession相同,查询条件相同,手动清除了缓存clearCache()
			ss.clearCache();*/
			
			Employee emp2=mapper.getEmployeeById(38);
			System.out.println(emp2);
			
			System.out.println(emp1==emp2);
			
			ss.commit();
		}
		finally {
			ss.close();
			}	
	
	}
	 
	/* 二级缓存:基于namespace级别的缓存,一个namespace对应一个二级缓存
               工作机制:
         1、一个会话查询一个数据,这个数据会被保存到当前会话的一级缓存中      
         2、如果会话关闭,一级缓存中的数据会被保存到二级缓存中,新的会话消息,就可以查询二级缓存
         3、不同namespace查出来的数据,会被放在自己对应的缓存中
	 
	 使用二级缓存的步骤:
		第一步:开启缓存
			在全局配置文件中开启缓存
			<setting name="cacheEnabled" value="true"></setting>
		第二步:在映射文件中配置缓存
			<cache></cache>
		第三步:pojo需要使用序列化接口
		
	和缓存有关的设置/属性:
		1.cacheEnabled=true;false:关闭缓存(二级缓存关闭(一级缓存一直可用))
		2.每个select标签都有useCache="true"
			false:不使用缓存(一级缓存依然使用,二级缓存不适用)
		3.每个增删改标签的:flushCache="true";(一级、二级缓存都会清除)
			增删改执行完成后就会清除缓存
			测试:flushCache="true":一级缓存就清空了,二级缓存也会被清除;
			查询标签:fulshCache="false";
				如果fulshCache="true";每次查询之后都会清空缓存,缓存是没有被使用的
		4.SqlSession.cleanCache();只是清除当前Session的一级缓存
		5.localCacheScope:本地缓存作用域:=SESSION(一级缓存SESSION):当前回话的所有数据保存在回话缓存中。
				=STATEMENT:可以禁用一级缓存	
	*/
	
	/*第三方缓存整合:
		1.导入第三方缓存包即可;
		2.导入与第三方缓存整合的适配包;官方有下载(与spring整合的包,与hibernate整合的包);
		3.mapper.xmm中使用自定义缓存
			<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>
		4.配置ehcache.xml*/
	
	@Test
	public void cahetest() throws IOException {
		SqlSessionFactory ssf=getSqlSessionFactory();
		SqlSession ss2=ssf.openSession();
		EmployeeMapper mapper2=ss2.getMapper(EmployeeMapper.class);
		SqlSession ss3=ssf.openSession();
		EmployeeMapper mapper3=ss3.getMapper(EmployeeMapper.class);
		
		Employee emp2=mapper2.getEmployeeById(42);
		System.out.println(emp2);
		ss2.close();//如果会话关闭,一级缓存中的数据会被保存到二级缓存中,新的会话消息,就可以查询二级缓存
		
		mapper3.addEmployeeBysql(new Employee(null,"songping","song@qq.com","1"));
		ss3.commit();
		
		Employee emp3=mapper3.getEmployeeById(42);
		System.out.println(emp3);
		ss3.close();
		
			
	}

}

mybatis-config.xml

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

	
	<!-- 在控制台打印sql语句 -->
	<settings> 
        <setting name="logImpl" value="STDOUT_LOGGING"/>  
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <setting name="cacheEnabled" value="true"></setting>
    </settings> 
    
  <environments default="dev_mysql"  >
    <environment id="dev_mysql">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis?allowMultiQueries=true"/>
        <property name="username" value="root"/>
        <property name="password" value="shapolang"/>
      </dataSource>
    </environment>
    
     <environment id="dev_oracle">
    	<transactionManager type="JDBC"></transactionManager>
    	<dataSource type="POOLED">
			<property name="driver" value="${oracle.driver}"></property>
			<property name="url" value="${oracle.url}"></property>
			<property name="username" value="${oracle.username" ></property>
			<property name="password" value="${oracle.password}"></property>
    	</dataSource>
    </environment>
  </environments>
  
  <!-- MyBatis 可以根据不同的数据库厂商执行不同的语句 -->
  <databaseIdProvider type="DB_VENDOR">
  	<property name="MySQL" value="mysql"/>
  	<property name="Oracle" value="oracle"/>
  	<property name="SQL Server" value="sqlserver"/>
  </databaseIdProvider>
  
  
  <!-- 写好的sql映射文件一定要注册到全局配置文件中 -->
  <mappers>
    <mapper resource="com/bean/EmployeeMapper.xml"/>
  </mappers>
</configuration>

整合ehcache需要的配置文件ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <diskStore path="F:/ehcache/"></diskStore>
    
    <!-- 默认缓存配置 -->
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
    />
    
    <!-- User缓存配置 -->
    <cache 
        name="employee" 
        maxElementsInMemory="10000" 
        eternal="false"
        timeToIdleSeconds="300" 
        timeToLiveSeconds="600" 
        overflowToDisk="true" 
    /> 

</ehcache>

3.mybatis缓存原理图


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值