石一歌的Mybatis笔记

mybatis

mybatis-demo

  1. pom.xml添加依赖

    	    <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.2</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis-spring</artifactId>
                <version>2.0.2</version>
            </dependency>
    
  2. 资源文件夹创建核心配置文件mybatise-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核心配置文件-->
    <configuration>
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/mybatis?userSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC"/>
                    <property name="username" value="root"/>
                    <property name="password" value="root"/>
                </dataSource>
            </environment>
        </environments>
    </configuration>
    
  3. 编写工具类

    //sqlSessionFactory --> sqlSession
    public class MybatisUtils {
    
        static SqlSessionFactory sqlSessionFactory = null;
    
        static {
            try {
                //使用Mybatis第一步 :获取sqlSessionFactory对象
                String resource = "mybatis-config.xml";
                InputStream inputStream = Resources.getResourceAsStream(resource);
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        //既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例.
        // SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。
        public static SqlSession getSqlSession(){
            return sqlSessionFactory.openSession();
        }
    }
    
  4. 代码调用

    Dao

    public interface UserDao {
        public List<User> getUserList();
    }
    

    实现类变为Mapper.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=绑定一个指定的Dao/Mapper接口-->
    <mapper namespace="com.kuang.dao.UserDao">
        <select id="getUserList" resultType="com.kuang.pojo.User">
        select * from USER
      </select>
    </mapper>
    
  5. 测试

     @Test
        public void test(){
    
            //1.获取SqlSession对象
            SqlSession sqlSession = MybatisUtils.getSqlSession();
            //2.执行SQL
            // 方式一:getMapper
            UserDao userDao = sqlSession.getMapper(UserDao.class);
            List<User> userList = userDao.getUserList();
            for (User user : userList) {
                System.out.println(user);
            }
    
            //关闭sqlSession
            sqlSession.close();
        }
    

mapper

  1. namespace

    namespace中的包名要和Dao/Mapper接口的包名一致

  2. select

​ id:就是对应的namespace中的方法名;
​ resultType : Sql语句执行的返回值;
​ parameterType : 参数类型;
注意:增删改一定要提交事务:
​ sqlSession.commit();

  1. 万能Map

    假设,我们的实体类,或者数据库中的表,字段或者参数过多,我们应该考虑使用Map!

    Map传递参数,#{ }直接在sql中取出key即可! 【parameter=“map”】
    对象传递参数,#{ }直接在sql中取出对象的属性即可! 【parameter=“Object”】

  2. 模糊查询

    Java代码执行的时候,传递通配符% %

	List<User> userList = mapper.getUserLike("%李%");

​ 在sql拼接中使用通配符

	select * from user where name like "%"#{value}"%";

mybatise-config

可配置项

	configuration(配置)
    properties(属性)
    settings(设置)
    typeAliases(类型别名)
    typeHandlers(类型处理器)
    objectFactory(对象工厂)
    plugins(插件)
    environments(环境配置)
    	environment(环境变量)
    		transactionManager(事务管理器)
    		dataSource(数据源)
    databaseIdProvider(数据库厂商标识)
    mappers(映射器)

environments

<environments default="development">
        <environment id="development-own">
            <transactionManager type="JDBC"/>
            <!--原生-->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?userSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    	<environment id="development-druid">
            <transactionManager type="JDBC"/>
            <!--druid 需要编写工具类-->
            <dataSource type="com.nuc.utils.DruidDataSourceFactory">
				<property name="driverClassName" value="${jdbcDriver}"/>
				<property name="url" value="${jdbcUrl}"/>
				<property name="username" value="${jdbcUser}"/>
				<property name="password" value="${jdbcPassword}"/>
			</dataSource>
        </environment>
    	<environment id="development-c3p0">
			<transactionManager type="JDBC"/>
            <!--c3p0 需要编写工具类-->
			<dataSource type="com.nuc.utils.c3p0DatasourceFactory">
				<property name="driverClass" value="${jdbcDriver}"/>
				<property name="jdbcUrl" value="${jdbcUrl}"/>
				<property name="user" value="${jdbcUser}"/>
				<property name="password" value="${jdbcPassword}"/>
				<property name="initialPoolSize" value="5"/>
                <property name="maxPoolSize" value="20"/>
                <property name="minPoolSize" value="5"/>
			</dataSource>
		</environment>
    	<environment id="development-dbcp">
            <transactionManager type="JDBC"/>
            <!--dbcp 需要编写工具类-->
            <dataSource type="com.nuc.utils.DbcpDataSourceFactory">
				<property name="driverClassName" value="${jdbcDriver}"/>
				<property name="url" value="${jdbcUrl}"/>
				<property name="username" value="${jdbcUser}"/>
				<property name="password" value="${jdbcPassword}"/>
			</dataSource>
        </environment>
        <environment id="development-hikaricp">
             <transactionManager type="JDBC"/>
               <!--hikaicp 需要编写工具类-->
              <dataSource type="com.nuc.utils.HikariDataSourceFactory"/>
        </environment>
    </environments>
public class c3p0DatasourceFactory  extends UnpooledDataSourceFactory{
	public c3p0DatasourceFactory() {
		this.dataSource=new ComboPooledDataSource();
	}
}
public class DruidDataSourceFactory  extends UnpooledDataSourceFactory{
	public DruidDataSourceFactory() {
		this.dataSource=new DruidDataSource();
	}
}
public class DbcpDataSourceFactory  extends UnpooledDataSourceFactory{
	public DruidDataSourceFactory() {
		this.dataSource=new PooledDataSource();
	}
}
public class HikariDataSourceFactory extends     
    UnpooledDataSourceFactory {
    public HikariDataSourceFactory(){
    HikariConfig config = new HikariConfig("hikariPool.properties");
    config.setMaximumPoolSize(5);
    this.dataSource = new HikariDataSource(config);
  }
}

hikariPool.properties

jdbcUrl=jdbc:mysql://localhost:3306/omc?characterEncoding=utf8&serverTimezone=UTC
dataSource.user=remote
dataSource.password=xxxxxx
dataSource.cachePrepStmts=true
dataSource.prepStmtCacheSize=250
dataSource.prepStmtCacheSqlLimit=2048
dataSource.useServerPrepStmts=true
dataSource.useLocalSessionState=true
dataSource.rewriteBatchedStatements=true
dataSource.cacheResultSetMetadata=true
dataSource.cacheServerConfiguration=true
dataSource.elideSetAutoCommits=true
dataSource.maintainTimeStats=false
# 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 缺省:30秒
dataSource.connectionTimeout=30000
# 一个连接idle状态的最大时长(毫秒),超时则被释放(retired),缺省:10分钟 -->
dataSource.idleTimeout=600000
# 一个连接的生命时长(毫秒),超时而且没被使用则被释放(retired),缺省:30分钟
# 建议设置比数据库超时时长少30秒,参考MySQL wait_timeout参数(show variables like '%timeout%';)
dataSource.maxLifetime=1800000
# 连接池中允许的最大连接数。缺省值:10;推荐的公式:((core_count * 2) + effective_spindle_count)
# core_count CPU的内核数量
# effective_spindle_count is the number of disks in a RAID.就是磁盘列阵中的硬盘数
dataSource.maximumPoolSize=10

properties

<properties resource="db.properties">
    <property name="username" value="root"/>
    <property name="password" value="root"/>
</properties>
<!--配置文件会覆盖子标签-->

typeAliases

手动指定

<typeAliases>
    <typeAlias type="com.kuang.pojo.User" alias="User"/>
</typeAliases>

包扫描(注解会覆盖)

<typeAliases>
    <package name="com.kuang.pojo"/>
</typeAliases>

注解

@Alias("author")

mapper

资源路径

<mappers>
    <mapper resource="com/kuang/dao/UserMapper.xml"/>
</mappers>

类路径

  • 接口和他的Mapper配置文件必须同名
  • 接口和他的Mapper配置文件必须在同一个包下
<mappers>
    <mapper class="com.kuang.dao.UserMapper"/>
</mappers>

包扫描

<mappers>
    <package name="com.kuang.dao"/>
</mappers>

结果集映射

<resultMap id="UserMap" type="User">
    <!--column数据库中的字段,property实体类中的属性-->
    <result column="id" property="id"></result>
    <result column="name" property="name"></result>
    <result column="pwd" property="password"></result>
</resultMap>

<select id="getUserList" resultMap="UserMap">
    select * from USER
</select>

驼峰命令

<settings>
    <setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

日志

  • SLF4J
  • LOG4J 【掌握】
  • LOG4J2
  • JDK_LOGGING
  • COMMONS_LOGGING
  • STDOUT_LOGGING 【掌握】
  • NO_LOGGING
<settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

log4j

#将等级为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/rzp.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.sq1.PreparedStatement=DEBUG

使用方法

  1. 在要使用Log4j的类中,导入包 import org.apache.log4j.Logger;

  2. 日志对象,参数为当前类的class对象

Logger logger = Logger.getLogger(UserDaoTest.class);
  1. 日志级别
logger.info("info: 测试log4j");
logger.debug("debug: 测试log4j");
logger.error("error:测试log4j");

分页

  1. limit

    接口

    List<User> getUserByLimit(Map<String,Integer> map);
    

    Mapper.xml

```

测试

@Test
public void getUserByLimit(){
 SqlSession sqlSession = MybatisUtils.getSqlSession();
 UserMapper mapper = sqlSession.getMapper(UserMapper.class);
 HashMap<String, Integer> map = new HashMap<String, Integer>();
 map.put("startIndex",1);
 map.put("pageSize",2);
 List<User> list = mapper.getUserByLimit(map);
 for (User user : list) {
     System.out.println(user);
 }
}
  1. rowbounds

    接口

    List<User> getUserByRowBounds();
    

    mapper.xml

```

测试

public void getUserByRowBounds(){
 SqlSession sqlSession = MybatisUtils.getSqlSession();
 //RowBounds实现
 RowBounds rowBounds = new RowBounds(1, 2);
 //通过Java代码层面实现分页
 List<User> userList = sqlSession.selectList("com.kaung.dao.UserMapper.getUserByRowBounds", null, rowBounds);
 for (User user : userList) {
     System.out.println(user);
 }
 sqlSession.close();
}
  1. 插件

    PageHelper

注解

  1. 注解在接口上实现

    public interface UserMapper {
     @Select("select * from user")
     List<User> getUsers();
    
     //方法具有多个参数,前必须加@param
     @Select("select * from user where id=#{id}")
     User getUserById(@Param("id") int id);
    
     @Insert("insert into user(id,name,pwd)values(#{id},#{name},#{password})")
     int addUser(User user);
    
     @Update("update user set name = #{name},pwd = #{password} where id = #{id}")
     int updateUser(User user);
    
     @Delete("delete from user where id = #{tid}")
     int deleteUser(@Param("tid") int id);
    }
    
  2. 绑定接口

    <mappers>
        <mapper class="com.kuang.dao.UserMapper"/>
    </mappers>
    

关于@Param( )注解

  • 基本类型的参数或者String类型,需要加上
  • 引用类型不需要加
  • 如果只有一个基本类型的话,可以忽略,但是建议大家都加上
  • 我们在SQL中引用的就是我们这里的@Param()中设定的属性名

一对一

按照查询嵌套处理

<!--
     思路:
        1. 查询所有的学生信息
        2. 根据查询出来的学生的tid寻找特定的老师 (子查询)
    -->
<select id="getStudent" resultMap="StudentTeacher">
    select * from student
</select>

<resultMap id="StudentTeacher" type="student">
    <result property="id" column="id"/>
    <result property="name" column="name"/>
    <!--对象:association 集合:collection-->
    <association property="teacher" column="tid" javaType="teacher" select="getTeacher"/>
</resultMap>

<select id="getTeacher" resultType="teacher">
    select * from teacher where id = #{id}
</select>

20200909144043629

  • javaType:把sql语句查询出的结果集,封装给某个类的某个对象-- 属性类型(指定实体类中的java返回值类型)

  • select:下一条要执行的sql语句

  • property:注入给一级查询结果实体类的某个属性-- 属性名 

  • column:在上一次查询的结果集中,用那些列值去执行下一条sql语句(传参)

按照结果嵌套处理 (简单)

 <!--按照结果进行查询-->
    <select id="getStudent2" resultMap="StudentTeacher2">
        select s.id sid , s.name sname, t.name tname
        from student s,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"></result>
        </association>
    </resultMap>

20200909144059395

一对多

按照查询嵌套处理

<!--子查询:按查询嵌套查询-->
<select id="getTeacher" resultMap="teacherToStudent">
    select id, name from mybatis.teacher where id = #{id}
</select>
<resultMap id="teacherToStudent" type="teacher">
    <result property="id" column="id"/>
    <result property="name" column="name"/>
    <!--  column="id"是teacher表中的id-->
    <collection property="students" javaType="List" ofType="student"
                column="id" select="getStudentsByTeacherId" />
    <!-- List<student> students -->
</resultMap>
<select id="getStudentsByTeacherId" resultType="student">
    select * from mybatis.student where tid = #{id}
</select>

20200909144117110

  • ofType:映射List或某些指定的pojo泛型的类型

按照结果嵌套处理

<!--联表查询:按结果嵌套查询-->
<select id="getTeacher1" resultMap="teacherAndStudent">
    select  s.id sid,s.name sname,t.name tname,t.id tid
    from mybatis.teacher t,mybatis.student s
    where s.tid=t.id and t.id =#{id}
</select>
<resultMap id="teacherAndStudent" type="teacher">
    <result property="id" column="tid"/>
    <result property="name" column="tname"/>
    <!--集合对象用collection绑定,javaType是返回单个属性,不能返回集合,
返回属性是集合用ofType绑定-->
    <collection property="students" ofType="student">
        <result property="id" column="sid"/>
        <result property="name" column="sname"/>
        <result property="tid" column="tid"/>
    </collection>
</resultMap>

动态SQL

if

<!--if:通过include跳转到使用,缺点是必须写上判断条件成立 where 1=1-->
<select id="queryBlogByIf" parameterType="map" resultType="Blog">
    select * from mybatis.blog where 1=1
    <include  refid="if_title_author_like" />
</select>
<sql id="if_title_author_like">
    <if test="title !=null">
        and  title like #{title}
    </if>
    <if test="author !=null">
        and author like #{author}
    </if>
</sql>
<!--if:通过where直接使用/直接使用if判断,但是不推荐。原理:如果test存在,就自动加上where -->
<select id="queryBlogByWhere" parameterType="map" resultType="Blog">
    select * from mybatis.blog
    <where>
        <if test="id !=null">
            id like #{id}
        </if>
        <if test="views !=null">
            and views like #{views}
        </if>
    </where>
</select>

choose

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

where

<select id="findActiveBlogLike" resultType="Blog">
  SELECT * FROM BLOG
  <where>
    <if test="state != null">
         state = #{state}
    </if>
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>
</select>
  • 优势:where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。

trim

  • 使用自定义 trim 元素来定制 where 元素的功能
    与< where>等价的< trim>:prefix="WHERE"满足条件,自动添加的字段:prefixOverrides自动忽略的字段,细节:AND |OR 两者后面都包含了一个空格,这是正确sql的书写要点。
<trim prefix="WHERE" prefixOverrides="AND |OR ">
</trim>

set

  • 概念:用于动态update语句的叫做 set。set 元素可以用于动态包含需要更新的列,忽略其它不更新的列

    等价的trim语句,set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)= 也就是说其实mybatis自动在update中set就给你加上了逗号,但是你自己手写加上了,< set> 也会给你忽略掉

<trim prefix="SET" suffixOverrides=",">
</trim>
<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>

foreach

  • 概念:动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)
  • 原生:SELECT * FROM blog WHERE 1=1 AND (id=1 OR id=2);
  • 细节:if < where> 多个条件成立时,就会忽略掉原生中and书写

2020090914415821

<select id="queryBlogByForeach" parameterType="map" resultType="Blog">
    select * from mybatis.blog
    <where>
   		<foreach collection="ids" item="id" open="(" separator="or" close=")">
    		id=#{id}
		</foreach>
    </where>
</select>
<!--官网案例:使用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>

SQL片段

  • 使用:< sql id= > 标签和< include refid= >引用
  • 细节:
    • 最好基于单表使用sql片段,多表别的表不一定支持
    • 使用sql片段复用,不要使用< where >标签,因为它内置了会忽略掉某些字段
<sql id="if_title_author_like">
    <if test="title !=null">
        and  title like #{title}
    </if>
    <if test="author !=null">
        and author like #{author}
    </if>
</sql>

<select id="queryBlogByIf" parameterType="map" resultType="Blog">
    select * from mybatis.blog where 1=1
    <include refid="if_title_author_like" />
</select>

缓存

一级缓存

  • 默认情况下,只启用了本地的会话(一级)缓存,它仅仅对一个会话中的数据进行缓存。

    • 把一级缓存想象成一个会话中的map,便于理解
  • 缓存失效

    • 增删改会把所有的sql缓存失效,下次会重写从数据库中查
    • 查询不同的东西,查询不同的mapper.xml
    • 手动清除缓存:sqlSession.clearCache();

二级缓存

mybatis-config,xml开启全局缓存

<settings>
    <setting name="logImpl" value="STDOUT_LOGGING"/>
    <!--开启全局缓存 默认是开启的,显示写便于可读-->
    <setting name="cacheEnabled" value="true"/>
</settings>

mappper.xml开启二级缓存

<!--开启二级缓存-->
<cache
  eviction="FIFO" 
  flushInterval="60000" 
  size="512" 
  readOnly="true"/>
<!--eviction:清楚算法,默认LRU -->
<!--flushInterval:刷新缓存间隔,默认无-->
<!--size:最多缓存数量,默认1024-->
<!--readOnly:只读缓存;写操作会不走缓存,直接从数据库查询,默认是读/写缓存-->
  • 映射语句文件中的所有 select 语句的结果将会被缓存。

  • 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。

  • 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。

  • 缓存不会定时进行刷新(也就是说,没有刷新间隔)。

  • 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。

  • 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

    读写缓存需要pojo开启序列化操作

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User implements Serializable {
        private int id;
        private String name;
        private String pwd;
    
        public static void main(String[] args) {
            new ArrayList<>();
            new HashMap<>();
            new LinkedList<>();
        }
    }
    

自定义缓存

  • 概念:ehcache是一个分布式缓存,主要面向通用缓存
  • 手写或者导入第三方的ehcache缓存依赖
  • 所以可以自定义ehcache.xml配置文件
<dependency>
    <groupId>org.mybatis.caches</groupId>
    <artifactId>mybatis-ehcache</artifactId>
    <version>1.2.0</version>
</dependency>
  • 在mapper.xml中配置
 <cache type="org.mybatis.caches.encache.EhcacheCache"/>
  • 在resource中创建ehcache.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
  <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
           updateCheck="false">
      
      <defaultCache
              eternal="false"
              maxElementsInMemory="10000"
              overflowToDisk="false"
              diskPersistent="false"
              timeToIdleSeconds="1800"
              timeToLiveSeconds="259200"
              memoryStoreEvictionPolicy="LRU"/>
   
      <cache
              name="cloud_user"
              eternal="false"
              maxElementsInMemory="5000"
              overflowToDisk="false"
              diskPersistent="false"
              timeToIdleSeconds="1800"
              timeToLiveSeconds="1800"
              memoryStoreEvictionPolicy="LRU"/>
      
      <!--
         diskStore:为缓存路径,ehcache分为内存和磁盘两级,此属性定义磁盘的缓存位置。参数解释如下:
         user.home – 用户主目录
         user.dir  – 用户当前工作目录
         java.io.tmpdir – 默认临时文件路径
       -->
      <diskStore path="java.io.tmpdir/Tmp_EhCache"/>
      <!--
         defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个。
       -->
      <!--
        name:缓存名称。
        maxElementsInMemory:缓存最大数目
        maxElementsOnDisk:硬盘最大缓存个数。
        eternal:对象是否永久有效,一但设置了,timeout将不起作用。
        overflowToDisk:是否保存到磁盘,当系统当机时
        timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
        timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
        diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
        diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
        diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
        memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
        clearOnFlush:内存数量最大时是否清除。
        memoryStoreEvictionPolicy:可选策略有:LRU(最近最少使用,默认策略)、FIFO(先进先出)、LFU(最少访问次数)。
        FIFO,first in first out,这个是大家最熟的,先进先出。
        LFU, Less Frequently Used,就是上面例子中使用的策略,直白一点就是讲一直以来最少被使用的。如上面所讲,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。
        LRU,Least Recently Used,最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清出缓存。
     -->
  </ehcache>
posted @   Faetbwac  阅读(56)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示