# mybatis **Repository Path**: xfanonymous/mybatis ## Basic Information - **Project Name**: mybatis - **Description**: MyBatis笔记,使用及实操。 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2023-09-26 - **Last Updated**: 2024-04-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 开发环境 - IDE:idea 2019.2 - 构建工具:maven 3.5.4 - MySQL版本:MySQL 5.7 - MyBatis版本:MyBatis 3.5.7 ## 说明 - mybatis_demo1: Mybatis核心文件与原理、CRUD基本功能实现与验证 - mybatis_demo2: 封装获取SqlSession的工具类、Mapper接口方法为多参数时SQL语句的动态赋值、查询结果多种保存场景、执行特殊SQL语句(模糊搜索、批量删除、获取自增主键) - mybatis_demo3: resultMap解决数据库字段名和类属性名不一致、多对一(属性对应对象)、一对多(属性对应集合)、动态SQL、MyBatis缓存 - mybatis_mbg: Mybatis逆向工程、分页插件的使用 ## 数据库 ```sql CREATE TABLE `t_user` ( `id` int NOT NULL AUTO_INCREMENT, `username` varchar(20) DEFAULT NULL, `password` varchar(20) DEFAULT NULL, `age` int DEFAULT NULL COMMENT 'char类型默认1长度', `sex` char(1) DEFAULT NULL, `email` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8mb3 CREATE TABLE `t_emp` ( `eid` int NOT NULL AUTO_INCREMENT, `emp_name` varchar(20) DEFAULT NULL, `age` int DEFAULT NULL, `sex` char(1) DEFAULT NULL, `email` varchar(20) DEFAULT NULL, `did` int DEFAULT NULL, PRIMARY KEY (`eid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 CREATE TABLE `t_dept` ( `did` int NOT NULL AUTO_INCREMENT, `dept_name` varchar(20) DEFAULT NULL, PRIMARY KEY (`did`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 ``` # MyBatis - MyBatis 是支持定制化 SQL、存储过程、高级映射的持久层框架,实现将业务数据持久化到数据库。 - MyBatis 避免了 JDBC SQL 硬编码、手动设置参数和获取结果集的操作。 - MyBatis 使用XML或注解进行配置和原始映射,将接口和POJO(Plain Old Java Objects,普通Java对象)映射成数据库中的记录。 - MyBatis 面向接口编程,是半自动的ORM(Object Relation Mapping,对象关系映射)框架。 # 核心步骤 1. 实体类 POJO,和数据库中的一行数据映射,定义属性、有参|无参构造方法、Getter|Setter、toString() 。 2. DAO 层 Mapper 接口,定义CRUD操作方法、关联XML映射文件。不需要提供实现类。 3. XML 映射文件,保存SQL语句、通过 `` 关联Mapper接口,通过 ``关联Mapper接口的方法。 4. 测试文件,通过核心配置文件`mybatis-config.xml`获取`SQLSessiond`对象、获取Mapper接口实现类的对象(代理模式)、调用Mapper接口方法映射执行XML文件SQL。 5. 要完成映射需要满足:Mapper接口文件名和XML映射文件名一致、Mapper接口所在的包路径要和XML映射文件所在包路径一致。 ## pom.xml引入依赖 - mybatis、junit、mysql、log4j。 - log4j 用于打印日志,在 resource 目录下创建 log4j.xml 配置文件,可以对不同 logger 设置不同日志级别,FATAL(致命)>ERROR(错误)>WARN(警告)>INFO(信息)>DEBUG(调试) 从左到右打印的内容越来越详细。 ```xml jar org.mybatis mybatis 3.5.7 junit junit 4.12 test mysql mysql-connector-java 5.1.3 log4j log4j 1.2.17 ``` ```xml # JDBC配置文件jdbc.properties jdbc.driver = com.mysql.jdbc.Driver jdbc.url = jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8 jdbc.username = root jdbc.password = root ``` ## mybatis.xml配置文件 - `mybatis-config.xml` 配置连接数据库的环境、映射文件等全局配置信息。此步骤在SSM整合阶段可以由Spring自动处理。 - ``引入JDBC配置文件后,可以通过``指定``参数连接数据库,``,${}。 - `` 通过包名统一引入映射文件,将所有的mapper文件放入同一个目录下,按包``````导入。 1. 在resource目录下保存配置文件,通过 new Resource Bundle 直接创建 .properties 文件。 2. 在resource目录下,new Directory 是一个文件夹,命名时 com/mybatis/mapper/xml 实现目录嵌套。 3. 在java目录下,new Package 是一层层文件夹嵌套命名直接使用 com.mybatis.mapper.xml。 ## POJO实体类 1. 定义属性,和数据库字段对应 2. 创建有参、无参构造函数 3. 创建Getter、Setter方法 4. 创建toString方法 ## Mapper接口 - Mapper接口定义CRUD方法,相当于DAO,但不需要提供实现类。 1. Mapper接口定义CRUD操作方法,同名的XML映射文件保存SQL语句。 2. 使用时通过MyBatis配置文件生成SqlSession,获取Mapper接口实现对象,再调用Mapper接口的方法调用XML映射文件执行SQL。 3. XML映射文件的 namespace 和 mapper接口的全类名保持一致。 4. XML映射文件的 SQL语句 和 mapper接口的方法名一致。 ## XML映射文件 - XML映射文件和Mapper接口关联,要保证两个一致。 1. `````` 标签中的 ```namespace``` 和 Mapper 接口的全类名保持一致。 2. `````` SQL语句标签中的 id 和Mapper接口的方法名保持一致。 - 在XML映射文件定义SQL执行CRUD操作,增删改操作返回影响的行数,查询操作返回结果。 - 执行查询操作` select id, username, password, age, sex, email from t_user where id = 3; ``` ## 测试MyBatis - 获取SQLSession、获取Mapper接口对象、调用Mapper接口方法映射XML文件SQL。 1. 加载MyBatis核心配置文件,转为字节流输入```Resources.getResourceAsStream("mybatis-config.xml")```。 2. 创建 ```new SqlSessionFactoryBuilder();```。 3. Builder 根据MyBatis核心配置文件创建 ```SqlSessionFactory```,是生产SqlSession的工厂。 4. 创建 ```SqlSession```,用于Java程序和数据库的交互,实现通过配置文件创建SqlSession。 5. ```SqlSession``` 默认不自动提交事务,若需自动提交可以使用 ```SqlSessionFactory.openSession(true);```。 6. ```SqlSession``` 也支持手动提交事务,在调用Mapper接口方法后使用 ```SqlSession.commit()``` 提交。 7. Mapper接口本身没有实现类,但是可以通过 ```SqlSession.getMapper(UserMapper.class)```方法获取接口实现类的实例对象。 8. ```SqlSession.getMapper(UserMapper.class)``` 方法传入 Mapper 接口.class,返回 UserMapper,通过动态代理实现。 9. 调用Mapper接口,通过全类名映射到XML文件,调用接口对应方法会执行XML对应SQL语句。 ```java import org.junit.Test; @Test public void testInsert() throws IOException { // TODO: 1. 获取SQLSession // 加载核心配置文件,转为字节流输入 InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); // 创建SqlSessionFactoryBuilder SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); // 创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is); // 获取SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(true); // 开启自动提交事务 // TODO: 2. 获取Mapper接口实现类的对象 // 传入Mapper接口,方法底层创建类实现接口,并且将实例对象返回。代理模式 UserMapper mapper = sqlSession.getMapper(UserMapper.class); // TODO: 3. 调用Mapper接口,通过全类名映射到XML文件,调用接口对应方法会执行XML对应SQL语句 int rows = mapper.insertUser(); // 方法1提交事务,JDBC默认需要手动处理。 // sqlSession.commit(); // 方法2在创建SQLSession时,指定开启自动提交事务 System.out.println("rows = " + rows); } ``` ## 封装工具类 ```java public class SqlSessionUtils { /** * 通过Mybatis主配置文件创建SqlSession并返回 * @return SqlSession */ public static SqlSession getSqlSession() { SqlSession sqlSession = null; try { InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); sqlSession = sqlSessionFactory.openSession(true); } catch (IOException e) { throw new RuntimeException(e); } return sqlSession; } } ``` # XML映射文件语句处理 ## SQL动态参数获取 1. 指定单个参数查询,XML映射文件可以通过 ```#{}```或```${}```获取动态传入的参数。 - `#{}` 的本质就是占位符赋值,为字符串类型或日期类型的字段进行赋值时,可以自动添加单引号 `username = #{username}`。 - `${}` 的本质就是字符串拼接,为字符串类型或日期类型的字段进行赋值时,需要手动加单引号 `username = '${username}'`。 ```xml ``` 2. 指定多个参数查询 - Mapper接口方法为多个参数时,MyBatis会将参数统一放到Map中保存,并规定XML映射文件的SQL使用`arg0、arg1`或`param1、param2`为key获取参数传值。 - Mapper接口方法为多个参数时,可以自定义map,指定参数动态访问key值,在XML映射文件中通过自定义key获取参数。 - Mapper接口方法在定义时,通过注解 `@Param("paraname")` 指定SQL获取参数值的参数名 `User getUserByParam(@Param("username") String username, @Param("password") String password);`。 - 除了实体类对象,建议都添加 `@Param("paraname")` 指定SQL获取参数的key。 ```xml ``` ```java /** * 接口方法包含多个参数 */ @Test public void testGetUserByUserNameAndPwd() { SqlSession sqlSession = SqlSessionUtils.getSqlSession(); ParamMapper mapper = sqlSession.getMapper(ParamMapper.class); User user = mapper.getUserByNameAndPwd("root", "1234"); System.out.println(user); } /** * 接口方法参数为Map对象 * 指定访问参数的key */ @Test public void testGetUserByMap() { SqlSession sqlSession = SqlSessionUtils.getSqlSession(); ParamMapper mapper = sqlSession.getMapper(ParamMapper.class); // TODO: 自定义map保存key值 Map map = new HashMap<>(); map.put("username", "root"); map.put("password", "1234"); User user = mapper.getUserByMap(map); System.out.println(user); } /** * 接口方法参数为@Param */ @Test public void testGetUserByParam() { SqlSession sqlSession = SqlSessionUtils.getSqlSession(); ParamMapper mapper = sqlSession.getMapper(ParamMapper.class); User user = mapper.getUserByParam("root", "1234"); System.out.println(user); } ``` 3. 输入参数为类对象 - Mapper接口方法参数为类对象时,可以通过类属性名对SQL动态赋值,要求类的属性需要有Getter、Setter方法。 - 执行查询操作必须有Getter方法,增删改操作必须有Setter方法。 ```xml insert into t_user values(null, #{username}, #{password}, #{age}, #{sex}, #{email}) ``` ```java /** * 接口方法参数为类对象 */ @Test public void testInsertUser() { SqlSession sqlSession = SqlSessionUtils.getSqlSession(); ParamMapper mapper = sqlSession.getMapper(ParamMapper.class); int rows = mapper.insertUser(new User(null, "jj", "1234", 12, "女", "qq.com")); System.out.println(rows); } ``` ## 查询结果处理 1. 查询结果只有一条时,可以直接映射保存到实体类对象```resultType="User"``` 或Map中 ```resultType="Map"```。 2. MyBatis 对常用容器做了别名处理,Integer、Map等在XML映射文件中的结果类型可以使用 Integer、int、integer、Map等。 ```xml ``` 3. 查询结果有多条,可以保存到 `List`,XML映射文件` select * from t_user ``` ## 特殊SQL 1. 模糊搜索 LIKE - `#{}` 会自动添加单引号作为占位符,但使用 `#{%username%}` 相当于`like '?'`,无法作为占位符使用。 - `${}` 字符串拼接方式,可以使用` like '%${username}%'`。 - 如果使用 `#{}`,可以使用`concat()`拼接`concat('%', #{username}, '%')`。 - 如果使用 `#{}`,采用手动双引号拼接的方式`select * from t_user where username like "%"#{username}"%"`。 ```xml ``` 2. 批量删除 IN - `#{}` 默认添加了单引号,不能使用,只能使用 `${}`。 - 相当于 `delete from t_user where id in (1, 2, 5)`。 ```xml delete from t_user where id in (${ids}) ``` 3. 动态获取表名 - 表名不能加单引号,只能使用 `${tablename}`,使用 `#{tablename}` 相当于 `'t_user'`。 ```xml ``` 4. 插入并获取自增主键值 - 场景:添加班级后,需要先获取新添加的自动生成的班级id,再为班级分配学生。 - 插入操作返回值固定为 int 表示影响的行数,无法返回生成的主键。 - 通过在SQL语句上添加控制字段获取 ``````。 1. useGeneratedKeys 使用自增主键 2. keyProperty 将自增主键的值保存到入参的属性 - 执行SQL后再次打印入参的实体类,可以获取生成的主键值。 ```xml insert into t_user values(null, #{username}, #{password}, #{age}, #{sex}, #{email}) ``` ```java @Test public void testInsertUser() { SqlSession sqlSession = SqlSessionUtils.getSqlSession(); SQLMapper mapper = sqlSession.getMapper(SQLMapper.class); User user = new User(null, "QQ", "1233", 12, "B", "123@com"); mapper.insertUser(user); // 执行SQL后再次打印入参的实体类,可以获取对应值 System.out.println(user); // User{id=36, username='QQ', password='1233', age=12, sex='B', email='123@com'} } ``` # resultMap - `resultMap` 用于自定义映射关系,处理数据库字段名和类属性名不一致、一对多、多对一的映射。 - 定义`resultMap`,通过`id`表示自定义映射的唯一标识,通过`type`标签指定查询的数据要映射的类名。 ## 数据库字段名和类属性名不一致 1. 通过SQL语句对不一致的字段名起别名 `select eid, emp_name empName, age, sex, email from t_emp`。 2. 在Mybatis配置文件设置全局配置,自动将下划线映射为驼峰 `` 3. 通过`resultMap`自定义映射关系。 - 在查询SQL语句标签指定 `resultMap`。 - 定义`resultMap`,通过`id`表示自定义映射的唯一标识,通过`type`标签指定查询的数据要映射的类名。 - 子标签 `id` 设置主键的映射关系,属性 `property`设置实体类中的属性名,属性`column`设置表中的字段名。 - 子标签 `result` 设置普通字段的映射关系,属性 `property`设置实体类中的属性名,属性`column`设置表中的字段名。 - 子标签 `association`设置多对一的映射关系。 - 子标签 `collection`设置一对多的映射关系。 ```xml ``` ## 多对一关系查询 - 多个员工信息对应一个部门,查询员工及其所在的部门信息。 - 员工类 Emp 中包含类属性 `private Dept dept;` - 只能使用`resultMap`。 1. 通过级联方式处理多对一映射关系 ```xml ``` 2. 通过标签 `` 处理多对一映射关系 - 属性 `property` 表示多对映射关系的类的属性名 - 属性`javaType` 该属性对应的类名 ```xml ``` 3. 分步查询多对一映射关系 - 先根据员工`eid`查询员工信息,再根据员工所在部门的`did`查询部门信息。 - 分步操作好处:每一步可以单独执行,提高复用率。可以实现延迟加载、按需加载,访问哪些信息,只执行相应的sql。 - 定义 `resultMap`。 - 标签 `association` 关联多对一关系。 - 属性 `property` 表示多对一映射关系的类的属性名。 - 属性`select` 关联下一步查询操作,表示分步查询SQL的唯一标识 namespace.SQLId 或 mapper接口的全类名.方法名。 - 属性`column` 将SQL以及查询结果中的某个字段设置为分步查询的条件,即输入参数。 - 在Dept的Mapper接口中实现第二步操作,通过`association`关联到第一步。 ```xml ``` ```java public interface DeptMapper { /** * 多对一映射关系,分步查询第二步,查询员工及其所在部门信息 */ Dept getEmpAndDeptByStepTwo(@Param("did") Integer did); } ``` 4. 延迟加载 - 在MyBatis的核心配置文件中设置全局配置信息: - 属性值 `lazyLoadingEnabled` 延迟加载的全局开关,当开启时,所有关联对象都会延迟加载。 - 属性值 `aggressiveLazyLoading` 当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载。默认关闭。 - 配置文件全局生效后,如果不需要延迟加载,可通过XML映射文件中的 `association`和`collection`中的`fetchTyp`设置当前分步延迟加载效果。 - `fetchType` 当开启了全局延迟加载后,可通过此属性控制是否进行延迟加载` lazy(延迟加载)|eager(立即加载)`。 ```xml ``` ```java /** * 分步处理员工及其所在部门的多对一关系 */ @Test public void testGetEmpAndDeptByStep() { SqlSession sqlSession = SqlSessionUtils.getSqlSession(); EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); Emp empAndDept = mapper.getEmpAndDeptByStepOne(3); // TODO: 延迟加载,只获取某个属性时,只执行对应的SQL System.out.println(empAndDept.getEmpName()); // 只执行第一步 select * from t_emp where eid = ? System.out.println("+++++++++++++++"); // 需要Dept属性时,才执行第二步 select * from t_dept where did = ? System.out.println(empAndDept.getDept()); } ``` ## 一对多关系查询 - 一个部门包含多个员工信息,查询部门及其所有员工信息。 - 部门类 Dept 中包含类属性 `private List emps;` 1. 通过 `collection` 处理多对一映射关系 - 定义 `resultMap`。 - 标签 `collection`关联一对多关系,接收查询结果的集合中的每一项元素。 - 属性`ofType`设置所处理的集合属性中存储的类型。 ```xml ``` 2. 分步处理一对多关系 - 先查询部门信息,再根据部门Id获取所有员工信息。 - 第一步SQL只需要写查询部门信息的操作,在 resultMap 中通过标签`collection`的属性`select`关联第二步的处理方法或SQL。 ```xml ``` ```java // 一对多第二步操作 public interface EmpMapper { /** * 一对多,分步查询部门及部门下所有员工信息 * 2. 查询对应部门下的员工信息 */ List getDeptAndEmpByStepTwo(@Param("did") Integer did); } ``` ```xml ``` ```java // 测试类 import org.junit.Test; @Test public void testGetDeptAndEmpByStep() { SqlSession sqlSession = SqlSessionUtils.getSqlSession(); DeptMapper mapper = sqlSession.getMapper(DeptMapper.class); Dept dept = mapper.getDeptAndEmpByStepOne(2); // select * from t_dept where did = ? // TODO: 延迟加载,只获取某个属性时,只执行对应的SQL System.out.println(dept.getDeptName()); System.out.println("+++++++++++++++"); // select * from t_emp where did = ? System.out.println(dept); } ``` # 动态SQL实现 - 重点: if、where、foreach ## if、where、trim 1. `` - `` 标签可通过`test`属性对表达式进行判断,若表达式的结果为`true`,则标签中的内容会执行;反之不会执行。 - ``标签中的参数为类的属性名,用于判断传入的参数是否满足条件。 - ``标签内容中的参数为数据库表的字段名,用于满足条件后对SQL语句赋值。 - 多条件语句要用 `and` 拼接SQL语句。 ```sql ``` ```java @Test public void testGetEmpByCondition() { SqlSession sqlSession = SqlSessionUtils.getSqlSession(); DynamicSqlMapper mapper = sqlSession.getMapper(DynamicSqlMapper.class); List empByCondition = mapper.getEmpByCondition(new Emp(null, "ww", 13, "b", "123@qq.com")); System.out.println(empByCondition); } ``` 2. `` - ``标签和``一般结合使用 - 若``标签中的``条件都不满足,则``标签不会生效,即SQL语句不会添加`where`关键字。 - 若``标签中的``条件满足,则``标签会自动添加`where`关键字,并将条件最前方多余的`and|or`去掉。 - ``标签只能去掉``内容开始时的`and|or`,不能去掉条件语句后的。 ```xml ``` 3. `` - ``标签用于去掉或添加SQL关键字,包含四个属性。 - 属性`prefix、suffix` 在``标签中SQL语句的前面、后面添加内容。 - 属性`prefixOverrides、suffixOverrides` 在``标签中SQL语句的前面、后面去掉内容。 - 示例:动态添加 `where` 动态去除 `and|or`。 ```xml ``` ## choose、when、otherwise - `` 相当于 `if...else if..else`,只要有一个条件成立,后面条件就不会执行。 - 当前面的 `` 条件都不满足时,再执行 `` 语句。 - `` 最少有一个, `` 最多有一个。 - 注意这种场景的SQL不会用到`and|or`。 ```xml ``` ## foreach - `` 用于遍历数组或集合的元素。 - 属性`collection`: 需要循环的数组或集合 - 属性`item`:数组或集合中的元素 - 属性`separator`:循环体之间的分隔符 - 属性`open|close`:只用于 `in` 语句,表示循环的所有内容的开始、结束符。 ```xml delete from t_emp where eid in #{eid} delete from t_emp where eid = #{eid} insert into t_emp values (null, #{emp.empName}, #{emp.age}, #{emp.sex}, #{emp.email}, null) ``` ## sql - 通过``标签复用SQL语句中重复内容,避免使用 `select *`。 - 定义``标签,通过属性`id`唯一标识要复用的语句。 - 使用``标签,通过``标签的属性`refid`引用语句。 ```xml eid,emp_name,age,sex,email ``` # MyBatis缓存 - 缓存只针对查询功能。 - 查缓存顺序 1. 先查询二级缓存,二级缓存中可能会有其他程序已经查出来的数据,范围更大。 2. 如果二级缓存没有命中,再查询一级缓存。 3. 如果一级缓存也没有命中,则查询数据库。 ## 一级缓存 - MyBatis 一级缓存默认开启,`SqlSession`级别,通过同一个`SqlSession`查询的数据会被缓存。 - 使用相同的SQLSession,获取相同的Mapper,执行相同的SQL查询操作,再次查询时,会从一级缓存中获取,不会重复执行SQL。 - 使用相同的SQLSession,获取不同的Mapper,执行相同的SQL查询操作,再次查询时,会从一级缓存中获取,不会重复执行SQL。 - 一级缓存失效场景: 1) 不同的SqlSession,对应不同的一级缓存 2) 同一个SqlSession,但是查询条件不同 3) 同一个SqlSession,两次查询期间执行了任何一次增删改操作 4) 同一个SqlSession,两次查询期间手动清空了缓存 ```sqlSession.clearCache();``` ```java @Test public void testFirstCache() { SqlSession sqlSession = SqlSessionUtils.getSqlSession(); CacheMapper mapper = sqlSession.getMapper(CacheMapper.class); Emp empById = mapper.getEmpById(3); System.out.println(empById); System.out.println("1. 同一个SQLSession,相同的Mapper,执行相同SQL查询操作,不会重复执行SQL:"); System.out.println(mapper.getEmpById(3)); System.out.println("2. 同一个SQLSession,获取不同的Mapper,执行相同SQL查询操作,不会重复执行SQL:"); CacheMapper mapper1 = sqlSession.getMapper(CacheMapper.class); Emp empById1 = mapper1.getEmpById(3); System.out.println(empById1); } ``` ## 二级缓存 - MyBatis 二级缓存需手动开启,`SqlSessionFactory`级别,通过同一个`SqlSessionFactory`创建的`SqlSession`查询的结果会被缓存。 - `SqlSession`关闭之后,一级缓存中的数据会写入二级缓存,所以多次执行都必须提交或关闭`SqlSession`才能取到二级缓存。 - 二级缓存失效场景:两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效。 - 可以引入三方缓存替换MyBatis二级缓存。 - 二级缓存开启的条件: 1) 无需操作,在核心配置文件中,默认设置了全局配置属性```cacheEnabled="true"```。 2) 在XML映射文件中设置标签 ``````。 3) 二级缓存必须在SqlSession关闭或提交之后有效,每次查询都需要执行 ```sqlSession.commit() sqlSession.close()``` 4) 查询的数据所转换的实体类类型必须实现序列化的接口 ```Emp implements Serializable``` --- cache 标签属性: 1. eviction:缓存回收策略,LRU、FIFO、SOFT、WEAK 2. flushInterval:缓存刷新间隔(ms),默认情况是不设置,也就是没有刷新间隔,仅仅调用增删改语句时刷新、清空缓存 3. size:数目,正整数, 代表缓存最多可以存储多少个对象,太大容易导致内存溢出 4. readOnly:true 只读缓存,返回缓存对象的实例,不能被修改。 5. readOnly:false 读写缓存,通过序列化返回缓存对象实例的拷贝,修改不影响缓存中的数据,慢但安全,默认false。 ```java @Test public void testSecondCache() { try { InputStream is = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); SqlSession sqlSession1 = sqlSessionFactory.openSession(true); CacheMapper mapper = sqlSession1.getMapper(CacheMapper.class); System.out.println(mapper.getEmpById(3)); sqlSession1.close(); SqlSession sqlSession2 = sqlSessionFactory.openSession(true); CacheMapper mapper1 = sqlSession2.getMapper(CacheMapper.class); System.out.println(mapper1.getEmpById(3)); // TODO:两次执行都必须提交或关闭才能取到缓存 sqlSession2.close(); } catch (IOException e) { throw new RuntimeException(e); } } ``` # MyBatis逆向工程 - 正向工程:先创建Java实体类,由框架负责根据实体类生成数据库表。Hibernate是支持正向工程的。 - 逆向工程:先创建数据库表,由框架负责根据数据库表,反向生成如下资源: 1. Java实体类 2. Mapper接口 3. Mapper映射文件 - 使用参考 MBGTest ## MyBatis分页插件使用 1. 在查询操作前,开启分页,指定页码和每页条数 ```PageHelper.startPage(2, 4);``` 2. 在查询操作后,获取分页相关信息,指定分页数据和导航分页的数量 ```PageInfo page = new PageInfo<>(emps, 5);``` # 参考 [MyBatis视频课](https://www.bilibili.com/video/BV1VP4y1c7j7/) [MyBatis下载地址](https://github.com/mybatis/mybatis-3) [MyBatis原理分析](https://blog.csdn.net/J080624/article/details/119510355)