mybatis

mybatis

java框架

框架会将很多基本功能进行了封装,程序员在框架基础上再进行业务开发.
代码简洁,开发高效

了解框架主要功能

搭建框架:
添加框架依赖的jar
写配置文件
框架中提供自己的一些接口,实现某种功能
业务开发

mybatis:

原来是apache的一个开源项目,2010迁移到谷歌.更名为mybatis

M 数据访问层(数据持久层) DAO(Data Access Object) model Student Admin User
Controller Servlet属于控制层

View(前端)

是一个优秀的java持久层框架.

是一个ORM框架.
ORM(Object Relational Mapping)

    Object
 java对象       映射          数据库表
 
 mybatis封装一些关于对数据库操作的一些接口,代替了jdbc
 
 对jdbc进行了封装,简化操作.

mybatis搭建:

1.导入mybatis jar mysql驱动
2.配置mybatis核心配置文件
3.创建表, 对应的类
4.创建映射接口(主要用于定义有哪些操作)
5.创建sql映射配置文件( sql实现 )
6.测试
读取核心配置文件
创建SqlSessionFactory
创建SqlSession
获得接口代理对象
代理对象.接口中的方法

JDBC 编程问题

1、 数据库连接的创建、释放频繁造成系统资源浪费从而影响系统性能,如果使

用数据库连接池可解决该问题。

2、 SQL 语句编写在 Java 代码中,这种硬编码造成代码不易维护,当 SQL 变动

时需要修改 java 源代码。

3、 使用 preparedStatement 向占位符传参数存在硬编码,因为 SQL 语句的

where 条件中占位符的个数可能会变化,修改 SQL 还要修改 Java 源代码,

系统不易维护。

4、 对结果集解析存在硬编码,

SQL 语句变化导致解析代码变化,系统不易维护。

MyBatis 架构

MyBatis 是优秀的持久层框架,它能够解决 JDBC 编程中存在的问题。接下

来先了解 MyBatis 的架构。

MyBatis[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w6FDroRQ-1636368484967)(D:\HJ2012\框架\mybatis\mybatis.png)] 环境搭建

导入 MyBatis jar 包数据库驱动包

<dependency> 

<groupId>org.mybatis</groupId> 

<artifactId>mybatis</artifactId> 

<version>3.4.2</version> 

</dependency>

Mybatis 源码下载

https://github.com/mybatis/mybatis-3/releases

创建 MyBatis 全局配置文件

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

<!--mybatis核心配置文件-->

<configuration>
    <properties resource="conf.properties">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
    </properties>

    <settings>
        <!--配置日志实现 使用log4j 添加log4j日志组件 导入jar包 配置属性文件-->
        <setting name="cacheEnabled" value="log4j"/>
        <!--是否开启驼峰命名自动映射,即从经典数据库列名 a_column映射到经典Java属性名aColumn-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!--启用二级缓存-->
        <setting name="cacheEnabled" value="true"/>

        <setting name="lazyLoadTriggerMethods" value=""/>

    </settings>

    
    <typeAliases>
        <typeAlias alias="Admin" type="mybatis.admin.Admin"></typeAlias>
        <typeAlias alias="Employee" type="mybatis.admin.Employee"></typeAlias>
        <typeAlias alias="Dept" type="mybatis.admin.Dept"></typeAlias>
    </typeAliases>
    <!--environments配置与数据库连接的信息-->
    <environments default="development">

        <!--配置本地开发信息-->
        <environment id="development">

            <!--配置事务管理类型,使用JDBC事务管理-->
            <transactionManager type="JDBC"></transactionManager>
            <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>
    <!--添加sql映射文件-->
    <mappers>
        <mapper resource="mapper/mapper.xml"/>
        <mapper resource="mapper/employeemapper.xml"/>
        <mapper resource="mapper/deptmapper.xml"/>
    </mappers>
</configuration>

conf.properties

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/mybatis_dbcharacterEncoding=utf8&useSSL=false&serverT     imezone=Asia/Shanghai
username=root
password=000124

log4j.properties

log4j.rootLogger = debug,stdout,D
#System out Console
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%p] %d{yyyy-MM-dd HH:mm:ss,SSS} %m%n

#System out File
log4j.appender.D = org.apache.log4j.FileAppender
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = D://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ] -[%l] %m%n

插入数据

<insert id="唯一标识" useGeneratedKeys="把新增加的主键赋值到自己定义的 

keyProperty " keyProperty=“ 接收主键的属性 parameterType="参数类型"> 

insert into 

user(userName,userAge)values(#{userName},#{userAge}) 

</insert> 

</mapper> 

#{} 占位符,是经过预编译的,编译好 SQL 语句再取值,#方式能够防止 sql 注入#{}:select * from t_user where uid=#{uid}

拼 接 符 , 会 传 入 参 数 字 符 串 , 取 值 以 后 再 去 编 译 S Q L 语 句 , {} 拼接符,会传入参数字符串,取值以后再去编译 SQL 语句, ,SQL,方式无法防止 Sql

注入 ${}

${}:select * from t_user where uid= ‘1’

注意:MyBatis 排序时使用 order by 动态参数时需要注意,用$而不是#

修改

<update id="唯一标识" parameterType=“参数类型"> 

update 

ts_user set userName = #{userName},userAge = #{userAge} 

where 

userId = #{userId} 

</update> 

删除

<delete id="唯一标识" parameterType="参数类型"> 

delete from ts_user where userId = #{id} 

</delete> 

查询

<select id="唯一标识" resultType="返回结果集类型"> 

select * 

from ts_user where id= #{id} 

</select>

Mybatis-Dao Mapper 接口

Mapper 接口开发方法只需要程序员编写 Mapper 接口(相当于 Dao 接口),

由 Mybatis 框架根据接口定义创建接口的动态代理对象.

使用 session.getMapper(接口.class);获得代理对象

Mapper 接口开发需要遵循以下规范:

1、 Mapper.xml 文件中的 namespace 与 mapper 接口的类路径相同

2、 Mapper 接口方法名和 Mapper.xml 中定义的每个 statement 的 id 相同

3、 Mapper 接口方法的输入参数类型和 mapper.xml 中定义的每个 sql 的 parameterType 的类型相同

4、 Mapper 接口方法的输出参数类型和 mapper.xml 中定义的每个 sql 的

resultType 的类型相同

测试 MyBatis

读取配置文件


public class mybatisutil {
    static Reader reader =null ;
    static SqlSessionFactory sessionFactory=null;
    static {
        try {
             reader = Resources.getResourceAsReader("mybatis.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
         sessionFactory = new SqlSessionFactoryBuilder().build(reader);

    }
    public static SqlSession getSession(){
        return sessionFactory.openSession();
    }

}

参数传递及结果处理

简单的参数形式不需要使用 parameterType 参数定义,例如:

    //传递多个参数 使用注解标签参数绑定@Param("acc")acc向SQL中传入得名称
    Admin getAdmin(@Param("acc")String account, @Param("sex")String sex);
    
    
    <select id="getAdmin" resultType="Admin" >
select * from admin where account=#{acc} and sex=#{sex}
    </select>
   <!--parameterType=”参数类型“-->
    <!--#{属性名}values(?,?,?)赋值方式时编译的,安全的,可以防止SQL注入-->
    <!--${属性}values('admin2','111','男') 字符串拼接方式
    ${}用来穿列名,而不是传数据
    select ${column1},${column2}  from admin order by ${column}      order by排序
useGeneratedKeys="true" 可以返回刚插入数据的主键
 keyColumn="id"  告知主键列
  keyProperty="id" 告知与主键列对应的属性

    -->

如果传入一个复杂的对象,就需要使用 parameterType 参数进行类型定义,例如: void Save admin(Admin admin);

void Saveadmin(Admin admin);


resultType="Admin" 返回值的类型 根据返回值类型 创建一个对象
将数据库数据自动映射到Java对象中,有前提表中的列名与类中的属性名相同
    <insert id="Saveadmin" parameterType="Admin" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
        INSERT INTO admin(account,password,sex)VALUES(#{account},#{password},#{sex})
        /*        INSERT INTO admin(account,password,sex)VALUES('${account}','${password}','${sex}')
*/
    </insert>

也可以使用 Map 对象传递

Admin getAdmin1(Map<String,Object> map);

在 sql 中使用表达式获取 map 的键即可.

Admin getAdmin1(Map<String,Object> map);


    <!--java中已有的类为类型使用时,可以直接使用mybatis定义好的别名-->
    <select id="getAdmin1" resultType="Admin" parameterType="map">
        select * from admin where account=#{acc} and sex=#{sex}
    </select>

POJO 对象输出映射

如果表中的类名与类中的属性名完全相同,mybatis会自动将查询结果封装

到POJO对象中.

如果java中使用标准驼峰命名,数据库中使用下划线连接命名,可以开始全局

设置实现自动转换

开启驼峰命名自动映射 从数据库命名转为Java驼峰命名 user_name - userName

定义 resultMap

<!-- 结果集映射   <resultMap id="adminMap" type="Admin">
        <id column="id" property="id"></id>
        <result column="account" property="account"></result>
        <result column="pass_word" property="passWord"></result>
        <result column="sex1" property="sex"></result>
    </resultMap>
    
        <select id="getAdminById" resultMap="adminMap">
        select * from admin where id=#{id}
    </select>

(1) resutlMap 的 id 属性是 resutlMap 的唯一标识,本例中定义为 “useresultMap”

(2) resutlMap 的 id 属性是映射的 POJO 类

(3) id 标签映射主键,result 标签映射非主键

(4) property 设置 POJO 的属性名称,column 映射查询结果的列名称

多表关联处理结果集

resultMap 元素中 association , collection 元素

association – 复杂类型联合; 许多查询结果合成这个类型

一对一结果映射– association 能引用自身, 或者从其它地方引用 collection – 复杂类型集合

嵌套结果映射– collection 能引用自身, 或者从其它地方引用 多对一与一对多association 关联元素处理“有一个”类型的关系,即一对一关联。它有两种关联 方式:

嵌套查询:通过执行另外一个 SQL 映射语句来返回预期的复杂类型。

嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集。

Collection 关联元素处理一对多关联。

    <resultMap id="emmap" type="Employee">
<id column="id" property="id"></id>
        <result column="ename" property="name"></result>
        <result column="age" property="age"></result>
        <association property="dept" javaType="Dept">
            <result column="dname" property="name"></result>
        </association>
        <association property="admin" javaType="Admin">
            <result column="account" property="account"></result>
        </association>
    </resultMap>
    
    
    
        <select id="getEmployById" resultMap="emmap">
    SELECT emp.id,
    emp.name ename,
    emp.age,
    a.account,
    d.name dname
    FROM employee emp LEFT JOIN dept d ON emp.deptId=d.id
    LEFT JOIN admin a ON emp.adminId=a.id
    WHERE emp.id=#{id}
    </select>

懒加载

需要查询关联信息时,使用 Mybatis 懒加载特性可有效的减少数据库压力, 首次查询只查询主表信息,关联表的信息在用户获取时再加载。

Mybatis 一对一关联的 association 和一对多的 collection 可以实现懒加 载。懒加载时要使用 resultMap,不能使用 resultType。

启动懒加载

Mybatis 默认没有打开懒加载配置,需要在 SqlMapperConfig.xml 中通过 settings 配置 lazyLoadingEnabled 来开启懒加载。

启用懒加载

<settings> 
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
<resultMap id="EmployeeMap1" type="Employee">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <result column="age" property="age"></result>
        <!--查询管理员信息-->
        <association property="admin" javaType="Admin" fetchType="lazy"
                     select="findadminbyid1" column="adminId">
            <result column="account" property="account"></result>
        </association>
        <!--查询部门信息-->
        <association property="dept" javaType="Dept" fetchType="lazy"
                     select="finddeptbyid1" column="deptId">
            <result column="name" property="name"></result>
        </association>
    </resultMap>
    <select id="getemployeeById1" resultMap="EmployeeMap1">
     select id,name,age,adminId,deptId from employee where id=#{id}
    </select>
    <select id="findadminbyid1" resultType="Admin">
        select account from admin where id=#{adminId}
    </select>
    <select id="finddeptbyid1" resultType="Dept">
        select name from dept where id=#{deptId}
    </select>

(1)Select:指定关联查询懒加载对象的 为 findadminbyid1

(2)column=“adminId”:关联查询时将adminId列的值传入 findadminbyid1,

并将 findadminbyid1查询的结果映射到admin的 adminId 属性中

(3)collection 和 association 都需要配置 select 和 column 属性,两者配置方法 相同

注解方式

常用注解标签

@Insert : 插入 sql , 和 xml insert sql 语法完全一样

@Select : 查询 sql, 和 xml select sql 语法完全一样

@Update : 更新 sql, 和 xml update sql 语法完全一样

@Delete : 删除 sql, 和 xml delete sql 语法完全一样

@Param : 入参

@Results : 设置结果集合

@Result : 结果使用案例

    //注解标签:简单一点的
@Select("select id,name from dept")
    List<Dept> depts();


@Delete("DELETE FROM dept WHERE id=#{id}")
    void delectDeptById(@Param("id") Integer id1);
}

Mybatis 动态 SQL

MyBatis 的一个强大的特性之一通常是它的动态 SQL 能力。 如果你有使用JDBC 或其他 相似框架的经验,你就明白条件地串联 SQL 字符串在一起是多么 的痛苦,确保不能忘了空 格或在列表的最后省略逗号。动态 SQL 可以彻底处理 这种痛苦。

MyBatis 中用于实现动态 SQL 的元素主要有:

If

where

trim

set

choose (when, otherwise)

foreach

if

 <select id="getemployeelist1" resultMap="emmap" parameterType="Employee">
        SELECT emp.id,
        emp.name ename,
        emp.age,
        a.account,
        d.name dname
        FROM employee emp LEFT JOIN dept d ON emp.deptId=d.name
        LEFT JOIN admin a ON emp.adminId=a.id
        <where>
            <if test="name!=null||name!=''">
                emp.name=#{name}
            </if>
            <if test="age!=null">
                and emp.age=#{age}
            </if>
        </where>

元素会进行判断,如果它包含的标签中有返回值的话,它就插入一个 ‘where’。此外,如果标签返回的内容是以 AND 或 OR 开头,它会剔除掉 AND 或 OR。

trim 元素

where 标签,其实用 trim 也可以表示,当 WHERE 后紧随 AND 或则 OR 的 时候,就去除 AND 或者 OR。prefix 前缀,prefixOverrides 覆盖首部指定 内容

<select id="getemployeelist1" resultMap="emmap" parameterType="Employee">
        SELECT emp.id,
        emp.name ename,
        emp.age,
        a.account,
        d.name dname
        FROM employee emp LEFT JOIN dept d ON emp.deptId=d.name
        LEFT JOIN admin a ON emp.adminId=a.id
        <trim prefix="where" prefixOverrides="and|or">
            <if test="name!=null||name!=''">
                emp.name=#{name}
            </if>
            <if test="age!=null">
                and emp.age=#{age}
            </if>

        </trim>
    </select>
    <select id="getemployeelist1" resultMap="emmap" parameterType="Employee">
        SELECT emp.id,
        emp.name ename,
        emp.age,
        a.account,
        d.name dname
        FROM employee emp LEFT JOIN dept d ON emp.deptId=d.name
        LEFT JOIN admin a ON emp.adminId=a.id
        <trim prefix="where" prefixOverrides="and|or">
            <if test="name!=null||name!=''">
                emp.name=#{name}
            </if>
            <if test="age!=null">
                and emp.age=#{age}
            </if>

        </trim>
    </select>

set

set标签可以动态添加set关键字,可以去掉set语句中最后一个逗号
     UPDATE employee
        <set>
            <if test="name!=null">
                name =#{name},
            </if>
            <if test="age!=null">
                age =#{age},
            </if>
            <if test="dept.id">
                deptId =#{dept.id}
            </if>
            </set>
            where id=#{id}

    </update>

Foreach 元素

主要用在构建 in 条件中,它可以在 SQL 语句中进行迭代一个集合。foreach 元素的属性主要有 item,index,collection,open,separator,close。

item 表示集合中每一个元素进行迭代时的别名,index 指定一个名字,用于 表示在迭代过程中,每次迭代到的位置,open 表示该语句以什么开始, separator 表示在每次进行迭代之间以什么符号作为分隔符,close 表示以什 么结束,在使用 foreach 的时候最关键的也是最容易出错的就是 collection 属性,该属性是必须指定的,但是在不同情况下,该属性的值是不一样的。

– 如果传入的是单参数且参数类型是一个 List 的时候,collection 属 性值为 list

– 如果传入的是单参数且参数类型是一个 array 数组的时候, collection 的属性值为 array

特殊符号处理

在 mybatis 中的 xml 文件中,存在一些特殊的符号,比如:<、>、"、&、<> 等,正常书写 mybatis 会报错,需要对这些符号进行转义。具体转义如下所示:

特殊字符 转义字符

< &lt; 
> &gt;
" &quot; 
’ &apos; 
& &amp;

除了可以使用上述转义字符外,还可以使用<![CDATA[]]>来包裹特殊字符。如 下所示:

AND <![CDATA[ id <> #{id} ]]>

<![CDATA[ ]]>是 XML 语法。在 CDATA 内部的所有内容都会被解析器忽略。
    <select id="getEmployeelistByAge2" resultType="Employee">
        <!--
  /*        select * from employee where age &lt;#{age}
*/
    -->

 select * from employee where age <![CDATA[ <]]> #{age}
</select>

但是有个问题那就是 等这些标签都不会被解析,所以 我们只把有特殊字符的语句放在 <![CDATA[ ]]> 尽量缩小<![CDATA[ ]]> 的范围。

mybatis 一级缓存二级缓存

为什么使用缓存

缓存(cache)的作用是为了减去数据库的压力,提高数据库的性能。缓存实现的 原理是从数据库中查询出来的对象在使用完后不要销毁,而是存储在内存(缓存) 中,当再次需要获取该对象时,直接从内存(缓存)中直接获取,不再向数据库 执行 select 语句,从而减少了对数据库的查询次数,因此提高了数据库的性能。 缓存是使用 Map 集合缓存数据的。 Mybatis 有一级缓存和二级缓存。一级缓存的作用域是同一个 SqlSession, 在同一个 sqlSession 中两次执行相同的 sql 语句,第一次执行完毕会将数据库 中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查 询,从而提高查询效率。当一个 sqlSession 结束后该 sqlSession 中的一级缓存 也就不存在了。Mybatis 默认开启一级缓存。 二 级 缓 存 是 多 个 SqlSession 共 享 的 , 其 作 用 域 是 mapper 的 同 一 个 namespace,不同的 sqlSession 两次执行相同 namespace 下的 sql 语句且向 sql 中传递参数也相同即最终执行相同的 sql 语句,第一次执行完毕会将数据库 中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。Mybatis 默认没有开启二级缓存需要在 setting 全局参 数中配置开启二级缓存。

一级缓存

Mybatis 对缓存提供支持,但是在没有配置的默认情况下,它只开启一级缓

存,一级缓存只是相对于同一个 SqlSession 而言。所以在参数和 SQL 完全一样

的情况下,我们使用同一个 SqlSession 对象调用一个 Mapper 方法,往往只执

行一次 SQL,因为使用 SelSession 第一次查询后,MyBatis 会将其放在缓存中,

以后再查询的时候,如果没有声明需要刷新,并且缓存没有超时的情况下,

SqlSession 都会取出当前缓存的数据,而不会再次发送 SQL 到数据库。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SB3A317w-1636368484971)(D:\HJ2012\框架\mybatis\二级缓存.png)]

一级缓存的生命周期

1、MyBatis 在开启一个数据库会话时,会 创建一个新的 SqlSession 对象, SqlSession 对象中会有一个新的 Executor 对象。Executor 对象中持有一个新 的 PerpetualCache 对象,如果 SqlSession 调用了 close()方法,会释放掉一级 缓存 PerpetualCache 对象,一级缓存将不可用。

2、如果 SqlSession 调用了 clearCache(),会清空 PerpetualCache 对象 中的数据,但是该对象仍可使用。

3、SqlSession 中执行了任何一个 update 操作(update()、delete()、 insert()) ,都会清空 PerpetualCache 对象的数据,但是该对象可以继续使用

二级缓存

二级缓存是 SqlSessionFactory 级别的,根据 mapper 的 namespace 划分区域

的,相同 namespace 的 mapper 查询的数据缓存在同一个区域,如果使用

mapper 代理方法每个 mapper 的 namespace 都不同,此时可以理解为二级缓

存区域是根据 mapper 划分。

每次查询会先从缓存区域查找,如果找不到则从数据库查询,并将查询到数据写

入缓存。Mybatis 内部存储缓存使用一个 HashMap,key 为

hashCode+sqlId+Sql 语句。value 为从查询出来映射生成的 java 对象。

sqlSession 执行 insert、update、delete 等操作 commit 提交后会清空缓存区

域,防止脏读。二级缓存参考下图所示:

MyBatis 的缓存机制整体设计以及二级缓存的工作模式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EWhAhBqu-1636368484973)(D:\HJ2012\框架\mybatis\二级缓存.png)]

配置二级缓存配置

第一步:启用二级缓存

在 SqlMapperConfig.xml 中启用二级缓存,如下代码所示,当

cacheEnabled 设置为 true 时启用二级缓存,设置为 false 时禁用二级缓存。

第二步:POJO 序列化

将所有的 POJO 类实现序列化接口 Java.io. Serializable。

model所有类继承Serializable

第三步:配置映射文件

在 Mapper 映射文件中添加,表示此 mapper 开启二级缓存。

space 的 mapper 查询的数据缓存在同一个区域,如果使用

mapper 代理方法每个 mapper 的 namespace 都不同,此时可以理解为二级缓

存区域是根据 mapper 划分。

每次查询会先从缓存区域查找,如果找不到则从数据库查询,并将查询到数据写

入缓存。Mybatis 内部存储缓存使用一个 HashMap,key 为

hashCode+sqlId+Sql 语句。value 为从查询出来映射生成的 java 对象。

sqlSession 执行 insert、update、delete 等操作 commit 提交后会清空缓存区

域,防止脏读。二级缓存参考下图所示:

MyBatis 的缓存机制整体设计以及二级缓存的工作模式

[外链图片转存中…(img-EWhAhBqu-1636368484973)]

配置二级缓存配置

第一步:启用二级缓存

在 SqlMapperConfig.xml 中启用二级缓存,如下代码所示,当

cacheEnabled 设置为 true 时启用二级缓存,设置为 false 时禁用二级缓存。

第二步:POJO 序列化

将所有的 POJO 类实现序列化接口 Java.io. Serializable。

model所有类继承Serializable

第三步:配置映射文件

在 Mapper 映射文件中添加,表示此 mapper 开启二级缓存。

当 SqlSeesion 关闭时,会将数据存入到二级缓存.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值