通用Mapper
1 引入
1.1作用
替我们生成常用增删改查操作的 SQL 语句。
1.2代码官方发布地址
https://gitee.com/free
https://gitee.com/free/Mapper/wikis/1.1-java?parent=1.integration
1.3前置知识
MyBatis
Spring
2 快速入门
Java 实体类
考虑到基本数据类型在 Java 类中都有默认值,会导致 MyBatis 在执行相关操作时很难判断当前字段是否为 null,所以在 MyBatis 环境下使用 Java 实体类时尽量不要使用基本数据类型,都使用对应的包装类型。
3集成 Mapper
加入 Maven 依赖信息
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>4.0.0-beta3</version>
</dependency>
修改 Spring 配置文件
<!-- 整合通用 Mapper 所需要做的配置修改: --> <!-- 原始全类名:org.mybatis.spring.mapper.MapperScannerConfigurer --> <!-- 通用 Mapper 使用:tk.mybatis.spring.mapper.MapperScannerConfigurer --> <bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.atguigu.mapper.mappers"/> </bean>
第一个操作
/**
* 具 体 操 作 数 据 库 的 Mapper 接 口 , 需 要 继 承 通 用 Mapper 提 供 的 核 心 接 口 : Mapper<Employee> * 泛型类型就是实体类的类型 */
public interface EmployeeMapper extends Mapper<Employee> {
}
3 常用注解
3.1@Table 注解
作用:建立实体类和数据库表之间的对应关系。
默认规则:实体类类名首字母小写作为表名。Employee 类→employee 表。
用法:在@Table 注解的 name 属性中指定目标数据库表的表名
3.2@Column 注解
作用:建立实体类字段和数据库表字段之间的对应关系。
默认规则:
实体类字段:驼峰式命名
数据库表字段:使用“_”区分各个单词
用法:在@Column 注解的 name 属性中指定目标字段的字段名
3.3@Id 注解
通用 Mapper 在执行 xxxByPrimaryKey(key)方法时,有两种情况。
情况 1:没有使用@Id 注解明确指定主键字段
SELECT emp_id,emp_name,emp_salary_apple,emp_age FROM tabple_emp WHERE emp_id = ? AND emp_name = ? AND emp_salary_apple = ? AND emp_age = ?
之所以会生成上面这样的 WHERE 子句是因为通用 Mapper 将实体类中的所有字段都拿来放在一起作为联合主键。
情况 2:使用@Id 主键明确标记和数据库表中主键字段对应的实体类字段。

3.4@GeneratedValue 注解
作用:让通用 Mapper 在执行 insert 操作之后将数据库自动生成的主键值回写到实体类对象中。
自增主键用法:
序列主键用法:(一般用于Oracle数据库)

3.5@Transient 主键
用于标记不与数据库表字段对应的实体类字段。
@Transient private String otherThings; //非数据库表中字段
4 常用方法
4.1selectOne 方法
通用 Mapper 替我们自动生成的 SQL 语句情况
实体类封装查询条件生成 WHERE 子句的规则:
- 使用非空的值生成 WHERE 子句
-
在条件表达式中使用“=”进行比较
要求必须返回一个实体类结果,如果有多个,则会抛出异常
4.2xxxByPrimaryKey 方法
需要使用@Id 主键明确标记和数据库表主键字段对应的实体类字段,否则通用
Mapper 会将所有实体类字段作为联合主键。
4.3xxxSelective 方法
非主键字段如果为 null 值,则不加入到 SQL 语句中。
5 QBC 查询
5.1概念
Query By Criteria
Criteria 是 Criterion 的复数形式。意思是:规则、标准、准则。在 SQL 语句中相当于查询条件。
QBC 查询是将查询条件通过 Java 对象进行模块化封装。
5.2示例代码
//目标:WHERE (emp_salary>? AND emp_age<?) OR (emp_salary<? AND emp_age>?) //1.创建 Example 对象 Example example = new Example(Employee.class); //*********************** //i.设置排序信息 example.orderBy("empSalary").asc().orderBy("empAge").desc(); //ii.设置“去重” example.setDistinct(true); //iii.设置 select 字段 example.selectProperties("empName","empSalary"); //*********************** //2.通过 Example 对象创建 Criteria 对象 Criteria criteria01 = example.createCriteria(); Criteria criteria02 = example.createCriteria(); //3.在两个 Criteria 对象中分别设置查询条件 //property 参数:实体类的属性名 //value 参数:实体类的属性值 criteria01.andGreaterThan("empSalary", 3000).andLessThan("empAge", 25); criteria02.andLessThan("empSalary", 5000).andGreaterThan("empAge", 30); //4.使用 OR 关键词组装两个 Criteria 对象 example.or(criteria02); //5.执行查询 List<Employee> empList = employeeService.getEmpListByExample(example); for (Employee employee : empList) { System.out.println(employee); }
6 逆向工程
6.1原生 MyBatis 逆向工程和通用 Mapper 逆向工程对比

6.2参考文档地址
https://github.com/abel533/Mapper/wiki/4.1.mappergenerator
7 自定义 Mapper<T>接口
7.1用途
让我们可以根据开发的实际需要对 Mapper<T>接口进行定制。
7.2创建自定义 Mapper<T>接口

7.3配置 MapperScannerConfigurer 注册 MyMapper<T>
<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.atguigu.mapper.mappers"/> <property name="properties"> <value> mappers=com.atguigu.mapper.mine_mappers.MyMapper </value> </property> </bean>
8 通用 Mapper 接口扩展
8.1说明
这里的扩展是指增加通用 Mapper 没有提供的功能。
8.2举例
通用 Mapper 官方文档中使用一个批量 insert 作为扩展功能的例子:
tk.mybatis.mapper.additional.insert.InsertListMapper<T>
tk.mybatis.mapper.additional.insert.InsertListProvider
我们来仿照写一个批量 update。假设我们想生成下面这样的 SQL 语句:
UPDATE tabple_emp SET emp_name=?,emp_age=?,emp_salary=? where emp_id=? ; UPDATE tabple_emp SET emp_name=?,emp_age=?,emp_salary=? where emp_id=? ; UPDATE tabple_emp SET emp_name=?,emp_age=?,emp_salary=? where emp_id=? ; ……
为了生成上面那样的 SQL 语句,我们需要使用到 MyBatis 的 foreach 标签。
<foreach collection="list" item="record" separator=";" >
UPDATE tabple_emp
SET emp_name=#{record.empName},
emp_age=#{record.empAge},
emp_salary=#{record.empSalary}
where emp_id=#{record.empId}
</foreach>
8.3我们需要提供的接口和实现类
8.4参考代码

9 二级缓存
9.1MyBatis 配置文件开启二级缓存功能
<settings> <setting name="cacheEnabled" value="true"/> </settings>
9.2在 XxxMapper 接口上使用@CacheNamespace 注解
@CacheNamespace public interface EmployeeMapper extends MyMapper<Employee> { }
10 类型处理器:TypeHandler
10.1简单类型和复杂类型
※通用 Mapper 默认情况下会忽略复杂类型,对复杂类型不进行“从类到表”的映射
10.2Address 处理
10.2.1自定义类型转换器
10.2.2 TypeHandler 接口
public interface TypeHandler<T> { //将 parameter 设置到 ps 对象中,位置是 i //在这个方法中将 parameter 转换为字符串 void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException; //根据列名从 ResultSet 中获取数据,通常是字符串形式 //将字符串还原为 Java 对象,以 T 类型返回 T getResult(ResultSet rs, String columnName) throws SQLException; T getResult(ResultSet rs, int columnIndex) throws SQLException; T getResult(CallableStatement cs, int columnIndex) throws SQLException; }
10.2.3继承树
10.2.4 BaseTypeHandler 类中的抽象方法说明
//将 parameter 对象转换为字符串存入到 ps 对象的 i 位置 public abstract void setNonNullParameter( PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
//从结果集中获取数据库对应查询结果 //将字符串还原为原始的 T 类型对象 public abstract T getNullableResult( ResultSet rs, String columnName) throws SQLException;
public abstract T getNullableResult( ResultSet rs, int columnIndex) throws SQLException;
public abstract T getNullableResult( CallableStatement cs, int columnIndex) throws SQLException;
10.2.5自定义类型转换器类
public class AddressTypeHandler extends BaseTypeHandler<Address> {
……
10.2.6注册自定义类型转换器
方法一 字段级别:@ColumnType 注解
方法二 全局级别:在 MyBatis 配置文件中配置 typeHandlers

10.3枚举类型
10.3.1办法一:让通用 Mapper 把枚举类型作为简单类型处理
增加一个通用 Mapper 的配置项
在 Spring 配置文件中找到 MapperScannerConfigurer
本质
使用了 org.apache.ibatis.type.EnumTypeHandler<E>
10.3.2办法二:为枚举类型配置对应的类型处理器
类型处理器
内置
org.apache.ibatis.type.EnumTypeHandler<E>
在数据库中存储枚举值本身
org.apache.ibatis.type.EnumOrdinalTypeHandler<E>
在数据库中仅仅存储枚举值的索引
自定义
内置枚举类型处理器注册
不能使用@ColumnType 注解
需要在 MyBatis 配置文件中配置专门的类型处理器并在字段上使用@Column 注解
注意:加@Column 注解的作用是让通用 Mapper 不忽略枚举类型。
《三体》中有句话——弱小和无知不是生存的障碍,傲慢才是。
所以我们不要做一个小青蛙

浙公网安备 33010602011771号