1. ActiveRecord
ActiveRecord(简称AR)一直广受动态语言( PHP 、 Ruby 等)的喜爱,而 Java 作为准静态语言,对于ActiveRecord 往往只能感叹其优雅,所以我们也在 AR 道路上进行了一定的探索,喜欢大家能够喜欢。
什么是ActiveRecord?
ActiveRecord也属于ORM(对象关系映射)层,由Rails最早提出,遵循标准的ORM模型:表映射到记录,记录映射到对象,字段映射到对象属性。配合遵循的命名和配置惯例,能够很大程度的快速实现模型的操作,而且简洁易懂。
ActiveRecord的主要思想是:
- 每一个数据库表对应创建一个类,类的每一个对象实例对应于数据库中表的一行记录;通常表的每个字段在类中都有相应的Field;
- ActiveRecord 同时负责把自己持久化,在ActiveRecord中封装了对数据库的访问,即CURD;;
- ActiveRecord 是一种领域模型(Domain Model),封装了部分业务逻辑;
1.1 开启AR之旅
在MP中,开启AR非常简单,只需要将实体对象继承Model即可。
1 | /** |
1.2 根据主键查询
1 | /** |
1.3 新增数据
1 | /** |
1.4 更新操作
1 | /** |
1.5 删除操作
1 | /** |
1.6 根据条件查询
1 | /** |
2. Oracle 主键Sequence
在mysql中,主键往往是自增长的,这样使用起来是比较方便的,如果使用的是Oracle数据库,那么就不能使用自增长了,就得使用Sequence 序列生成id值了。
2.1 部署Oracle环境
为了简化环境部署,这里使用Docker环境进行部署安装Oracle。
1 | # 拉取镜像 |
下面使用navicat12进行连接并操作oracle。
需要注意的是:由于安装的Oracle是64位版本,所以navicat也是需要使用64为版本,否则连接不成功。
2.2 创建表以及序列
1 | -- 创建表,表名以及字段名都要大写 |
2.3 jdbc驱动包
由于版权原因,我们不能直接通过maven的中央仓库下载oracle数据库的jdbc驱动包,所以我们需要将驱动包安装到本地仓库。
1 | #ojdbc8.jar |
安装完成后的坐标:
1 | <dependency> |
2.4 修改application.properties
对于application.properties的修改,需要修改2个位置,分别是:
1 | # 数据库连接配置 |
2.5 配置序列
使用Oracle的序列需要做2件事情:
1、需要配置MP的序列生成器到Spring容器:
1 | /** |
2、在实体对象中指定序列的名称:
1 | /** |
2.6 测试
1 | /** |
3. 插件
3.1 mybatis的插件机制
MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:
- Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
- ParameterHandler (getParameterObject, setParameters)
- ResultSetHandler (handleResultSets, handleOutputParameters)
- StatementHandler (prepare, parameterize, batch, update, query)
我们看到了可以拦截Executor接口的部分方法,比如update,query,commit,rollback等方法,还有其他接口的一些方法等。
总体概括为:
- 拦截执行器的方法
- 拦截参数的处理
- 拦截结果集的处理
- 拦截Sql语法构建的处理
拦截器示例:
1 | /** |
注入到Spring容器:
1 | /** |
或者通过xml配置,mybatis-config.xml:
1 |
|
3.2 执行分析插件
在MP中提供了对SQL执行的分析的插件,可用作阻断全表更新、删除的操作,注意:该插件仅适用于开发环境,不适用于生产环境。
SpringBoot配置:
1 | /** |
测试:
1 | /** |
结果:
1 | Caused by: com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Prohibition of table update operation |
可以看到,当执行全表更新时,会抛出异常,这样有效防止了一些误操作。
3.3 性能分析插件
性能分析拦截器,用于输出每条 SQL 语句及其执行时间,可以设置最大执行时间,超过时间会抛出异常。
该插件只用于开发环境,不建议生产环境使用。
配置:
1 |
|
执行结果:
1 | Time:11 ms - ID:com.wgy.mapper.UserMapper.selectById |
可以看到,执行时间为11ms。如果将maxTime设置为1,那么,该操作会抛出异常。
1 | Caused by: com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: The SQL execution time is too large, please optimize ! |
3.4 乐观锁插件
3.4.1 主要适用场景
意图:
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
- 取出记录时,获取当前 version
- 更新时,带上这个 version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果 version不对,就更新失败
3.4.2 插件配置
spring xml:
1 | <bean class="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"/> |
spring boot:
1 | /** |
或者通过xml配置,mybatis-config.xml:
1 |
|
3.4.3 注解实体字段
需要为实体字段添加@Version注解。
1、为表添加version字段,并且设置初始值为1:
1 | ALTER TABLE `tb_user` ADD COLUMN `version` int(10) NULL AFTER `email`; |
2、为User实体对象添加version字段,并且添加@Version注解:
1 | /** |
3.4.4 测试
1 | /** |
更新的条件中有version条件,并且更新的version为2。
如果再次执行,更新则不成功。这样就避免了多人同时更新时导致数据的不一致。
3.4.5 特别说明
- 支持的数据类型只有 :int,Integer,long,Long,Date,Timestamp,LocalDateTime
- 整数类型下 newVersion = oldVersion + 1
- newVersion 会回写到 entity 中
- 仅支持 updateById(id) 与 update(entity, wrapper) 方法
- 在 update(entity, wrapper) 方法下, wrapper 不能复用!!!
4. Sql 注入器
我们已经知道,在MP中,通过AbstractSqlInjector将BaseMapper中的方法注入到了Mybatis容器,这样这些方法才可以正常执行。
那么,如果我们需要扩充BaseMapper中的方法,又该如何实现呢?
下面我们以扩展findAll方法为例进行学习。
4.1 编写MyBaseMapper
1 | /** |
其他的Mapper都可以继承该Mapper,这样实现了统一的扩展。
如:
1 | /** |
4.2 编写MySqlInjector
如果直接继承AbstractSqlInjector的话,原有的BaseMapper中的方法将失效,所以我们选择继承DefaultSqlInjector进行扩展。
1 | /** |
4.3 编写FindAll
1 | /** |
4.4 注册到Spring容器
1 | /** |
4.5 测试
1 | /** |
5. 自动填充功能
有些时候我们可能会有这样的需求,插入或者更新数据时,希望有些字段可以自动填充数据,比如密码、version等。在MP中提供了这样的功能,可以实现自动填充。
5.1 添加@TableField注解
1 | /** |
为password添加自动填充功能,在新增数据时有效。
FieldFill提供了多种模式选择:
1 | public enum FieldFill { |
5.2 编写MyMetaObjectHandler
1 | /** |
5.3 测试
1 |
|
6. 逻辑删除
开发系统时,有时候在实现功能时,删除操作需要实现逻辑删除,所谓逻辑删除就是将数据标记为删除,而并非真正的物理删除(非DELETE操作),查询时需要携带状态条件,确保被标记的数据不被查询到。这样做的目的就是避免数据被真正的删除。
6.1 修改表结构
为tb_user表增加deleted字段,用于表示数据是否被删除,1代表删除,0代表未删除。
1 | ALTER TABLE `tb_user` ADD COLUMN `deleted` int(1) NULL DEFAULT 0 COMMENT '1代表删除,0代表未删除' AFTER `version`; |
同时,也修改User实体,增加deleted属性并且添加@TableLogic注解:
1 | /** |
6.2 配置
application.properties:
1 | # 删除状态的值为:1 |
6.3 测试
1 | /** |
执行的SQL:
1 | [main] [com.wgy.mapper.UserMapper.deleteById]-[DEBUG] ==> Preparing: UPDATE tb_user SET deleted=1 WHERE id=? AND deleted=0 |
测试查询:
1 | /** |
执行的SQL:
1 | [main] [com.wgy.mapper.UserMapper.selectById]-[DEBUG] ==> Preparing: SELECT |
可见,已经实现了逻辑删除。
7. 通用枚举
解决了繁琐的配置,让 mybatis 优雅的使用枚举属性!
7.1 修改表结构
1 | ALTER TABLE `tb_user` ADD COLUMN `sex` int(1) NULL DEFAULT 1 COMMENT '1-男,2-女' AFTER `deleted`; |
7.2 定义枚举
1 | /** |
7.3 配置
1 | # 枚举包扫描 |
7.4 修改实体
1 | /** |
7.5 测试
1 | /** |
查询:
1 | /** |
结果:
1 | [main] [com.wgy.mapper.UserMapper.selectById]-[DEBUG] ==> Preparing: SELECT id,user_name,password,name,age,email,version,deleted,sex FROM tb_user WHERE id=? AND |
从测试可以看出,可以很方便的使用枚举了。
查询条件时也是有效的:
1 | /** |
SQL:
1 | [main] [com.wgy.mapper.UserMapper.selectList]-[DEBUG] ==> Preparing: SELECT id,user_name,password,name,age,email,version,deleted,sex FROM tb_user WHERE deleted=0 |
8. 代码生成器
AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
8.1 创建工程
pom.xml:
1 |
|
8.2 代码
1 | /** |
8.3 测试
代码已生成:
9. MybatisX 快速开发插件
MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。
安装方法:打开 IDEA,进入 File -> Settings -> Plugins -> Browse Repositories,输入 mybatisx 搜索并安装。
功能:
- Java 与 XML 来回跳转
- Mapper 方法自动生成 XML
-------------本文结束感谢您的阅读-------------
本文标题: Mybatis-Plus(二)
本文链接: https://wgy1993.gitee.io/archives/1ea41e8e.html
版权声明: 本作品采用 CC BY-NC-SA 4.0 进行许可。转载请注明出处!
