Table of contents
3. Comparison of framework functions
5.2. Data source configuration
5.3. Create entity classes and tables
5.6. Create Controller interface test
1 Introduction
There are many mainstream Mybatis enhancement frameworks. Of course, MybatisPlus is the most commonly used in projects. However, friends who have used MybatisPlus also know that for single-table operations, the chained coding method and the provided Lambda support can simplify a lot of code, but for multi-table operations, it seems to be more than enough. Therefore, in most projects, XML is still chosen for multi-table operations. So here we introduce a Mybatis enhancement framework, which claims to integrate the advantages of multiple frameworks such as MybatisPlus. That is Mybatis-Flex.
2. What is MyBatis-Flex?
Official website address: MyBatis-Flex - MyBatis-Flex official website
Similar to Mybatis Plus, Mybatis Flex is also an enhanced ORM framework based on Mybatis. But it is lighter, more flexible and has higher performance than before.
The following is excerpted from the official website:
MyBatis-Flex is an elegant MyBatis enhancement framework that is very lightweight and has extremely high performance and flexibility. We can easily use Mybaits-Flex to connect to any database, and its built-in QueryWrapper helps us greatly reduce the work of SQL writing and reduce the possibility of errors.
All in all, MyBatis-Flex can greatly improve our development efficiency and development experience, allowing us to have more time to focus on our own things.
3. Comparison of framework functions
function or feature |
MyBatis-Flex |
MyBatis-Plus |
Fluent-MyBatis |
Basic addition, deletion, modification and query of entities |
✅ |
✅ |
✅ |
Paging query |
✅ |
✅ |
✅ |
Total cache of paging query |
✅ |
✅ |
❌ |
Paging query without SQL parsing design (more lightweight, and higher performance) |
✅ |
❌ |
✅ |
Multi-table query: from multiple tables |
✅ |
❌ |
❌ |
Multi-table query: left join, inner join, etc. |
✅ |
❌ |
✅ |
Multi-table query: union, union all |
✅ |
❌ |
✅ |
Single primary key configuration |
✅ |
✅ |
✅ |
Multiple ID generation strategies |
✅ |
✅ |
✅ |
Support multiple primary keys and composite primary keys |
✅ |
❌ |
❌ |
Field typeHandler configuration |
✅ |
✅ |
✅ |
Except MyBatis, no other third-party dependencies (more lightweight) |
✅ |
❌ |
❌ |
Does QueryWrapper support RPC transmission under microservice projects? |
✅ |
❌ |
unknown |
Tombstone |
✅ |
✅ |
✅ |
optimistic locking |
✅ |
✅ |
✅ |
SQL audit |
✅ |
❌ |
❌ |
data filling |
✅ |
✅ |
✅ |
Data desensitization |
✅ |
✔️(charged) |
❌ |
Field permissions |
✅ |
✔️(charged) |
❌ |
Field encryption |
✅ |
✔️(charged) |
❌ |
dictionary writeback |
✅ |
✔️(charged) |
❌ |
Db + Row |
✅ |
❌ |
❌ |
Entity monitoring |
✅ |
❌ |
❌ |
Multiple data sources support |
✅ |
With the help of other frameworks or charges |
❌ |
Whether multiple data sources support Spring's transaction management, such as @Transactional and TransactionTemplate, etc. |
✅ |
❌ |
❌ |
Does multiple data sources support "non-Spring" projects? |
✅ |
❌ |
❌ |
multi-tenant |
✅ |
✅ |
❌ |
Dynamic table name |
✅ |
✅ |
❌ |
Dynamic Schema |
✅ |
❌ |
❌ |
4. Performance comparison
You can take a look at the specific performance comparison (I have not tested it specifically here). Here is the conclusion from the official website:
5. Quick to use
5.1. Maven adds dependencies
<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>
5.2. Data source configuration
The multi-data source here uses SpringBoot's multi-data source, and Mybatis-Flex also supports multi-data source configuration.
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
5.3. Create entity classes and tables
Entity class 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;
}
Table 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;
5.4. Create Dao
package org.shamee.demo.dao;
import com.mybatisflex.core.BaseMapper;
import org.shamee.demo.entity.User;
public interface UserDao extends BaseMapper<User> {
}
5.5. Create Service
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);
}
}
5.6. Create Controller interface test
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<User> 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;
}
}
5.7. Test results
After first executing the insert interface to insert data, call listall to view the data list.
6. Summary
After getting used to Mybatis Plus, getting started with Mybatis Flex is still very similar, but there will be some syntax differences. Such as declaring primary key annotations, field mapping annotations, QueryWrapper usage differences, etc. Overall, it is an enhanced version of Mybatis. The official also provides a lot of advanced usage configurations. If you are interested, you can explore it.