大纲 前言 版本说明 本文的教程内容是基于 MyBatis-Plus 3.5.2
版本编写的,若你使用的是 2.x
或其他版本,可能会有部分知识点、案例代码不兼容,一切以 MyBatis-Plus 官方文档为准。
MyBatis-Plus 主键生成策略 主键生成策略 使用方式:在实体类的主键属性上添加注解 @TableId(type = IdType.AUTO)
,或者在全局配置文件中通过 idType
属性指定 MyBatis-Plus 的主键生成策略 主键生成策略 描述 AUTO 数据库 ID 自增,该类型必须确保数据库表的主键字段设置了 ID 自增,否则无法生效 NONE 无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT) INPUT 用户自行设置主键值,该类型可以通过自己注册自动填充插件进行填充 ASSIGN_ID 分配 ID,主键类型为 Number [Long 和 Integer] 或 String(@since 3.3.0 version
),使用的是 IdentifierGenerator
接口的 nextId
方法(默认实现类为 DefaultIdentifierGenerator
,使用的是雪花算法) ASSIGN_UUID 分配 UUID,主键类型为 String(@since 3.3.0 version
),使用的是 IdentifierGenerator
接口的 nextUUID
方法 ID_WORKER 分布式全局唯一 ID 长整型类型(请使用 ASSIGN_ID
) UUID32 位 UUID 字符串(请使用 ASSIGN_UUID
) ID_WORKER_STR 分布式全局唯一 ID 字符串类型(请使用 ASSIGN_ID
)
注意
1、AUTO
主键类型必须确保数据库表的主键字段设置了 ID 自增,否则无法生效 2、ASSIGN_ID
主键类型(使用雪花算法生成 ID),与数据库表的主键字段是否设置 ID 自增没有任何关系 3、ASSIGN_ID
和 ASSIGN_UUID
这两种主键类型,只有当插入对象的 ID 为空时,才会自动填充主键值
Sequence 序列生成器 对于 INPUT
类型的主键生成策略,一种情况是程序里面自己指定主键,另一种是利用 MyBatis-Plus 内置的序列生成器来生成主键。由于不是所有数据库都像 MySQL 一样支持自增主键,例如在 Oracle 数据库中就不支持主键自增长,它是通过 Sequence
序列来获取主键的,MyBatis-Plus 为了解决该问题提供了序列生成器。MyBatis-Plus 内置支持以下序列生成器,如果内置支持不满足你的需求,可实现 IKeyGenerator
接口来进行扩展。
DB2KeyGenerator H2KeyGenerator KingbaseKeyGenerator OracleKeyGenerator PostgreKeyGenerator Oracle 主键生成策略使用案例 指定 Oracle 主键生成策略的步骤
1、实体类添加 @KeySequence(value = "seq_employee", dbType = DbType.ORACLE)
注解,指定数据库中序列的名称 2、实体类属性添加 @TableId
注解,指定主键生成策略为 IdType.INPUT
,或者在配置文件中全局指定 MyBatis-Plus 的主键生成策略为 IdType.INPUT
3、注入 com.baomidou.mybatisplus.extension.incrementer.OracleKeyGenerator
序列生成器到 Spring 容器中 初始化数据库 1 2 3 4 5 6 7 8 9 10 11 CREATE TABLE t_employee(id number(11 ) primary key, last_name varchar (255 ) DEFAULT NULL , gender char (1 ) DEFAULT NULL , email varchar (255 ) DEFAULT NULL , age number DEFAULT NULL );create sequence seq_employee start with 100 increment by 2 ;insert into t_employee(id, last_name, gender, email, age) values (1 , 'Jim' ,'1' , 'jim@gmail.com' , 26 );insert into t_employee(id, last_name, gender, email, age) values (2 , 'Peter' ,'1' , 'peter@gmail.com' , 29 );insert into t_employee(id, last_name, gender, email, age) values (3 , 'David' ,'1' , 'david@gmail.com' , 28 );insert into t_employee(id, last_name, gender, email, age) values (4 , 'Tom' ,'1' , 'tom@gmail.com' , 25 );
引入 Oracle 依赖 由于 Oracle 授权的问题,不能直接从 Maven 的仓库中下载到 Oracle 驱动。为了简单演示,这里直接将驱动包存放在项目的 lib
目录中,然后通过本地文件的方式引用,其他引入方式可以看 这里 。
1 2 3 4 5 6 7 8 9 10 <dependencies > <dependency > <groupId > oracle</groupId > <artifactId > ojdbc6</artifactId > <version > 11.2.0.2.0</version > <scope > system</scope > <systemPath > ${project.basedir}/lib/ojdbc6.jar</systemPath > </dependency > </dependencies >
Oracle 数据库连接信息 1 2 3 4 driver-class-name: oracle.jdbc.OracleDriver url: jdbc:oracle:thin:@localhost:1521:xe username: system password: oracle
@KeySequence
注解指定序列名称指定序列名称,在实体类上添加 @KeySequence
注解,value
属性是 Oracle 数据库中序列的名称,dbType
属性是数据库的类型,完整的数据库类型列表可查看 DbType
类的源码注释。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @KeySequence(value = "seq_employee", dbType = DbType.ORACLE) public class Employee { private Long id; private String email; private String lastName; private String gender; private Integer age; .... }
指定主键生成策略 @TableId 注解方式 指定主键生成策略,在实体类的主键属性上添加 @TableId
注解,type
属性必须为 IdType.INPUT
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @KeySequence(value = "seq_employee", dbType = DbType.ORACLE) public class Employee { @TableId(type = IdType.INPUT) private Long id; private String email; private String lastName; private String gender; private Integer age; .... }
全局配置文件方式 除了可以使用 @TableId
注解单独指定主键生成策略外,还可以在配置文件中全局指定 MyBatis-Plus 的主键生成策略。
Spring XML 配置文件 1 2 3 4 5 6 7 8 9 10 11 <bean id ="sqlSessionFactory" class ="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean" > <property name ="globalConfig" ref ="globalConfig" > </property > </bean > <bean id ="globalConfig" class ="com.baomidou.mybatisplus.core.config.GlobalConfig" > <property name ="dbConfig" ref ="dbConfig" /> </bean > <bean id ="dbConfig" class ="com.baomidou.mybatisplus.core.config.GlobalConfig.DbConfig" > <property name ="idType" value ="INPUT" > </property > </bean >
SpringBoot 配置文件 1 2 3 4 mybatis-plus: global-config: db-config: id-type: INPUT
注入序列生成器 将 Oracle 的序列生成器注入到 Spring 容器中。
Spring XML 配置文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <bean id ="sqlSessionFactory" class ="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean" > <property name ="globalConfig" ref ="globalConfig" > </property > </bean > <bean id ="globalConfig" class ="com.baomidou.mybatisplus.core.config.GlobalConfig" > <property name ="dbConfig" ref ="dbConfig" /> </bean > <bean id ="dbConfig" class ="com.baomidou.mybatisplus.core.config.GlobalConfig.DbConfig" > <property name ="keyGenerator" ref ="keyGenerator" /> </bean > <bean id ="keyGenerator" class ="com.baomidou.mybatisplus.extension.incrementer.OracleKeyGenerator" />
SpringBoot 配置类 1 2 3 4 5 6 7 8 9 10 @Configuration @MapperScan("com.clay.mybatis.dao") public class MybatisPlusConfig { @Bean public IKeyGenerator keyGenerator () { return new OracleKeyGenerator(); } }
Oracle 多个表共用一个序列 在特殊的业务场景下,若希望多个数据库表共用一个 Sequence
序列,那么可以将 @keySequence
注解定义在父类中,这样就可以实现多个子类对应的多个表共用一个 Sequence
序列。
1 2 3 4 @KeySequence(value = "seq_employee", dbType = DbType.ORACLE) public abstract class BaseEntity {}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Employee extends BaseEntity { @TableId(type = IdType.INPUT) private Long id; private String email; private String lastName; private String gender; private Integer age; .... }
MyBatis-Plus 自定义 ID 生成器 若 MyBatis-Plus 提供的主键生成策略不能满足业务需求,则可以自定义 MyBatis-Plus 的 ID 生成器,例如使用分布式全局唯一 ID 方案来生成主键。
自定义 ID 生成器的步骤
1、实现 IdentifierGenerator
接口 2、将自定义 ID 生成器类注入到 Spring 容器中 自定义 ID 生成器 1 2 3 4 5 6 7 8 9 10 11 public class CustomIdGenerator implements IdentifierGenerator { @Override public Long nextId (Object entity) { String bizKey = entity.getClass().getName(); long id = ....; return id; } }
注入自定义 ID 生成器 Spring XML 配置文件 1 2 3 4 5 6 7 8 9 <bean id ="sqlSessionFactory" class ="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean" > <property name ="globalConfig" ref ="globalConfig" > </property > </bean > <bean id ="globalConfig" class ="com.baomidou.mybatisplus.core.config.GlobalConfig" > <property name ="identifierGenerator" ref ="customIdGenerator" /> </bean > <bean name ="customIdGenerator" class ="com.clay.mybatis.incrementer.CustomIdGenerator" />
SpringBoot 配置类 1 2 3 4 5 6 7 8 9 10 @Configuration @MapperScan("com.clay.mybatis.dao") public class MybatisPlusConfig { @Bean public IdentifierGenerator idGenerator () { return new CustomIdGenerator(); } }
MyBatis-Plus 执行 SQL 分析打印 值得一提的是,执行 SQL 分析打印会产生性能损耗,不建议在生产环境使用。
普通打印方式 使用案例 在 SpringBoot 的 YML 配置文件中,指定 MyBatis-Plus 的 log-impl
配置参数
1 2 3 4 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
打印结果 1 2 3 22:16:13,481 DEBUG getById:137 - ==> Preparing: select id, last_name as lastName, gender, email from t_employee where id = ? 22:16:13,521 DEBUG getById:137 - ==> Parameters: 1(Long) 22:16:13,570 DEBUG getById:137 - <== Total: 1
可以发现上述的打印方式,不会自动替换 SQL 中的 ?
符号为真实参数值
P6Spy 打印方式 使用案例 引入 Maven 依赖 MyBatis-Plus 执行 SQL 分析打印需要依赖 P6Spy 主组件。
1 2 3 4 5 <dependency > <groupId > p6spy</groupId > <artifactId > p6spy</artifactId > <version > 3.9.1</version > </dependency >
数据库连接配置 提示
driver-class-name
为 P6Spy 提供的驱动类url
前缀为 jdbc:p6spy
,后面跟着冒号为对应数据库的连接地址1 2 3 4 5 spring: datasource: driver-class-name: com.p6spy.engine.spy.P6SpyDriver url: jdbc:p6spy:mysql://127.0.0.1:3306/mybatis_plus_lesson?characterEncoding=utf8&autoReconnect=true&useSSL=false&useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC ...
创建 P6Spy 配置文件 在项目的 src/main/resources
目录下创建 spy.properties
配置文件,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 modulelist =com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory logMessageFormat =com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger appender =com.baomidou.mybatisplus.extension.p6spy.StdoutLogger deregisterdrivers =true useprefix =true excludecategories =info,debug,result,commit,resultset dateformat =yyyy-MM-dd HH:mm:ss outagedetection =true outagedetectioninterval =2
日志打印结果 简单执行 CRUD 操作后,MyBatis-Plus 打印的日志信息如下:
1 2 3 4 5 6 7 8 ==> Preparing: SELECT id,email,last_name,gender,age FROM t_employee WHERE id=? ==> Parameters: 1(Long) Consume Time:2 ms 2022-09-17 19:38:30 Execute SQL:SELECT id,email,last_name,gender,age FROM t_employee WHERE id=1 <== Columns: id, email, last_name, gender, age <== Row: 1, empty@gmai.com, Clion, 1, 26 <== Total: 1
可以发现 P6Spy 组件会打印出完整的 SQL 语句和执行 SQL 语句所耗费的时间,而且它会自动替换 SQL 中的 ?
为真实参数值并输出。