收集整理的mybatis资料
这是个系列文章,讲的非常不错
mybatis 详解(一)------JDBC https://www.cnblogs.com/ysocean/p/7271600.html
mybatis http://www.mybatis.org/mybatis-3/zh/java-api.html
Mybatis mapper.xml中常用标签详解 https://blog.csdn.net/liu_yanzhao/article/details/78572973
mybatise中文官网:https://mybatis.net.cn/index.html
传参:读取会有提示的,这里只给出写常用例子
/** * 读取方式:name = #{arg0} | #{param1} * 读取方式:age = #{myage} | #{param2} */ // List<PersonPojo> selectPerson1(String name, @Param("myage") Integer age); /** * 读取方式: name = #{arg0} | #{param1} * 读取方式: age = #{arg1} | #{param2} */ // List<PersonPojo> selectPerson1(String name, Integer age); /** * javabean参数:使用参数属性 * 读取方式: name = #{name} * 读取方式: age = #{age} */ // List<PersonPojo> selectPerson1(PersonPojo personPojo); /** * 读取方式: #{arg0} | #{param1} * 读取方式: #{arg1.name} | #{param2.name} */ // List<PersonPojo> selectPerson1(int age, PersonPojo personPojo); /** * 读取方式: #{list[0]} | #{arg0[0]} | #{collection[0]} */ // List<PersonPojo> selectPerson2(List<Integer> list); /** * 读取方式: #{listname[0]} | #{param1[0]} */ // List<PersonPojo> selectPerson2(@Param("listname") List<Integer> list); /** * 读取方式: #{array[0]} | #{arg0[0]} */ // List<PersonPojo> selectPerson2(Integer[] ary); /** * 读取方式: #{aryname[0]} | #{param1[0]} */ // List<PersonPojo> selectPerson2(@Param("aryname") Integer[] ary); /** * 读取方式: #{age} */ // List<PersonPojo> selectPerson3(Map<String, Integer> map); /** * 读取方式: #{mapname.age} */ // List<PersonPojo> selectPerson3(@Param("mapname") Map<String, Integer> map);
返回值
<!-- ==============返回值 resultMap ===================== --> <!-- ================基本mapper================ --> <resultMap id="MyTablePolyBase" type="com.mybatise.test.pojo.MyTablePojo"> <!-- id 元素对应的属性会被标记为对象的标识符,在比较对象实例时使用。 这样可以提高整体的性能,尤其是进行缓存和嵌套结果映射 column 数据库中的列名,或者是列的别名 property 映射到列结果的字段或属性。如果 JavaBean 有这个名字的属性(property),会先使用该属性。 比如,映射:“username”,或者:“address.street.number” --> <id column="id" property="id"></id> <result column="name" property="name"></result> </resultMap> <resultMap id="PersonpolyBase" type="com.mybatise.test.pojo.PersonPojo"> <id column="id" property="id"></id> <result column="name" property="name"></result> <result column="pass" property="pass"></result> <result column="age" property="age"></result> </resultMap> <!--===================== InnerJoinMap1 association测试多对一 ==================================--> <!-- 结果: [PersonPojo{id=4, name='小红', pass='5', age=30}InnerJoinPojo{myTablePojo=MyTablePojo{id=4, name='小红'}} , PersonPojo{id=6, name='aa', pass='5', age=18}InnerJoinPojo{myTablePojo=MyTablePojo{id=6, name='aa'}} , PersonPojo{id=9, name='王五', pass='5', age=18}InnerJoinPojo{myTablePojo=MyTablePojo{id=9, name='王五'}} ] --> <resultMap id="InnerJoinMap" type="com.mybatise.test.pojo.InnerJoinPojo"> <id column="id" property="id"></id> <result column="name" property="name"></result> <result column="pass" property="pass"></result> <result column="age" property="age"></result> <!--1.直接指定--> <!--<result column="tid" property="myTablePojo.id"/>--> <!--<result column="tname" property="myTablePojo.name"/>--> <!--2.association指定 javaType属性指定--> <!-- <association property="myTablePojo" javaType="com.mybatise.test.pojo.MyTablePojo">--> <!-- <id column="tid" property="id"></id>--> <!-- <result column="tname" property="name"></result>--> <!-- </association>--> <!--3.association resultMap类型指定--> <!-- <association property="myTablePojo" resultMap="MyTablePolyBase"></association>--> </resultMap> <!--===================== InnerJoinMap2 association测试一对多==================================--> <resultMap id="InnerJoinMap2" type="com.mybatise.test.pojo.InnerJoinPojo2"> <id column="tid" property="id"></id> <result column="tname" property="name"></result> <!-- 1.直接指定 结果: [MyTablePojo{id=5, name='五年级'}InnerJoinPojo2{personPojo=PersonPojo{id=4, name='小红', pass='5', age=30}} , MyTablePojo{id=5, name='五年级'}InnerJoinPojo2{personPojo=PersonPojo{id=6, name='aa', pass='5', age=18}} , MyTablePojo{id=5, name='五年级'}InnerJoinPojo2{personPojo=PersonPojo{id=9, name='王五', pass='5', age=18}} ] --> <!-- <result column="id" property="personPojo.id"></result>--> <!-- <result column="name" property="personPojo.name"></result>--> <!-- <result column="pass" property="personPojo.pass"></result>--> <!-- <result column="age" property="personPojo.age"></result>--> <!-- 2.association 方式 此处javaType属性可以省略 注意:association会简化合并结果 (id 重复覆盖原因) 结果:注意association 会舍弃多余重复主键的数据 [MyTablePojo{id=5, name='五年级'}InnerJoinPojo2{personPojo=PersonPojo{id=9, name='王五', pass='5', age=18}}] --> <!-- <association property="personPojo" javaType="com.mybatise.test.pojo.PersonPojo">--> <!-- <id column="id" property="id"></id>--> <!-- <result column="name" property="name"></result>--> <!-- <result column="pass" property="pass"></result>--> <!-- <result column="age" property="age"></result>--> <!-- </association>--> <!-- 3.association 方式 指定resultMap解析 结果同2 结果:注意association 会舍弃多余重复主键的数据 [MyTablePojo{id=5, name='五年级'}InnerJoinPojo2{personPojo=PersonPojo{id=9, name='王五', pass='5', age=18}}] --> <association property="personPojo" resultMap="PersonpolyBase"></association> </resultMap> <!--===================== InnerJoinMap3 测试collection==================================--> <!-- 结果: [MyTablePojo{id=5, name='五年级'} InnerJoinPojo3{personPojo=[PersonPojo{id=4, name='小红', pass='5', age=30}, PersonPojo{id=6, name='aa', pass='5', age=18}, PersonPojo{id=9, name='王五', pass='5', age=18}]} ] --> <resultMap id="InnerJoinMap3" type="com.mybatise.test.pojo.InnerJoinPojo3"> <id column="tid" property="id"></id> <result column="tname" property="name"></result> <!-- 1.使用resultMap属性接收--> <!-- <collection property="personPojoList" resultMap="PersonpolyBase"></collection>--> <!-- 2. 指定解析类 例如:List<PersonPojo> personPojoList property:属性名称:personPojoList (不可省略) javaType:属性类型:list (可省略) ofType:属性类型下的子类型:com.mybatise.test.pojo.PersonPojo (不可省略) --> <!-- <collection property="personPojoList" javaType="list" ofType="com.mybatise.test.pojo.PersonPojo">--> <!-- <id column="id" property="id"></id>--> <!-- <result column="name" property="name"></result>--> <!-- <result column="pass" property="pass"></result>--> <!-- <result column="age" property="age"></result>--> <!-- </collection>--> <!-- 3.使用resultMap 指定解析map (推荐)--> <collection property="personPojoList" resultMap="PersonpolyBase"></collection> </resultMap> <!-- <select id="selectPersonInnerJoin" resultType="com.mybatise.test.pojo.InnerJoinPojo">无法初始化内部嵌套属性--> <!-- <select id="selectPersonInnerJoin" resultMap="InnerJoinMap">--> <!-- <select id="selectPersonInnerJoin" resultMap="InnerJoinMap2">--> <select id="selectPersonInnerJoin" resultMap="InnerJoinMap3"> SELECT p.*, ta.id tid, ta.name tname FROM mytable ta INNER JOIN person p ON ta.id = p.pass WHERE ta.id = #{gradid}; </select>
分步查询
<!--================分步查询====================--> <select id="stepSelect" resultType="string"> SELECT m.name FROM mytable m where m.id = #{id} </select> <select id="stepSelect2" resultType="int"> SELECT m.id FROM mytable m where m.id = #{id} </select> <resultMap id="stepSelect" type="myTablePojo"> <association column="pass" property="id" select="stepSelect2"></association> <association column="pass" property="name" select="stepSelect"></association> </resultMap> <select id="selectFromOtherSelect" resultMap="stepSelect"> SELECT p.pass FROM person p where p.name = #{name} </select>
动态sql
<!--=====================动态sql===============================--> <!-- SELECT * FROM person p WHERE p.id =#{id} and p.name =#{name} and p.pass=#{pass} and p.age=#{age}--> <!-- where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除 SELECT * FROM person p <where> <if test="id != null and id != 0"> p.id=#{id} </if> <if test="name != null and name != ''"> and p.name=#{name} </if> <if test="pass != null and pass != ''"> and p.pass=#{pass} </if> <if test="age != null and age != ''"> and p.age=#{age} </if> </where> --> <!-- trim截取字符串: prefix:前缀,为sql整体添加一个前缀 prefixOverrides:去除整体字符串前面多余的字符 suffix: 后缀,为sql整体添加一个后缀 suffixOverrides:去除后面多余的字符串 SELECT * FROM person p <trim prefix="where" prefixOverrides="and" suffixOverrides="and"> <if test="id != null and id != 0"> p.id=#{id} </if> <if test="name != null and name != ''"> and p.name=#{name} </if> <if test="pass != null and pass != ''"> and p.pass=#{pass} </if> <if test="age != null and age != 0"> and p.age=#{age} </if> </trim> --> <!-- <choose> 语句,类似JAVA的switch,只需要有一个条件成立 SELECT * FROM person p <where> <choose> <when test="id!=null and id != 0"> p.id = #{id} </when> <when test="name != null and name != ''"> p.name = #{name} </when> <when test="pass != null and pass != ''"> p.pass = #{pass} </when> <when test="age != null and age != 0"> p.age = #{age} </when> <otherwise></otherwise> </choose> </where> --> <select id="slectDynamic" resultType="personPojo"> SELECT * FROM person p <where> <choose> <when test="id!=null and id != 0"> p.id = #{id} </when> <when test="name != null and name != ''"> p.name = #{name} </when> <when test="pass != null and pass != ''"> p.pass = #{pass} </when> <when test="age != null and age != 0"> p.age = #{age} </when> <otherwise></otherwise> </choose> </where> </select> <!--‐‐ <foreach> 是对集合进行遍历 collection="deptnos" 指定要遍历的集合 可以使用 @Param("ids") 指定参数集合的别名 不使用别名可以用: Available parameters are [arg0, collection, list] close="" 表示以什么结束 index="" 给定一个索引值 item="" 遍历的每一个元素的值 open="" 表示以什么开始 separator="" 表示多个元素的分隔符 SELECT * FROM person p <where> <foreach collection="ids" open="p.id IN (" close=")" item="id" separator=","> #{id} </foreach> </where> --> <select id="selectDynamic2" resultType="personPojo"> SELECT * FROM person p <where> <foreach collection="list" open="p.id IN (" close=")" item="id" separator=","> #{id} </foreach> </where> </select> <!-- <set> 需要全部参数都会更新 UPDATE person SET name=#{name}, pass=#{pass}, age=#{age} WHERE id=#{id} --> <!-- UPDATE person <set> <if test="name != null and name != ''"> name = #{name}, #注意逗号 </if> <if test="pass != null and pass != ''"> pass = #{pass}, </if> <if test="age != null and age != 0"> age = #{age}, </if> </set> <where> <if test="id != null"> id = #{id} </if> </where> --> <update id="updateDynamic3"> UPDATE person <set> <if test="name != null and name != ''"> name = #{name}, </if> <if test="pass != null and pass != ''"> pass = #{pass}, </if> <if test="age != null and age != 0"> age = #{age}, </if> </set> <where> <if test="id != null"> id = #{id} </if> </where> </update> <!-- <bind> 元素允许你在 OGNL 表达式以外创建一个变量,并将其绑定到当前的上下文 _parameter:函数传进来的参数 #{bindname} 是通过bind 创建的变量 <bind name="bindname" value="'%'+ _parameter + '%'"/> SELECT * From person where name LIKE #{bindname} --> <select id="selectDynamic3" resultType="personPojo"> <bind name="bindname" value="'%'+ _parameter + '%'"/> SELECT * From person where name LIKE #{bindname} </select> <!-- <sql> 使用sql 片段 --> <sql id="personColumns"> ${alisea}.name, ${alisea}.pass, ${alisea}.age </sql> <select id="selectDynamic4" resultType="personPojo"> SELECT <include refid="personColumns"> <property name="alisea" value="p"/> </include> FROM person p WHERE p.id=#{arg0} </select>
配置
mybatise.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> <typeAliases> <package name="com.mybatise.test.pojo"/> </typeAliases> <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/mytest"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <mapper resource="com/mybatise/test/pojo/PersonMapper.xml"/> <mapper resource="com/mybatise/test/pojo/MyTableMapper.xml"/> </mappers> </configuration>
MyTableMapper.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:编写接口的全类名,就是告诉要实现该配置文件是哪个接口的具体实现--> <mapper namespace="com.mybatise.test.mapper.IMyTable"> <!--增删改查操作不需要返回值,增删改返回的是影响的行数,mybatis会自动做判断--> <!--支持自增主键 useGeneratedKeys="true" keyProperty="id" --> <insert id="insertMyTablePojo" useGeneratedKeys="true" keyProperty="id"> -- 不支持自增主键配置 <!-- <selectKey order="BEFORE" resultType="int" keyProperty="id">--> <!-- SELECT MAX(id)+1 FROM mytable--> <!-- </selectKey>--> INSERT INTO mytable VALUES (#{id}, #{name}); </insert> <update id="updateMyTablePojo"> UPDATE mytable SET name=#{name} WHERE id = #{id}; </update> <delete id="deleteMyTablePojo" parameterType="int"> DELETE FROM mytable WHERE id = #{id}; </delete> <!-- select:表示这个操作是一个查询操作 id表示的是要匹配的方法的名称 resultType:表示返回值的类型,查询操作必须要包含返回值的类型 #{属性名}:表示要传递的参数的名称 --> <select id="selectMyTablePojo" resultType="com.mybatise.test.pojo.MyTablePojo"> SELECT * FROM mytable WHERE id = #{id}; </select> </mapper>
使用mybaties
private SqlSessionFactory sqlSessionFactory; private SqlSession sqlSession; @Before public void befor() throws IOException { /** * 根据全局配置文件创建出SqlSessionFactory * SqlSessionFactory:负责创建SqlSession对象的工厂 * SqlSession:表示跟数据库建议的一次会话 */ String resource = "mybatise.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); sqlSession = sqlSessionFactory.openSession(true); } @After public void after() { sqlSession.close(); } //单个参数测试一:简单参数 @Test public void test01() { IPerson mapper = sqlSession.getMapper(IPerson.class); //单一简单参数:随便写 if (mapper.deletePerson(10)) { System.out.println("成功"); } else { System.out.println("失败"); } }
缓存:
默认情况下,只启用了本地的会话缓存,它仅仅对一个会话中的数据进行缓存。 要启用全局的二级缓存,只需要在你的 SQL 映射文件中添加一行:
<cache/>
当添加上该标签之后,会有如下效果:
- 映射语句文件中的所有 select 语句的结果将会被缓存。
- 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
- 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来
- 清除不需要的缓存。
- 缓存不会定时进行刷新(也就是说,没有刷新间隔)。
- 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。
- 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以
- 安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。
- 在进行配置的时候还会分为一级缓存和二级缓存:
一级缓存:线程级别的缓存,是本地缓存,sqlSession级别的缓存
二级缓存:二级缓存是全局作用域缓存,默认是不开启的,需要手动进行配置。Mybatis提供二级缓存的接口以及实现,缓存实现的时候要求实体类实现Serializable接口,二级缓存在sqlSession关闭或提交之后才会生效。
一级缓存的使用
一级缓存是sqlsession级别的缓存,默认是存在的。在下面的案例中,大家发现我发送了两个相同的请求,但是sql语句仅仅执行了一次,那么就意味着第一次查询的时候已经将结果进行了缓存。
@Test public void test01() { SqlSession sqlSession = sqlSessionFactory.openSession(); try { EmpDao mapper = sqlSession.getMapper(EmpDao.class); List<Emp> list = mapper.selectAllEmp(); for (Emp emp : list) { System.out.println(emp); } System.out.println("‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐"); List<Emp> list2 = mapper.selectAllEmp(); for (Emp emp : list2) { System.out.println(emp); } } catch (Exception e) { e.printStackTrace(); } finally { sqlSession.close(); } }
在大部分的情况下一级缓存是可以的,但是有几种特殊的情况会造成一级缓存失效:
1.一级缓存是sqlSession级别的缓存,如果在应用程序中只有开启了多个sqlsession,那么会造成缓存失效
@Test public void test02() { SqlSession sqlSession = sqlSessionFactory.openSession(); EmpDao mapper = sqlSession.getMapper(EmpDao.class); List<Emp> list = mapper.selectAllEmp(); for (Emp emp : list) { System.out.println(emp); } System.out.println("================================"); SqlSession sqlSession2 = sqlSessionFactory.openSession(); EmpDao mapper2 = sqlSession2.getMapper(EmpDao.class); List<Emp> list2 = mapper2.selectAllEmp(); for (Emp emp : list2) { System.out.println(emp); } sqlSession.close(); sqlSession2.close(); }
2、在编写查询的sql语句的时候,一定要注意传递的参数,如果参数不一致,那么也不会缓存结果
3、如果在发送过程中发生了数据的修改,那么结果就不会缓存
@Test public void test03() { SqlSession sqlSession = sqlSessionFactory.openSession(); EmpDao mapper = sqlSession.getMapper(EmpDao.class); Emp empByEmpno = mapper.findEmpByEmpno(1111); System.out.println(empByEmpno); System.out.println("================================"); empByEmpno.setEname("zhangsan"); int i = mapper.updateEmp(empByEmpno); System.out.println(i); System.out.println("================================"); Emp empByEmpno1 = mapper.findEmpByEmpno(1111); System.out.println(empByEmpno1); sqlSession.close(); }
4、在两次查询期间,手动去清空缓存,也会让缓存失效
@Test public void test03() { SqlSession sqlSession = sqlSessionFactory.openSession(); EmpDao mapper = sqlSession.getMapper(EmpDao.class); Emp empByEmpno = mapper.findEmpByEmpno(1111); System.out.println(empByEmpno); System.out.println("================================"); System.out.println("手动清空缓存"); sqlSession.clearCache(); System.out.println("================================"); Emp empByEmpno1 = mapper.findEmpByEmpno(1111); System.out.println(empByEmpno1); sqlSession.close(); }
二级缓存的使用
步骤:
1、全局配置文件中添加如下配置:<setting name="cacheEnabled" value="true"/>
2、需要在使用二级缓存的映射文件出使用<cache/>标签标注
3、实体类必须要实现Serializable接口
@Test public void test04() { SqlSession sqlSession = sqlSessionFactory.openSession(); SqlSession sqlSession2 = sqlSessionFactory.openSession(); EmpDao mapper = sqlSession.getMapper(EmpDao.class); EmpDao mapper2 = sqlSession2.getMapper(EmpDao.class); Emp empByEmpno = mapper.findEmpByEmpno(1111); System.out.println(empByEmpno); sqlSession.close(); Emp empByEmpno1 = mapper2.findEmpByEmpno(1111); System.out.println(empByEmpno1); sqlSession2.close(); }
缓存属性属性
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
eviction:表示缓存回收策略,默认是LRU
LRU:最近最少使用的,移除最长时间不被使用的对象
FIFO:先进先出,按照对象进入缓存的顺序来移除
SOFT:软引用,移除基于垃圾回收器状态和软引用规则的对象
WEAK:弱引用,更积极地移除基于垃圾收集器状态和弱引用规则的对象
flushInternal:刷新间隔,单位毫秒默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新
size:引用数目,正整数代表缓存最多可以存储多少个对象,太大容易导致内存溢出
readonly:只读,true/false
true:只读缓存,会给所有调用这返回缓存对象的相同实例,因此这些对象不能被修改。
false:读写缓存,会返回缓存对象的拷贝(序列化实现),这种方式比较安全,默认值
//可以看到会去二级缓存中查找数据,而且二级缓存跟一级缓存中不会同时存在数据,因为二级缓存中的数据是在sqlsession 关闭之后才生效的 @Test public void test05() { SqlSession sqlSession = sqlSessionFactory.openSession(); EmpDao mapper = sqlSession.getMapper(EmpDao.class); Emp empByEmpno = mapper.findEmpByEmpno(1111); System.out.println(empByEmpno); sqlSession.close(); SqlSession sqlSession2 = sqlSessionFactory.openSession(); EmpDao mapper2 = sqlSession2.getMapper(EmpDao.class); Emp empByEmpno2 = mapper2.findEmpByEmpno(1111); System.out.println(empByEmpno2); Emp empByEmpno3 = mapper2.findEmpByEmpno(1111); System.out.println(empByEmpno3); sqlSession2.close(); }
// 缓存查询的顺序是先查询二级缓存再查询一级缓存 @Test public void test05() { SqlSession sqlSession = sqlSessionFactory.openSession(); EmpDao mapper = sqlSession.getMapper(EmpDao.class); Emp empByEmpno = mapper.findEmpByEmpno(1111); System.out.println(empByEmpno); sqlSession.close(); SqlSession sqlSession2 = sqlSessionFactory.openSession(); EmpDao mapper2 = sqlSession2.getMapper(EmpDao.class); Emp empByEmpno2 = mapper2.findEmpByEmpno(1111); System.out.println(empByEmpno2); Emp empByEmpno3 = mapper2.findEmpByEmpno(1111); System.out.println(empByEmpno3); Emp empByEmpno4 = mapper2.findEmpByEmpno(7369); System.out.println(empByEmpno4); Emp empByEmpno5 = mapper2.findEmpByEmpno(7369); System.out.println(empByEmpno5); sqlSession2.close(); }
二级缓存的作用范围:
如果设置了全局的二级缓存配置,那么在使用的时候需要注意,在每一个单独的select语句中,可以设置将查询缓存关闭,以完成特殊的设置
1、在setting中设置,是配置二级缓存开启,一级缓存默认一直开启 <setting name="cacheEnabled" value="true"/>
2、select标签的useCache属性:在每一个select的查询中可以设置当前查询是否要使用二级缓存,只对二级缓存有效
3、sql标签的flushCache属性:增删改操作默认值为true,sql执行之后会清空一级缓存和二级缓存,而查询操作默认是false
4、sqlSession.clearCache() 只是用来清楚一级缓存
整合redis缓存:https://github.com/mybatis/redis-cache
1. 添加redis-mybatis 缓存适配器 依赖
<dependencies> ... <dependency> <groupId>org.mybatis.caches</groupId> <artifactId>mybatis-redis</artifactId> <version>1.0.0-beta2</version> </dependency> ... </dependencies>
2 添加redis.properties在resources根目录
host=localhost port=6379 connectionTimeout=5000 soTimeout=5000 password=无密码可不填 database=0 clientName=
3 设置mybatis二级缓存实现类
<mapper namespace="org.acme.FooMapper">
<cache type="org.mybatis.caches.redis.RedisCache" />
...
</mapper>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!