参考文档:
视频:【狂神说Java】
官方文档:https://mybatis.org/mybatis-3/zh/getting-started.html
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
数据持久化:持久化是程序数据在瞬时状态和持久状态间转换的过程
完成持久化工作的代码块
2.1 新建一个普通的maven项目
2.2 删除src
2.3 导入依赖:
mysql驱动,mybatis,junit(Java单元测试框架)
数据库版本5.7,所以驱动版本为5
<dependencies>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.47version>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.9version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
dependencies>
编写mybatis的核心配置文件:mybatis-config.xml
XML 配置文件中包含了对 MyBatis 系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)。
DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=utf-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
dataSource>
environment>
environments>
<mappers>
<mapper resource="com/company/dao/UserMapper.xml"/>
mappers>
configuration>
编写mybatis的工具类:
package com.company.util;
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 java.io.IOException;
import java.io.InputStream;
/**
* author: Sheryl
* create time: 2022/4/3 4:30 下午
*/
public class mybatisUtils {
private static SqlSessionFactory sqlSessionFactory = null;
//SqlSessionFactoryBuilder -> sqlSessionFactory - > sqlSession
static{
try {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
public static SqlSession getSqlSession(){
return sqlSessionFactory.openSession();
}
}
流程:mybatis-config.xml -> SqlSessionFactoryBuilder -> SqlSessionFactory -> SqlSession
生命周期: 理解我们之前讨论过的不同作用域和生命周期类别是至关重要的,因为错误的使用会导致非常严重的并发问题。
SqlSessionFactoryBuilder:一旦创建了 SqlSessionFactory,就不再需要它了。设置为一个局部变量
SqlSessionFactory: 类似于数据库连接池。一旦被创建就应该在应用的运行期间一直存在,可以重用生成多个SqlSession。最简单的就是使用单例模式(只创建一个,否则造成资源浪费)或者静态单例模式。
SqlSession: 连接到连接池的请求。每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的。绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。
类似于http请求,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。
//实体类
public class User {
private int id;
private String name;
private String pwd;
public User(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
public interface userDao {
List<User> getUserList();
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.company.dao.userDao">
<select id="getUserList" resultType="com.company.pojo.User">
select * from mybatis.user
select>
mapper>
public class userDaoTest {
@Test
public void test(){
//获得SqlSession对象
try (SqlSession sqlSession = mybatisUtils.getSqlSession()) {
//执行sql
userDao mapper = sqlSession.getMapper(userDao.class);
List<User> userList = mapper.getUserList();
//输出结果
for (User user : userList) {
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
问题1:
org.apache.ibatis.binding.BindingException: Type class com.company.dao.userDao is not known to the MapperRegistry.
分析:新建mapper没有在配置文件mybatis-config.xml中注册
<mappers>
<mapper resource="com/company/dao/UserMapper.xml"/>
mappers>
问题2:
The error may exist in com/company/dao/UserMapper.xml
分析:由于maven在构建项目时默认是不支持打包自建的xml或者properties配置文件,所以需要添加在项目pom.xml中配置信息,支持资源导出。这里没有按照往常写法,排除src/main/resorces目录下的xml文件是因为会导致mybatis-config.xml无法找到,即问题3。
<build>
<resource>
<directory>src/main/javadirectory>
<includes>
<include>**/*.propertiesinclude>
<include>**/*.xmlinclude>
includes>
<filtering>falsefiltering>
resource>
resources>
build>
关于标签: 表示关于资源的信息,资源往往不是代码,无需编译,而是一些properties或XML配置文件,构建过程中会往往会将资源文件从源路径复制到指定的目标路径。
filtering,构建过程中是否对资源进行过滤,默认false
directory,资源文件的路径,默认位于${basedir}/src/main/resources/目录下
includes,一组文件名的匹配模式,被匹配的资源文件将被构建过程处理。
excludes,一组文件名的匹配模式,被匹配的资源文件将被构建过程忽略。
问题3:
Could not find resource mybatis-config.xml
分析:
注意mybatis-config.xml放在root resorces文件下,如果没有,需要对文件夹标注
由于按照往常写法,排除src/main/resorces目录下的xml文件是因为会导致mybatis-config.xml无法找到,所以不添加以下部分代码。
修改配置pom.xml文件后记得clean清除缓存,重启idea
错误写法:
<resource>
<directory>src/main/resourcesdirectory>
<excludes>
<exclude>**/*.propertiesexclude>
<exclude>**/*.xmlexclude>
excludes>
<filtering>falsefiltering>
resource>
package com.company.dao;
import com.company.pojo.User;
import java.util.List;
/**
* author: Sheryl
* create time: 2022/4/3 4:58 下午
*/
public interface userMapper {
//查询全部用户
List<User> getUserList();
//根据ID查询用户
User getUserByID(int id);
//insert
int addUser(User user);
//update
int updateUser(User user);
//delete
int deleteUser(int id);
}
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.company.dao.userMapper">
<select id="getUserList" resultType="com.company.pojo.User">
select * from mybatis.user
select>
<select id="getUserByID" parameterType="int" resultType="com.company.pojo.User">
select * from mybatis.user where id = #{id}
select>
<insert id="addUser" parameterType="com.company.pojo.User">
insert into mybatis.user values (#{id}, #{name}, #{pwd})
insert>
<update id="updateUser" parameterType="com.company.pojo.User">
update user set name = #{name}, pwd = #{pwd} where id = #{id}
update>
<delete id="deleteUser" parameterType="com.company.pojo.User">
delete from user where id = #{id}
delete>
mapper>
public class userMapperTest {
@Test
public void test(){
//获得SqlSession对象
try (SqlSession sqlSession = mybatisUtils.getSqlSession()) {
//执行sql
userMapper mapper = sqlSession.getMapper(userMapper.class);
List<User> userList = mapper.getUserList();
for (User user : userList) {
System.out.println(user);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/*
2. select
- Id:对应的namespace中的方法名
- ResultType:sql语句执行的返回值
- ParamterType:传入参数的类型
*/
@Test
public void getUserByIDTest(){
try(SqlSession sqlSession = mybatisUtils.getSqlSession()) {
userMapper mapper = sqlSession.getMapper(userMapper.class);
User user = mapper.getUserByID(1);
System.out.println(user);
}catch (Exception e){
e.printStackTrace();
}
}
@Test
//增删改需要提交事务
public void addUserTest(){
try(SqlSession sqlSession = mybatisUtils.getSqlSession()) {
userMapper mapper = sqlSession.getMapper(userMapper.class);
int res = mapper.addUser(new User(4, "李六", "89437957"));
sqlSession.commit();
if(res > 0){
System.out.println(res + " insert sucess!");
}
}catch (Exception e){
e.printStackTrace();
}
}
@Test
public void updateUserTest(){
try(SqlSession sqlSession = mybatisUtils.getSqlSession()){
userMapper mapper = sqlSession.getMapper(userMapper.class);
int res = mapper.updateUser(new User(1, "你好","ahjkffj3"));
sqlSession.commit();
if(res > 0){
System.out.println(res + " update sucess!");
}
}catch (Exception e){
e.printStackTrace();
}
}
@Test
public void deleteUserTest(){
try(SqlSession sqlSession = mybatisUtils.getSqlSession()){
userMapper mapper = sqlSession.getMapper(userMapper.class);
int res = mapper.deleteUser(3);
sqlSession.commit();
if(res > 0){
System.out.println(res + " delete sucess!");
}
}catch (Exception e){
e.printStackTrace();
}
}
}
parameterType="map"
parameterType="com.company.pojo.User"
parameterType="int"
两种方式:推荐第一种更安全
//查询名字中含有”李“字的记录
List<User> userList = mapper.getUserLike("%李%");
<select id="getUserLike" resultType="com.company.pojo.User">
select * from user where name like #{value}
select>
//拼接sql有sql注入的风险
select * from user where name like "%"#{value}"%"
在xml标签都是有顺序的,必须按照顺序填写,否则会报错
configuration(配置):
properties(属性)
settings(设置)
typeAliases(类型别名)
typeHandlers(类型处理器)
objectFactory(对象工厂)
plugins(插件)
environments(环境配置)
environment(环境变量)
transactionManager(事务管理器)
dataSource(数据源)
databaseIdProvider(数据库厂商标识)
mappers(映射器)
MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中。
尽管可以配置多个环境,但每个 SqlSessionFactory 实例只能选择一种环境。
变换环境通过修改
实现
注意一些关键点:
Mybatis默认的事物管理器就是jdbc,连接池:POOLED
属性可以在外部进行配置,并可以进行动态替换(environmnet中的property)。
外部配置:可以直接引入外部配置文件db.properties,或者在标签中直接添加属性
driver = com.mysql.jdbc.Driver
url = jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=utf-8
username = root
password = 123456
<properties resource="db.properties">
<property name="username" value="root"/>
<property name="password" value="123456"/>
properties>
如果一个属性在不只一个地方进行了配置,那么,MyBatis 将按照下面的顺序来加载:
因此,通过方法参数传递的属性具有最高优先级,resource 属性中指定的配置文件次之,最低优先级的则是 properties 元素中指定的属性。
如果使用上述两种方法:environment中可以不用修改
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
dataSource>
environment>
如果动态替换,可以直接修改environmnet中的property达到相同效果。
方法一、类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。
<typeAliases>
<typeAlias type="com.company.pojo.User" alias="User"/>
typeAliases>
方法二、也可以指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean。扫描实体类的包,默认别名就为类名(一般推荐首字母消息,即“user”),可以使用注解修改别名。
<typeAliases>
<package name="com.company.pojo"/>
typeAliases>
在实体类中添加注解,修改别名
@Alias("user")
public class User {
...
}
在实体类比较少的时候,推荐使用第一种方式
实体类比较多得的时候,推荐使用第二种方式
设置会改变 MyBatis 的运行时行为
部分设置:
cacheEnabled | 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 | true | false | true |
---|---|---|---|
lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。 |
true | false | false |
MapperRegistry:注册绑定我们的mapper文件
方式一:resources(推荐)
<mappers>
<mapper resource="com/company/dao/UserMapper.xml"/>
mappers>
方式二:class
<mappers>
<mapper class="com.company.dao.userMapper"/>
mappers>
方式三:package
<mappers>
<package name="com.company.dao"/>
mappers>
注意点:
映射接口和mapper配置文件必须同名
映射接口和mapper配置文件必须在同一个包下
数据库:
(id, name, pwd)
实体类:
(id, name, password)
解决方式:
<select id="getUserByID" parameterType="int" resultType="com.company.pojo.User">
select id, name, pwd as password from mybatis.user where id = #{id}
select>
结果集映射:
id
– 当前命名空间中的一个唯一标识,用于标识一个结果映射。type
-类的完全限定名, 或者一个类型别名。result
– 注入到字段或 JavaBean 属性的普通结果association
一个复杂类型的关联(多对一);许多结果将包装成这种类型
resultMap
元素,或是对其它结果映射的引用collection
一个复杂类型的集合(一对多)
resultMap
元素,或是对其它结果映射的引用 <resultMap id="UserMap" type="User">
<result column="pwd" property="password"/>
resultMap>
多对一:关联
一对多:集合
MyBatis 有两种不同的方式加载关联:
public class Student {
private int id;
private String name;
//学生关联老师(使用teacher, 而不直接用int)
private Teacher teacher;
}
public class Teacher {
private int id;
private String name;
}
按照查询嵌套处理:
<select id="getStudent" resultMap="StudentTeacher">
select * from student s, teacher t where s.tid = t.id
select>
<resultMap id="StudentTeacher" type="Student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
resultMap>
<select id="getTeacher" resultType="Teacher">
select * from teacher where id = #{id}
select>
${column}
:会被直接替换,不会转义
#{value}
会使用 ?
预处理,之后会转义成相应的数据
按照结果嵌套处理:
注意查询中的连接,以及为确保结果能够拥有唯一且清晰的名字
<select id="getStudent2" resultMap="StudentTeacher2">
select s.id sid, s.name sname, t.name tname
from mybatis.student s, mybatis.teacher t
where s.tid = t.id
select>
<resultMap id="StudentTeacher2" type="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
association>
resultMap>
public class Teacher {
private int id;
private String name;
private List<Student> students;
}
public class Student {
private int id;
private String name;
private int tid;
}
<select id="getTeacher" resultMap="TeacherMap">
select s.id sid, s.name sname, t.id tid, t.name tname
from mybatis.student s, mybatis.teacher t
where s.tid = t.id and t.id = #{id}
select>
<resultMap id="TeacherMap" type="Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<collection property="students" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<result property="tid" column="tid"/>
collection>
resultMap>
<select id="getTeacher2" resultMap="TeacherMap2">
select * from teacher where id = #{tid};
select>
<resultMap id="TeacherMap2" type="Teacher">
<id property="id" column="id"/>
<collection property="students" column="id" javaType="ArrayList" ofType="Student" select="getStudent"/>
resultMap>
<select id="getStudent" resultType="Student">
select * from student where tid = #{tid}
select>
指定 MyBatis 所用日志的具体实现,未指定时将自动查找
形式:SLF4J | LOG4J(deprecated since 3.5.9) | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING
例如标准日志(STDOUT_LOGGING)实现:
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
settings>
输出结果:可以看到整个数据库连接,查询,释放连接的过程
Opening JDBC Connection
Created connection 1586845078.
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5e955596]
==> Preparing: select id, name, pwd from mybatis.user where id = ?
==> Parameters: 1(Integer)
<== Columns: id, name, pwd
<== Row: 1, 你好, ahjkffj3
<== Total: 1
User{id=1, name='你好', password='ahjkffj3'}
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5e955596]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@5e955596]
Returned connection 1586845078 to pool.
分页的作用:减少数据的处理量
select * from user limit startIndex, pageSize
//分页查询
List<User> getUserByLimit(Map<String, Object> map);
<select id="getUserByLimit" parameterType="map" resultType="User">
select * from user limit #{start}, #{size}
</select>
public void getUserByLimitTest(){
try(SqlSession sqlSession = mybatisUtils.getSqlSession()) {
userMapper mapper = sqlSession.getMapper(userMapper.class);
Map<String, Object> map = new HashMap<>();
map.put("start",1);
map.put("size", 3);
List<User> userByLimit = mapper.getUserByLimit(map);
for (User user: userByLimit){
System.out.println(user);
}
}
}
Mybatis pagehelper
编写注解,和接口
public interface userMapper {
//查询全部用户
@Select("select * from user")
List<User> getUserList();
//根据ID查询用户
//方法存在多个参数,所有的参数前面必须加上@Param("id")注解
@Select("select * from user where id = #{id}")
User getUserByID(@Param("id") int id);
//insert
@Insert("insert into user values (#{id}, #{name}, #{password})")
int addUser(User user);
//update
@Update("update user set name=#{name}, pwd=#{password} where id=#{id}")
int updateUser(User user);
//delete
@Delete("delete from user where id=#{uid}")
int deleteUser(@Param("uid") int id);
}
必须将接口绑定到注册文件:最好不要用通配符
<mappers>
<mapper class="com.company.dao.userMapper"/>
mappers>
关于@Param( )注解
介绍:
Lombok项目是一个Java库,它会自动插入编辑器和构建工具中,Lombok提供了一组有用的注释,用来消除Java类中的大量样板代码。(getter setter等)
导入依赖:
org.projectlombok
lombok
1.18.22
在实体类上添加注解。
常用注解:
@Data //无参构造, get, set, tostring, hashcode,equals
@AllArgsConstructor //有参构造
@NoArgsConstructor //无参构造
//实体类
public class User {
private int id;
private String name;
private String password;
}
动态SQL:根据不同的条件去拼接SQL,生成不同的SQL语句
动态SQL种类:
if条件前需要添加and 或者or,从而判断多个条件的关系
//if查询
List<Blog> queryBlogIF(Map map);
可以用标签代替where
如果不传入“title”和“author”,那么就查询select * from blog
。
<select id="queryBlogIF" parameterType="map" resultType="Blog">
select * from blog
<where>
<if test="title != null">
and title = #{title}
if>
<if test="author != null">
and author = #{author}
if>
where>
select>
@Test
public void queryBlogIFTest(){
try(SqlSession sqlSession = mybatisUtils.getSqlSession()) {
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
map.put("title", "mybatis");
map.put("author","小李");
List<Blog> blogs = mapper.queryBlogIF(map);
for (Blog b : blogs){
System.out.println(b);
}
}
}
< where > 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。
如果 where 元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:
where语句中可能带前缀prefixOverrides = “and/or”,根据情况去除。
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
trim>
set语句中可能会有后缀suffixOverrides = “,” 根据情况去除。
<trim prefix="SET" suffixOverrides=",">
...
trim>
必须要使用where和set标签才有用
set
<update id="updateBlog" parameterType="Blog">
update Blog
<set>
<if test="title != null">
title = #{title},
if>
<if test="author != null">
author = #{author}
if>
set>
where id = #{id}
update>
有点像 Java 中的 switch 语句,从多个条件中选择一个,条件或的关系
官网例子:传入了 “title” 就按 “title” 查找,传入了 “author” 就按 “author” 查找的情形。若两者都没有传入,就返回标记为 featured 的 BLOG。
switch -> choose
Case ->when
Default ->otherwise
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<choose>
<when test="title != null">
AND title like #{title}
when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
when>
<otherwise>
AND featured = 1
otherwise>
choose>
select>
动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)
Foreach允许你指定一个集合(id表示集合名),声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。
可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。
<select id="queryBlogForeach" parameterType="map" resultType="Blog">
select * from blog
<where>
<foreach collection="ids" item="id" open="(" close=")" separator="or">
id = #{id}
foreach>
where>
select>
这里使用了list
@Test
public void queryBlogForeachTest(){
try(SqlSession sqlSession = mybatisUtils.getSqlSession()) {
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
Map map = new HashMap();
ArrayList<Integer> ids = new ArrayList<>();
ids.add(1);
ids.add(2);
ids.add(3);
map.put("ids", ids);
List<Blog> blogs = mapper.queryBlogForeach(map);
for (Blog b : blogs){
System.out.println(b);
}
}
}
将公共部分放入< sql >内,方便进行复用。使用
引用元素
<sql id="if-select">
<if test="title != null">
and title = #{title}
if>
<if test="author != null">
and author = #{author}
if>
sql>
<select id="queryBlogIF" parameterType="map" resultType="Blog">
select * from blog
<where>
<include refid="if-select">include>
where>
select>
什么是缓存 [ Cache ]?
存在内存中的临时数据。
将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。
为什么使用缓存?
减少和数据库的交互次数,减少系统开销,提高系统效率。
什么样的数据能使用缓存?
经常查询并且不经常改变的数据。
Mybatis缓存
可用的清除策略有:
一级缓存也叫本地缓存:
与数据库同一次会话期间查询到的数据会放在本地缓存中。(sqlSession获得与释放的过程中)
以后如果需要获取相同的数据,直接从缓存中拿,没必须再去查询数据库;
一级缓存默认开启
11.3 二级缓存
步骤:
方式一:
<cache/>
1.什么是序列化和反序列化?
Java序列化是指把Java对象转换为字节序列的过程;Java反序列化是指把字节序列恢复为Java对象的过程;
2. 为什么要序列化?
3.实现序列化
实现序列化的要求:目标对象实现Serializable接口
方式二:
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"/>
查询不同的记录(一级)
增删改操作,可能改变原来的数据,所以会更新缓存(一级)
手动清理缓存(一级)
sqlSession.clearCache();
查询不同的mapper.xml(2级)
先查找二级缓存,再查找一级缓存,都没有就查询数据库