您当前的位置: 首页 >  mybatis

MyBatis3——入门介绍

发布时间:2021-09-16 20:23:02 ,浏览量:7

目录
  • 1.MyBatis简介
  • 2.MyBatis——入门案例
  • 3.MyBatis——全局配置文件常用标签
    • (1)properties属性
    • (2)settings设置
    • (3)typeAliases别名处理器
    • (4)typeHandlers类型处理器
    • (5)plugins插件
    • (6)environments环境
    • (7)databaseIdProvider环境
    • (7)mapper映射
  • 4.MyBatis——映射文件
    • (1)简单的增删改查
    • (2)获取自增主键的值
    • (3)获取非自增主键的值(Oracle)
    • (4)参数处理——单个参数
    • (5)参数处理——多个参数
    • (6)参数处理——命名参数
    • (7)参数处理——POJO & Map & TO
    • (8)参数处理——参数封装扩展思考
    • (9)参数处理——#与&取值的区别
    • (10)Select
      • ① 返回值类型为List
      • ② 记录封装map
      • ③ resultMap——自定义结果映射规则
      • ④ resultMap——关联查询_环境搭建
      • ⑤ resultMap——级联属性封装结果
      • ⑥ resultMap——association定义关联对象封装规则
      • ⑦ resultMap——association分步查询 & 延迟加载
      • ⑧ resultMap——collection定义关联集合封装规则
      • ⑨ resultMap——collection分步查询 & 延迟加载
      • ⑩ resultMap——discriminator鉴别器
  • 5.MyBatis——动态SQL
    • (1)简介 & 环境搭建
    • (2)动态SQL标签——if
    • (3)动态SQL标签——where
    • (3)动态SQL标签——trim
    • (4)动态SQL标签——choose
    • (5)动态SQL标签——set(与if结合的动态更新)
    • (6)动态SQL标签——foreach遍历集合
    • (7)动态SQL标签——mysql下foreach批量插入的两种方式
    • (8)动态SQL标签——内置参数_parameter和_databaseId
    • (9)动态SQL标签——bind绑定
    • (10)动态SQL标签——抽取可重用的sql片段
  • 6.MyBatis——缓存机制
    • (1)缓存介绍
      • ① 一级缓存
      • ② 二级缓存
    • (2)一级缓存体验
    • (3)一级失效的四种情况
    • (4)二级缓存的使用
    • (5)缓存有关的设置/属性
    • (6)缓存原理图示
    • (7)第三方缓存整合——ehcache
      • ① 导入ehcache适配包
      • ② 在config目录下添加ehcache.xml文件
      • ③ 在EmployeeMapper.xml文件中进行配置
      • ④ 测试
      • ⑤ 扩展——引用缓存
  • 7.MyBatis——SSM框架整合
    • (1)在IDEA中新建一个Java Web项目
    • (2)导入需要的jar包
    • (3)进行各种配置以及代码的编写
    • (4)测试
  • 8.MyBatis——逆向工程
    • (1)MyBatis Generator
    • (2)编写相应的配置文件及代码
  • 9.MyBatis——工作原理
    • (1)框架分层架构
    • (2)入门案例的运行流程
  • 10.MyBatis——插件开发
    • (1)插件原理
    • (2)编写插件
    • (3)多个插件运行流程
    • (4)开发插件
    • (5)PageHelper分页插件的使用
  • 11.Mybatis扩展
    • (1)批量操作
    • (2)自定义类型处理器——MyBatis中枚举类型的默认处理
    • (3)自定义类型处理器——使用自定义的类型处理器处理枚举类型

本文章的笔记整理来自尚硅谷视频https://www.bilibili.com/video/BV1mW411M737

1.MyBatis简介

(1)MyBatis历史 原是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation 迁移到了Google Code,随着开发团队转投Google Code旗下, iBatis3.x正式更名为MyBatis ,代码于2013年11月迁移到Github。iBatis一词来源于“internet”和“abatis”的组合,是一个基于Java的持久层框架。 iBatis提供的持久层框架包括SQL Maps和Data Access Objects(DAO)。 (2)MyBatis特点 ① MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的半自动化持久层框架。 ② MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。 ③ MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录。 (3)MyBatis与其它对应框架或组件的对比

MyBatis 半自动化的持久化层框架 JDBC ① SQL夹在Java代码块里,耦合度高导致硬编码内伤。② 维护不易且实际开发需求中sql是有变化,频繁修改的情况多见。 Hibernate和JPA ① 长难复杂SQL,对于Hibernate而言处理也不容易内部自动生产的SQL,不容易做特殊优化。② 基于全映射的全自动框架,大量字段的POJO进行部分映射时比较困难,这会导致数据库性能下降。

总之,对开发人员而言,核心sql还是需要自己来优化的。除此之外,如果sql代码和java代码分开,那么它们的功能边界就更加清晰,一个专注业务、一个专注数据。

(4)MyBatis地址为https://github.com/mybatis/mybatis-3/

2.MyBatis——入门案例

(1)创建测试表tbl_employee并添加一条测试数据,表结构及数据如下:

在这里插入图片描述 在这里插入图片描述

(2)在IDEA中创建一个Java项目,并在项目的根目录下创建lib目录(用于存放要导入的 jar 包)和config目录(用于存放配置文件),另外,需要右键点击config目录,找到Mark Directoy as并选择Resources Root。

在这里插入图片描述 (3)导入相关的 jar 包并引入到项目中

在这里插入图片描述 在这里插入图片描述 (4)Mybatis入门案例项目的整体目录结构如下:

在这里插入图片描述

各个部分的具体代码如下: ① 日志配置文件log4j.xml

  //属性名称应该与对应数据库表(tbl_employee)中的字段一致 private Integer id; private String last_name; private String email; private String gender; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getLast_name() { return last_name; } public void setLast_name(String last_name) { this.last_name = last_name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } @Override public String toString() { return "Employee [id=" + id + ", lastName=" + last_name + ", email=" + email + ", gender=" + gender + "]"; } } 

③ Mapper接口EmployeeMapper.java

package com.atguigu.mybatis.dao; import com.atguigu.mybatis.bean.Employee; public interface EmployeeMapper { public Employee getEmpById(Integer id); } 

④ sql映射文件EmployeeMapper.xml

   <select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee"> select * from tbl_employee where id = #{id}   <mappers> <mapper resource="EmployeeMapper.xml" />  //根据全局配置文件mybatis-config.xml,利用SqlSessionFactoryBuilder创建SqlSessionFactory public SqlSessionFactory getSqlSessionFactory() throws IOException { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); return new SqlSessionFactoryBuilder().build(inputStream); } /*
     * 1、根据xml配置文件(全局配置文件)创建一个SqlSessionFactory对象,其包含数据源等一些运行环境信息
     * 2、sql映射文件;配置了每一个sql,以及sql的封装规则等。
     * 3、将sql映射文件注册在全局配置文件中
     * 4、写代码:
     * 		1)、根据全局配置文件得到SqlSessionFactory;
     * 		2)、使用sqlSession工厂,获取到sqlSession对象使用他来执行增删改查
     * 			一个sqlSession就是代表和数据库的一次会话,用完关闭
     * 		3)、使用sql的唯一标志来告诉MyBatis执行哪个sql。sql都是保存在sql映射文件中的。
     *
     * @throws IOException
     */ //旧版本常用方式 @Test public void test01() throws IOException { // 获取sqlSession实例,能直接执行已经映射的sql语句 // sql的唯一标识:statement Unique identifier matching the statement to use. // 执行sql要用的参数:parameter A parameter object to pass to the statement. //使用SqlSessionFactory获取sqlSession对象,一个SqlSession对象代表和数据库的一次会话 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try { Employee employee = openSession.selectOne( "com.atguigu.mybatis.dao.EmployeeMapper.getEmpById", 1); System.out.println(employee); } finally { openSession.close(); } } //新版本常用的方式:接口式编程 /*
     * 1、接口式编程
     * 	原生:		Dao		====>  DaoImpl
     * 	mybatis:	Mapper	====>  xxMapper.xml
     *
     * 2、SqlSession代表和数据库的一次会话;用完必须关闭;
     * 3、SqlSession和connection一样她都是非线程安全。每次使用都应该去获取新的对象。
     * 4、mapper接口没有实现类,但是mybatis会为这个接口生成一个代理对象。
     * 		(将接口和xml进行绑定)
     * 		EmployeeMapper empMapper =	sqlSession.getMapper(EmployeeMapper.class);
     * 5、两个重要的配置文件:
     * 		mybatis的全局配置文件:包含数据库连接池信息,事务管理器信息等...系统运行环境信息
     * 		sql映射文件:保存了每一个sql语句的映射信息:将sql抽取出来。
     *
     */ @Test public void test02() throws IOException { // 1、获取sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、获取sqlSession对象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、获取接口的实现类对象 //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法 EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); Employee employee = mapper.getEmpById(1); System.out.println(mapper.getClass()); System.out.println(employee); }finally{ openSession.close(); } } } 

结果如下: 在这里插入图片描述

3.MyBatis——全局配置文件常用标签 (1)properties属性

MyBatis可以使用properties来引入外部properties配置文件的内容。

# 数据库配置文件dbconfig.properties
jdbc.drive=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456
 <properties resource="dbconfig.properties"> <setting name="mapUnderscoreToCamelCase" value="true"/>    <package name="com.atguigu.mybatis.bean"/>   <databaseIdProvider type="DB_VENDOR">  <property name="MySQL" value="mysql"/> <property name="Oracle" value="oracle"/> <property name="SQL Server" value="sqlserver"/>  <select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee" databaseId="mysql"> select * from tbl_employee where id = #{id}  <mapper resource="EmployeeMapper.xml" /> <mapper class="com.atguigu.mybatis.dao.EmployeeMapperAnnotation"/>  <package name="com.atguigu.mybatis.dao"/>  //直接在注解中编写sql语句,不要sql映射文件 @Select("select * from tbl_employee where id = #{id}") public Employee getEmpById(Integer id); } 

以上介绍了MyBatis中常用的标签,所有的标签如下图所示。不过在使用这些标签时也需要按照下图中从上到下规定的顺序(某个标签可以没有,但如果有则顺序不能颠倒,否则会报错!!!) 在这里插入图片描述

4.MyBatis——映射文件

映射文件指导着MyBatis如何进行数据库增删改查,有着非常重要的意义。

(1)简单的增删改查

① 在接口EmployeeMapper中编写抽象的增删改查方法

package com.atguigu.mybatis.dao; import com.atguigu.mybatis.bean.Employee; public interface EmployeeMapper { Employee getEmpById(Integer id); void addEmp(Employee employee); boolean updateEmp(Employee employee); void deleteEmpById(Integer id); } 

② 在对应的sql映射文件EmployeeMapper.xml中编写sql语句

  <select id="getEmpById" resultType="com.atguigu.mybatis.bean.Employee" databaseId="mysql"> select * from tbl_employee where id = #{id}  <insert id="addEmp" parameterType="com.atguigu.mybatis.bean.Employee"> insert into tbl_employee(last_name,email,gender)
        values (#{last_name},#{email},#{gender})  // 1、获取sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、获取sqlSession对象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、获取接口的实现类对象 //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法 EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); //添加数据 Employee employee1 = new Employee(null, "Jerry", "1","Jerry@163.com"); mapper.addEmp(employee1); //修改数据 Employee employee2 = new Employee(2, "Hi", "1","Hi@163.com"); //若修改影响的行数大于等于1,则返回true,否则返回false boolean flag = mapper.updateEmp(employee2); System.out.println(flag); //删除数据 mapper.deleteEmpById(2); //手动提交数据 openSession.commit(); }finally{ openSession.close(); } } 

除此之外,insert、update、delete标签中常见的属性如下: 在这里插入图片描述

(2)获取自增主键的值
 <insert id="addEmp" parameterType="com.atguigu.mybatis.bean.Employee" useGeneratedKeys="true" keyProperty="id"> insert into tbl_employee(last_name,email,gender)
    values (#{last_name},#{email},#{gender})  <insert id="addEmp" databaseId="oracle">  <selectKey keyProperty="id" order="BEFORE" resultType="Integer">   select EMPLOYEES_SEQ.nextval from dual    insert into employees(EMPLOYEE_ID,LAST_NAME,EMAIL) 
	values(#{id},#{lastName},#{email})   <delete id="deleteEmpById"> delete from tbl_employee where id=#{id}   // 1、获取sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、获取sqlSession对象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、获取接口的实现类对象 //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法 EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); Employee employee = mapper.getEmpByIdAndLast_name(1, "Tom"); System.out.println(employee); openSession.commit(); }finally{ openSession.close(); } } 

错误提示如下:

### Error querying database. Cause: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [0, 1, param1, param2] ### Cause: org.apache.ibatis.binding.BindingException: Parameter 'id' not found. Available parameters are [0, 1, param1, param2] 

③ 正确示例

<select id="getEmpByIdAndLast_name" resultType="com.atguigu.mybatis.bean.Employee"> select * from tbl_employee where id=#{param1} and last_name=#{param2}   // 1、获取sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、获取sqlSession对象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、获取接口的实现类对象 //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法 EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); Map<String,Object> map = new HashMap<>(); map.put("id",1); map.put("last_name","Tom"); Employee employee = mapper.getEmpByMap(map); System.out.println(employee); openSession.commit(); }finally{ openSession.close(); } } 

③ 如果多个参数不是业务模型中的数据,但是经常要使用,推荐来编写一个TO(Transfer Object)来数据传输对象。 例如对于数据的分页处理,我们可以单独定义一个Page类,里面自定义需要的属性,其用法与POJO类似。

(8)参数处理——参数封装扩展思考 public Employee getEmp(@Param(“id”)Integer id,String last_name); 取值:id==>#{id/param1} last_name==>#{param2} public Employee getEmp(Integer id, @Param(“e”)Employee emp); 取值:id==>#{param1} last_name===>#{param2.last_name/e.last_name} 如果是Collection(List、Set)类型或者是数组,也会特殊处理,也是把传入的list或者数组封装在map中 key:Collection(collection) 如果是List数组 使用这个key(list)数组(array) public Employee getEmpById(List ids); 取值:取出第一个id的值: #{list[0]} (9)参数处理——#与&取值的区别

① #{ } 与 ${ }都可以获取map中的值或者pojo对象属性的值。 ② 在具体的细节上#{ } 与 ${ }有一些不同:

#{ } 是以预编译的形式,将参数设置到 sql 语句中,可以防止 sql 注入 ${ } 取出的值直接拼装在 sql 语句中,可能会存在安全问题

在这里插入图片描述 ③ 在大多情况下,我们应该使用 #{ } 去取参数的值,但是在一些特殊情况下需要使用 ${ }:

# 在原生JDBC不支持占位符的地方,就可以使用${}进行取值,例如分表、排序等 select * from ${year}_salary where xxx; select * from ${tbl_name} where id=${id} and last_name=#{last_name}; 
(10)Select

Select标签用来定义查询操作,常用的属性如下:

id 唯一标识符,用来引用这条语句,需要和接口的方法名一致 parameterType 参数类型,可以不传,MyBatis会根据TypeHandler自动推断 resultType 返回值类型,别名或者全类名,如果返回的是集合,定义集合中元素的类型,不能和resultMap同时使用 其余属性如下: 在这里插入图片描述 ① 返回值类型为List
List<Employee> getEmpsByLast_NameLike(String last_name); 
 <select id="getEmpsByLast_NameLike" resultType="com.atguigu.mybatis.bean.Employee"> select * from tbl_employee where last_name like #{last_name}  // 1、获取sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、获取sqlSession对象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、获取接口的实现类对象 //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法 EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); //查询姓名中含有字母e的所有员工 List<Employee> emps = mapper.getEmpsByLast_NameLike("%e%"); System.out.println(emps); openSession.commit(); }finally{ openSession.close(); } } 
② 记录封装map

1)返回一条记录的map,key为列名,value为对应的值

Map<String,Object> getEmpByIdReturnMap(Integer id); 
<select id="getEmpByIdReturnMap" resultType="map"> select * from tbl_employee where id=#{id}  // 1、获取sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、获取sqlSession对象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、获取接口的实现类对象 //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法 EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); Map<String, Object> map = mapper.getEmpByIdReturnMap(1); System.out.println(map); openSession.commit(); }finally{ openSession.close(); } } 

2)多条记录封装一个map:Map,键是这条记录的主键,值是记录封装后的javaBean

//@MapKey:告诉mybatis封装这个map的时候使用哪个属性作为map的key @MapKey("id") Map<String, Employee> getEmpByLast_NameLikeReturnMap(String last_name); 
<select id="getEmpByLast_NameLikeReturnMap" resultType="com.atguigu.mybatis.bean.Employee"> select * from tbl_employee where last_name like #{last_name}  // 1、获取sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、获取sqlSession对象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、获取接口的实现类对象 //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法 EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); Map<String, Employee> map = mapper.getEmpByLast_NameLikeReturnMap("%r%"); System.out.println(map); openSession.commit(); }finally{ openSession.close(); } } 
③ resultMap——自定义结果映射规则
package com.atguigu.mybatis.dao; import com.atguigu.mybatis.bean.Employee; public interface EmployeeMapperPlus{ Employee getEmpById(Integer id); } 

注:记得要在MyBatis全局配置文件(mybatis-config.xml)中注册新的sql映射文件!

  <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmp">  <id column="id" property="id"/>  <result column="last_name" property="last_name"/>  <result column="email" property="email"/> <result column="gender" property="gender"/>  <select id="getEmpById" resultMap="MyEmp"> select  * from tbl_employee where id=#{id}  private Integer id; private String departmentName; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getDepartmentName() { return departmentName; } public void setDepartmentName(String departmentName) { this.departmentName = departmentName; } @Override public String toString() { return "Department{" + "id=" + id + ", departmentName='" + departmentName + '\'' + '}'; } } 

5)在Employee.java中添加新的属性(即员工所在的部门Department),并添加对应的 get/set 方法

private Department dept; public Department getDept() { return dept; } public void setDept(Department dept) { this.dept = dept; } 
⑤ resultMap——级联属性封装结果
//EmployeeMapperPlus.java Employee getEmpAndDept(Integer id); 
   <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp"> <id column="id" property="id"/> <result column="last_name" property="last_name"/> <result column="gender" property="gender"/> <result column="email" property="email"/> <result column="did" property="dept.id"/> <result column="deptName" property="dept.deptName"/>  <select id="getEmpAndDept" resultMap="MyDifEmp"> SELECT e.id id,e.last_name last_name,e.gender gender,e.email email,e.d_id d_id,
           d.id did,d.deptName deptName
    FROM tbl_employee e,tbl_dept d
    WHERE e.d_id=d.id AND e.id=#{id}  // 1、获取sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、获取sqlSession对象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、获取接口的实现类对象 //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法 EmployeeMapperPlus mapper = openSession.getMapper(EmployeeMapperPlus.class); Employee employee = mapper.getEmpAndDept(1); System.out.println(employee); System.out.println(employee.getDept()); openSession.commit(); }finally{ openSession.close(); } } 
⑥ resultMap——association定义关联对象封装规则
 <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyDifEmp2"> <id column="id" property="id"/> <result column="last_name" property="last_name"/> <result column="gender" property="gender"/> <result column="email" property="email"/>  <association property="dept" javaType="com.atguigu.mybatis.bean.Department"> <id column="did" property="id"/> <result column="deptName" property="deptName"/>  //根据部门id查询部门信息 Department getDeptById(Integer id); } 

2)新建对应的sql映射文件(记得要在MyBatis全局配置文件(mybatis-config.xml)中注册)。

  <select id="getDeptById" resultType="com.atguigu.mybatis.bean.Department"> select id,deptName from tbl_dept where id=#{id}    <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmpByStep"> <id column="id" property="id"/> <result column="last_name" property="last_name"/> <result column="email" property="email"/> <result column="gender" property="gender"/>  <association property="dept" select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById" column="d_id">  <select id="getEmpByIdStep" resultMap="MyEmpByStep"> select * from tbl_employee where id=#{id}  // 1、获取sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、获取sqlSession对象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、获取接口的实现类对象 //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法 EmployeeMapperPlus mapper = openSession.getMapper(EmployeeMapperPlus.class); //分步查询 Employee employee = mapper.getEmpByIdStep(1); System.out.println(employee); System.out.println(employee.getDept()); openSession.commit(); }finally{ openSession.close(); } } 

6)延迟加载——在MyBatis全局配置文件(mybatis-config.xml)中加上两个设置 在这里插入图片描述

<settings>    <setting name="lazyLoadingEnabled" value="true"/>  <setting name="aggressiveLazyLoading" value="false"/>   private Integer id; private String deptName; private List<Employee> emps; public List<Employee> getEmps() { return emps; } public void setEmps(List<Employee> emps) { this.emps = emps; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this.deptName = deptName; } @Override public String toString() { return "Department{" + "id=" + id + ", deptName='" + deptName + '\'' + '}'; } } 

2)在EmployeeMapperPlus.java中添加抽象方法getDeptByIdPlus()。

//EmployeeMapperPlus.java //通过部门id查询部门信息,以及属于该部门的所有员工的集合List Department getDeptByIdPlus(Integer id); 

3)在DepartmentMapper.xml中编写上述方法对应的sql语句。

  <resultMap id="MyDept" type="com.atguigu.mybatis.bean.Department"> <id column="did" property="id"/> <result column="deptName" property="deptName"/>  <collection property="emps" ofType="com.atguigu.mybatis.bean.Employee">  <id column="eid" property="id"/> <result column="last_name" property="last_name"/> <result column="email" property="email"/> <result column="gender" property="gender"/>  <select id="getDeptByIdPlus" resultMap="MyDept"> select d.id did,d.deptName deptName,
           e.id eid,e.last_name last_name,e.email email,e.gender gender
    from tbl_dept d
    left join tbl_employee e
    on d.id=e.d_id
    where d.id=#{id};  // 1、获取sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、获取sqlSession对象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、获取接口的实现类对象 //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法 DepartmentMapper mapper = openSession.getMapper(DepartmentMapper.class); //查询部门id为1的部门信息,以及属于该部门的所有员工信息(在list中) Department dept = mapper.getDeptByIdPlus(1); //输出部门信息 System.out.println(dept); //输出属于该部门的所有员工信息 System.out.println(dept.getEmps()); openSession.commit(); }finally{ openSession.close(); } } 

在这里插入图片描述

⑨ resultMap——collection分步查询 & 延迟加载

1)在EmployeeMapperPlus.java中添加抽象方法getEmpsByDeptId()。

//EmployeeMapperPlus.java //根据部门id查询所有属于该部门的员工信息 List<Employee> getEmpsByDeptId(Integer deptId); 

2)在EmployeeMapperPlus.xml中编写对应的sql语句。

 <select id="getEmpsByDeptId" resultType="com.atguigu.mybatis.bean.Employee"> select * from tbl_employee where d_id=#{deptId};  <resultMap type="com.atguigu.mybatis.bean.Department" id="MyDeptStep"> <id column="id" property="id"/> <id column="deptName" property="deptName"/> <collection property="emps" select="com.atguigu.mybatis.dao.EmployeeMapperPlus.getEmpsByDeptId" column="id"> <select id="getDeptByIdStep" resultMap="MyDeptStep"> select id,deptName from tbl_dept where id=#{id}  // 1、获取sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、获取sqlSession对象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、获取接口的实现类对象 //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法 DepartmentMapper mapper = openSession.getMapper(DepartmentMapper.class); Department dept = mapper.getDeptByIdStep(1); System.out.println(dept.getDeptName()); System.out.println(dept.getEmps()); openSession.commit(); }finally{ openSession.close(); } } 

测试对比: 在这里插入图片描述 在这里插入图片描述

⑩ resultMap——discriminator鉴别器

在EmployeeMapper.xml中添加鉴别器

  <resultMap type="com.atguigu.mybatis.bean.Employee" id="MyEmpDis"> <id column="id" property="id"/> <result column="last_name" property="last_name"/> <result column="email" property="email"/> <result column="gender" property="gender"/>  <discriminator javaType="string" column="gender">  <case value="0" resultType="com.atguigu.mybatis.bean.Employee"> <association property="dept" select="com.atguigu.mybatis.dao.DepartmentMapper.getDeptById" column="d_id">  <case value="1" resultType="com.atguigu.mybatis.bean.Employee"> <id column="id" property="id"/> <result column="last_name" property="last_name"/> <result column="last_name" property="email"/> <result column="gender" property="gender"/>  } 

新建EmployeeMapperDynamicSQL.xml(记得要在全局配置文件中注册该sql映射文件!)

  <select id="getEmpsByConditionIf" resultType="com.atguigu.mybatis.bean.Employee"> select * from tbl_employee
    where 1=1  <if test="id!=null"> and id=#{id}  <if test="gender==0 or gender==1"> and gender=#{gender}  // 1、获取sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、获取sqlSession对象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、获取接口的实现类对象 //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法 EmployeeMapperDynamicSQL mapper = openSession.getMapper(EmployeeMapperDynamicSQL.class); Employee employee = new Employee(null,"%e%",null,null); List<Employee> emps = mapper.getEmpsByConditionIf(employee); System.out.println(emps); openSession.commit(); }finally{ openSession.close(); } } 

在这里插入图片描述

(3)动态SQL标签——where

查询的时候如果某些条件没带可能会出现sql拼装问题,现有以下两种解决方案: ① 给where后面加上1=1,以后的条件都是and xxx(上面(2)中的代码就是这样写的)。 ② MyBatis使用 where 标签来将所有的查询条件包括在内。即在where标签拼装sql语句,并且会去掉多出来的and或者or,但是where只会去掉第一个多出来的and或者or。

 <select id="getEmpsByConditionIf" resultType="com.atguigu.mybatis.bean.Employee"> select * from tbl_employee <where> <if test="id!=null"> id=#{id}  <if test="gender==0 or gender==1"> and gender=#{gender}  <select id="getEmpsByConditionTrim" resultType="com.atguigu.mybatis.bean.Employee"> select * from tbl_employee   <trim prefix="where" suffixOverrides="and"> <if test="id!=null"> id=#{id} and  <if test="gender==0 or gender==1"> gender=#{gender}  <select id="getEmpsByConditionChoose" resultType="com.atguigu.mybatis.bean.Employee"> select * from tbl_employee <where>  <choose> <when test="id!=null"> id=#{id}  <update id="updateEmp"> update tbl_employee  <set> <if test="last_name!=null"> last_name=#{last_name},  <select id="getEmpsByConditionForeach" resultType="com.atguigu.mybatis.bean.Employee"> select * from tbl_employee  <foreach collection="ids" item="item_id" separator="," open="where id in(" close=")"> #{item_id}  // 1、获取sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、获取sqlSession对象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、获取接口的实现类对象 //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法 EmployeeMapperDynamicSQL mapper = openSession.getMapper(EmployeeMapperDynamicSQL.class); Employee employee = new Employee(null,null,null,null); List<Integer> ids = new ArrayList<>(); ids.add(1); ids.add(2); ids.add(3); List<Employee> emps = mapper.getEmpsByConditionForeach(ids); for (Employee emp : emps) { System.out.println(emp); } openSession.commit(); }finally{ openSession.close(); } } 

在这里插入图片描述

(7)动态SQL标签——mysql下foreach批量插入的两种方式

① 在EmployeeMapperDynamicSQL.java中添加抽象方法

//批量插入员工信息 void addEmps(@Param("emps")List<Employee> emps); 

② 在EmployeeMapperDynamicSQL.xml中编写对应的sql语句

<!-- 批量保存 
-->  <insert id="addEmps"> insert into tbl_employee(last_name, email, gender,d_id)
	values <foreach collection="emps" item="emp" separator=","> (#{emp.last_name},#{emp.email},#{emp.gender},#{emp.dept.id})   <insert id="addEmps"> <foreach collection="emps" item="emp" separator=";"> insert into tbl_employee(last_name,email,gender,d_id)
		values(#{emp.last_name},#{emp.email},#{emp.gender},#{emp.dept.id})  // 1、获取sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、获取sqlSession对象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、获取接口的实现类对象 //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法 EmployeeMapperDynamicSQL mapper = openSession.getMapper(EmployeeMapperDynamicSQL.class); List<Employee> emps = new ArrayList<>(); emps.add(new Employee(null,"Smith","1","Smith@163.com",new Department(1))); emps.add(new Employee(null,"Smith2","1","Smith2@163.com",new Department(2))); 9 mapper.addEmps(emps); openSession.commit(); }finally{ openSession.close(); } } 
(8)动态SQL标签——内置参数_parameter和_databaseId

① 在EmployeeMapperDynamicSQL.java中添加抽象方法

List<Employee> getEmpsTestInnerParameter(Employee employee); 

② 在EmployeeMapperDynamicSQL.xml中编写对应的sql语句

 <select id="getEmpsTestInnerParameter" resultType="com.atguigu.mybatis.bean.Employee"> <if test="_databaseId=='mysql'"> select * from tbl_employee <if test="_parameter!=null"> where last_name like #{_parameter.last_name}  <select id="getEmpsTestInnerParameter" resultType="com.atguigu.mybatis.bean.Employee">  <bind name="_lastName" value="'%'+last_name+'%'"/> <if test="_databaseId=='mysql'"> select * from tbl_employee <if test="_parameter!=null"> where last_name like #{_lastName}  // 1、获取sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、获取sqlSession对象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、获取接口的实现类对象 //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法 EmployeeMapperDynamicSQL mapper = openSession.getMapper(EmployeeMapperDynamicSQL.class); Employee employee = new Employee(); employee.setLast_name("e"); List<Employee> emps = mapper.getEmpsTestInnerParameter(employee); System.out.println(emps); openSession.commit(); }finally{ openSession.close(); } } 
(10)动态SQL标签——抽取可重用的sql片段

抽取可重用的sql片段,方便后面引用 ① sql抽取:将经常要查询的列名,或者插入用的列名抽取出来,方便引用; ② 用include来引用已经抽取的sql; ③ 此外,include还可以自定义一些property,sql标签内部就能使用自定义的属性;include-property:正确的取值方式为${prop}

<sql id="insertColumn"> <if test="_databaseId=='oracle'"> employee_id,last_name,email  // 1、获取sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、获取sqlSession对象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、获取接口的实现类对象 //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法 EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); Employee emp01 = mapper.getEmpById(1); System.out.println(emp01); //xxx //再次调用getEmpById()方法 Employee emp02 = mapper.getEmpById(1); System.out.println(emp02); //判断emp01和emp02是否为同一个对象 System.out.println(emp01==emp02); openSession.commit(); }finally{ openSession.close(); } } 

在这里插入图片描述

(3)一级失效的四种情况

① 不同的SqlSession对应不同的一级缓存 ② 同一个SqlSession但是查询条件不同 ③ 两次查询之间执行了增删改操作(这次增删改可能对当前数据有影响) ④ 同一个SqlSession两次查询期间手动清空了缓存(openSession.clearCache())

(4)二级缓存的使用

① 在全局配置文件 mybatis-config.xml 中开启全局二级缓存配置:

<setting name="cacheEnabled" value="true"/> 

② 去相应的mapper.xml(以EmployeeMapper.xml为例)中配置使用二级缓存:

 <cache eviction="FIFO" flushInterval="" readOnly="false" size="1024"> SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); SqlSession openSession2 = sqlSessionFactory.openSession(); try { EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); EmployeeMapper mapper2 = openSession2.getMapper(EmployeeMapper.class); Employee emp01 = mapper.getEmpById(1); System.out.println(emp01); //会话关闭,那么一级缓存中的数据会被保存到二级缓存中,新的会话查询信息,就可以参照二级缓存中的内容 openSession.close(); //第二次查询是从二级缓存中拿到的数据,并没有发送新的sql Employee emp02 = mapper2.getEmpById(1); System.out.println(emp02); System.out.println(emp01==emp02); openSession.close(); }finally{ } } 

在这里插入图片描述

(5)缓存有关的设置/属性 全局setting的cacheEnable 配置二级缓存的开关,true为打开,false为关闭(一级缓存一直是打开的) 全局setting的localCacheScope 值为SESSION时,当前会话的所有数据保存在会话缓存中;值为STATEMENT时,禁用一级缓存 select标签的useCache属性 配置这个select是否使用二级缓存,true为使用,false为不使用(一级缓存一直是使用的 ) sql标签的flushCache属性 在增删改标签中默认flushCache=true,即sql执行以后,会同时清空一级和二级缓存。在查询标签中则默认flushCache=false sqlSession.clearCache() 只用来清除当前sqlSession一级缓存 (6)缓存原理图示

在这里插入图片描述

(7)第三方缓存整合——ehcache ① 导入ehcache适配包

在这里插入图片描述 在这里插入图片描述

② 在config目录下添加ehcache.xml文件
 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">  <diskStore path="E:\ehcache" /> <defaultCache maxElementsInMemory="10000" maxElementsOnDisk="10000000" eternal="false" overflowToDisk="true" timeToIdleSeconds="120" timeToLiveSeconds="120" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU">  
③ 在EmployeeMapper.xml文件中进行配置
<cache type="org.mybatis.caches.ehcache.EhcacheCache"> SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); SqlSession openSession2 = sqlSessionFactory.openSession(); try { EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); EmployeeMapper mapper2 = openSession2.getMapper(EmployeeMapper.class); Employee emp01 = mapper.getEmpById(1); System.out.println(emp01); openSession.close(); //第二次查询是从二级缓存中拿到的数据,并没有发送新的sql Employee emp02 = mapper2.getEmpById(1); System.out.println(emp02); System.out.println("emp01==emp02的结果为:"+(emp01==emp02)); openSession.close(); }finally{ } } 

在这里插入图片描述 在这里插入图片描述

⑤ 扩展——引用缓存

在DepartmentMapper.xml中引用缓存

 <cache-ref namespace="com.atguigu.mybatis.dao.EmployeeMapper"/> 
7.MyBatis——SSM框架整合

此处的SSM框架整合未使用Maven等项目管理工具,若想看Maven版本的可以查看这篇文章。

(1)在IDEA中新建一个Java Web项目

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

(2)导入需要的jar包

在这里插入图片描述 右键lib,点击"Add as Library…",再点击OK即可。

(3)进行各种配置以及代码的编写

整体的项目结构如下: 在这里插入图片描述 有需要的可以下载本项目的源代码(提取码:test)

(4)测试

在这里插入图片描述 在这里插入图片描述

8.MyBatis——逆向工程 (1)MyBatis Generator

MyBatis Generator简称MBG,是一个专门为MyBatis框架使用者定制的代码生成器,可以快速的根据表生成对应的映射文件、接口、以及bean类等。它支持基本的增删改查,以及QBC风格的条件查询。但是表连接、存储过程等这些复杂sql的定义需要我们手工编写。

(2)编写相应的配置文件及代码

① 将之前Mybatis项目复制一份并改名为MyBatis_07_mbg,删除一些不用的文件,并导入Myabtis Generator的包: 在这里插入图片描述 ② 新建mbg.xml文件,放在src目录下(可以先从官网中复制过来,然后再根据实际情况进行修改)

  <context id="DB2Tables" targetRuntime="MyBatis3">  <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/mybatis?allowMultiQueries=true" userId="root" password="123456">  <javaTypeResolver > <property name="forceBigDecimals" value="false" />  <javaModelGenerator targetPackage="com.atguigu.mybatis.bean" targetProject=".\src"> <property name="enableSubPackages" value="true" /> <property name="trimStrings" value="true" />  <sqlMapGenerator targetPackage="com.atguigu.mybatis.dao" targetProject=".\conf"> <property name="enableSubPackages" value="true" />  <javaClientGenerator type="XMLMAPPER" targetPackage="com.atguigu.mybatis.dao" targetProject=".\src"> <property name="enableSubPackages" value="true" />  <table tableName="tbl_dept" domainObjectName="Department"> List<String> warnings = new ArrayList<String>(); boolean overwrite = true; File configFile = new File("mbg.xml"); ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = cp.parseConfiguration(configFile); DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(null); } 

④ 测试

@Test public void testMyBatis3() throws IOException{ SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try{ EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); //xxxExample就是封装查询条件的 //1、查询所有 //Listemps = mapper.selectByExample(null); //2、查询员工名字中有e字母的,和员工性别是1的 //封装员工查询条件的example EmployeeExample example = new EmployeeExample(); //创建一个Criteria,这个Criteria就是拼装查询条件 //select id, last_name, email, gender, d_id from tbl_employee  //WHERE ( last_name like ? and gender = ? ) or email like "%e%" Criteria criteria = example.createCriteria(); criteria.andLastNameLike("%e%"); criteria.andGenderEqualTo("1"); Criteria criteria2 = example.createCriteria(); criteria2.andEmailLike("%e%"); example.or(criteria2); List<Employee> list = mapper.selectByExample(example); for (Employee employee : list) { System.out.println(employee.getId()); } }finally{ openSession.close(); } } 
9.MyBatis——工作原理 (1)框架分层架构

在这里插入图片描述 在这里插入图片描述

(2)入门案例的运行流程

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

10.MyBatis——插件开发 (1)插件原理

MyBatis在四大对象Executor、ParameterHandler、ResultSetHandler、StatementHandler的创建过程中,都会有插件进行介入。插件可以利用动态代理机制一层层的包装目标对象,而实现在目标对象执行目标方法之前进行拦截的效果。MyBatis 允许在已映射语句执行过程中的某一点进行拦截调用。 ① 每个创建出来的对象不是直接返回的,而是调用方法 interceptorChain.pluginAll(parameterHandler) 后返回。

public Object pluginAll(Object target) { for (Interceptor interceptor : interceptors) { target = interceptor.plugin(target); } return target; } 

② pluginAll() 方法获取到所有的Interceptor(拦截器,插件需要实现的接口)后,调用interceptor.plugin(target),即返回target包装后的对象。 ③ 插件机制,我们可以使用插件为目标对象创建一个代理对象(即AOP,面向切面编程),我们的插件可以为四大对象创建出代理对象,代理对象就可以拦截到四大对象的每一个执行。

(2)编写插件

以入门案例的代码为基础来编写插件,其具体步骤如下: ① 编写Interceptor的实现类 ② 使用@Intercepts注解完成插件签名

package com.atguigu.mybatis.dao; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.plugin.*; import java.util.Properties; //完成插件签名:告诉MyBatis当前插件用来拦截哪个对象的哪个方法 @Intercepts( { @Signature(type= StatementHandler.class,method="parameterize",args=java.sql.Statement.class) }) public class MyFirstPlugin implements Interceptor { //intercept:拦截目标对象的目标方法的执行 @Override public Object intercept(Invocation invocation) throws Throwable { //执行目标方法 Object proceed = invocation.proceed(); //返回执行后的返回值 return null; } //plugin:包装目标对象的,包装:为目标对象创建一个代理对象 @Override public Object plugin(Object target) { //我们可以借助Plugin的wrap方法来使用当前Interceptor包装我们目标对象 System.out.println("MyFirstPlugin...plugin:mybatis将要包装的对象"+target); Object wrap = Plugin.wrap(target, this); //返回为当前target创建的动态代理 return wrap; } //setProperties:将插件注册时的property属性设置进来 @Override public void setProperties(Properties properties) { System.out.println("插件配置的信息:"+properties); } } 

③ 将写好的插件注册到全局配置文件mybatis-config中

 <plugins> <plugin interceptor="com.atguigu.mybatis.dao.MyFirstPlugin"> <property name="username" value="root"/> <property name="password" value="123456"/>  // 1、获取sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、获取sqlSession对象 SqlSession openSession = sqlSessionFactory.openSession(); try { // 3、获取接口的实现类对象 //会为接口自动的创建一个代理对象,代理对象去执行增删改查方法 EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); Employee employee = mapper.getEmpById(1); System.out.println(mapper.getClass()); System.out.println(employee); }finally{ openSession.close(); } } 

在这里插入图片描述

(3)多个插件运行流程

① 编写第二个插件

package com.atguigu.mybatis.dao; import java.util.Properties; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.plugin.Intercepts; import org.apache.ibatis.plugin.Invocation; import org.apache.ibatis.plugin.Plugin; import org.apache.ibatis.plugin.Signature; @Intercepts( { @Signature(type=StatementHandler.class,method="parameterize",args=java.sql.Statement.class) }) public class MySecondPlugin implements Interceptor{ @Override public Object intercept(Invocation invocation) throws Throwable { System.out.println("MySecondPlugin...intercept:"+invocation.getMethod()); return invocation.proceed(); } @Override public Object plugin(Object target) { // TODO Auto-generated method stub System.out.println("MySecondPlugin...plugin:"+target); return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { // TODO Auto-generated method stub } } 

② 注册插件

 <plugins> <plugin interceptor="com.atguigu.mybatis.dao.MyFirstPlugin"> <property name="username" value="root"/> <property name="password" value="123456"/>  // TODO Auto-generated method stub System.out.println("MyFirstPlugin...intercept:"+invocation.getMethod()); //动态的改变一下sql运行的参数:以前1号员工,实际从数据库查询3号员工 Object target = invocation.getTarget(); System.out.println("当前拦截到的对象:"+target); //拿到:StatementHandler==>ParameterHandler===>parameterObject //拿到target的元数据 MetaObject metaObject = SystemMetaObject.forObject(target); Object value = metaObject.getValue("parameterHandler.parameterObject"); System.out.println("sql语句用的参数是:"+value); //修改完sql语句要用的参数 metaObject.setValue("parameterHandler.parameterObject", 3); //执行目标方法 Object proceed = invocation.proceed(); //返回执行后的返回值 return proceed; } 
(5)PageHelper分页插件的使用

① PageHelper插件官网地址 ② 以入门案例的代码为例,在其基础上使用PageHelper插件。 1)导入需要的 jar 包 在这里插入图片描述 2)在全局配置文件mybatis-config中注册pageHelper插件

 <plugins> <plugin interceptor="com.github.pagehelper.PageInterceptor"> SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try { EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); //查询第1页的5条记录 Page<Object> page = PageHelper.startPage(1, 5); List<Employee> emps = mapper.getEmps(); for (Employee emp : emps) { System.out.println(emp); } System.out.println("当前页码:"+page.getPageNum()); System.out.println("总记录数:"+page.getTotal()); System.out.println("每页的记录数:"+page.getPageSize()); }finally{ openSession.close(); } } 

在这里插入图片描述

@Test public void testPageHelper02() throws IOException { // 1、获取sqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); // 2、获取sqlSession对象 SqlSession openSession = sqlSessionFactory.openSession(); try { EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); //查询第5页的1条记录 Page<Object> page = PageHelper.startPage(5, 1); List<Employee> emps = mapper.getEmps(); //传入要连续显示多少页 PageInfo<Employee> info = new PageInfo<>(emps, 5); for (Employee employee : emps) { System.out.println(employee); } System.out.println("当前页码:"+info.getPageNum()); System.out.println("总记录数:"+info.getTotal()); System.out.println("每页的记录数:"+info.getPageSize()); System.out.println("总页码:"+info.getPages()); System.out.println("是否第一页:"+info.isIsFirstPage()); int[] nums = info.getNavigatepageNums(); System.out.println("连续显示的页码:"); //当前页码为第5页,在连续显示时,当前页码居中 for (int i = 0; i < nums.length; i++) { System.out.println(nums[i]); } } finally { openSession.close(); } } 

在这里插入图片描述

11.Mybatis扩展 (1)批量操作

以入门案例的代码为例,在其基础上进行批量操作。 ① 在EmployeeMapper.java中添加抽象方法

Long addEmp(Employee employee); 

② 在EmployeeMapper.xml编写对应的sql语句

 <insert id="addEmp"> insert into tbl_employee(last_name, gender, email)
    values (#{last_name},#{gender},#{email})  SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); //可以执行批量操作的sqlSession SqlSession openSession = sqlSessionFactory.openSession(ExecutorType.BATCH); long start = System.currentTimeMillis(); try{ EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); //插入1000条数据 for (int i = 0; i < 1000; i++) { String last_name = UUID.randomUUID().toString().substring(0, 5); mapper.addEmp(new Employee(last_name, last_name+"@163.com", "1")); } openSession.commit(); long end = System.currentTimeMillis(); //批量:(预编译sql一次==>设置参数===>10000次===>执行(1次)) //Parameters: 616c1(String), 616c1@163.com(String), 1(String)==>4598 //非批量:(预编译sql=设置参数=执行)==》10000    10200 System.out.println("执行时长:"+(end-start)+"毫秒"); }finally{ openSession.close(); } } 

在这里插入图片描述 ④ 与Spring整合中,推荐额外的配置一个可以专门用来执行批量操作的sqlSession

 <bean id="sqlSession" class="org.mybatis.spring.sqLSessionTemplate"> <constructor-arg name="sqLSessionFactory" ref= "sqLSessionFactoryBean"> //员工状态 LOGIN,LOGOUT,REMOVE } 
//员工状态 private EmpStatus empStatus=EmpStatus.LOGOUT; 

② 在表tbl_employee中新增一列,表示员工状态,同时也需要改变aEmployeeMapper.xml中对应的sql语句

alter table tbl_employee add empStatus varchar(11) 
 <insert id="addEmp"> insert into tbl_employee(last_name, gender, email,empStatus)
    values (#{last_name},#{gender},#{email},#{empStatus})  SqlSessionFactory sqlSessionFactory = getSqlSessionFactory(); SqlSession openSession = sqlSessionFactory.openSession(); try{ EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class); Employee employee = new Employee("test_enum", "enum@163.com","1"); mapper.addEmp(employee); openSession.commit(); }finally{ openSession.close(); } } 

在这里插入图片描述 在全局配置文件mybatis-config.xml添加如下配置之后,再次测试时便保存枚举的索引

<typeHandlers> <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="com.atguigu.mybatis.bean.EmpStatus"/>  LOGIN(100,"用户登录"),LOGOUT(200,"用户登出"),REMOVE(300,"用户不存在"); private Integer code; private String msg; private EmpStatus(Integer code,String msg){ this.code = code; this.msg = msg; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } //按照状态码返回枚举对象 public static EmpStatus getEmpStatusByCode(Integer code){ switch (code) { case 100: return LOGIN; case 200: return LOGOUT; case 300: return REMOVE; default: return LOGOUT; } } } 

② 自定义TypeHandler类

package com.atguigu.mybatis.typehandler; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.TypeHandler; import com.atguigu.mybatis.bean.EmpStatus; //1、实现TypeHandler接口,或者继承BaseTypeHandler public class MyEnumEmpStatusTypeHandler implements TypeHandler<EmpStatus> { //定义当前数据如何保存到数据库中 @Override public void setParameter(PreparedStatement ps, int i, EmpStatus parameter, JdbcType jdbcType) throws SQLException { // TODO Auto-generated method stub System.out.println("要保存的状态码:"+parameter.getCode()); ps.setString(i, parameter.getCode().toString()); } @Override public EmpStatus getResult(ResultSet rs, String columnName) throws SQLException { // TODO Auto-generated method stub //需要根据从数据库中拿到的枚举的状态码返回一个枚举对象 int code = rs.getInt(columnName); System.out.println("从数据库中获取的状态码:"+code); EmpStatus status = EmpStatus.getEmpStatusByCode(code); return status; } @Override public EmpStatus getResult(ResultSet rs, int columnIndex) throws SQLException { // TODO Auto-generated method stub int code = rs.getInt(columnIndex); System.out.println("从数据库中获取的状态码:"+code); EmpStatus status = EmpStatus.getEmpStatusByCode(code); return status; } @Override public EmpStatus getResult(CallableStatement cs, int columnIndex) throws SQLException { // TODO Auto-generated method stub int code = cs.getInt(columnIndex); System.out.println("从数据库中获取的状态码:"+code); EmpStatus status = EmpStatus.getEmpStatusByCode(code); return status; } } 

③ 在全局配置文件mybatis-config.xml注册

 <typeHandlers>  <typeHandler handler="com.atguigu.mybatis.typehandler.MyEnumEmpStatusTypeHandler" javaType="com.atguigu.mybatis.bean.EmpStatus"/>              
关注
打赏
1688896170
查看更多评论

暂无认证

  • 7浏览

    0关注

    115984博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文
立即登录/注册

微信扫码登录

0.1233s