本篇文章內(nèi)容主要包括:
MyBatis-Flex 介紹
MyBatis-Flex 是一個(gè)優(yōu)雅的 MyBatis 增強(qiáng)框架,它非常輕量、同時(shí)擁有極高的性能與靈活性。我們可以輕松的使用 MybAIts-Flex 鏈接任何數(shù)據(jù)庫(kù),其內(nèi)置的 QueryWrApper^亮點(diǎn) 幫助我們極大的減少了 SQL 編寫(xiě)的工作的同時(shí),減少出錯(cuò)的可能性。
總而言之,MyBatis-Flex 能夠極大地提高我們的開(kāi)發(fā)效率和開(kāi)發(fā)體驗(yàn),讓我們有更多的時(shí)間專注于自己的事情。
主要特點(diǎn)
- 輕量
除了 MyBatis,沒(méi)有任何第三方依賴輕依賴、沒(méi)有任何攔截器,其原理是通過(guò) SqlProvider 的方式實(shí)現(xiàn)的輕實(shí)現(xiàn)。同時(shí),在執(zhí)行的過(guò)程中,沒(méi)有任何的 Sql 解析(Parse)輕運(yùn)行。 這帶來(lái)了幾個(gè)好處:1、極高的性能;2、極易對(duì)代碼進(jìn)行跟蹤和調(diào)試; 3、更高的把控性。
- 靈活
支持 Entity 的增刪改查、以及分頁(yè)查詢的同時(shí),MyBatis-Flex 提供了 Db + Row^靈活 工具,可以無(wú)需實(shí)體類對(duì)數(shù)據(jù)庫(kù)進(jìn)行增刪改查以及分頁(yè)查詢。 與此同時(shí),MyBatis-Flex 內(nèi)置的 QueryWrapper^靈活 可以輕易的幫助我們實(shí)現(xiàn) 多表查詢、鏈接查詢、子查詢 等等常見(jiàn)的 SQL 場(chǎng)景。
- 強(qiáng)大
支持任意關(guān)系型數(shù)據(jù)庫(kù),還可以通過(guò)方言持續(xù)擴(kuò)展,同時(shí)支持 多(復(fù)合)主鍵、邏輯刪除、樂(lè)觀鎖配置、數(shù)據(jù)脫敏、數(shù)據(jù)審計(jì)、 數(shù)據(jù)填充 等等功能。
與同類框架的對(duì)比
功能對(duì)比
功能或特點(diǎn) |
MyBatis-Flex |
MyBatis-Plus |
Fluent-MyBatis |
對(duì) entity 的基本增刪改查 |
? |
? |
? |
分頁(yè)查詢 |
? |
? |
? |
分頁(yè)查詢之總量緩存 |
? |
? |
? |
分頁(yè)查詢無(wú) SQL 解析設(shè)計(jì)(更輕量,及更高性能) |
? |
? |
? |
多表查詢: from 多張表 |
? |
? |
? |
多表查詢: left join、inner join 等等 |
? |
? |
? |
多表查詢: union,union all |
? |
? |
? |
單主鍵配置 |
? |
? |
? |
多種 id 生成策略 |
? |
? |
? |
支持多主鍵、復(fù)合主鍵 |
? |
? |
? |
字段的 typeHandler 配置 |
? |
? |
? |
除了 MyBatis,無(wú)其他第三方依賴(更輕量) |
? |
? |
? |
QueryWrapper 是否支持在微服務(wù)項(xiàng)目下進(jìn)行 RPC 傳輸 |
? |
? |
未知 |
邏輯刪除 |
? |
? |
? |
樂(lè)觀鎖 |
? |
? |
? |
SQL 審計(jì) |
? |
? |
? |
數(shù)據(jù)填充 |
? |
? |
? |
數(shù)據(jù)脫敏 |
? |
?? (收費(fèi)) |
? |
字段權(quán)限 |
? |
?? (收費(fèi)) |
? |
字段加密 |
? |
?? (收費(fèi)) |
? |
字典回寫(xiě) |
? |
?? (收費(fèi)) |
? |
Db + Row |
? |
? |
? |
Entity 監(jiān)聽(tīng) |
? |
? |
? |
多數(shù)據(jù)源支持 |
? |
借助其他框架或收費(fèi) |
? |
多數(shù)據(jù)源是否支持 Spring 的事務(wù)管理,比如 @Transactional 和 TransactionTemplate 等 |
? |
? |
? |
多數(shù)據(jù)源是否支持 "非Spring" 項(xiàng)目 |
? |
? |
? |
多租戶 |
? |
? |
? |
動(dòng)態(tài)表名 |
? |
? |
? |
動(dòng)態(tài) Schema |
? |
? |
? |
性能對(duì)比
測(cè)試結(jié)果如下:
- MyBatis-Flex 的查詢單條數(shù)據(jù)的速度,大概是 MyBatis-Plus 的 5 ~ 10+ 倍。
- MyBatis-Flex 的查詢 10 條數(shù)據(jù)的速度,大概是 MyBatis-Plus 的 5~10 倍左右。
- Mybatis-Flex 的分頁(yè)查詢速度,大概是 Mybatis-Plus 的 5~10 倍左右。
- Mybatis-Flex 的數(shù)據(jù)更新速度,大概是 Mybatis-Plus 的 5~10+ 倍。
測(cè)試代碼:
https://gitee.com/mybatis-flex/mybatis-benchmark
Mybatis-Flex支持哪些數(shù)據(jù)庫(kù)
MyBatis-Flex 支持的數(shù)據(jù)庫(kù)類型,如下表格所示,我們還可以通過(guò)自定義方言的方式,持續(xù)添加更多的數(shù)據(jù)庫(kù)支持。
數(shù)據(jù)庫(kù) |
描述 |
MySQL |
MySQL 數(shù)據(jù)庫(kù) |
mariadb |
MariaDB 數(shù)據(jù)庫(kù) |
oracle |
Oracle11g 及以下數(shù)據(jù)庫(kù) |
oracle12c |
Oracle12c 及以上數(shù)據(jù)庫(kù) |
db2 |
DB2 數(shù)據(jù)庫(kù) |
H2 |
H2 數(shù)據(jù)庫(kù) |
hsql |
HSQL 數(shù)據(jù)庫(kù) |
sqlite |
SQLite 數(shù)據(jù)庫(kù) |
postgresql |
PostgreSQL 數(shù)據(jù)庫(kù) |
sqlserver2005 |
SQLServer2005 數(shù)據(jù)庫(kù) |
sqlserver |
SQLServer 數(shù)據(jù)庫(kù) |
dm |
達(dá)夢(mèng)數(shù)據(jù)庫(kù) |
xugu |
虛谷數(shù)據(jù)庫(kù) |
kingbasees |
人大金倉(cāng)數(shù)據(jù)庫(kù) |
phoenix |
Phoenix HBase 數(shù)據(jù)庫(kù) |
gauss |
Gauss 數(shù)據(jù)庫(kù) |
clickhouse |
ClickHouse 數(shù)據(jù)庫(kù) |
gbase |
南大通用(華庫(kù))數(shù)據(jù)庫(kù) |
gbase-8s |
南大通用數(shù)據(jù)庫(kù) GBase 8s |
oscar |
神通數(shù)據(jù)庫(kù) |
sybase |
Sybase ASE 數(shù)據(jù)庫(kù) |
OceanBase |
OceanBase 數(shù)據(jù)庫(kù) |
Firebird |
Firebird 數(shù)據(jù)庫(kù) |
derby |
Derby 數(shù)據(jù)庫(kù) |
highgo |
瀚高數(shù)據(jù)庫(kù) |
cubrid |
CUBRID 數(shù)據(jù)庫(kù) |
goldilocks |
GOLDILOCKS 數(shù)據(jù)庫(kù) |
csiidb |
CSIIDB 數(shù)據(jù)庫(kù) |
hana |
SAP_HANA 數(shù)據(jù)庫(kù) |
impala |
Impala 數(shù)據(jù)庫(kù) |
vertica |
Vertica 數(shù)據(jù)庫(kù) |
xcloud |
行云數(shù)據(jù)庫(kù) |
redshift |
亞馬遜 redshift 數(shù)據(jù)庫(kù) |
openGauss |
華為 openGauss 數(shù)據(jù)庫(kù) |
TDengine |
TDengine 數(shù)據(jù)庫(kù) |
informix |
Informix 數(shù)據(jù)庫(kù) |
greenplum |
Greenplum 數(shù)據(jù)庫(kù) |
uxdb |
優(yōu)炫數(shù)據(jù)庫(kù) |
Doris |
Doris數(shù)據(jù)庫(kù) |
Hive SQL |
Hive 數(shù)據(jù)庫(kù) |
lealone |
Lealone 數(shù)據(jù)庫(kù) |
sinodb |
星瑞格數(shù)據(jù)庫(kù) |
基本使用
下面的演示案例代碼,基于MyBatis-Flex的代碼生成器進(jìn)行實(shí)現(xiàn)。
創(chuàng)建數(shù)據(jù)表
創(chuàng)建數(shù)據(jù)表user_order,建表腳本如下:
DROP TABLE IF EXISTS `user_order`;
CREATE TABLE `user_order`
(
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID;【必須保留自增ID,不要將一些有隨機(jī)特性的字段值設(shè)計(jì)為主鍵,例如order_id,會(huì)導(dǎo)致innodb內(nèi)部page分裂和大量隨機(jī)I/O,性能下降】int 大約21億左右,超過(guò)會(huì)報(bào)錯(cuò)。bigint 大約9千億左右。',
`user_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用戶姓名;',
`user_id` varchar(24) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用戶編號(hào);',
`user_mobile` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '用戶電話;使用varchar(20)存儲(chǔ)手機(jī)號(hào),不要使用整型。手機(jī)號(hào)不會(huì)做數(shù)學(xué)計(jì)算、涉及到區(qū)號(hào)或者國(guó)家代號(hào),可能出現(xiàn)+-()、支持模糊查詢,例如:like“135%”',
`sku` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品編號(hào)',
`sku_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '商品名稱',
`order_id` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '訂單ID',
`quantity` int(11) NOT NULL DEFAULT 1 COMMENT '商品數(shù)量;整形定義中不顯示規(guī)定顯示長(zhǎng)度,比如使用 INT,而不使用 INT(4)',
`unit_price` decimal(10, 2) NOT NULL COMMENT '商品價(jià)格;小數(shù)類型為 decimal,禁止使用 float、double',
`discount_amount` decimal(10, 2) NOT NULL COMMENT '折扣金額;',
`tax` decimal(4, 2) NOT NULL COMMENT '費(fèi)率金額;',
`total_amount` decimal(10, 2) NOT NULL COMMENT '支付金額;(商品的總金額 - 折扣) * (1 - 費(fèi)率)',
`order_date` datetime NOT NULL COMMENT '訂單日期;timestamp的時(shí)間范圍在1970-01-01 00:00:01到2038-01-01 00:00:00之間',
`order_status` tinyint(1) NOT NULL COMMENT '訂單狀態(tài);0 創(chuàng)建、1完成、2掉單、3關(guān)單 【不要使用 enum 要使用 tinyint 替代。0-80 范圍,都可以使用 tinyint】',
`is_delete` tinyint(1) NOT NULL DEFAULT 0 COMMENT '邏輯刪單;0未刪除,1已刪除 【表達(dá)是否概念的字段必須使用is_】',
`uuid` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '唯一索引;分布式下全局唯一,用于binlog 同步 ES 方便使用',
`ipv4` int(10) UNSIGNED NOT NULL DEFAULT 2130706433 COMMENT '設(shè)備地址;存儲(chǔ)IPV4地址,通過(guò)MySQL 函數(shù)轉(zhuǎn)換,.NET_ntoa、inet_aton 示例;SELECT INET_ATON(‘209.207.224.40′); 3520061480 SELECT INET_NTOA(3520061480); 209.207.224.40所有字段定義為NOT NULL,并設(shè)置默認(rèn)值,因?yàn)閚ull值的字段會(huì)導(dǎo)致每一行都占用額外存儲(chǔ)空間\n數(shù)據(jù)遷移容易出錯(cuò),在聚合函數(shù)計(jì)算結(jié)果偏差(如count結(jié)果不準(zhǔn))并且null的列使索引/索引統(tǒng)計(jì)/值比較都更加復(fù)雜,MySQL內(nèi)部需要進(jìn)行特殊處理,表中有較多空字段的時(shí)候,數(shù)據(jù)庫(kù)性能下降嚴(yán)重。開(kāi)發(fā)中null只能采用is null或is not null檢索,而不能采用=、in、<、<>、!=、not in這些操作符號(hào)。如:where name!=’abc’,如果存在name為null值的記錄,查詢結(jié)果就不會(huì)包含name為null值的記錄',
`ipv6` varbinary(16) NOT NULL COMMENT '設(shè)備地址;存儲(chǔ)IPV6地址,VARBINARY(16) 插入:INET6_ATON('2001:0db8:85a3:0000:0000:8a2e:0370:7334') 查詢:SELECT INET6_NTOA(ip_address) ',
`ext_data` json NOT NULL COMMENT '擴(kuò)展數(shù)據(jù);記錄下單時(shí)用戶的設(shè)備環(huán)境等信息(核心業(yè)務(wù)字段,要單獨(dú)拆表)。【select user_name, ext_data, ext_data->>'$.device', ext_data->>'$.device.machine' from `user_order`;】',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時(shí)間',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時(shí)間',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `uq_orderid` (`order_id`) USING BTREE,
UNIQUE INDEX `uq_uuid` (`uuid`) USING BTREE,
INDEX `idx_order_date` (`order_date`) USING BTREE,
INDEX `idx_sku_unit_price_total_amount` (`sku`, `unit_price`, `total_amount`) USING BTREE
);
創(chuàng)建Spring Boot項(xiàng)目
項(xiàng)目工程結(jié)構(gòu)如下,在pomx.xml中添加相關(guān)依賴。
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
<version>1.6.5</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>1.6.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-codegen</artifactId>
<version>1.6.5</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>4.0.3</version>
</dependency>
項(xiàng)目配置
在配置文件application.yml中配置數(shù)據(jù)源等。
# 數(shù)據(jù)源配置
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/ballcat
username: root
password: root_123
在項(xiàng)目啟動(dòng)類上添加@MapperScan 配置掃描的文件夾:
@SpringBootApplication
@MapperScan("com.xxkfz.simplememory.mapper")
public class XxkfzMybatisFlexApplication {
public static void main(String[] args) {
SpringApplication.run(XxkfzMybatisFlexApplication.class, args);
}
}
經(jīng)過(guò)上面的步驟,一個(gè)基于Mybatis-Flex的簡(jiǎn)單Spring Boot項(xiàng)目創(chuàng)建并配置完成了。
下面我們將使用Mybatis-Flex代碼生成器,生成基于表user-order的基本操作代碼。
配置代碼生成器
運(yùn)行CodegenMain.JAVA main方法即可,即可在路徑:com/xxkfz/simplememory/下面生成相應(yīng)的文件。
import com.mybatisflex.codegen.Generator;
import com.mybatisflex.codegen.config.ColumnConfig;
import com.mybatisflex.codegen.config.GlobalConfig;
import com.mybatisflex.core.service.IService;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.zaxxer.hikari.HikariDataSource;
/**
* @author 公眾號(hào): SimpleMemory
* @version 1.0.0
* @ClassName Codegen.java
* @Description 代碼生成器
* @createTime 2023年09月21日 18:12:00
*/
public class CodegenMain {
public static void main(String[] args) {
//數(shù)據(jù)源配置
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/ballcat?characterEncoding=utf-8");
dataSource.setUsername("xxkfz");
dataSource.setPassword("xxkfz");
//創(chuàng)建配置內(nèi)容,兩種風(fēng)格都可以。
GlobalConfig globalConfig = createGlobalConfig();
//GlobalConfig globalConfig = createGlobalConfigUseStyle2();
//通過(guò) datasource 和 globalConfig 創(chuàng)建代碼生成器
Generator generator = new Generator(dataSource, globalConfig);
//生成代碼
generator.generate();
}
/**
* GlobalConfig 基本配置
*
* @return
*/
public static GlobalConfig createGlobalConfig() {
//創(chuàng)建配置內(nèi)容
GlobalConfig globalConfig = new GlobalConfig();
//設(shè)置根包
globalConfig.setBasePackage("com.xxkfz.simplememory");
//設(shè)置表前綴和只生成哪些表
globalConfig.setGenerateTable("user_order");
//設(shè)置生成 entity 并啟用 Lombok
globalConfig.setEntityGenerateEnable(true);
globalConfig.setEntityWithLombok(true);
//設(shè)置生成 controller
globalConfig.setControllerGenerateEnable(true);
//設(shè)置生成 service
globalConfig.setServiceGenerateEnable(true);
//設(shè)置生成 serviceImpl
globalConfig.setServiceImplGenerateEnable(true);
//設(shè)置生成 mapper
globalConfig.setMapperGenerateEnable(true);
//設(shè)置生成 mapperXml
globalConfig.setMapperXmlGenerateEnable(true);
globalConfig.getControllerConfig().setClassPrefix("").setClassSuffix("Controller").setRestStyle(true);
globalConfig.getServiceConfig().setClassPrefix("").setClassSuffix("Service").setSuperClass(IService.class).setOverwriteEnable(true);
globalConfig.getServiceImplConfig().setClassPrefix("").setClassSuffix("ServiceImpl").setSuperClass(ServiceImpl.class).setOverwriteEnable(true);
globalConfig.getMapperXmlConfig().setFilePrefix("/com/xxkfz/simplememory/").setFileSuffix("Mapper").setOverwriteEnable(true);
//可以單獨(dú)配置某個(gè)列
ColumnConfig columnConfig = new ColumnConfig();
columnConfig.setColumnName("tenant_id");
columnConfig.setLarge(true);
columnConfig.setVersion(true);
globalConfig.setColumnConfig("tb_account", columnConfig);
return globalConfig;
}
}
生成的代碼結(jié)構(gòu)如下:
啟動(dòng)項(xiàng)目測(cè)試
代碼生成后,我們直接主啟動(dòng)類
XxkfzMybatisFlexApplication,即可啟動(dòng)項(xiàng)目。
啟動(dòng)成功后,訪問(wèn)UserOrderController 中分頁(yè)查詢中的page方法:
http://127.0.0.1:8080/userOrder/page
其他操作QueryWrapper的使用
查詢表中user_name等于公眾號(hào)Simplememory的user_id、order_id列
QueryWrapper queryWrapper = QueryWrapper.create()
.select(USER_ORDER.USER_ID, USER_ORDER.ORDER_ID)
.where(USER_ORDER.USER_NAME
.eq("公眾號(hào)Simplememory"));
List<UserOrder> userOrders = userOrderMapper.selectListByQuery(queryWrapper);
System.out.println(userOrders);
在上面的例子中, USER_ORDER 為 MyBatis-Flex 通過(guò) APT 自動(dòng)生成的,無(wú)需手動(dòng)編碼,只需通過(guò)靜態(tài)導(dǎo)入即可!
關(guān)于其他的用法可以進(jìn)入:
https://mybatis-flex.com/zh/base/add-delete-update.html
Mybatis-Flex官方文檔: https://mybatis-flex.com/
最后,關(guān)于上面的代碼工程已上傳到Gitee:
https://gitee.com/xxkfz/xxkfz-mybatis-flex.git