[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MInA7Ng1-1620752631550)(assets/mybatis-logo.png)]
1.入门
安装
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>x.x.x</version>
</dependency>
使用 Maven 来构建项目,则需将下面的依赖代码置于 pom.xml 文件中:
SqlSessionFactory
<?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>
<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="xxxx"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="com/xue/dao/UserMapper.xml"/>
</mappers>
</configuration>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eQHBKtqj-1620752631552)(assets/image-20210509213949655.png)]
注意文件的配置
获取 SqlSessionFactory
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
探究已映射的 SQL 语句
<?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">
<mapper namespace="com.xue.dao.UserMapper">
<select id="getUserList" resultType="com.xue.pojo.User">
select *
from mybatis.user
</select>
</mapper>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m9GIZWGB-1620752631554)(assets/image-20210509214223736.png)]
2.CRUD
命名空间
全限定名(比如 “com.mypackage.MyMapper.selectAllThings)将被直接用于查找及使用。
XML内的配置
查询
<select id="getUserList" resultType="com.xue.pojo.User">
select *
from mybatis.user
</select>
<select id="getUserById" parameterType="int" resultType="com.xue.pojo.User">
select *
from mybatis.user
where id = #{id}
</select>
增加
<insert id="addUser" parameterType="com.xue.pojo.User" >
insert into mybatis.user(id, name, password)
value (#{id}, #{name}, #{password})
</insert>
修改
<update id="updateUser" parameterType="com.xue.pojo.User">
update mybatis.user
set name=#{name},
password=#{password}
where id = #{id}
</update>
删除
<delete id="deleteUser" parameterType="int">
delete
from mybatis.user
where id = #{id}
</delete>
测试代码
查询
@Test
public void test() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
try {
//获取dao
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.getUserList();
for (User user : userList) {
System.out.println(user);
}
} finally {
sqlSession.clearCache();
}
}
@Test
public void test2() {
//获取一个连接
SqlSession sqlSession = MybatisUtils.getSqlSession();
try {
//我猜是利用反射来获取 操作方法
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User userById = mapper.getUserById(1);
System.out.println(userById);
} finally {
sqlSession.close();
}
}
增删改
@Test
public void test3() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
try {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
int xue3 = mapper.addUser(new User(1234, "xue3", "123"));
System.out.println(xue3);
sqlSession.commit();
} finally {
sqlSession.rollback();
sqlSession.close();
}
}
通过map来操作
类似于把map内的键和值 直接放了进去
因为之前是用user 如果我们传递一个user进去 类似于传递进去了一个map 我的假设是他穿进去了一个dao层然后呢 利用get来获取到了变量的具体的值 然后变成了map
也可以是我传进去了一个user 然后呢 我利用反射来获取user里的get方法 我岂不是不用map
这都是假设,后面需要从源码来进行分析
这里的
#{userid}, #{username}, #{userpassword}
可以随意的控制 只需要在map传递的时候控制好map即可
<insert id="addUser2" parameterType="map" >
insert into mybatis.user(id, name, password)
value (#{userid}, #{username}, #{userpassword})
</insert>
这个是测试方法
@Test
public void test5() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
try {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
HashMap<String, Object> map = new HashMap<>();
map.put("userid",123);
map.put("username","xue6");
map.put("userpassword","xue6");
int xue3 = mapper.addUser2(map);
System.out.println(xue3);
sqlSession.commit();
} finally {
sqlSession.rollback();
sqlSession.close();
}
}
模糊查询
<select id="getUserLike" resultType="com.xue.pojo.User">
select *
from mybatis.user
where name like #{value}
</select>
其中访问的时候可以是
@Test
public void test11() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
try {
//获取dao
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = mapper.getUserLike("xue%");
for (User user : userList) {
System.out.println(user);
}
} finally {
sqlSession.clearCache();
}
}
3.配置信息*
核心配置
mybatis-config.xml(官方推荐的命名)
configuration(配置)
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- environment(环境变量)
- databaseIdProvider(数据库厂商标识)
- mappers(映射器)
属性(properties)
这些属性可以在外部进行配置,并可以进行动态替换。你既可以在典型的 Java 属性文件中配置这些属性,也可以在 properties 元素的子元素中设置。可以指定一个文件
<properties resource="org/mybatis/example/config.properties">
<property name="username" value="dev_user"/>
<property name="password" value="F2Fa3!33TYyg"/>
</properties>
编写一个 db.properties文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8
username=root
password=xxx
在配置中引入
<properties resource="db.properties">
</properties>
环境配置(environments)
默认设置
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
.....
</dataSource>
设置(settings)
这是 MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为。 下表描述了设置中各项设置的含义、默认值等。、
设置名 | 描述 | 有效值 | 默认值 |
---|---|---|---|
cacheEnabled | 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存。 | true | false | true |
lazyLoadingEnabled | 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。 | true | false | false |
类型别名(typeAliases)
类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如:
<typeAliases>
<typeAlias alias="Author" type="domain.blog.Author"/>
<typeAlias alias="Blog" type="domain.blog.Blog"/>
<typeAlias alias="Comment" type="domain.blog.Comment"/>
<typeAlias alias="Post" type="domain.blog.Post"/>
<typeAlias alias="Section" type="domain.blog.Section"/>
<typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>
<package name="com.xue.pojo"/>
每一个在包 domain.blog
中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 domain.blog.Author
的别名为 author
;若有注解,则别名为其注解值。见下面的例子:
@Alias("author")
public class Author {
...
}
插件(plugins)
映射器(mappers)
既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 file:///
形式的 URL),或类名和包名等。例如:
任何地方都可以用的方法
<!-- 使用相对于类路径的资源引用 -->
<mappers>
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
</mappers>
必须要mapper和xml同名 且在一个目录下
<!-- 使用映射器接口实现类的完全限定类名 -->
<mappers>
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
</mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 -->
<mappers>
<package name="org.mybatis.builder"/>
</mappers>
这些配置会告诉 MyBatis 去哪里找映射文件,剩下的细节就应该是每个 SQL 映射文件了,也就是接下来我们要讨论的。
4.生命周期
SqlSessionFactoryBuilder
- 这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。
- 局部变量
SqlSessionFactory
- SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。
- SqlSessionFactory 的最佳作用域是应用作用域
SqlSession
- 每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
- 为了确保每次都能执行关闭操作,你应该把这个关闭操作
5.resultMap
-
当数据库和pojo的类型不一样时,我们可以使用别名来进行操作
-
使用结果集来映射
resultMap
元素是 MyBatis 中最重要最强大的元素。它可以让你从 90% 的 JDBC ResultSets
数据提取代码中解放出来,并在一些情形下允许你进行一些 JDBC 不支持的操作。实际上,在为一些比如连接的复杂语句编写映射代码的时候,一份 resultMap
能够代替实现同等功能的数千行代码。ResultMap 的设计思想是,对简单的语句做到零配置,对于复杂一点的语句,只需要描述语句之间的关系就行了。
在学习了上面的知识后,你会发现上面的例子没有一个需要显式配置 ResultMap
,这就是 ResultMap
的优秀之处——你完全可以不用显式地配置它们。 虽然上面的例子不用显式配置 ResultMap
。 但为了讲解,我们来看看如果在刚刚的示例中,显式使用外部的 resultMap
会怎样,这也是解决列名不匹配的另外一种方式。
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id" />
<result property="username" column="user_name"/>
<result property="password" column="hashed_password"/>
</resultMap>
然后在引用它的语句中设置 resultMap
属性就行了(注意我们去掉了 resultType
属性)。比如:
<select id="selectUsers" resultMap="userResultMap">
select user_id, user_name, hashed_password
from some_table
where id = #{id}
</select>
世界要是总是这么简单就行了
对于复杂的
6.日志工厂
日志工程的配置,注意name不能变,后面的value都是固定的
<configuration>
<settings>
...
<setting name="logImpl" value="LOG4J"/>
...
</settings>
</configuration>
可选的值有:
SLF4J
LOG4J
LOG4J2
JDK_LOGGING
COMMONS_LOGGING
STDOUT_LOGGING(直接设置就行了)
NO_LOGGING
或者是实现了 org.apache.ibatis.logging.Log
接口,且构造方法以字符串为参数的类完全限定名。
关于 log4j配置
1.导包
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
2.在CLASSPATH下建立log4j.properties
配置内容参考
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file
#控制台输出的相关设置
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.Target = System.out
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/xueBatis.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
3.将log4j实现
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
4.简单的使用
切记导
import org.apache.log4j.Logger;
这个包 声明一个变量
//加载一个日志对象
static Logger logger = Logger.getLogger(UserDaoTest.class);
@Test
public void LogTest() {
//日志工程的测试实现
logger.info("info:进入了级别");
logger.debug("debug");
logger.error("error");
}
7.分页
1.使用limit分页 Map实现
select * from user limit 1,5
接口
List<User> getUserByLimit(Map<String,Integer> map);
实现
<resultMap id="UserMap" type="User">
<result column="id" property="id"/>
<result column="name" property="name"/>
<result column="password" property="pwd"/>
</resultMap>
<select id="getUserByLimit" parameterType="map" resultMap="UserMap">
select *
from user
limit #{startIndex},#{endIndex}
</select>
测试
@Test
public void getUserByLimit() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
try {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String, Integer> map = new HashMap<>();
map.put("startIndex", 1);
map.put("endIndex", 3);
List<User> userByLimit = mapper.getUserByLimit(map);
userByLimit.forEach(System.out::println);
} finally {
sqlSession.close();
}
}
2.使用RowBounds(老东西)
接口
List<User> getUserByRowBounds();
实现
select id="getUserByRowBounds" resultMap="UserMap">
select *
from user
</select>
测试
@Test
public void getUserByRowBounds() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
try {
//通过java代码
//RowBounds
RowBounds rowBounds = new RowBounds(1, 1);
List<User> userByLimit = sqlSession.selectList("com.xue.dao.UserMapper.getUserByRowBounds",null,rowBounds);
userByLimit.forEach(System.out::println);
} finally {
sqlSession.close();
}
}
3.分页插件*
MyBatis 分页插件 PageHelper
8.注解开发
面向接口编程
面向接口编程 可以降低耦合度
选择
@Select("select * from user")
List<User> getUserListByAn();
带参数的
@Select("select * from User where name =#{name}")
List<User> getUserListByName(@Param("name") String name);
@Param()注解 **
- 基本的参数要加上
- 引用不用加
- 如果有一个可以 忽略 但是建议加
9.Lombok(不建议使用)
在maven里添加
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>provided</scope>
</dependency>
@Data
@AllArgsConstructor
@NoArgsConstructor
10.多对一
1.嵌套查询
<select id="getStudentAndTeacher" resultMap="StudentJoinTeacher">
select *
from student
</select>
<resultMap id="StudentJoinTeacher" type="com.xue.pojo.Student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<association property="teacher" javaType="Teacher" select="com.xue.dao.TeacherMapper.getTeacher" column="tid"/>
</resultMap>
2.Join查询
<resultMap id="StudentJoinTeacher" type="com.xue.pojo.Student">
<result property="id" column="id"/>
<result property="name" column="name"/>
<association property="teacher" javaType="Teacher">
<result property="id" column="id"/>
<result property="name" column="name"/>
</association>
</resultMap>
<select id="getStudentAndTeacher" resultMap="StudentJoinTeacher">
select *
from student
join teacher t on t.id = student.tid
</select>
11 一对多 (集合)
<resultMap id="TeacherStudent2" type="Teacher">
<result property="id" column="tid"/>
<result property="name" column="tname"/>
<collection property="students" javaType="ArrayList" ofType="Student">
<result property="id" column="sid"/>
<result property="name" column="sid"/>
</collection>
</resultMap>
<select id="getTeacherAndStudent" resultMap="TeacherStudent2">
select teacher.id as tid,
teacher.name as tname,
s.id as sid,
s.name as snaem,
s.tid as sstid
from teacher
join student s on teacher.id = s.tid
where tid = #{id}
</select>
Mysql 引擎
InnoDB底层引擎
索引
索引优化
12 动态SQL
动态sql就是根据不同的条件生成sql语句
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
数据库环境
CREATE TABLE `blog`(
`id` VARCHAR(50) NOT NULL COMMENT "博客id",
`title` VARCHAR(100) NOT NULL COMMENT "博客标题",
`author` VARCHAR(30) NOT NULL COMMENT "博客作者",
`create_time` DATETIME NOT NULL COMMENT "创建时间",
`views` INT(30) NOT NULL COMMENT "浏览量"
)
pojo
@Data
public class Blog {
private int id;
private String title;
private String author;
private Date createTime;
private int views;
}
IF
<select id="queryBlog" resultType="Blog" parameterType="map">
select *
from blog
<where>
<if test="{title != null}">
and title=#{title}
</if>
<if test="{title != null}">
and title=#{title}
</if>
</where>
</select>
TEST
@Test
public void test2() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
HashMap<String, Object> map = new HashMap<>();
//map.put("title", "xx");
List<Blog> blogs = mapper.queryBlog(map);
blogs.forEach(System.out::println);
}
完美的复用了Map
choose
有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
还是上面的例子,但是策略变为:传入了 “title” 就按 “title” 查找,传入了 “author” 就按 “author” 查找的情形。若两者都没有传入,就返回标记为 featured 的 BLOG(这可能是管理员认为,与其返回大量的无意义随机 Blog,还不如返回一些由管理员精选的 Blog)。
<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>
SET
where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。
如果 where 元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:
<trim prefix="WHERE" prefixOverrides="AND |OR ">
...
</trim>
prefixOverrides 属性会忽略通过管道符分隔的文本序列(注意此例中的空格是必要的)。上述例子会移除所有 prefixOverrides 属性中指定的内容,并且插入 prefix 属性中指定的内容。
用于动态更新语句的类似解决方案叫做 set。set 元素可以用于动态包含需要更新的列,忽略其它不更新的列。比如:
<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>
这个例子中,set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)。
来看看与 set 元素等价的自定义 trim 元素吧:
<trim prefix="SET" suffixOverrides=",">
...
</trim>
注意,我们覆盖了后缀值设置,并且自定义了前缀值。
foreach
动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)。比如:
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</select>
foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符,看它多智能!
提示 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。
至此,我们已经完成了与 XML 配置及映射文件相关的讨论。下一章将详细探讨 Java API,以便你能充分利用已经创建的映射配置。
13 缓存
Redis
Memcache
nginx
主从复制
Mybatis 使用到了两种缓存:本地缓存(local cache)和二级缓存(second level cache)。
每当一个新 session 被创建,MyBatis 就会创建一个与之相关联的本地缓存。任何在 session 执行过的查询结果都会被保存在本地缓存中,所以,当再次执行参数相同的相同查询时,就不需要实际查询数据库了。本地缓存将会在做出修改、事务提交或回滚,以及关闭 session 时清空。
默认情况下,本地缓存数据的生命周期等同于整个 session 的周期。由于缓存会被用来解决循环引用问题和加快重复嵌套查询的速度,所以无法将其完全禁用。但是你可以通过设置 localCacheScope=STATEMENT 来只在语句执行时使用缓存。
注意,如果 localCacheScope 被设置为 SESSION,对于某个对象,MyBatis 将返回在本地缓存中唯一对象的引用。对返回的对象(例如 list)做出的任何修改将会影响本地缓存的内容,进而将会影响到在本次 session 中从缓存返回的值。因此,不要对 MyBatis 所返回的对象作出更改,以防后患。
一级缓存
一级缓存也叫本地缓存,MyBatis 的一级缓存是在会话(SqlSession)层面进行缓存的。MyBatis 的一级缓存是默认开启的,不需要任何的配置。会话(SqlSession)层面进行缓存的
你可以随时调用以下方法来清空本地缓存:
void clearCache()
确保 SqlSession 被关闭
void close()
缓存失效情况:
- 映射语句文件中的所有 select 语句的结果将会被缓存。
- 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
- 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
- 缓存不会定时进行刷新(也就是说,没有刷新间隔)。
- 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。
- 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
二级缓存
二级缓存是用来解决一级缓存不能跨会话共享的问题的,范围是namespace 级别的,可以被多个SqlSession 共享(只要是同一个接口里面的相同方法,都可以共享),生命周期和应用同步。如果你的MyBatis使用了二级缓存,并且你的Mapper和select语句也配置使用了二级缓存,那么在执行select查询的时候,MyBatis会先从二级缓存中取输入,其次才是一级缓存,即MyBatis查询数据的顺序是:二级缓存 —> 一级缓存 —> 数据库。
第一步:配置 mybatis.configuration.cache-enabled=true,只要没有显式地设置cacheEnabled=false,都会用CachingExecutor 装饰基本的执行器。
<settings>
<setting name="logImpl" value="LOG4J"/>
<setting name="cacheEnabled" value="true"/>
</settings>
第二步:在Mapper.xml 中配置标签:
<cache
size="1024"
eviction="LRU"
flushInterval="120000"
readOnly="false"/>
这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。可用的清除策略有:
LRU
– 最近最少使用:移除最长时间不被使用的对象。FIFO
– 先进先出:按对象进入缓存的顺序来移除它们。SOFT
– 软引用:基于垃圾回收器状态和软引用规则移除对象。WEAK
– 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。
默认的清除策略是 LRU。
缓存的原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bp8INice-1620752631557)(assets/1383365-20190628180149776-546074458.png)]
自定义缓存 ehcache
1.导入Maven
<!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache -->
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.2.1</version>
</dependency>
顺序是:二级缓存 —> 一级缓存 —> 数据库。
第一步:配置 mybatis.configuration.cache-enabled=true,只要没有显式地设置cacheEnabled=false,都会用CachingExecutor 装饰基本的执行器。
<settings>
<setting name="logImpl" value="LOG4J"/>
<setting name="cacheEnabled" value="true"/>
</settings>
第二步:在Mapper.xml 中配置标签:
<cache
size="1024"
eviction="LRU"
flushInterval="120000"
readOnly="false"/>
这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。可用的清除策略有:
LRU
– 最近最少使用:移除最长时间不被使用的对象。FIFO
– 先进先出:按对象进入缓存的顺序来移除它们。SOFT
– 软引用:基于垃圾回收器状态和软引用规则移除对象。WEAK
– 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。
默认的清除策略是 LRU。
缓存的原理
[外链图片转存中…(img-Bp8INice-1620752631557)]
自定义缓存 ehcache
1.导入Maven
<!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache -->
<dependency>
<groupId>org.mybatis.caches</groupId>
<artifactId>mybatis-ehcache</artifactId>
<version>1.2.1</version>
</dependency>