之前一直使用Mybatis-Plus
,说实话,个人还是比较喜欢Mybatis-Plus
。
ORM
框架用的比较多的就两个,JPA
和Mybatis
。据说国内用Mybatis
比较多,国外用JPA
比较多。
而Mybatis-Plus
是在Mybatis
的基础上,增加了很多牛🍺的功能。
再粘一下官网介绍的特性,又啰嗦了:
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
- 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
- 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
- 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
- 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
- 内置性能分析插件:可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
详细的可以去官网看:mybatis.plus/
官网新域名也是牛🍺。反正用过的都说好。
至于JPA
,虽然个人觉得有点太死板,不过也有值得学习的地方。
很早以前,用Mybatis-Plus
的时候,有一个比较麻烦的问题,就是如果一组数据存在多张表中,这些表之间可能是一对一,一对多或者多对一,那我要想全部查出来就要调好几个Mapper
的查询方法。代码行数一下就增加了很多。
之前也看过Mybatis-Plus
的源码,想过如何使Mybatis-Plus
支持多表联接查询。可是发现难度不小。因为Mybatis-Plus
底层就只支持单表。
最近看到JPA
的@OneToOne
、@OneToMany
、@ManyToMany
这些注解,忽然一个想法就在我的脑海里闪现出来,如果像JPA
那样使用注解的方式,是不是简单很多呢?
事先声明,全是自己想的,没有看JPA
源码, 所以实现方式可能和JPA
不一样。
说干就干
- 添加注解
- 处理注解
- 打包发布
可能有人不知道,其实Mybatis
也是支持拦截器的,既然如此,用拦截器处理注解就可以啦。
注解 One2One
1 | java复制代码@Inherited |
说一下,假如有两张表,A
和B
是一对一的关系,A
表id
在B
表中是a_id
,用这样的方式关联的。
在A
的实体类中使用这个注解,self
就是id
,而as
就是a_id
,意思就是A
的id
作为a_id
来查询,而mapper
就是B
的Mapper
,下面是例子A
就是UserAccount
,B
就是UserAddress
。
1 | java复制代码@Data |
Mybatis拦截器 One2OneInterceptor
这里不再详细介绍拦截器了,之前也写了几篇关于Mybatis拦截器的,有兴趣的可以去看看。
1 | java复制代码@Intercepts({ |
Mybatis
拦截器可以针对不同的场景进行拦截,比如:
Executor
:拦截执行器的方法。ParameterHandler
:拦截参数的处理。ResultHandler
:拦截结果集的处理。StatementHandler
:拦截Sql语法构建的处理。
这里是通过拦截结果集的方式,在返回的对象上查找这个注解,找到注解后,再根据注解的配置,自动去数据库查询,查到结果后把数据封装到返回的结果集中。这样就避免了自己去多次调Mapper
的查询方法。
难点:虽然注解上标明了是什么Mapper
,可是在拦截器中取到的还是BaseMapper
,而用BaseMapper
实在不好查询,我试了很多方法,不过还好Mybatis-Plus
支持使用Condition.create().eq(as, value);
拼接条件SQL
,然后可以使用baseMapper.selectOne(eq);
去查询。
1 | java复制代码public class MpExtraUtil { |
MpExtraUtil
就是使用反射的方式,获取id
的值。
再讲一个多对多的注解
1 | java复制代码@Inherited |
假设有A
、 A_B
,B
三张表,在A
的实体类中使用这个注解, self
就是A
表主键id
,leftMid
就是A
表的id
在中间表中的名字,也就是a_id
,而rightMid
是B
表主键在中间表的名字,就是b_id
, origin
就是B
表自己主键原来的名字,即id
,midMapper
是中间表的Mapper
,也就是A_B
对应的Mapper
,mapper
是B
表的Mapper
。
这个确实有点绕。
还有一个@One2Many
就不说了,和@One2One
一样,至于Many2One
,从另一个角度看就是@One2One
。
使用方法
先把表创建好,然后代码生成器一键生成代码。
1 | sql复制代码CREATE TABLE `user_account` ( |
添加依赖,已经发布到中央仓库了,可以直接使用:
1 | xml复制代码<dependency> |
在启动类上添加注解
@EnableMpExtra
配置拦截器
因为一般项目都会配置自己的MybatisConfiguration
,我在这里配置后,打包,然后被引入,是无法生效的。
所以就想了一种折中的方法。
以前MybatisConfiguration
是通过new
出来的,现在通过MybatisExtraConfig.getMPConfig();
来获取,这样获取到的MybatisConfiguration
就已经添加好了拦截器。
完整Mybatis-Plus
配置类例子,注意第43行:
1 | java复制代码@Slf4j |
在实体类上建立关系
1 | java复制代码@Data |
主要是那几个注解。对了还要加@TableField(exist = false)
,不然会报错。
测试接口
1 | java复制代码@Slf4j |
接口非常简单,调用内置的getById
,可是却查出了所有相关的数据,这都是因为配置的那些注解。
可以看到其实发送了好几条SQL
。第一条是userAccountService.getById(1L)
,后面几条都是自动发送的。
GitHub: github.com/LerDer/mp-e…
总结
实在不想贴太多代码,其实还是挺简单的,源码地址还有示例地址都贴出来啦,有兴趣的可以去看一下。觉得好用可以点个Star
。欢迎大家一起来贡献。
最后欢迎大家关注我的公众号,共同学习,一起进步。加油🤣
搜索 南诏Blog 关注
本文转载自: 掘金