MyBatis基础 MyBatis概述 (1)MyBatis 是一款优秀的持久层框架,内部对 JDBC 代码进行了封装,使开发者只需要关注 SQL 语句本身,不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程
(2)MyBatis可以使用XML或注解,来配置SQL语句和参数映射关系,将POJO映射为数据库中的记录,避免了JDBC代码和手动设置参数以及获取结果集
ORM思想 ORM(Object Relational Mapping)是一种编程思想,它的主要目标是将关系数据库中的数据表映射到面向对象编程语言的类和对象上
Java概念 数据库概念 类 表 类中属性 字段/列 类的对象 记录/行
持久化层技术对比 持久化层技术 简介 JDBC 代码冗长,开发效率低,耦合度高,不易维护,硬编码,操作繁琐 Hibernate 和 JPA 操作简便,开发效率高,内部自动生产的 SQL,不容易做特殊优化,反射操作太多,导致数据库性能下降 MyBatis 轻量级,性能出色,开发效率稍逊于HIbernate,但是完全能够接受
MyBatis核心配置文件 核心配置文件中的标签,必须按照固定的顺序:properties—>settings—>typeAliases—>typeHandlers—>objectFactory—>objectWrapperFactory—>refl ectorFactory—>plugins—>environments—>databaseIdProvider—>mappers
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 <?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 ="jdbc.properties" /> <settings > <setting name ="mapUnderscoreToCamelCase" value ="true" /> <setting name ="lazyLoadingEnabled" value ="true" /> <setting name ="aggressiveLazyLoading" value ="false" /> </settings > <typeAliases > <package name ="pojo" /> </typeAliases > <environments default ="development" > <environment id ="development" > <transactionManager type ="JDBC" /> <dataSource type ="POOLED" > <property name ="driver" value ="${jdbc.driver}" /> <property name ="url" value ="${jdbc.url}" /> <property name ="username" value ="${jdbc.username}" /> <property name ="password" value ="${jdbc.password}" /> </dataSource > </environment > <environment id ="test" > <transactionManager type ="JDBC" /> <dataSource type ="POOLED" > <property name ="driver" value ="com.mysql.jdbc.Driver" /> <property name ="url" value ="jdbc:mysql://localhost:3306/mybatis" /> <property name ="username" value ="root" /> <property name ="password" value ="123456" /> </dataSource > </environment > </environments > <mappers > <package name ="mapper" /> </mappers > </configuration >
MyBatis获取参数值 MyBatis获取参数值的两种方式 方式 简介 #{参数名}本质是占位符赋值(?), #{}使用占位符赋值的方式拼接sql,为字符串类型或日期类型的字段进行赋值时,自动添加单引号; ${参数名}本质是字符串拼接, ${}使用字符串拼接的方式拼接sql,为字符串类型或日期类型的字段进行赋值时,手动添加单引号;
使用@Param注解标识参数 实体类类型的参数不使用@Param、其他参数可使用@Param标识参数
(1)通过@Param注解标识mapper接口中的方法参数,MyBatis以两种方式,自动将这些参数放在一个map集合中存储数据,只需要通过${}和#{}访问map集合的键就可以获取相对应的值(注意${}需要手动加单引号)
方式 简介 方式一 以@Param注解的value属性值为键,以参数为值 方式二 以param1,param2…为键,以参数为值
(2)使用 @Param(“参数名称”) 标记每一个参数
1 User checkloginByParam (@Param("username") String username, @Param("password") String password) ;
(3)在映射配置文件中就需要使用 #{参数名称} 进行占位
1 2 3 <select id ="checkloginByParam" resultType ="User" > select * from t_user where username = #{username} and password = #{password} </select >
MyBatis的各种功能 查询一个实体类对象 (1)接口中的方法
1 2 User getUserById (@Param("id") int id) ;
(2)对应的映射文件
1 2 3 4 <select id ="getUserById" resultType ="User" > select * from t_user where id = #{id} </select >
(3)测试方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Test public void getUserById () { SqlSession sqlSession = SqlSessionUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User userById = mapper.getUserById(1 ); System.out.println(userById); sqlSession.close(); }
查询一个List集合 (1)接口中的方法
1 2 List<User> getUserList () ;
(2)对应的映射文件
1 2 3 4 <select id ="getUserList" resultType ="User" > select * from t_user </select >
(3)测试方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Test public void getUserList () { SqlSession sqlSession = SqlSessionUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> userList = mapper.getUserList(); System.out.println(userList); userList.forEach(System.out::println); sqlSession.close(); }
查询单个数据 (1)接口中的方法
(2)对应的映射文件
1 2 3 4 <select id ="getCount" resultType ="_integer" > select count(id) from t_user </select >
(3)测试方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Test public void getCount () { SqlSession sqlSession = SqlSessionUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); int count = mapper.getCount(); System.out.println(count); sqlSession.close(); }
查询一条数据为map集合 (1)接口中的方法
1 2 Map<String, Object> getUserToMap (@Param("id") int id) ;xxxxxxxxxx
(2)对应的映射文件
1 2 3 4 <select id ="getUserToMap" resultType ="map" > select * from t_user where id = #{id} </select >
(3)测试方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Test public void getUserToMap () { SqlSession sqlSession = SqlSessionUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); Map<String, Object> userToMap = mapper.getUserToMap(1 ); System.out.println(userToMap); sqlSession.close(); }
查询多条数据为map集合 (1)接口中的方法
1 2 3 4 5 List<Map<String, Object>> getAllUserToMap_1 () ; @MapKey("id") Map<String, Object> getAllUserToMap_2 () ;
(2)对应的映射文件
1 2 3 4 5 6 7 8 <select id ="getAllUserToMap_1" resultType ="map" > select * from t_user </select > <select id ="getAllUserToMap_2" resultType ="map" > select * from t_user </select >
(3)测试方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Test public void getAllUserToMap () { SqlSession sqlSession = SqlSessionUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<Map<String, Object>> allUserToMap_1 = mapper.getAllUserToMap_1(); System.out.println(allUserToMap_1); Map<String, Object> allUserToMap_2 = mapper.getAllUserToMap_2(); System.out.println(allUserToMap_2); sqlSession.close(); }
模糊查询 (1)接口中的方法
1 2 List<User> getUserByLike (@Param("mohu") String mohu) ;
(2)对应的映射文件
1 2 3 4 5 6 7 8 9 <select id ="getUserByLike" resultType ="User" > select * from t_user where username like "%"#{mohu}"%" </select >
(3)测试方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Test public void getUserByLike () { SqlSession sqlSession = SqlSessionUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> listroot = mapper.getUserByLike("root" ); System.out.println(listroot); listroot.forEach(System.out::println); sqlSession.close(); }
批量删除 (1)接口中的方法
1 2 int deleteMore (@Param("ids") String ids) ;
(2)对应的映射文件
1 2 3 <delete id ="deleteMore" > delete from t_user where id in (${ids}) </delete >
(3)测试方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Test public void deleteMore () { SqlSession sqlSession = SqlSessionUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); int result = mapper.deleteMore("1,2,3,8" ); System.out.println(result); sqlSession.close(); }
动态查询指定表名 (1)接口中的方法
1 2 List<User> getUserByTable (@Param("tableName") String tableName) ;
(2)对应的映射文件
1 2 3 4 5 <select id ="getUserByTable" resultType ="User" > select * from ${tableName} </select >
(3)测试方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Test public void getUserByLike () { SqlSession sqlSession = SqlSessionUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); List<User> t_user = mapper.getUserByTable("t_user" ); System.out.println(t_user); t_user.forEach(System.out::println); sqlSession.close(); }
添加功能获取自增的主键 需要先在mapper.xml中设置两个属性
属性 简介 useGeneratedKeys 设置使用自增的主键 keyProperty 因为增删改有统一的返回值是受影响的行数,因此只能将获取的自增的主键放在传输的参数user对象的某个属性中
(1)接口中的方法
1 2 void insertUser (User user) ;
(2)对应的映射文件
1 2 3 4 5 6 <insert id ="insertUser" useGeneratedKeys ="true" keyProperty ="id" > insert into t_user values(null,#{username},#{password},#{gender},#{age},#{email}) </insert >
(3)测试方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Test public void insertUser () { SqlSession sqlSession = SqlSessionUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = new User (null , "tom" , "123" , "男" , 18 , "123@321.com" ); mapper.insertUser(user); System.out.println(user); sqlSession.close(); }
MyBatis映射关系处理 什么是映射关系? Java概念 数据库概念 类 表 属性 字段/列 对象 记录/行
如果数据库中的字段名和实体类中的属性名不一致,如何解决映射?
方案 简介 方案一 查询时为字段起别名,保证与实体类中的属性名保持一致 方案二 使用MyBatis的核心配置文件设置全局配置,自动将下划线映射为驼峰 方案三 使用resultMap自定义映射关系
别名或全局配置方式处理 (1)数据库中的字段,符合Mysql的命名规范使用下划线(_)
(2)实体类中的属性,符合java驼峰命名规范
1 2 3 4 5 6 public class Emp { private Integer empId; private String empName; private Integer age; private String gender; }
(3)此时可以使用MyBatis的核心配置文件设置全局配置,自动将下划线映射为驼峰
1 2 3 <settings > <setting name ="mapUnderscoreToCamelCase" value ="true" /> </settings >
(4)接口中的方法
1 2 Emp getEmpByEmpId_1 (@Param("empId") Integer empId) ;
(5)对应的映射文件
1 2 3 4 5 6 <select id ="getEmpByEmpId_1" resultType ="Emp" > select * from t_emp where emp_id = #{empId} </select >
(6)测试方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Test public void getEmpByEmpId () { SqlSession sqlSession = SqlSessionUtil.getSqlSession(); EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); Emp empByEmpId_1 = mapper.getEmpByEmpId_1(1 ); System.out.println(empByEmpId_1); sqlSession.close(); }
resultMap自定义映射关系 (1)接口中的方法
1 2 Emp getEmpByEmpId_2 (@Param("empId") Integer empId) ;
(2)对应的映射文件,使用resultMap标签设置自定义映射关系
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <resultMap id ="EmpByEmpId_2" type ="Emp" > <id column ="emp_id" property ="empId" > </id > <result column ="emp_name" property ="empName" > </result > <result column ="age" property ="age" > </result > <result column ="gender" property ="gender" > </result > </resultMap > <select id ="getEmpByEmpId_2" resultMap ="EmpByEmpId_2" > select * from t_emp where emp_id = #{empId} </select >
(3)测试方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Test public void getEmpByEmpId () { SqlSession sqlSession = SqlSessionUtil.getSqlSession(); EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); Emp empByEmpId_2 = mapper.getEmpByEmpId_2(1 ); System.out.println(empByEmpId_2); sqlSession.close(); }
MyBatis动态SQL Mybatis框架的动态SQL技术是一种根据特定条件动态拼装SQL语句的功能,存在的意义是为了解决拼接SQL语句字符串时的痛点问题
if、where 1 2 3 4 5 6 7 8 9 <select id ="getEmpByCondition_where" resultType ="Emp" > select * from t_emp <where > <if test ="empName != null and empName !=''" > emp_name=#{empName} </if > </where > </select >
trim 1 2 3 4 5 6 7 8 9 10 11 12 13 <select id ="getEmpByCondition_trim" resultType ="Emp" > select * from t_emp <trim prefix ="where" prefixOverrides ="and" > <if test ="empName != null and empName !=''" > emp_name=#{empName} </if > <if test ="age != null and age !=''" > and age=#{age} </if > </trim > </select >
choose、when、otherwise 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <select id ="getEmpBychoose_cwo" resultType ="Emp" > select * from t_emp <where > <choose > <when test ="empName != null and empName !=''" > emp_name=#{empName} </when > <when test ="age != null and age !=''" > age=#{age} </when > <when test ="gender != null and gender !=''" > gender=#{gender} </when > <otherwise > </otherwise > </choose > </where > </select >
foreach 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 <insert id ="insertMoreEmp" > insert into t_emp values <foreach collection ="emps" item ="emp" separator ="," > (null,#{emp.empName},#{emp.age},#{emp.gender},null) </foreach > </insert > <delete id ="deleteMoreEmpByArray" > delete from t_emp where emp_id in <foreach collection ="empIds" item ="eid" separator ="," open ="(" close =")" > #{eid} </foreach > </delete > <delete id ="deleteMoreEmpByArray" > delete from t_emp where <foreach collection ="empIds" item ="eid" separator ="or" > emp_id = #{eid} </foreach > </delete >
sql片段 1 2 3 4 5 6 7 8 <sql id ="testsql" > emp_id,emp_name,age,gender,dept_id </sql > <select id ="selectAllEmp" resultType ="Emp" > select <include refid ="testsql" > </include > from t_emp </select >
分页插件 常用数据 字段 简介 pageNum 当前页的页码 pageSize 每页显示的条数 size 当前页显示的真实条数 total 总记录数 pages 总页数 prePage 上一页的页码 nextPage 下一页的页码 isFirstPage/isLastPage 是否为第一页/最后一页 hasPreviousPage/hasNextPage 是否存在上一页/下一页 navigatePages 导航分页的页码数 navigatepageNums 导航分页的页码,[1,2,3,4,5]
使用前提 (1)在pom文件中,添加分页插件依赖
1 2 3 4 5 6 <dependency > <groupId > com.github.pagehelper</groupId > <artifactId > pagehelper</artifactId > <version > 5.2.0</version > </dependency >
(2)在MyBatis的核心配置文件(mybatis-config.xml)中配置插件
1 2 3 4 <plugins > <plugin interceptor ="com.github.pagehelper.PageInterceptor" > </plugin > </plugins >
分页插件的使用 (1)测试使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 @Test public void Test () { SqlSession sqlSession = SqlSessionUtil.getSqlSession(); EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); Page<Object> objects = PageHelper.startPage(2 , 5 ); List<Emp> emps = mapper.selectByExample(null ); emps.forEach(System.out::println); PageInfo<Emp> empPageInfo = new PageInfo <>(emps, 5 ); System.out.println(empPageInfo); sqlSession.close(); }
(2)使用案例
1 2 3 4 5 6 7 8 9 10 public PageInfo<Emp> getEmpPage (Integer pageNum) { PageHelper.startPage(pageNum, 5 ); List<Emp> list = empMapper.getAll(); PageInfo<Emp> page = new PageInfo <>(list, 5 ); return page; }
MyBatis注解开发 (1)注解是用来替换映射配置文件方式配置的,使用注解开发会比配置文件开发更加方便,但对应复杂开发需要使用配置文件
(2)注解完成简单功能(增删改查),配置文件完成复杂功能(动态SQL),针对 CURD 操作都提供了对应的注解
操作 注解 查询 @Select(value = “sql语句”) 添加 @Insert(value = “sql语句”) 修改 @Update(value = “sql语句”) 删除 @Delete(value = “sql语句”)
(3)@Select注解使用案例,其他注解类似
1 2 @Select(value = "select * from tb_user where id = #{id}") public User select (int id) ;