Mybatis学习笔记
Mybatis
一、第一个 Mybatis 程序
1. 创建一个简单的 Maven 项目
2. 导入相关 jar 包
pom.xml
:
<dependencies>
<!-- 导入相关 jar 包 -->
<dependency>
<!-- mybatis jar 包 -->
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<!-- 数据库驱动 jar 包 -->
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>2.7.2</version>
<type>pom</type>
</dependency>
<dependency>
<!-- junit 包,测试使用 -->
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<type>pom</type>
</dependency>
</dependencies>
<!-- 防止 maven 读取不到配置文件 -->
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>
3. 创建 mybatis xml 配置文件
与数据库进行交互
src / main / resources / mybatis-config.xml
<configuration>
<!-- 核心配置文件-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="org.mariadb.jdbc.Driver"/>
<property name="url" value="jdbc:mariadb://localhost:3306/mybatis?useSSL=false&characterEncoding=UTF-8&useUnicode=true"/>
<property name="username" value="root"/>
<property name="password" value="ruirui"/>
</dataSource>
</environment>
</environments>
<!-- 需与 mapper.xml 映射起来-->
<mappers>
<mapper resource="com/nari/mybatis/mapper/MybatisDemoMapper.xml"/>
</mappers>
</configuration>
4. 创建 mapper.xml 文件
可放在任意位置,类必须使用全限定类名
<!-- 命名空间是 mapper 接口 -->
<mapper namespace="com.nari.mybatis.mapper.IMybatisDemoMapper">
<!-- id 是接口中的方法,resultType 是实体类 -->
<select id="findAll" resultType="com.nari.mybatis.pojo.MybatisDemo1Pojo">
select * from mybatisdemo1
</select>
</mapper>
5. 使用 SqlSessionFactoryBuilder 创建 SqlSession 对象
// 创建 builder 对象
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
String mybatisXml = "mybatis-config.xml";
// 通过流读取 mybatis 配置文件
InputStream inputStream = Resources.getResourceAsStream(mybatisXml);
// 通过 builder 得到 SqlSessionFactory 对象,用于创建 SqlSession
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
6. 测试连接
@Test
public void MybatisDemo1Test(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
// 参数是 mapper 接口的类
IMybatisDemoMapper mapper = sqlSession.getMapper(IMybatisDemoMapper.class);
for (MybatisDemo1Pojo mybatisDemo1Pojo : mapper.findAll()){
System.out.println(mybatisDemo1Pojo);
}
sqlSession.close();
}
二、mapper 配置文件详解
1. SELECT 标签
id:对应的 namespace 中的接口方法名
resultType:结果集类型
parameterType:参数类型
2. INSERT 、UPDATE、DELETE 标签
id:对应的 namespace 中的接口方法名
parameterType:参数类型
mapper.xml:
<select id="findAll" resultType="com.nari.mybatis.pojo.MybatisDemo1Pojo">
select * from mybatisdemo1
</select>
<select id="findById" resultType="com.nari.mybatis.pojo.MybatisDemo1Pojo" parameterType="Integer">
select * from mybatisdemo1 where id = #{id}
</select>
<insert id="insertUser" parameterType="com.nari.mybatis.pojo.MybatisDemo1Pojo">
insert into mybatisdemo1 (id, name, age, address) value (#{id}, #{name}, #{age}, #{address})
</insert>
<update id="updateUser" parameterType="com.nari.mybatis.pojo.MybatisDemo1Pojo">
update mybatisdemo1 set name=#{name}, age=#{age}, address=#{address} where id=#{id}
</update>
<delete id="deleteUser" parameterType="int">
delete from mybatisdemo1 where id=#{id}
</delete>
IMybatisMapper:
// 查询所有用户
List<MybatisDemo1Pojo> findAll();
// 通过 ID 查询用户
MybatisDemo1Pojo findById(Integer id);
// 插入
void insertUser(MybatisDemo1Pojo mybatisDemo1Pojo);
// 修改
void updateUser(MybatisDemo1Pojo mybatisDemo1Pojo);
// 删除
void deleteUser(Integer id);
test:
@Test
public void FindAll(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
IMybatisDemoMapper mapper = sqlSession.getMapper(IMybatisDemoMapper.class);
for (MybatisDemo1Pojo mybatisDemo1Pojo : mapper.findAll()){
System.out.println(mybatisDemo1Pojo);
}
sqlSession.close();
}
@Test
public void FindById(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
IMybatisDemoMapper mapper = sqlSession.getMapper(IMybatisDemoMapper.class);
MybatisDemo1Pojo byId = mapper.findById(2);
System.out.println(byId);
sqlSession.close();
}
@Test
public void InsertUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
IMybatisDemoMapper mapper = sqlSession.getMapper(IMybatisDemoMapper.class);
mapper.insertUser(new MybatisDemo1Pojo(null, "王五", 32, "太原"));
sqlSession.commit();
sqlSession.close();
}
@Test
public void UpdateUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
IMybatisDemoMapper mapper = sqlSession.getMapper(IMybatisDemoMapper.class);
mapper.updateUser(new MybatisDemo1Pojo(2, "孙六", 33, "运城"));
sqlSession.commit();
sqlSession.close();
}
@Test
public void DeleteUser(){
SqlSession sqlSession = MybatisUtils.getSqlSession();
IMybatisDemoMapper mapper = sqlSession.getMapper(IMybatisDemoMapper.class);
mapper.deleteUser(3);
sqlSession.commit();
sqlSession.close();
}
注意点:
1. 除了 SELECT 有结果集类型,其它没有结果集类型
2. 除了查询外,增删改完成后,需要提交事务,否则数据不会更新
三、万能的 map
- 如果数据库中的字段很多,我们在插入或更新数据库数据的时候,如果是使用实体类当参数,就要填入很多的参数,而且有的参数我们是用不到的,比如下面这个 insert 语句:
<insert id="insertUser" parameterType="com.nari.mybatis.pojo.MybatisDemo1Pojo">
insert into mybatisdemo1 (id, name, age, address) value (#{id}, #{name}, #{age}, #{address})
</insert>
如果我们只想插入 name、address 字段,我们也需要把实体类所有的字段都填上,而且名字还得和实体类中的一样,因为实体类中只有无参和全参构造,否则只能在实体类中在添加一个只有 name 和 address 的有参构造,这样的话就不太灵活,如果要解决这个问题,我们就可以使用 map,接口方法的参数为 map,mapper 映射文件中的类型也是 map,这样我们就可以只传入 name 和 address 了,而且名字也可以自定义,如下:
接口方法:
public interface IMybatisDemoMapper {
public void insertUser(HashMap user);
}
mapper 映射文件:
<insert id="insertUser" parameterType="map">
insert into mybatisdemo1 (name,age,address) values (#{userName}, #{userAge}, #{userAddress})
</insert>
test 方法中:
@Test
public void insertUsers(){
SqlSession sqlSession = MybatisDemoUtils.getSqlSession();
IMybatisDemoMapper mapper = sqlSession.getMapper(IMybatisDemoMapper.class);
HashMap map = new HashMap();
map.put("userName", "孙六");
map.put("userAge", 33);
map.put("userAddress", "广东");
mapper.insertUser(map);
sqlSession.commit();
sqlSession.close();
}
四、配置文件解析
核心配置文件
mybatis-config.xml
1. properties(属性)
2. settings(设置)
3. typeAliases(类型别名)
4. typeHandlers(类型处理器)
5. objectFactory(对象工厂)
6. plugins(插件)
7. environments(环境配置)
8. environment(环境变量)
9. transactionManager(事务管理器)
10. dataSource(数据源)
11. databaseIdProvider(数据库厂商标识)
12. mappers(映射器)
a)environments:环境配置
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="org.mariadb.jdbc.Driver"/>
<property name="url" value="jdbc:mariadb://localhost:3306/mybatis?useSSL=false&characterEncoding=UTF-8&useUnicode=true"/>
<property name="username" value="root"/>
<property name="password" value="ruirui"/>
</dataSource>
</environment>
<environment id="oracle">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="org.mariadb.jdbc.Driver"/>
<property name="url" value="jdbc:mariadb://localhost:3306/mybatis?useSSL=false&characterEncoding=UTF-8&useUnicode=true"/>
<property name="username" value="root"/>
<property name="password" value="ruirui"/>
</dataSource>
</environment>
</environments>
上面就是环境的配置,即可以在里面配置多套不同的数据库或者不同的应用环境(生产 or 测试)
b)transactionManager:事务管理
默认是 JDBC,还有一个 MANAGED,但是这个一般不用,只有在老的项目才会有用,如:EJB。。
c)dataSource:数据源
默认是 POOLED,还有 UNPOOLED、JNDI
POOLED:数据源连接池,每次用完都会把连接放回到池里,而不是关闭,以供下次使用
UNPOOLED:非池,每次都会创建和关闭连接
JNDI:正常的数据源
d)mappers:映射器
用于告诉 mybatis 哪里可以找到 sql 语句,可以通过四种方式定位资源,一般使用第一种
<mappers>
<!-- 方式一:类路径 -->
<mapper resource="com/nari/mybatismapper/IMybatisDemoMapper.xml"></mapper>
<!-- 方式二:文件绝对路径 -->
<mapper url="file:///var/mappers/AuthorMapper.xml"></mapper>
<!-- 方式三:接口实现类的完全限定类名 -->
<mapper class="com.nari.mybatismapper.IMybatisDemoMapper"></mapper>
<!-- 方式四:将包内的映射器接口实现全部注册为映射器 -->
<mapper name="com.nari.mybatismapper"></mapper>
</mappers>
注意点:
- 推荐使用方式一
- 极不推荐使用方式二
- 使用方式三和方式四,mapper 映射文件必须和类同名,且必须在同一个包下
e)properties:属性
<!-- 两种方式配置 -->
<!-- 方式一,引入外部属性 -->
<properties resource="db.properties"/>
src / main / resources / db.properties:
url=jdbc:mariadb://localhost:3306/mybatis?useSSL=false&characterEncoding=UTF-8&useUnicode=true
driver=org.mariadb.jdbc.Driver
username=root
password=ruirui
<!-- 方式二,内部标签写属性 -->
<properties>
<property name="username" value="root"/>
<property name="password" value="ruirui"/>
</properties>
然后在 mybatis-config.xml 中配置:
把属性以 ${ } 的方式引入外部变量
<environments default="development">
<environment id="development">
<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>
</environments>
两种方式的优先级:
- 优先使用外部的配置文件内容
f)typeAliases :类型别名
为 javaBean 对象起别名,用来代替 mapper.xml 文件中的全限定类名
两种方式:
方式一:为具体的实体类起别名
<typeAliases>
<typeAlias type="com.nari.mybatisPojo.User" alias="User"/>
<typeAlias type="com.nari.mybatisPojo.Admin" alias="Admin"/>
</typeAliases>
方式二:扫描整个包下的实体类
<typeAliases>
<package name="com.nari.mybatisPojo"/>
</typeAliases>
二者区别:
- 为具体的类起别名,可以自定义别名,而扫描整个包的话,不可以自定义别名
- 建议具体的类别名为首字母大写,扫描包的别名首字母小写,作为区分
- 可以用注解的方式为扫描包的实体类自定义别名,如下:
@Alias("Admin")
public class MybatisDemoEntry {...}
- 二者没有优先级问题,都可以使用
- 如果实体类比较少的话,推荐使用方式一,如果实体类比较多的话,就扫描整个包,然后用注解
mybatis 中的默认别名:
-
_int int
-
int Intrger
-
map Map
-
hashmap HashMap
-
list List
总结就是:
- 如果想使用基本类型,就在基本类型前加下划线 _
- 如果使用包装类,就使用小写的基本类型
g)settings:设置
mybatis 的设置,该设置会直接影响 mybatis 的运行时行为,需记住以下几个即可:
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="logImpl" value="LOG4J"/>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
cacheEnabled:是否开启映射器配置文件中已配置的缓存
lazyLoadingEnabled:延迟加载的全局开关
logImpl:指定 MyBatis 所用日志的具体实现,未指定时将自动查找,其值有:SLF4J、LOG4J、LOG4J2、JDK_LOGGING、COMMONS_LOGGING、STDOUT_LOGGING、NO_LOGGING
- LOG4J(需引入 jar 包)
- STDOUT_LOGGING(不需要配置任何东西就可以使用)
mapUnderscoreToCamelCase:是否开启驼峰命名自动映射,即从经典数据库列名 user_name 映射到经典 Java 属性名 userName
h)其它配置
plugins:插件
常用插件:
- mybatis-generator-core
- mybatis-plus
- 通用 mapper
五、生命周期和作用域
生命周期和作用域极其重要,因为错误的使用会导致很严重的并发问题
SqlSessionFactoryBuilder:
- 一旦创建就不需要了,所以最佳作用域是方法作用域(局部方法变量)
- 可以使用它创建多个 SqlSessionFactory
SqlSessionFactory:
- 最佳作用域是整个应用的的作用域,即 applicationScope
- 使用单例模式
- 应用存活期间,只保留一份即可
SqlSession:
- 每个线程都应该有自己的 SqlSession
- 不是线程安全的,所以不能被共享,否则会有并发问题
- 最好放到每个方法中,用完即关闭
- 关闭操作最好是放到 finally 块中,以保证数据库资源能被正确的关闭
六、ResultMap结果集映射
将数据库中的字段与实体类属性映射起来
<resultMap id="userResultMap" type="user">
<id property="id" column="id"></id>
<result property="userAge" column="age"/>
<result property="userName" column="name"/>
<result property="userAddress" column="address"/>
</resultMap>
<select id="findById" resultMap="userResultMap" parameterType="int">
select * from mybatisdemo1 where id = #{id}
</select>
id:可自定义,需要与 select 标签中的一致
type:实体类,可用别名代替
property:实体类中的属性名
column:数据库中的字段名
需注意:
- resultMap 标签中的 id 标签,必须与数据库中的主键字段一致,否则报错
- resultMap 可以代替 resultType,写上 resultMap 后,就无需在写 resultType 了
七、Log4j简单使用
1、导入依赖
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
2、mybatis 核心配置文件
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>
3、log4j 配置文件
#设置日志级别,以及输出位置
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/mybatis.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
4、基本使用
// 创建日志对象,导的包是 log4j
Logger logger = Logger.getLogger(UserTest.class);
// 输出信息
logger.info("[INFO]:进入了 INFO 信息");
logger.debug("[DEBUG]:进入了 DEBUG 信息");
logger.error("[ERROR]:进入了 ERROR 信息");
八、分页
九、多对一查询
两种方式:
- 连接查询方式(推荐)
<select id="getStudents" resultMap="StudentsTeachers">
select
s.id sid, s.name sname, t.name tname
from
student s
right join
teacher t
on
s.tid = t.id;
</select>
<resultMap id="StudentsTeachers" type="Students">
<id property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teachers" javaType="Teachers">
<result property="name" column="tname"/>
</association>
</resultMap>
- 子查询(嵌套查询)方式
<select id="getStudents1" resultMap="StudentsTeachers1">
select * from student;
</select>
<resultMap id="StudentsTeachers1" type="Students">
<association property="teachers" column="tid" javaType="Teachers" select="getTeachers"/>
</resultMap>
<select id="getTeachers" resultType="Teachers">
select * from teacher where id=#{tid};
</select>
注意点:
- 多对一查询,使用 association 标签关联实体类中的对象
- javaType 是实体类中对象的 java 类型
- 如果使用了别名,需要让实体类中的类型和别名映射起来,别名是数据库层面的
- 如果使用嵌套查询方式,#{tid} 中的 tid 可以随便写变量,mybatis 会自动与数据库中的 id 映射起来
- 使用嵌套查询方式,SQL 中必须写上 where 条件,否则报结果集过多的错,相当于是两个表的关联条件
十、一对多查询
<select id="getTeachers" resultMap="TeacherStudent">
select t.id tid, t.name tname, s.id sid, s.name sname from teacher t left join student s on t.id=s.tid where t.id=${tid}
</select>
<resultMap id="TeacherStudent" type="teacher">
<id property="id" column="tid"/>
<result property="name" column="sname"/>
<collection property="students" ofType="student" javaType="ArrayList">
<id property="id" column="sid"/>
<result property="name" column="sname"/>
</collection>
</resultMap>
public void getTeachers(){
try(SqlSession sqlSession = MybatisUtils.getSqlSession();) {
// 两种方式实现查询
// ITeachersMapper mapper = sqlSession.getMapper(ITeachersMapper.class);
// Teachers teachers = mapper.getTeachers(1);
// System.out.println(teachers);
val students = sqlSession.selectOne("com.nariit.mybatisdemo.mapper.ITeachersMapper.getTeachers", 1);
System.out.println(students);
}
}
resultMap属性解释:
- type:实体类的别名,或者全限定名称
- collection:一对多的表嵌套方式
- property:需要映射的对象属性名
- ofType:范型的类型
- javaType:复杂属性的类型
十一、动态SQL
if:
<select id="selectBlogIf" parameterType="map" resultType="BlogPojo">
select * from blog
<where>
<if test="title != null">
title like #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
<if test="views != null">
and views > #{views}
</if>
</where>
</select>
java:
public void SelectBlogIf(){
try (SqlSession sqlSession = MybatisUtils.getSqlSession();){
IBlogMapper mapper = sqlSession.getMapper(IBlogMapper.class);
HashMap map = new HashMap();
map.put("title","%spring%");
map.put("views",9000);
List<BlogPojo> blogPojo = mapper.selectBlogIf(map);
for (BlogPojo pojo : blogPojo) {
System.out.println(pojo);
}
}catch (Exception e){
e.printStackTrace();
}
}
choose、when:
<select id="selectBlogChoose" resultType="BlogPojo" parameterType="map">
select * from blog
<where>
<choose>
<when test="title != null">
title like #{title}
</when>
<when test="author != null">
and author = #{author}
</when>
<otherwise>
and views > #{views}
</otherwise>
</choose>
</where>
</select>
java:
public void SelectBlogChoose(){
try (SqlSession sqlSession = MybatisUtils.getSqlSession();){
IBlogMapper mapper = sqlSession.getMapper(IBlogMapper.class);
HashMap map = new HashMap();
//map.put("title","%spring%");
map.put("author","很简单1");
map.put("views",2000);
List<BlogPojo> blogPojos = mapper.selectBlogChoose(map);
for (BlogPojo blogPojo : blogPojos) {
System.out.println(blogPojo);
}
}catch (Exception e){
e.printStackTrace();
}
}
set:
<update id="updateBlogSet" parameterType="map">
update blog
<set>
<if test="title != null">
title = #{title},
</if>
<if test="author != null">
author = #{author}
</if>
</set>
<where>
id = #{id}
</where>
</update>
java:
public void UpdateBlogSet(){
try (SqlSession sqlSession = MybatisUtils.getSqlSession();){
IBlogMapper mapper = sqlSession.getMapper(IBlogMapper.class);
HashMap map = new HashMap();
map.put("title","spring不应该这样学");
map.put("author","不简单");
map.put("id","baa23393d6c44c7e8e1dd233e08b84a5");
mapper.updateBlogSet(map);
sqlSession.commit();
}catch (Exception e){
e.printStackTrace();
}
}
foreach:
<select id="queryBlogForeach" parameterType="map" resultType="BlogPojo">
select * from blog
<where>
id in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</where>
</select>
java:
public void QueryBlogForeach(){
try (SqlSession sqlSession = MybatisUtils.getSqlSession();){
IBlogMapper mapper = sqlSession.getMapper(IBlogMapper.class);
HashMap map = new HashMap();
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
map.put("ids",list);
List<BlogPojo> blogPojos = mapper.queryBlogForeach(map);
for (BlogPojo blogPojo : blogPojos) {
System.out.println(blogPojo);
}
}catch (Exception e){
e.printStackTrace();
}
}
注意点:
- collection 里的值需与 java 里的 map 值对应
十二、缓存机制
1、一级缓存:
SqlSession 级别的缓存,即只在 SqlSession 有效期的缓存,当 SqlSession 对象关闭或被释放,缓存就会失效
mybatis 默认是开启一级缓存的。
2、二级缓存:
NameSpace 级别的缓存,就是每个 mapper.xml 的作用域
当 SqlSession 对象被关闭或释放,即一级缓存失效,如果此时开启了二级缓存,mybatis 就会把数据放到二级缓存中。
优先级:
当用户查询数据时,mybatis 会优先读取二级缓存中的数据,如果二级缓存中没有想要的数据,会去一级缓存中查找,如果一级缓存中还没有该数据,才会去连接数据库查询。
开启二级缓存:
只用在 mapper.xml 文件最前面添加 标签即可
<mapper namespace="com.nariit.mybatisdemo.mapper.IBlogMapper">
<!-- 开启二级缓存 -->
<cache/>
<insert id="addBlog" parameterType="BlogPojo">
insert into blog (id, title, author, create_time, views) values (#{id}, #{title}, #{author}, #{createTime}, #{views})
</insert>
<select id="selectBlogIf" parameterType="map" resultType="BlogPojo">
select * from blog
<where>
<if test="title != null">
title like #{title}
</if>
<if test="author != null">
and author = #{author}
</if>
<if test="views != null">
and views > #{views}
</if>
</where>
</select>
</mapper>
也可以自定义一些二级缓存的参数:
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
这个更高级的配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。
可用的清除策略有:
LRU – 最近最少使用:移除最长时间不被使用的对象。
FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。
WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。
默认的清除策略是 LRU。
或者使用自定义的缓存:
<cache type="com.domain.something.MyCustomCache"/>
一般的自定义的缓存:
Ehcache、memcache
使用第三方的缓存,需要 maven 导入 jar 包。