目录
现在主流的Mybatis增强框架有很多,当然项目中最经常使用的还是MybatisPlus为主。但是用过MybatisPlus的小伙伴也知道,对于单表操作,链式的编码方式以及提供的Lambda支持可以简化很多代码量,但是如果多表操作,就显得心有余而力不足了。因此大多数项目中对于多表操作,仍然选择采用XML的编写方式。那么这里介绍一款Mybatis增强框架,号称集成了MybatisPlus等多个框架的优点。那就是Mybatis-Flex。
官网地址:MyBatis-Flex - MyBatis-Flex 官方网站
与Mybatis Plus类似,Mybatis Flex也是基于Mybatis的一个增强的ORM框架。但是相比之前更轻量,更灵活,性能更高。
以下摘抄自官网:
MyBatis-Flex 是一个优雅的 MyBatis 增强框架,它非常轻量、同时拥有极高的性能与灵活性。我们可以轻松的使用 Mybaits-Flex 链接任何数据库,其内置的 QueryWrapper帮助我们极大的减少了 SQL 编写的工作的同时,减少出错的可能性。
总而言之,MyBatis-Flex 能够极大地提高我们的开发效率和开发体验,让我们有更多的时间专注于自己的事情。
MyBatis-Flex 和同类框架「功能」对比 - MyBatis-Flex 官方网站
功能或特点 | MyBatis-Flex | MyBatis-Plus | Fluent-MyBatis |
对 entity 的基本增删改查 | ✅ | ✅ | ✅ |
分页查询 | ✅ | ✅ | ✅ |
分页查询之总量缓存 | ✅ | ✅ | ❌ |
分页查询无 SQL 解析设计(更轻量,及更高性能) | ✅ | ❌ | ✅ |
多表查询: from 多张表 | ✅ | ❌ | ❌ |
多表查询: left join、inner join 等等 | ✅ | ❌ | ✅ |
多表查询: union,union all | ✅ | ❌ | ✅ |
单主键配置 | ✅ | ✅ | ✅ |
多种 id 生成策略 | ✅ | ✅ | ✅ |
支持多主键、复合主键 | ✅ | ❌ | ❌ |
字段的 typeHandler 配置 | ✅ | ✅ | ✅ |
除了 MyBatis,无其他第三方依赖(更轻量) | ✅ | ❌ | ❌ |
QueryWrapper 是否支持在微服务项目下进行 RPC 传输 | ✅ | ❌ | 未知 |
逻辑删除 | ✅ | ✅ | ✅ |
乐观锁 | ✅ | ✅ | ✅ |
SQL 审计 | ✅ | ❌ | ❌ |
数据填充 | ✅ | ✅ | ✅ |
数据脱敏 | ✅ | ✔️(收费) | ❌ |
字段权限 | ✅ | ✔️(收费) | ❌ |
字段加密 | ✅ | ✔️(收费) | ❌ |
字典回写 | ✅ | ✔️(收费) | ❌ |
Db + Row | ✅ | ❌ | ❌ |
Entity 监听 | ✅ | ❌ | ❌ |
多数据源支持 | ✅ | 借助其他框架或收费 | ❌ |
多数据源是否支持 Spring 的事务管理,比如@Transactional和TransactionTemplate等 | ✅ | ❌ | ❌ |
多数据源是否支持 "非Spring" 项目 | ✅ | ❌ | ❌ |
多租户 | ✅ | ✅ | ❌ |
动态表名 | ✅ | ✅ | ❌ |
动态 Schema | ✅ | ❌ | ❌ |
MyBatis-Flex 和同类框架「性能」对比 - MyBatis-Flex 官方网站
可以看下具体的性能对比(我这边没有具体测试过),这里直接给出官网的结论:
- <dependencies>
- <!-- 这里为mybatis-flex依赖 -->
- <dependency>
- <groupId>com.mybatis-flex</groupId>
- <artifactId>mybatis-flex-spring-boot-starter</artifactId>
- <version>1.6.4</version>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-configuration-processor</artifactId>
- <optional>true</optional>
- </dependency>
-
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>druid-spring-boot-starter</artifactId>
- <version>1.2.8</version>
- </dependency>
-
- <dependency>
- <groupId>com.baomidou</groupId>
- <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
- <version>3.5.0</version>
- </dependency>
-
- <dependency>
- <groupId>com.mysql</groupId>
- <artifactId>mysql-connector-j</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <version>1.18.24</version>
- </dependency>
-
- <dependency>
- <groupId>cn.hutool</groupId>
- <artifactId>hutool-all</artifactId>
- <version>5.8.21</version>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-validation</artifactId>
- </dependency>
- </dependencies>
这里多数据源使用SpringBoot的多数据源,Mybatis-Flex也支持多数据源配置。
- server:
- port: 8080
-
- spring:
- application:
- name: springboot-mybatis-flex
- profiles:
- active: dev
- jackson:
- # 不要全局限制,避免字段格式不一致
- date-format: "yyyy-MM-dd HH:mm:ss"
- locale: zh_CN
- time-zone: GMT+8
-
- # druid config
- datasource:
- dynamic:
- primary: primary
- datasource:
- primary:
- driver-class-name: com.mysql.cj.jdbc.Driver
- url: jdbc:mysql://localhost:3306/my-game?useUnicode=true&characterEncoding=utf8&useSSL=false
- username: root
- password: root
-
-
- type: com.alibaba.druid.pool.DruidDataSource
- druid:
- validation-query: SELECT 1
- initial-size: 10
- min-idle: 10
- max-active: 20
- min-evictable-idle-time-millis: 180000
- test-on-borrow: false
- test-while-idle: true
- remove-abandoned: true
- remove-abandoned-timeout-millis: 1800
- log-abandoned: true
- pool-prepared-statements: true
- max-open-prepared-statements: 100
- filter:
- slf4j:
- enabled: false
- web-stat-filter:
- enabled: false
- autoconfigure:
- exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
实体类User:
- package org.shamee.demo.entity;
-
- import com.mybatisflex.annotation.Column;
- import com.mybatisflex.annotation.Id;
- import com.mybatisflex.annotation.KeyType;
- import com.mybatisflex.annotation.Table;
- import com.mybatisflex.core.keygen.KeyGenerators;
- import lombok.*;
-
- import java.io.Serializable;
- import java.util.Date;
-
-
- /**
- * @Table 注解自动映射实体类和表字段
- */
- @Data
- @Builder
- @NoArgsConstructor
- @AllArgsConstructor
- @Table("t_user")
- public class User implements Serializable {
-
- /**
- * 声明主键ID,并指定生成器为雪花ID
- */
- @Id(keyType = KeyType.Generator, value = KeyGenerators.snowFlakeId)
- private String id;
-
- /**
- * Column声明字段名称,onInsertValue 自动填充时间
- */
- @Column(value = "createdTime", onInsertValue = "now()")
- private Date createdTime;
-
- @Column(value = "updatedTime", onInsertValue = "now()", onUpdateValue = "now()")
- private Date updatedTime;
-
- /**
- * Column声明字段名称,isLogicDelete 逻辑删除
- */
- @Column(value = "isDeleted", isLogicDelete = true)
- private Boolean isDeleted = false;
-
- @Column(value = "userId")
- private String userId;
-
- @Column(value = "userName")
- private String userName;
-
- @Column(value = "isUse")
- private Boolean isUse;
-
- @Column(value = "battleNum")
- private Integer battleNum;
-
- @Column(value = "atk")
- private Integer atk;
-
- private String extension;
- }
表t_user:
- CREATE TABLE `t_user` (
- `id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
- `userId` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
- `userName` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
- `isUse` tinyint(4) NULL DEFAULT NULL,
- `battleNum` int(11) NULL DEFAULT NULL,
- `atk` int(11) NULL DEFAULT NULL,
- `extension` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL,
- `createdTime` datetime(0) NULL DEFAULT NULL,
- `updatedTime` datetime(0) NULL DEFAULT NULL,
- `isDeleted` tinyint(4) NULL DEFAULT NULL,
- PRIMARY KEY (`id`) USING BTREE
- ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;
- package org.shamee.demo.dao;
-
- import com.mybatisflex.core.BaseMapper;
- import org.shamee.demo.entity.User;
-
- public interface UserDao extends BaseMapper<User> {
- }
- package org.shamee.demo.service;
-
- import com.mybatisflex.core.query.QueryWrapper;
- import com.mybatisflex.core.update.UpdateChain;
- import com.mybatisflex.spring.service.impl.ServiceImpl;
- import org.shamee.demo.dao.UserDao;
- import org.shamee.demo.entity.User;
- import org.shamee.demo.entity.table.UserTableDef;
- import org.springframework.stereotype.Service;
-
- import java.util.List;
-
- @Service
- public class UserService extends ServiceImpl<UserDao, User> {
-
- /**
- * 查询全部
- * @return
- */
- public List<User> selectAll(){
- return this.getMapper().selectAll();
- }
-
- /**
- * 根据userId获取User数据
- * @param userId
- * @return
- */
- public User listById(String userId){
- QueryWrapper wrapper = QueryWrapper.create()
- // 这里可以指定查询字段
- .select(UserTableDef.USER.USER_ID, UserTableDef.USER.USER_NAME, UserTableDef.USER.ATK)
- // sql from表名
- .from(User.class)
- // 查询条件,这里的UserTableDef.USER代码自动编译生成,类似lombok
- .where(UserTableDef.USER.USER_ID.eq(userId));
- return this.getMapper().selectOneByQuery(wrapper);
- }
-
-
- /**
- * 新增
- * @param user
- */
- public void insert(User user){
- this.getMapper().insert(user);
- }
-
- /**
- * 更新User
- * @param user
- */
- public void updateEntity(User user){
- this.getMapper().update(user);
- }
-
- /**
- * 局部更新
- * @param userId
- * @param userName
- */
- public void updateRow(String userId, String userName){
- UpdateChain.of(User.class)
- .set(User::getUserName, userName)
- .where(User::getUserId).eq(userId).update();
- }
-
- /**
- * 删除
- * @param userName
- */
- public void deleteByWrapper(String userName){
- QueryWrapper queryWrapper = QueryWrapper.create().where(UserTableDef.USER.USER_NAME.eq(userName));
- this.getMapper().deleteByQuery(queryWrapper);
- }
- }
- package org.shamee.demo.controller;
-
- import org.shamee.demo.entity.User;
- import org.shamee.demo.service.UserService;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
-
- import javax.annotation.Resource;
- import java.util.List;
-
- @RestController
- @RequestMapping("/api/demo/user")
- public class UserController {
-
- @Resource
- private UserService userService;
-
-
- /**
- * 查询全部
- * @return
- */
- @GetMapping("listall")
- public List
listall(){ - return userService.selectAll();
- }
-
- /**
- * 按userId查询
- * @return
- */
- @GetMapping("listById")
- public User listById(){
- return userService.listById("zhangsan");
- }
-
- /**
- * 新增
- * @return
- */
- @GetMapping("insert")
- public Boolean insert(){
- User user = User.builder().userId("zhangsan").userName("张三").atk(100).battleNum(200).build();
- userService.insert(user);
- return Boolean.TRUE;
- }
-
- /**
- * 更新
- * @return
- */
- @GetMapping("update")
- public Boolean update(){
- userService.updateRow("zhangsan", "张三三");
- return Boolean.TRUE;
- }
-
- /**
- * 删除
- * @return
- */
- @GetMapping("delete")
- public Boolean delete(){
- userService.deleteByWrapper("张三三");
- return Boolean.TRUE;
- }
- }
先执行insert接口插入数据后,调用listall查看数据列表。
习惯了Mybatis Plus后,Mybatis Flex上手还是很类似的,就是会有一些语法的差异。如声明主键注解,字段映射注解,QueryWrapper使用差异等等。整体来说是Mybatis增强版,官方也提供了很多高级使用配置,感兴趣的可以探索一下。