Mybatis笔记

    科技2022-07-10  142

    Mybatis笔记

    常用快捷键 代码块:Ctrl+Shift+K 公式块:Ctrl+Shift+M 引用:Ctrl+Shift+Q 有序列表:Ctrl+Shift+[ 无序列表:Ctrl+Shift+]

    1、Mybatis简介

    官网:https://mybatis.org/mybatis-3/zh/index.html

    ​ MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

    2、第一个Mybatis程序

    2.1、基本步骤

    1)建立一个maven项目,

    ** 在pom.xml文件中**加载mysql驱动依赖、mybatis依赖和junit依赖****

    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.bjpowernode</groupId> <artifactId>LogMybatis</artifactId> <version>1.0-SNAPSHOT</version> <name>LogMybatis</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <!--mysqL驱动依赖版本不能过高--> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.35</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.5</version> </dependency> <!--log4j依赖--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies> <build> <resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> <include>**/*.properties</include> </includes> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.xml</include> <include>**/*.properties</include> </includes> </resource> </resources> </build> </project>
    2)配置mybatis-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> <!--各种配置文件有固定的顺序--> <!--引入外部配置文件--> <properties resource="dp.properties"/> <settings> <setting name="logImpl" value="LOG4J"/> </settings> <!--别名--> <typeAliases> <typeAlias type="com.bjpowernode.pojo.user" alias="User" /> </typeAliases> <environments default="jdbc"> <environment id="jdbc"> <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> <!--连接mapper, 注意路径是target下面生成的路径,使用斜杠"/",使用复制路径--> <mappers> <mapper resource="com/bjpowernode/dao/UserDao.xml"/> </mappers> </configuration>

    其中,JDBC注册驱动按下面的properties配置文件进行注册连接

    driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/bjpowernode?useSSL=true&useUnicode=true&characterEncoding=UTF-8 username=root password=199478
    3)书写相关类

    ​ 书写pojo.user(数据库表)实例类、utils.util的JDBC工具类和dao.userdao(userMapper)接口,并配置实现方法的xml文件

    ​ a. 书写pojo.user数据库实例类(注意和数据库名字保持一致)

    package com.bjpowernode.pojo; public class user { private int Id; private String name; private int age; public user() { } public user(int id, String name, int age) { Id = id; this.name = name; this.age = age; } public int getId() { return Id; } public void setId(int id) { Id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "user{" + "Id=" + Id + ", name='" + name + '\'' + ", age=" + age + '}'; } }

    ​ b. 书写dao.userdao接口和实现xml配置文件

    //dao.userdao接口 package com.bjpowernode.dao; import com.bjpowernode.pojo.user; import java.util.List; import java.util.Map; public interface UserDao { List<user> selectUser(); //插入数据 public int insertUser(user u); //根据id查找数据 public user getuserById(int id); //更新 public int updateById(user user); //删除数据 public int deleteById(int Id); //通过map方式操作数据库 public int addByMap(Map<String, Object> map); //根据Id实现分页查询 public List<user> selectByLimit(Map<String, Integer> map1); }

    <?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.bjpowernode.dao.UserDao"> <!--借助与map实现limit分页查询--> <select id="selectByLimit" parameterType="map" resultType="User"> select * from user limit #{startIndex}, #{pageSize} </select> <!--普通查询--> <select id="selectUser" resultType="com.bjpowernode.pojo.user"> select * from user </select> <!--插入数据--> <insert id="insertUser" parameterType="com.bjpowernode.pojo.user"> insert into user (Id,name,age) values (#{Id},#{name}, #{age}) </insert> <!--插入map类型数据--> <insert id="addByMap" parameterType="map"> insert into user (Id,name,age) values (#{mapId},#{mapName},#{mapAge}) </insert> <!--获取数据--> <select id="getuserById" resultType="com.bjpowernode.pojo.user"> select * from user where Id=#{Id} </select> <!--根据id更新数据--> <update id="updateById" parameterType="com.bjpowernode.pojo.user"> update user set name = #{name}, age =#{age} where Id=#{Id} </update> <!--根据id删除数据--> <delete id="deleteById" > delete from user where Id=#{Id} </delete> </mapper>

    ​ c. 书写util工具类,包装SqlSession实例对象

    package com.bjpowernode.Utils; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException; import java.io.InputStream; public class utils { static private SqlSessionFactory sqlSessionFactory; static { try { //这三句话是mybatis官网固定写法 String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } public static SqlSession getsqlSession(){ return sqlSessionFactory.openSession(); } }
    4) 编写测试类,实现测试
    package com.bjpowernode.dao; import com.bjpowernode.Utils.utils; import com.bjpowernode.pojo.user; import org.apache.ibatis.session.SqlSession; import org.apache.log4j.Logger; import org.junit.Test; import java.util.HashMap; import java.util.List; import java.util.Map; public class Testdao { static Logger logger = Logger.getLogger(Testdao.class); //增、删、改需要提交事务 @Test public void selectByLimit(){ //实现分页查询的功能 SqlSession sqlSession = null; try{ sqlSession = utils.getsqlSession(); UserDao mapper = sqlSession.getMapper(UserDao.class); Map<String,Integer> map1 = new HashMap<>(); //Map<String,Integer> map2 = new HashMap<>(); map1.put("startIndex", 1); map1.put("pageSize", 2); List<user> users = mapper.selectByLimit(map1); for (user user : users) { System.out.println(user); } }finally { sqlSession.close(); } } //采用map方式插入数据 @Test public void insertByMap(){ SqlSession sqlSession = null; try { sqlSession = utils.getsqlSession(); UserDao mapper = sqlSession.getMapper(UserDao.class); Map<String, Object> map = new HashMap<String, Object>(); map.put("mapId", 7); map.put("mapName", "张飞"); map.put("mapAge", 42); int nums = mapper.addByMap(map); sqlSession.commit(); if (nums>0) System.out.println("数据插入成功~"); else System.out.println("数据插入失败~~"); }finally { sqlSession.close(); } } }

    3、CRUD 增删改查

    package com.bjpowernode.dao; import com.bjpowernode.Utils.utils; import com.bjpowernode.pojo.user; import org.apache.ibatis.session.SqlSession; import org.apache.log4j.Logger; import org.junit.Test; import java.util.HashMap; import java.util.List; import java.util.Map; public class Testdao { static Logger logger = Logger.getLogger(Testdao.class); //增、删、改需要提交事务 //查询 @Test public void selectByLimit(){ //实现分页查询的功能 SqlSession sqlSession = null; try{ sqlSession = utils.getsqlSession(); UserDao mapper = sqlSession.getMapper(UserDao.class); Map<String,Integer> map1 = new HashMap<>(); //Map<String,Integer> map2 = new HashMap<>(); map1.put("startIndex", 1); map1.put("pageSize", 2); List<user> users = mapper.selectByLimit(map1); for (user user : users) { System.out.println(user); } }finally { sqlSession.close(); } } @Test public void tse01(){ SqlSession sqlSession = null; try{ //获取SqlSession sqlSession = utils.getsqlSession(); //获取mapper,等价于dao。用于操作数据库的对象实例 UserDao mapper = sqlSession.getMapper(UserDao.class); //调用方法,进行查询操作 List<user> userList = mapper.selectUser(); for (user user : userList) { System.out.println(user); } }finally { //关闭资源,放在finally块中,防止忘记关闭 sqlSession.close(); } } @Test public void testLog4j(){ logger.debug("DUBUG:进入了Bug测试"); logger.error("Error:进入了Bug测试"); logger.info("Info:进入了Bug测试"); } @Test public void testInsert(){ user us = new user(11,"鲁智深",35); SqlSession sqlSession = null; try{ sqlSession = utils.getsqlSession(); UserDao mapper = sqlSession.getMapper(UserDao.class); int nums = mapper.insertUser(us); //注意提交事务 sqlSession.commit(); if (nums > 0){ System.out.println("插入数据成功~~"); }else { System.out.println("插入输入失败~~~"); } }finally { sqlSession.close(); } } //根据id查询 @Test public void getuserById(){ SqlSession sqlSession = null; try{ sqlSession = utils.getsqlSession(); UserDao mapper = sqlSession.getMapper(UserDao.class); user user = mapper.getuserById(4); System.out.println(user); }finally { sqlSession.close(); } } //更新数据库 @Test public void updateUser(){ SqlSession sql = null; try{ user us = new user(1,"关羽",56); sql = utils.getsqlSession(); UserDao mapper = sql.getMapper(UserDao.class); int nums = mapper.updateById(us); //提交事务 sql.commit(); if(nums > 0){ System.out.println("数据更新成功~~~"); }else { System.out.println("数据更新失败~~"); } }finally { sql.close(); } } @Test public void deleteById(){ SqlSession sqlSession = null; try{ sqlSession = utils.getsqlSession(); UserDao mapper = sqlSession.getMapper(UserDao.class); int nums = mapper.deleteById(3); //提交事务 sqlSession.commit(); if(nums > 0) System.out.println("数据删除成功~~"); else System.out.println("数据删除失败~~"); }finally { sqlSession.close(); } } //采用map方式插入数据 @Test public void insertByMap(){ SqlSession sqlSession = null; try { sqlSession = utils.getsqlSession(); UserDao mapper = sqlSession.getMapper(UserDao.class); Map<String, Object> map = new HashMap<String, Object>(); map.put("mapId", 7); map.put("mapName", "张飞"); map.put("mapAge", 42); int nums = mapper.addByMap(map); sqlSession.commit(); if (nums>0) System.out.println("数据插入成功~"); else System.out.println("数据插入失败~~"); }finally { sqlSession.close(); } } }

    4、配置解析

    5、resultMap

    解决字段名和属性名字不一致的情况

    6、日志

    7、分页

    1)limit

    2)RowBounds(了解)

    8、使用注解开发

    8.1 面向接口编程

    根本原因:解耦和

    关于接口的理解

    接口从更深层次的理解,应该是定义(规范、约束)与实现(名、实分离的原则)的分离接口的本身反映了系统设计人员的抽象理解接口应该有两类: 第一类是对一个个体的抽象,即对应一个抽象体第二类是对一个个体某一方面的抽象,即形成一个抽象面 一个个体可能有多个抽象面,抽象体与抽象面是由区别的

    三个面向区别

    面向对象是指,我们在考虑问题时,以对象为单位,考虑他的属性及方法面向过程是指,我们在考虑问题时,以一个具体的流程(事务过程)为单位,考虑他的实现接口设计与非接口设计是针对复用技术而言的,与面向对象(过程)不是一个问题。更多的体现是对系统整体的架构。

    8.2 面向注解开发流程

    1. 注解在接口中的实现
    package com.bjpowernode.dao; import com.bjpowernode.pojo.user; import org.apache.ibatis.annotations.Select; import java.util.List; import java.util.Map; public interface UserDao { //使用注解方式进行查询、删除、增加、更新等操作 @Select("select * from user limit 1,3") public List<user> selectUser(); }
    2. 需要在核心配置mybatis-config.xml文件中绑定接口
    <mappers> <!--mapper class绑定接口--> <mapper class="com.bjpowernode.dao.UserDao"/> </mappers>
    3. 测试:编写测试类
    4. 底层实现原理:动态代理;本质:反射

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ul9IOBS5-1601702455044)(C:\Users\李柏松\AppData\Roaming\Typora\typora-user-images\image-20201001180836065.png)]

    8.3 注解的CRUD

    设置自动提交

    public static SqlSession getsqlSession(){ //true表示设置自动提交事务 return sqlSessionFactory.openSession(true); }

    使用注解实现增删改查

    package com.bjpowernode.dao; import com.bjpowernode.pojo.user; import org.apache.ibatis.annotations.*; import java.util.List; import java.util.Map; public interface UserDao { @Select("select * from user") List<user> selectUser(); //根据id查询, 注意Param中的参数名字与#{Id}一致 @Select("select * from user where Id = #{userId}") user getUserById(@Param("userId") int id); //添加用户 @Insert("insert into user(Id, name, age) values (#{userId}, #{userName}, #{userAge})") int addUser(@Param("userId") int id, @Param("userName") String name, @Param("userAge") int age); //更新 @Update("update user set name=#{name}, age=#{age} where Id=#{Id}") int updateUser(user user); //删除 @Delete("delete from user where Id=#{userId}") int deleteUser(@Param("userId") int id); }

    编写测试类执行操作

    @Test public void tse01(){ SqlSession sqlSession = null; try{ //获取SqlSession sqlSession = utils.getsqlSession(); //获取mapper,等价于dao。用于操作数据库的对象实例 UserDao mapper = sqlSession.getMapper(UserDao.class); //调用方法,进行查询操作 List<user> userList = mapper.selectUser(); for (user user : userList) { System.out.println(user); } }finally { //关闭资源,放在finally块中,防止忘记关闭 sqlSession.close(); } }

    注意:在mybatis-config中绑定接口

    <mappers> <mapper class="com.bjpowernode.dao.UserDao"/> </mappers>

    关于@Param()注解

    基本类型的参数或者String类型,需要加入,引用类型不需要加

    //更新 @Update("update user set name=#{name}, age=#{age} where Id=#{Id}") int updateUser(user user);

    如果只有一个基本类型,可以忽略,但是建议加上

    在SQL中引用的就是@Param()中设置的属性名字

    9、Lombok

    ​ idea构造方法的插件,一般不用

    10、多对一处理

    测试环境搭建

    新建实体类Teacher、Student

    建立Mapper接口

    建立Mapper.xml文件

    在核心配置文件中绑定注册我们的Mapper接口或者文件

    <mappers> <!--绑定class--> <mapper class="com.bjpowernode.dao.TeacherMapper"/> <mapper class="com.bjpowernode.dao.StudentMapper"/> <!--第二种:绑定mapper配置文件--> </mappers>

    测试

    案例:需求:查找所有学生,即对应的老师

    方式1:按照查询嵌套处理:对应于子查询 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.bjpowernode.dao.StudentMapper"> <!--查询所有学生的信息,以及对应的老师的信息 1. 查询所有的学生 2. 根据查询出来的学生的id,寻找对应的老师 --> <select id="SelectStudent" resultMap="StudentTeacher"> select * from student </select> <!--StudentTeacher表示查询出来的学生对应的老师 ,进行结果集映射--> <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="selectTeacher"/> </resultMap> <select id="selectTeacher" resultType="Teacher"> select * from teacher where id=#{id}; </select> </mapper>

    方式2:按照结果映射处理:对应于连表查询

    <!--第二种:按照结果映射查询--> <!--查询语句 select s.id sid, s.name sname, t.name from student s, teacher t where sid = tid --> <select id="SelectStudent2" resultMap="StudentTeacher2"> select s.id sid, s.name sname, t.id tid, t.name tname from student s, teacher t where s.tid = t.id </select> <!--type指java实体类的类型,这儿查询出来的是一个Student类--> <resultMap id="StudentTeacher2" type="Student"> <!--property是java实体类的类型的属性名字 column是数据库的名字--> <result property="id" column="sid"/> <result property="name" column="sname"/> <association property="teacher" javaType="Teacher"> <result property="id" column="tid"/> <result property="name" column="tname"/> </association> </resultMap>

    11、一对多处理

    一个老师对应多个学生,对于老师来说是一对多关系

    1. 方式1:

    按照查询嵌套处理:对应于子查询

    <!--方式1:按照查询映射处理,对应于子查询--> <select id="selectTeacher2" resultMap="TeacherStudent2"> select * from teacher </select> <resultMap id="TeacherStudent2" type="Teacher"> <result property="id" column="id"/> <result property="name" column="name"/> <collection property="student" column="id" select="studentselect" javaType="ArrayList" ofType="Student"/> </resultMap> <select id="studentselect" resultType="Student"> select * from student where tid=#{id} </select>

    2. 方式2:结果集映射

    按照结果嵌套处理:对应于子查询 <!--方式2:按照结果嵌套查询(简单),resultMap的使用理解--> <select id="selectTeacher" resultMap="TeacherStudent"> select t.id tid, t.name tname, s.id sid, s.name sname, s.tid from teacher t, student s where s.tid=t.id </select> <resultMap id="TeacherStudent" type="teacher"> <result property="id" column="tid"/> <result property="name" column="tname"/> <!--复杂的属性,我们需要单独处理,对象使用association处理 集合使用collection处理 ofType是java指定的属性类型,集合中的泛型使用ofType获取 --> <collection property="student" ofType="Student"> <result property="id" column="sid"/> <result property="name" column="sname"/> <result property="tid" column="tid"/> </collection> </resultMap>

    3. 小结

    关联 --association【多对一】集合–collection 【一对多】javaType 和 ofType javaType:指定实体类中属性的类型ofType:指定映射到List或者集合中的泛型(pojo) 类型,泛型中的约束类型

    注意点:

    保证SQL的可读性,尽量保证通俗易懂注意一对多和多对一中,属性名字和字段的问题如果问题不好排查错误,可以使用日志,建议使用log4j

    面试高频(慢sql):

    Mysql引擎InnoDB底层原理索引索引优化

    12、动态SQL

    动态SQL:根据不同的条件生成不同的SQL语句

    动态SQL就是拼接sql语句,首先需要保证sql语句正确

    所以在写的时候,建议首先写出正确的sql语句,然后再在mybatis中写出对应的操作语句

    1. if

    <!--动态Sql之if的用法--> <select id="selectBlogByIf" parameterType="map" resultType="blog"> select * from blog where 1=1 <if test="title != null"> and title=#{title} </if> <if test="author != null"> and author=#{author} </if> </select>

    2. where

    where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。

    <select id="selectBlogByIfWhere" parameterType="map" resultType="blog"> select * from blog <where> <!--智能的自动拼接sql--> <if test="title != null"> title=#{title} </if> <if test="author != null"> and author=#{author} </if> </where> </select>

    3. choose、when、otherwise

    ​ 有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

    下面的语句实现选择查询:如果传入了 “title” 就按 “title” 查找,传入了 “author” 就按 “author” 查找的情形。若两者都没有传入,就返回标记为 featured 的 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>

    4. sql片段

    使用sql标签抽取公共部分,实现代码复用,在使用地方使用include标签引用即可

    注意事项:

    1. 最好基于单表来定义sql片段; 2. 不要存在where标签 <sql id="sqlpianduan"> <if test="title != null"> and title=#{title} </if> <if test="author != null"> and author=#{author} </if> </sql> <!--动态Sql之if的用法--> <select id="selectBlogByIf" parameterType="map" resultType="blog"> select * from blog where 1=1 <include refid="sqlpianduan"></include> </select>

    5. trim、where、set

    <update id="updateBlogBySet" parameterType="map"> update blog <set> <if test="author != null"> author=#{author}, </if> <if test="title != null"> title=#{title} </if> </set> where id=#{id} </update>

    6. Foreach

    动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)

    foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符。

    <!--参数解释:select * from blog where (id = 1 or id = 2 or id = 3) collection 传入的进行遍历的list集合 item 集合中的每一个元素 open 拼接的sql以什么开头, 这里以"("开头 close 拼接的sql以什么结尾,这里以")"开头 separator 以什么分割,这里是or index 起始下标 这里没有(默认从头开始) --> <select id="selectBlogByForeach" parameterType="map" resultType="blog"> select * from blog <where> <foreach collection="ids" item="id" separator=" or " open=" (" close=" )"> id=#{id} </foreach> </where> </select> //测试foreach的测试函数 @Test public void selectBlogByForeach(){ SqlSession sqlSession = null; try { sqlSession = utils.getsqlSession(); BlogMapper mapper = sqlSession.getMapper(BlogMapper.class); //传入一个map集合,集合中的元素就是需要遍历的list集合 HashMap map = new HashMap(); List<Integer> ids = new ArrayList<>(); ids.add(1); ids.add(2); ids.add(3); //注意这儿的key需要与xml文件中的foreach语句中名字对应,否则找不到 //比如map中放的key应该和collection="ids"名字一致 map.put("ids",ids); List<Blog> blogs = mapper.selectBlogByForeach(map); for (Blog blog : blogs) { System.out.println(blog); } }finally { sqlSession.close(); } }

    13、缓存

    1. 缓存简介

    定义:存在内存中的临时数据叫做缓存

    目的:提高查询速度

    能够使用缓存的数据:经常使用且不经常改变的数据

    2. mybatis缓存

    mybatis系统默认定义了两级缓存:一级缓存和二级缓存默认情况开启一级缓存二级缓存需要手动开启和配置,基于namespace级别的缓存mybatis定义了缓存接口Cache,可以通过实现Cache接口自定义二级缓存基本上就是这样。Mybatis简单语句的效果如下: 映射语句文件中的所有 select 语句的结果将会被缓存。映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。缓存不会定时进行刷新(也就是说,没有刷新间隔)。缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

    3. 一级缓存

    一级缓存也叫本地缓存:SqlSession (SqlSession 开启到关闭阶段)一级缓存默认自动开启,只在一次SqlSession 中有用一级缓存相当于一个map

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b97vy4Un-1601702455047)(C:\Users\李柏松\AppData\Roaming\Typora\typora-user-images\image-20201002105704407.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9bTYiR9c-1601702455049)(C:\Users\李柏松\AppData\Roaming\Typora\typora-user-images\image-20201002110137484.png)]

    4. 二级缓存

    二级缓存是事务性的。这意味着,当 SqlSession 完成并提交时,或是完成并回滚,但没有执行 flushCache=true 的 insert/delete/update 语句时,缓存会获得更新。

    二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存基于namespace级别的缓存,一个名称空间,对应一个二级缓存工作机制 一个会话查询一条数据,这个数据会被放在当前会话的一级缓存中如果当前会话关闭了,这个会话对应的一级缓存就没了,但是我们想要的是:会话关闭了,一级缓存中的数据会被保存到二级缓存中新的会话查询信息,就可以从二级缓存中获取内容不同的mapper查出的数据会放在自己对应的缓存中

    步骤:

    开启全局缓存

    <!--配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。--> <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>

    在要使用二级缓存的mapper中开启

    <cache/>

    5. 缓存原理

    查询时,先看二级缓存有没有数据,再看一级缓存有没有,否则走数据库。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nRiu7hDU-1601702455051)(C:\Users\李柏松\AppData\Roaming\Typora\typora-user-images\image-20201002130721204.png)]

    6. 自定义缓存

    Ehcacha是一种广泛使用的开源Java分布式缓存。主要面向通用缓存 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.bjpowernode.dao.TeacherMapper"> <!--配置Ehcache缓存--> <cache type="org.mybatis.caches.ehcache.EhcacheCache"/> </mapper>

    。这意味着,当 SqlSession 完成并提交时,或是完成并回滚,但没有执行 flushCache=true 的 insert/delete/update 语句时,缓存会获得更新。

    二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存基于namespace级别的缓存,一个名称空间,对应一个二级缓存工作机制 一个会话查询一条数据,这个数据会被放在当前会话的一级缓存中如果当前会话关闭了,这个会话对应的一级缓存就没了,但是我们想要的是:会话关闭了,一级缓存中的数据会被保存到二级缓存中新的会话查询信息,就可以从二级缓存中获取内容不同的mapper查出的数据会放在自己对应的缓存中

    步骤:

    开启全局缓存

    <!--配置创建了一个 FIFO 缓存,每隔 60 秒刷新,最多可以存储结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此对它们进行修改可能会在不同线程中的调用者产生冲突。--> <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>

    在要使用二级缓存的mapper中开启

    <cache/>

    5. 缓存原理

    查询时,先看二级缓存有没有数据,再看一级缓存有没有,否则走数据库。

    [外链图片转存中…(img-nRiu7hDU-1601702455051)]

    6. 自定义缓存

    Ehcacha是一种广泛使用的开源Java分布式缓存。主要面向通用缓存 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.bjpowernode.dao.TeacherMapper"> <!--配置Ehcache缓存--> <cache type="org.mybatis.caches.ehcache.EhcacheCache"/> </mapper>

    Redis数据库来做缓存

    Processed: 0.023, SQL: 8