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);
}
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缓存原理图