fluent-mybatis入门,更优雅的mybatis
fluent-mybatis入门1.引子mybatis作为传统的数据库映射框架相比JPA要灵活的多,但是使用xml方式过于繁琐,使用注解会简单一些,但是仍要在mapper接口中的注解中编写sql,不是太方便,而且IDE没有语法检查,出错的概率很大。Mybatis Plus将jpa和mybatis进行了整合,取各自的优点,使用wapper来构造sql,十分方便灵活,目前是大多数项目的首选。但是在wa
fluent-mybatis入门
1. 引子
mybatis作为传统的数据库映射框架相比JPA要灵活的多,但是使用xml方式过于繁琐,使用注解会简单一些,但是仍要在mapper接口中的注解中编写sql,不是太方便,而且IDE没有语法检查,出错的概率很大。
Mybatis Plus将jpa和mybatis进行了整合,取各自的优点,使用wapper来构造sql,十分方便灵活,目前是大多数项目的首选。但是在wapper构造sql的时候需要对数据库表的字段名进行魔法值编写,并不十分优雅,无法做到将生成的entity类完全利用。
那有没有一个框架可以实现简单、方便、灵活、快速、优雅的操作数据库呢?有的,就是我要吹爆的 FluentMybatis。
顾名思义是对mybatis的框架的修改,fluent是流式的意思,即使用流式编程的方式来使用mybatis。
2.FluentMybatis官方介绍
-
No XML, No Mapper, No If else, No String魔法值编码
-
只需Entity就实现强大的FluentAPI: 支持分页, 嵌套查询, AND OR组合, 聚合函数…
3.简单增删改查
引入依赖
maven:
<properties>
<fluent-mybatis.version>1.6.14</fluent-mybatis.version>
</properties>
<dependencies>
<!-- 引入fluent-mybatis 运行依赖包, scope为compile -->
<dependency>
<groupId>com.github.atool</groupId>
<artifactId>fluent-mybatis</artifactId>
<version>${fluent-mybatis.version}</version>
</dependency>
<!-- 引入fluent-mybatis-processor, scope设置为provider 编译需要,运行时不需要 -->
<dependency>
<groupId>com.github.atool</groupId>
<artifactId>fluent-mybatis-processor</artifactId>
<scope>provided</scope>
<version>${fluent-mybatis.version}</version>
</dependency>
</dependencies>
其中fluent-mybatis是fluent-mybatis运行时的正主,需要设置为compile级别
而fluent-mybatis-processor是编译时,根据Entity文件生成一系列辅助类的处理器,依赖级别为provided就可以。
gradle:
buildscript {
ext {
lombokVersion = '1.18.8'
fluentMybatisVersion = '1.6.14'
springVersion = '5.3.7'
}
}
plugins {
id 'net.ltgt.apt' version '0.21'
}
subprojects {
apply plugin: 'net.ltgt.apt-idea'
apply plugin: 'net.ltgt.apt-eclipse'
sourceCompatibility = 1.8
targetCompatibility = 1.8
dependencies {
compile("com.github.atool:fluent-mybatis:${fluentMybatisVersion}")
compileOnly("org.projectlombok:lombok:${lombokVersion}")
compileOnly("com.github.atool:fluent-mybatis-processor:${fluentMybatisVersion}")
// annotation processor配置
annotationProcessor("org.projectlombok:lombok:${lombokVersion}")
annotationProcessor("com.github.atool:fluent-mybatis-processor:${fluentMybatisVersion}")
}
}
创建数据库
建立一个用户表sys_user:
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`account` varchar(50) NOT NULL COMMENT '账号',
`describe` varchar(100) DEFAULT NULL COMMENT '描述',
`nick_name` varchar(50) DEFAULT NULL COMMENT '昵称',
`phone` varchar(20) DEFAULT NULL COMMENT '手机号',
`email` varchar(50) DEFAULT NULL COMMENT '邮箱',
`state` int(4) NOT NULL DEFAULT 0 COMMENT '状态0正常',
`avatar_url` varchar(200) DEFAULT NULL COMMENT '头像url',
`created_time` datetime NOT NULL COMMENT '创建时间',
`modified_time` datetime DEFAULT NULL COMMENT '修改时间',
`del_flag` int(4) NOT NULL DEFAULT 0 COMMENT '删除标记',
PRIMARY KEY (`id`),
UNIQUE KEY `unique_sys_user_account` (`account`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4;
编写代码
创建一个springboot工程:
启动类和mybatis一样新增一个@MapperScan,但是扫描的mapper包不需要创建。
@SpringBootApplication
@MapperScan("com.example.fluent.mapper")
public class FluentMybatisApplication {
public static void main(String[] args) {
SpringApplication.run(FluentMybatisApplication.class, args);
}
}
创建一个实体类,也可以生成出来。
@FluentMybatis
@Data
@Builder
public class SysUser implements IEntity {
private Long id;
private String account;
private String describe;
private String nickName;
private String phone;
private String email;
private Integer state;
private String avatarUrl;
private LocalDateTime createdTime;
private LocalDateTime modifiedTime;
private Integer delFlag;
@Tolerate
public SysUser(){}
}
配置数据库连接:
server.servlet.context-path=/test
server.port=8080
spring.datasource.url=jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123456
编译项目生成实体类对应的mapper、dao等文件,这一步和其他框架有所不同。
生成的class在target中,代码里面可以直接使用。
这些生成的文件熟悉mybatis的都知道有什么作用了。启动类里面的mapper也是对应这里的包。
编写数据库操作代码,比较简单直接写在controller里面:
@RestController
public class WebController {
@Resource
private SysUserMapper sysUserMapper;
/**
* 使用id查询
* @param id
* @return
*/
@GetMapping("queryById")
public String queryById(Long id) {
SysUser sysUser = sysUserMapper.findOne(sysUserMapper
.query()
.where
.id()
.eq(id)
.end()
);
System.out.println(sysUser.getAccount());
return "ok";
}
/**
* 保存
* @return
*/
@GetMapping("save")
public String save() {
sysUserMapper.insert(SysUser.builder()
.account("aaa" + System.currentTimeMillis())
.createdTime(LocalDateTime.now())
.delFlag(0)
.describe("13131")
.state(0)
.build());
return "ok";
}
/**
* 更新
* @param id
* @param describe
* @return
*/
@GetMapping("update")
public String update(Long id, String describe) {
sysUserMapper.updateBy(sysUserMapper.updater().set.describe().is(describe).end()
.where.id().eq(id).end());
return "ok";
}
/**
* 删除
* @param id
* @return
*/
@GetMapping("delete")
public String delete(Long id) {
sysUserMapper.delete(sysUserMapper.query().where.id().eq(id).end());
return "ok";
}
}
通过例子可以看出,fluent-mybatis很简单的就可以完成单表的操作,无需sql、xml,和mapper,只需要一个实体类,然鹅这个实体类还是可以生成的!
直接看代码就能看出来框架将sql语句中的语法映射到代码中,其实就是类似dsl对象化的方式。很多习惯了xml或者注解直出sql方式的人会认为这种不伦不类,直接sql不好吗?或者jpa大神会说——就这,知道什么是DDD吗?
其实还是没有使用习惯的,当你是mybatis-plus用户或者习惯了在代码方式流式写sql语句你就会觉得——真香!
对生成文件的解析
- 核心接口类, 使用时需要了解
- mapper/*Mapper: mybatis的Mapper定义接口, 定义了一系列通用的数据操作接口方法。
- dao/*BaseDao: Dao实现基类, 所有的DaoImpl都继承各自基类 根据分层编码的原则,我们不会在Service类中直接使用Mapper类,而是引用Dao类。我们在Dao实现类中根据条件实现具体的数据操作方法。
- wrapper/*Query: fluent mybatis核心类, 用来进行动态sql的构造, 进行条件查询。
- wrapper/*Updater: fluent mybatis核心类, 用来动态构造update语句。
- entity/*EntityHelper: Entity帮助类, 实现了Entity和Map的转换方法
- 辅助实现时, 实现fluent mybatis动态sql拼装和fluent api时内部用到的类,使用时无需了解 在使用上,我们主要会接触到上述5个生成的java类。Fluent Mybatis为了实现动态拼接和Fluent API功能,还生成了一系列辅助类。
- helper/*Mapping: 表字段和Entity属性映射定义类
- helper/*SqlProviderP: Mapper接口动态sql提供者
- helper/*WrapperHelper: Query和Updater具体功能实现, 包含几个实现:select, where, group by, having by, order by, limit
mapper类中生成的基本上包含所有要使用的方法。
当然有人会说这是单表操作,如果复杂查询,多变关联,分组、函数等等呢?别急这些可都是mybatis的特长,所有fluent也会有完美的解决方式,会在后面的文章中写道。
4.和其他框架对比
- | Mybatis Plus | Fluent Mybatis |
---|---|---|
代码生成 | 生成 Entity, Mapper, Wrapper等文件, 并且Generator很好用 | 只生成Entity, 再通过编译生成 Mapper, Query, Update 和 SqlProvider |
和Mybatis的共生关系 | 需要替换原有的SqlSessionFactoryBean | 对Mybatis没有任何修改,原来怎么用还是怎么用 |
动态SQL构造方式 | 应用启动时, 根据Entity注解信息构造动态xml片段,注入到Mybatis解析器 | 应用编译时,根据Entity注解,编译生成对应方法的SqlProvider,利用mybatis的Mapper上@InsertProvider @SelectProvider @UpdateProvider注解关联 |
动态SQL结果是否容易DEBUG跟踪 | 不容易debug | 容易,直接定位到SQLProvider方法上,设置断点即可 |
动态SQL构造 | 通过硬编码字段名称, 或者利用Entity的get方法的lambda表达式 | 通过编译手段生成对应的方法名,直接调用方法即可 |
字段变更后的错误发现 | 通过get方法的lambda表达的可以编译发现,通过字段编码的无法编译发现 | 编译时便可发现 |
不同字段动态SQL构造方法 | 通过接口参数方式 | 通过接口名称方式, FluentAPI的编码效率更高 |
语法渲染特点 | 无 | 通过关键变量select, update, set, and, or可以利用IDE语法渲染, 可读性更高 |
主要和mybatis-plus对比,两者并不存在哪个更好,哪个不好。基本上都是对mybatis的增强,如果你比较懒就阔以选择fluent-mybatis。
至于jpa,喜欢的都喜欢,不喜欢的怎么都不喜欢,各取所需吧。
5.参考文档
官方文档: https://gitee.com/fluent-mybatis/fluent-mybatis-docs
更多推荐
所有评论(0)