Compare commits

...

165 Commits

Author SHA1 Message Date
Michael Yang
d555a8e289
!561 mybatis-flex-solon-plugin:当有 mapperLocations 配置又没有相关注册时,改为 warn 日志(之前为异常)
Merge pull request !561 from 西东/main
2025-11-28 13:14:26 +00:00
noear
536f4f6058 mybatis-flex-solon-plugin:当有 mapperLocations 配置又没有相关注册时,改为 warn 日志(之前为异常) 2025-11-28 18:00:48 +08:00
noear
c80284ef68 mybatis-flex-solon-plugin:当有 mapperLocations 配置又没有相关注册时,改为 warn 日志(之前为异常) 2025-11-28 17:32:33 +08:00
Michael Yang
f02b8857d1 feat: mybatis-flex-spring-boot4-starter prepare 2025-11-26 16:59:37 +08:00
Michael Yang
0e83000168
Merge pull request #613 from Macrow/main
feat: add module mybatis-flex-spring-boot4-starter
2025-11-26 16:19:48 +08:00
Michael Yang
5814d254b8
Merge pull request #614 from AXBest/main
fix(sql):优化删除语句中单主键条件的拼接逻辑
2025-11-26 16:19:18 +08:00
Michael Yang
9895a79a5b
Merge pull request #615 from ruansheng8/feat-orderBy
QueryOrderBy 新增获取字段属性方法
2025-11-26 16:16:57 +08:00
ruansheng
9469a727a2 feat: -m core 风格统一 2025-11-22 11:57:07 +08:00
ruansheng
ce23df8b09 feat: -m query 新增OrderType获取方法 2025-11-21 17:28:46 +08:00
ruansheng
ed4f30cb2c feat: -m core 新增getQueryColumn方法 2025-11-21 17:13:52 +08:00
Macrow
69c80d251d chore: upgrade springboot4 to v4.0.0 2025-11-21 10:05:41 +08:00
Macrow
04ffb316bf chore: rollback config for maven-gpg-plugin 2025-11-20 12:36:16 +08:00
Macrow
f1ba1b2bb9 Merge branch 'springboot4' 2025-11-20 09:45:26 +08:00
Macrow
40f98c84d0 chore: add dependency mybatis-flex-spring-boot4-starter in module mybatis-flex-dependencies 2025-11-20 09:45:15 +08:00
axbest
af3451b43f fix(sql):优化删除语句中单主键条件的拼接逻辑
- 将单主键删除条件从 OR 拼接改为 IN 方式拼接
2025-11-19 16:13:04 +08:00
Michael Yang
7185d2c79b
Merge pull request #612 from Fengxq2014/fix_version
Update version
2025-11-18 18:32:13 +08:00
Macrow
9a83f1b695 feat: add module mybatis-flex-spring-boot4-starter 2025-11-17 16:17:04 +08:00
Macrow
a5f56db1d0 feat: add module mybatis-flex-spring-boot4-starter 2025-11-17 16:00:19 +08:00
DefNed
d770b550b2
Update version 2025-11-17 14:53:12 +08:00
Michael Yang
de26c7a668
Merge pull request #610 from cybzzz/main
fix: 带子查询的场景下,分页优化误删 join 的修复
2025-11-16 13:49:59 +08:00
Michael Yang
ad154da481
Merge pull request #611 from 4ucl/patch-1
fix: 代码生成器指定 EntityConfig#withBasePackage 时, 生成文件路径错误
2025-11-16 13:49:46 +08:00
Michael Yang
c17e747012
Merge pull request #609 from ruansheng8/feat-tx
refactor: -m flex 调整TransactionObject访问修饰符为public
2025-11-16 13:48:42 +08:00
Lucas C
b78ae2c6c5
Fix base entity package path replacement logic 2025-11-15 18:31:58 +08:00
cybzzz
9343c8eabd fix: 带子查询的场景下,分页优化误删 join 的修复 2025-11-15 13:24:36 +08:00
ruansheng
45ac06ff97 refactor: -m flex 调整TransactionObject访问修饰符为public 2025-11-14 14:14:00 +08:00
Michael Yang
ed09906361 build: v1.11.4 release (^.^)YYa!! 2025-11-13 12:47:38 +08:00
Michael Yang
7cfc1d3432 build: v1.11.4 release (^.^)YYa!! 2025-11-13 12:36:27 +08:00
Michael Yang
4b022408a5 build: v1.11.4 release (^.^)YYa!! 2025-11-13 12:34:05 +08:00
Michael Yang
10e595a628 fix: fixed and close https://gitee.com/mybatis-flex/mybatis-flex/issues/ID64KB 2025-11-13 12:23:23 +08:00
Michael Yang
4d82711fa8
!560 update mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/DbTypeUtil.java.
Merge pull request !560 from younger/N/A
2025-11-10 10:30:10 +00:00
younger
61857a00fe
update mybatis-flex-core/src/main/java/com/mybatisflex/core/dialect/DbTypeUtil.java.
修复根据人大金仓url识别错误类型的bug

Signed-off-by: younger <1095367863@qq.com>
2025-11-10 10:28:26 +00:00
Michael Yang
25e00c677e Merge remote-tracking branch 'gitee/main' 2025-11-10 10:29:20 +08:00
Michael Yang
eefded34f9 Merge branch 'main' of https://github.com/mybatis-flex/mybatis-flex 2025-11-10 10:29:08 +08:00
Michael Yang
a4793eaceb
Merge pull request #600 from Arowa-Z/main
fix: 修复EXISTS、NOT EXISTS的子select语句无法自动附加逻辑删除的问题
2025-11-10 10:26:42 +08:00
Michael Yang
f7ec9689d6
Merge pull request #605 from CShisan/main
fix 修复@EnumValue应用在接口方法且返回类型为泛型时失效的问题
2025-11-10 10:24:36 +08:00
CShisan
c1cd6dcecd fix 修复@EnumValue应用在接口方法且返回类型为泛型时失效的问题 2025-11-07 18:01:11 +08:00
Arowa_Z
66ca2981da fix: 修复EXISTS、NOT EXISTS的子select语句无法自动附加逻辑删除的问题 2025-10-17 23:27:14 +08:00
Michael Yang
12e9243934
!558 update docs/zh/base/db-row.md.
Merge pull request !558 from 涛声依旧/N/A
2025-10-14 09:47:55 +00:00
涛声依旧
b0ecb07e1d
update docs/zh/base/db-row.md.
修正示例代码中的语法错误
2025-10-14 06:34:19 +00:00
Michael Yang
23236e6ec2 build: v1.11.3 release (^.^)YYa!! 2025-09-26 12:12:04 +08:00
Michael Yang
70a97bb0eb build: v1.11.3 release (^.^)YYa!! 2025-09-26 12:09:44 +08:00
Michael Yang
efd2a442d4 fix: 修复 QueryColumn.between_(values) 不能为 null 的问题 2025-09-26 12:02:26 +08:00
Michael Yang
d5d7c3e250 build: v1.11.2 release (^.^)YYa!! 2025-09-26 11:05:18 +08:00
Michael Yang
3c26f72df8 chore: code format 2025-09-25 19:29:37 +08:00
Michael Yang
3618f70055
Merge pull request #587 from ruansheng8/fix-relationQueryNullValue
feat: -m core 优化关联查询使用逗号分割逻辑
2025-09-25 19:23:03 +08:00
Michael Yang
c7bc207ce7
Merge pull request #589 from ruansheng8/fix-relationTableQuery
fix: -m core 修复自动关联表信息查找逻辑
2025-09-25 19:22:20 +08:00
Michael Yang
ec768d2423 docs: update doc 2025-09-25 19:13:39 +08:00
Michael Yang
bf05d11d8e feat: 添加 Assert 方便在执行 update 的时候进行断言 2025-09-25 19:13:07 +08:00
ruansheng
2e5bde372f fix: -m core 修复自动关联查询功能:表信息查找根据Schema+表名 2025-09-25 17:07:54 +08:00
ruansheng
01ab3023df feat: -m core 优化关联查询使用逗号分割时排除空值 2025-09-23 19:59:30 +08:00
Michael Yang
41b52fa6c2 Merge branch 'main' of https://gitee.com/mybatis-flex/mybatis-flex 2025-08-29 09:05:45 +08:00
Michael Yang
29d82efa64
Merge pull request #579 from pbnoyz/feat/audit
feat/audit: 审计功能优化
2025-08-29 09:02:54 +08:00
pbnoyz
9afcb9514d feat: add stmtId for AuditMessage 2025-08-26 22:36:36 +08:00
pbnoyz
c65a3608f8 fix: use ${project.version} for module deps 2025-08-26 22:34:28 +08:00
Michael Yang
324810803b
Merge pull request #563 from ruansheng8/feat-pom
feat: -m bom 框架版本统一管理
2025-08-20 18:41:53 +08:00
Michael Yang
be7d089264
Merge pull request #570 from fangzhengjin/feat-QueryMethods
feat: 增加STRING_AGG、LISTAGG、CAST函数支持
2025-08-20 18:41:37 +08:00
Michael Yang
c19896750c
Merge pull request #573 from whaon/main
fix: spring-batch更改为optional
2025-08-20 18:39:31 +08:00
whaon
c3346a4aac fix: spring-batch更改为optional 2025-08-08 16:06:01 +08:00
ZhengJin
3cb3563508
feat(core): 添加 CAST 函数支持
- 新增 CastQueryColumn 类实现 CAST 函数查询列
- 在 QueryColumn 中添加 cast 方法支持类型转换
- 在 QueryMethods 中提供静态方法创建 CAST 函数查询列
2025-08-08 11:16:21 +08:00
ZhengJin
aa08da881a
feat(core): 添加 stringAgg 和 listAgg 函数的重载方法 2025-08-07 18:17:59 +08:00
ZhengJin
aaa2566b12
feat(core): 添加新函数并增强数据库类型判断能力
- 在 FuncName 中添加 STRING_AGG 和 LISTAGG 函数
- 在 DbType 中添加方法判断数据库类型是否支持 MySQL、Oracle 或 PostgreSQL
- 在 DbTypeUtil 中添加获取当前数据库类型的方法
- 在 QueryMethods 中添加 STRING_AGG 和 LISTAGG聚合函数的支持
2025-08-07 17:09:24 +08:00
Michael Yang
3967aac363
!555 update docs/zh/core/id.md.
Merge pull request !555 from 励志理智离职/N/A
2025-07-29 07:59:38 +00:00
周正伟
4b1e4fa021
update docs/zh/core/id.md.
Signed-off-by: 周正伟 <14040017+java-coding@user.noreply.gitee.com>
2025-07-29 07:36:15 +00:00
ruansheng
66c1cd0850 feat: -m bom 同步最新版本依赖 2025-07-27 15:43:56 +08:00
ruansheng
7289b15478 feat: -m bom revision版本调整 2025-07-27 15:39:23 +08:00
ruansheng
ecbd87a1ae feat: -m bom 框架版本统一管理 2025-07-27 15:29:14 +08:00
Michael Yang
354f9d11a3 build: v1.11.1 release (^.^)YYa!! 2025-07-25 10:30:36 +08:00
Michael Yang
03f6c28463 build: v1.11.1 release (^.^)YYa!! 2025-07-25 10:25:31 +08:00
Michael Yang
f786fd64b5 test: fixed test 2025-07-25 09:52:51 +08:00
Michael Yang
bf973f9f06 Merge branch 'main' of https://gitee.com/mybatis-flex/mybatis-flex 2025-07-25 09:35:47 +08:00
Michael Yang
60a30deea2
!545 增加SpringBatch的支持的测试demo
Merge pull request !545 from zhj149/main
2025-07-25 01:35:11 +00:00
Michael Yang
d47465a91e Merge branch 'main' of https://github.com/mybatis-flex/mybatis-flex 2025-07-25 09:32:34 +08:00
Michael Yang
4d8c132b8d
!552 fix:lambda的orElse是方法的话,会在执行lambda之前堆栈就调用了,那么Optional的逻辑就失去作用了,并且发现了一个逻…
Merge pull request !552 from 谨宸/main
2025-07-25 01:25:03 +00:00
Michael Yang
ece2adc0e3
Merge pull request #562 from ruansheng8/fix-pkgImport
修复Optional包依赖问题
2025-07-24 12:18:05 +08:00
ruansheng
acba6066bc feat: -m core 导入Optional包依赖 2025-07-23 18:51:32 +08:00
谨宸
08d6dae776 fix:lambda的orElse是方法的话,会在执行lambda之前堆栈就调用了,那么Optional的逻辑就失去作用了,并且发现了一个逻辑问题,addDataSource没有使用到参数,会导致multiple逻辑有问题 2025-07-15 19:00:10 +08:00
Michael Yang
6e6f6de0f8
!530 feat: 添加数据源缺失处理器
Merge pull request !530 from oc/dev-20250219
2025-07-14 05:09:02 +00:00
Michael Yang
b196fbb561 feat: 新增 between 条件遇到 一个参数为 null 时自动转换成 LE 或 GE 逻辑 close #ICKPDB 2025-07-14 13:05:43 +08:00
Michael Yang
cc2ca249e0 fix: fix and close #ICLQQ3 2025-07-14 12:48:51 +08:00
Michael Yang
97bf853364 build: v1.11.0 release (^.^)YYa!! 2025-07-13 09:51:49 +08:00
Michael Yang
19a090c4a5 build: v1.11.0 release (^.^)YYa!! 2025-07-13 09:42:15 +08:00
Michael Yang
531152e1d4 Merge branch 'main' of https://github.com/mybatis-flex/mybatis-flex 2025-07-13 09:26:27 +08:00
Michael Yang
7e09e4eb5e docs: update docs 2025-07-13 09:26:17 +08:00
Michael Yang
6f0444a139
!547 修复在使用 UpdateChain 更新实体类字段时偶发 ClassCastException 异常问题
Merge pull request !547 from iminifly/main
2025-07-13 01:23:56 +00:00
Michael Yang
b6d35c8513
!549 fix(DialectFactory): 高斯数据库调整为无反义处理,避免严格大小写处理
Merge pull request !549 from all-around-badass/main
2025-07-13 01:22:24 +00:00
Michael Yang
80ebb40481
Merge pull request #542 from BenLocal/set_prop
feat(Column): 支持带有范型的类型
2025-07-13 09:20:25 +08:00
Michael Yang
be21245b3c
Merge pull request #531 from itfsw/main
feat: 对于用户常用类,启用代码折叠支持
2025-07-13 09:19:20 +08:00
Michael Yang
37afc9ca5b
Merge pull request #536 from wcc1433/main
多环境导入相同 Mapper 冲突问题
2025-07-13 09:17:30 +08:00
Michael Yang
ce86692bcd
Merge pull request #540 from BenLocal/main
feat: mybatis-flex-codegen实体类添加setProperty方法
2025-07-13 09:15:50 +08:00
Michael Yang
cbb9f55cdf
!551 update docs/zh/intro/what-is-mybatisflex.md.
Merge pull request !551 from zhangzq/N/A
2025-07-10 06:25:29 +00:00
zhangzq
46767593a2
update docs/zh/intro/what-is-mybatisflex.md.
修改错别字

Signed-off-by: zhangzq <zhiqingzhang18@163.com>
2025-07-10 06:23:12 +00:00
benshi
dcc9dfb187 feat(Column): 支持带有范型的类型
- 例如`java.util.Optional<java.time.LocalDateTime>`这种类型

Signed-off-by: benshi <807629978@qq.com>
2025-05-28 22:35:29 +08:00
all-aroundbadass
ac5a7bf511 fix(DialectFactory): 高斯数据库调整为无反义处理,避免严格大小写处理 2025-05-28 20:07:35 +08:00
benshi
62b28a33a4 feat(Column): add setter for property
Signed-off-by: benshi <807629978@qq.com>
2025-05-27 21:09:18 +08:00
Michael Yang
ed2621f71f
!548 fix(DbTypeUtil): sqlserver 在 2012 版本开始支持 offset 语法,调整 sqlserver 2008 版…
Merge pull request !548 from all-around-badass/main
2025-05-27 07:47:11 +00:00
all-aroundbadass
99c277545e fix(DbTypeUtil): sqlserver 在 2012 版本开始支持 offset 语法,调整 sqlserver 2008 版本的 DbType 为 SQLSERVER_2005,修复分页语句不支持 offset 问题 2025-05-27 12:07:11 +08:00
wcc1433
cc374a6aa2
多个环境,每个环境加载相同 Mapper (例如 RowMapper)会导致环境冲突。
创建多个环境,每个环境加载相同 Mapper (例如 RowMapper)会导致环境冲突。
代码:
// 环境实例1
MybatisFlexBootstrap client1 = ...;
client1.addMapper(RowMapper.class);
// 环境实例2:
MybatisFlexBootstrap client2 = // ;
client2.addMapper(RowMapper.class);

client1.getMapper(RowMapper.class);
// client2 拿到的永远都是 client1 的 RowMapper
client2.getMapper(RowMapper.class);
2025-05-26 19:19:00 +08:00
wcc1433
c969ee388d
多环境导入相同 Mapper 冲突问题
创建多个环境,每个环境加载相同 Mapper (例如 RowMapper)会导致环境冲突。
代码:
// 环境实例1
MybatisFlexBootstrap client1 = ...;
client1.addMapper(RowMapper.class);
// 环境实例2:
MybatisFlexBootstrap client2 = // ;
client2.addMapper(RowMapper.class);

client1.getMapper(RowMapper.class);
// client2 拿到的永远都是 client1 的 RowMapper
client2.getMapper(RowMapper.class);
2025-05-25 15:40:10 +08:00
lvxiaofei
15e93168b6 修复在使用 UpdateChain 更新实体类字段时偶发 ClassCastException 异常问题 2025-05-16 15:05:53 +08:00
Michael Yang
0baa61fe03
!546 update mybatis-flex-codegen/src/main/resources/templates/enjoy/controller.tpl.
Merge pull request !546 from Mele/N/A
2025-05-11 02:48:21 +00:00
Mele
1ed62629c2
update mybatis-flex-codegen/src/main/resources/templates/enjoy/controller.tpl.
语句不通

Signed-off-by: Mele <lxzgga@163.com>
2025-05-10 19:25:15 +00:00
hewei
a37bdaabf1 feat: 对于用户常用类,启用代码折叠支持 2025-05-10 11:15:30 +08:00
zhj149
336e938471 增加SpringBatch的支持的测试demo 2025-04-28 15:13:52 +08:00
zhj149
ea03a5f3df 增加SpringBatch的支持,Linux下开发,有大小写名称的问题.所以AccountMapper改了下名字. 无法install到本地测试,没写测试 2025-04-28 13:47:12 +08:00
Michael Yang
82ed8229e2 docs: update docs 2025-04-24 18:30:55 +08:00
Michael Yang
a12f528388 Merge branch 'main' of https://github.com/mybatis-flex/mybatis-flex 2025-04-24 18:28:09 +08:00
Michael Yang
0f46023741
!544 update mybatis-flex-core/src/main/java/com/mybatisflex/core/transaction/Propagation.java.
Merge pull request !544 from oc/N/A
2025-04-24 06:28:44 +00:00
oc
cd7eb10758
update mybatis-flex-core/src/main/java/com/mybatisflex/core/transaction/Propagation.java.
refactor: 优化 Propagation 枚举类

- 为每个枚举值添加了相应的 JavaDoc 注释,提高代码可读性
- 将 value 字段声明为 final,确保枚举值的不可变性
- 删除了不必要的 setValue 方法,因为枚举值在构造时设置且不应更改


Signed-off-by: oc <1490535+ocoooo@user.noreply.gitee.com>
2025-04-24 06:25:18 +00:00
Michael Yang
ea45ff983c
Merge pull request #520 from fangzhengjin/dbtype
数据库驱动识别优化
2025-04-21 15:36:08 +08:00
Michael Yang
d943caaad1
!542 update docs/zh/base/parts/base-mapper-insert-methods.md.
Merge pull request !542 from 6岁/N/A
2025-04-20 03:03:07 +00:00
6岁
af88769761
update docs/zh/base/parts/base-mapper-insert-methods.md.
- **`insertBatchSelective(entities)`**:批量插入实体类数据,忽略 `null` 值。

Signed-off-by: 6岁 <r.xiaolong@qq.com>
2025-04-10 07:52:00 +00:00
ZhengJin
2bd5c039d1
1. 增加 GBASE_8C、GBASE_8S_PG、GOLDENDB、SUNDB、VASTBASE、YASDB、PRESTO 驱动识别
2. 修正高斯企业版数据库驱动识别问题
2025-04-08 16:28:17 +08:00
Michael Yang
06a798eed7 test: add test for issues IBYEZ7 2025-04-03 09:22:00 +08:00
Michael Yang
848d709140 test: add lambada test 2025-04-03 09:15:33 +08:00
Michael Yang
d20377c049
!540 &gt;=逻辑和&lt;=逻辑保持一致
Merge pull request !540 from 道友小会/main
2025-04-01 07:10:19 +00:00
fyh
3d1bbbf235 >=逻辑和<=逻辑保持一致 2025-04-01 15:05:54 +08:00
Michael Yang
4bf41c414b
!539 fix: 在 join 多次相同的表时, 构建租户条件没能取到正确的别名
Merge pull request !539 from gzkemays/fix/find_join_alias
2025-04-01 06:25:35 +00:00
huangweiye
2a64e3115f fix: 在 join 多次相同的表时, 构建租户条件没能取到正确的别名 2025-04-01 14:02:12 +08:00
Michael Yang
65b1161651
!536 feat:新增 loveqq-framework 框架下的启动器
Merge pull request !536 from kfyty/main
2025-03-31 03:01:48 +00:00
Michael Yang
1ddc316f7c
!537 update docs/zh/others/codegen.md.
Merge pull request !537 from A.Ming/N/A
2025-03-20 12:13:47 +00:00
A.Ming
7ac13da064
update docs/zh/others/codegen.md.
Signed-off-by: A.Ming <itaming@163.com>
2025-03-20 11:57:24 +00:00
kfyty725
2fb2582d9b opt:update loveqq-framework starter version 2025-03-20 17:00:44 +08:00
kfyty725
366d556bad feat:添加loveqq-framework启动器 2025-03-20 17:00:25 +08:00
Michael Yang
ea1dd46566
!535 自定义DbType&主键提示优化
Merge pull request !535 from 谨宸/main
2025-03-19 23:23:19 +00:00
winston
624ae4d4a0 [20250319]jinchen@feat&fix:
1. 创建Flex数据源时,支持手动置顶DbType,防止route数据源的时候dbtype不一直导致的问题
2. 修复没有指定主键的时候,出现下标越界的异常,提示更加友好
2025-03-19 23:37:35 +08:00
Michael Yang
6c75b6e692 build: v1.10.9 release (^.^)YYa!! 2025-03-19 18:34:30 +08:00
Michael Yang
6fa86a03a5 build: v1.10.9 release (^.^)YYa!! 2025-03-19 18:31:01 +08:00
Michael Yang
097d93a343 build: v1.10.9 release (^.^)YYa!! 2025-03-19 18:25:12 +08:00
Michael Yang
ecfea5e683 fix: fix RowMapperInvoker error in dialect 2025-03-19 18:19:00 +08:00
Michael Yang
1987df70a5 Merge remote-tracking branch 'gitee/main' 2025-03-17 09:17:21 +08:00
Michael Yang
eafe6d338f
Merge pull request #515 from cybzzz/main
fix: exists 条件中的表别名和父查询保持一致
2025-03-17 09:16:21 +08:00
cybzzz
a35ca5cd62 fix: exists 别名单侧修改 2025-03-16 22:43:22 +08:00
cybzzz
5afd03c948 fix: exists 条件中的表别名和父查询保持一致 2025-03-16 20:27:58 +08:00
Michael Yang
cfa7a75205
!533 增加全局忽略 schema
Merge pull request !533 from 代码裁缝/main
2025-03-04 01:38:11 +00:00
home\cuiyuan
1c9d3f6a96 增加全局忽略 schema 2025-03-03 23:40:48 +08:00
Michael Yang
b326a824b8
Merge pull request #502 from coder-xiaomo/feat-lombokConstructorEnable
feat: 支持配置 entity 类 lombok 注解生成 (`@NoArgsConstructor`, `@AllArgsConstructor`)
2025-02-28 13:24:27 +08:00
Michael Yang
a0db718ed2
Merge pull request #505 from skating/main
fix:批量插入传set报错问题
2025-02-28 13:23:52 +08:00
zhb
b1a2980ac5 批量插入传set报错问题 2025-02-24 12:35:21 +08:00
oc
a39fb3d014 feat: 添加数据源缺失处理器 2025-02-19 15:55:26 +08:00
程序员小墨
f6b22c1da7 feat: 支持配置 entity 类 lombok 注解生成 (@NoArgsConstructor, @AllArgsConstructor) 2025-02-17 16:43:33 +08:00
oc
5fccfa6c4b build: 添加 maven-wrapper 2025-02-17 13:53:31 +08:00
Michael Yang
77f0d6c173 build: v1.10.8 release (^.^)YYa!! 2025-02-17 11:47:10 +08:00
Michael Yang
61006c5057 build: v1.10.8 release (^.^)YYa!! 2025-02-17 11:44:27 +08:00
Michael Yang
2bf1bdb454
Merge pull request #501 from weicm/main
fix: 修复pr-494导致单元测试不通过问题
2025-02-17 11:07:49 +08:00
weichangming
890e0c3944 fix: 修复pr-494导致单元测试不通过问题 2025-02-17 09:14:07 +08:00
Michael Yang
fc0812228a Merge branch 'main' of https://gitee.com/mybatis-flex/mybatis-flex 2025-02-14 09:56:59 +08:00
Michael Yang
be123d50d0
Merge pull request #495 from coder-xiaomo/feat-base-override
feat: Codegen 生成 entity base 时支持设置是否覆盖已有文件
2025-02-14 09:56:11 +08:00
Michael Yang
38e74544db
Merge pull request #494 from weicm/main
!491 fix: QueryWrapper无法支持常量查询
2025-02-14 09:55:33 +08:00
Michael Yang
9cd42b5f14
Merge pull request #493 from coder-xiaomo/chore
chore: entityWithBase.tpl 文件注解间多了一个换行
2025-02-14 09:53:53 +08:00
Michael Yang
351fd7facd
Merge pull request #492 from coder-xiaomo/main
chore: Gitee 贡献者列表已达到4页,运行 ContributorsDocGen 脚本更新文档贡献者
2025-02-14 09:53:34 +08:00
程序员小墨
3a28c3b3b4 feat: Codegen 生成 entity base 时支持设置是否覆盖已有文件 2025-02-13 18:05:21 +08:00
weichangming
2b22bdc015 !491 fix: QueryWrapper无法支持常量查询 2025-02-13 17:29:06 +08:00
程序员小墨
92cc0d8438 chore: entityWithBase.tpl 文件注解间多了一个换行 2025-02-13 17:16:28 +08:00
程序员小墨
af8616e371 chore: Gitee 贡献者列表已达到4页,运行 ContributorsDocGen 脚本更新文档贡献者 2025-02-13 16:57:07 +08:00
Michael Yang
5c851e0b81
!527 优化TenantManager.withoutTenantCondition测试代码
Merge pull request !527 from tangxin/main
2025-02-13 02:37:04 +00:00
tangxin
80a42efb61 优化TenantManager.withoutTenantCondition修改测试 2025-02-13 10:32:58 +08:00
Michael Yang
e74e4044d1 Merge branch 'main' of https://github.com/mybatis-flex/mybatis-flex 2025-02-12 21:43:23 +08:00
Michael Yang
7796f970b0
!526 fix:TenantFactory.withoutTenantCondition 在修改时 无效
Merge pull request !526 from tangxin/main
2025-02-12 13:42:39 +00:00
Michael Yang
138bc6ca1e
Merge pull request #490 from coder-xiaomo/main
feat: JavadocConfig setAuthor 和 setSince 方法传入空字符串时,不添加注释 @author, @since 部分
2025-02-12 17:50:01 +08:00
tangxin
e5501e9e3f fix:TenantFactory.withoutTenantCondition 在修改时 无效 2025-02-12 17:25:00 +08:00
程序员小墨
8e0a2b32e2 feat: JavadocConfig setAuthor 和 setSince 方法传入空字符串时,不添加注释 @author, @since 部分 2025-02-12 17:02:10 +08:00
Michael Yang
71f456bc93
Merge pull request #489 from coder-xiaomo/fix-setEntityWithBaseClassEnable
fix: 修复 Codegen GlobalConfig 类缺少 setEntityWithBaseClassEnable 函数问题
2025-02-12 16:44:02 +08:00
程序员小墨
ea5836ab51 fix: 修复 Codegen GlobalConfig 类缺少 setEntityWithBaseClassEnable 函数问题 globalConfig.getEntityConfig().setWithBaseClassEnable(true); 2025-02-12 16:40:36 +08:00
王帅
0c4b0c2266
!525 fix 报错java.lang.NoClassDefFoundError: com/mybatisflex/processor/util/StrUtil
Merge pull request !525 from tangxin/main
2025-02-11 02:42:37 +00:00
tangxin
afa483d606 fix 报错java.lang.NoClassDefFoundError: com/mybatisflex/processor/util/StrUtil 2025-02-11 10:26:20 +08:00
262 changed files with 13841 additions and 910 deletions

View File

@ -7,7 +7,7 @@ body:
attributes:
label: 这个 Bug 是否已经存在:
options:
- label: 我确定已经把 MyBatis-Flex 升级到最新版本 v1.10.7,并已搜索过现有的问题 (https://gitee.com/mybatis-flex/mybatis-flex/issues)
- label: 我确定已经把 MyBatis-Flex 升级到最新版本 v1.11.1,并已搜索过现有的问题 (https://gitee.com/mybatis-flex/mybatis-flex/issues)
required: true
- type: textarea
attributes:

BIN
.mvn/wrapper/maven-wrapper.jar vendored Normal file

Binary file not shown.

18
.mvn/wrapper/maven-wrapper.properties vendored Normal file
View File

@ -0,0 +1,18 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar

View File

@ -2,9 +2,80 @@
查看 [全部代码贡献者](/zh/intro/what-is-mybatisflex.html#贡献者)。
## v1.11.4 20251113
- 修复:修复 EXISTS、NOT EXISTS 的子 select 语句无法自动附加逻辑删除的问题,感谢 @Arowa_Z
- 修复:@EnumValue 应用在接口方法且返回类型为泛型时失效的问题,感谢 @CShisan
- 修复:人大金仓方言类型判断不准确的问题,感谢 @younger
- 修复RowKeyGenerator 的 autoKeyGeneratorNames 在某些情况下累积导致缓存污染的问题
- 文档:修正示例代码中的语法错误,感谢 @涛声依旧
## v1.11.3 20250926
- 修复QueryColumn.between_(values) 不能为 null 的问题 #ID03CH
## v1.11.2 20250926
- 新增:添加 Assert 方便在执行 update 的时候进行断言
- 新增:添加新函数并增强数据库类型判断能力,感谢 @fangzhengjin
- 新增:添加 stringAgg 和 listAgg 函数的重载方法,感谢 @fangzhengjin
- 新增:添加新函数并增强数据库类型判断能力,感谢 @fangzhengjin
- 新增AuditMessage 添加 stmtId ,感谢 @pbnoyz
- 优化bom 框架版本统一管理,感谢 @ruansheng8
- 优化bom 同步最新版本依赖,感谢 @ruansheng8
- 优化:优化关联查询使用逗号分割时排除空值,感谢 @ruansheng8
- 修复修复自动关联查询功能表信息查找根据Schema+表名,感谢 @ruansheng8
- 文档:更新相关文档 docs/zh/core/id.md感谢 @java-coding
## v1.11.1 20250725
- 新增:添加数据源缺失处理器,方便项目启动后,再通过代码添加数据源
- 新增between 条件遇到 一个参数为 null 时自动转换成 LE 或 GE 逻辑 #ICKPDB
- 新增:添加对 Spring Batch 的支持
- 修复:动态添加数据源第二次切换数据源无效的问题 #ICLQQ3
- 修复Datasource lambda 的 orElse 是方法的话,会在执行 lambda 之前堆栈就调用了,那么 Optional 的逻辑就失去作用了
- 测试:添加对 Spring Batch 的单元测试
## v1.11.0 20250713
- 新增:代码生成器 Column 支持带有范型的类型,感谢 @benshi
- 新增:对于用户常用类,启用代码折叠支持,感谢 @hewei
- 新增Column 添加 setProperty 方法的支持,感谢 @benshi
- 新增:增加 GBASE_8C、GBASE_8S_PG、GOLDENDB、SUNDB、VASTBASE、YASDB、PRESTO 驱动识别,感谢 @fangzhengjin
- 新增:添加 loveqq-framework 启动器,感谢 @kfyty725
- 优化:优化 `>=` 逻辑和 `<=` 逻辑保持一致,感谢 @fyh
- 优化:调整 sqlserver 2008 版本的 DbType 为 SQLSERVER_2005修复分页语句不支持 offset 问题,感谢 @all-around-badass
- 修复:高斯数据库调整为无反义处理,避免严格大小写处理,感谢 @all-around-badass
- 修复:在 join 多次相同的表时, 构建租户条件没能取到正确的别名,感谢 @gzkemays
- 修复:在使用 UpdateChain 更新实体类字段时偶发 ClassCastException 异常问题,感谢 @iminifly
- 修复:多环境导入相同 Mapper 冲突问题,感谢 @wcc1433
- 文档:更新代码生成器的相关文档
## v1.10.9 20250319
- 新增: 代码生成器支持配置 entity 类 lombok 注解生成 (@NoArgsConstructor, @AllArgsConstructor),感谢 @coder-xiaomo
- 新增:增加全局忽略 schema 配置的支持,感谢 @cui
- 修复MultiEntityKeyGenerator 不支持 set 设置的问题,感谢 @zhb
- 修复exists 条件中的表别名和父查询保持一致的问题,感谢 @cybzzz
- 修复:修复在 diaelct 中去调用 Db 工具时可能出现类型转换错误的问题
## v1.10.8 20250217
- 新增:代码生成器 GlobalConfig 添加 setEntityWithBaseClassEnable 设置,感谢 @coder-xiaomo
- 新增:代码生成器生成 entity base 时支持设置是否覆盖已有文件,感谢 @coder-xiaomo
- 新增QueryWrapper 支持常量查询,感谢 @weichangming
- 优化:代码生成器 setAuthor 和 setSince 方法传入空字符串时,不添加注释 @author, @since 部分,感谢 @coder-xiaomo
- 修复:在不使用 mybatis-flex-processor 模块时,会出现 StrUtil 找不到的问题,感谢 @codetangxin
- 修复TenantFactory.withoutTenantCondition 在修改时无效的问题,感谢 @codetangxin
## v1.10.7 20250210
- 修复:在不使用 mybatis-flex-processor 模块时,会出现 StrUtil 找不到的问题
- 修复:代码生成器 Controller 代码生成格式和详情无法生成文档的问题

View File

@ -97,21 +97,21 @@ const {Layout} = DefaultTheme
<Layout>
<!--docs: https://vitepress.dev/guide/extending-default-theme#layout-slots-->
<!-- <template #doc-before>-->
<!-- <div style="margin-bottom: 30px">-->
<!-- <a href="https://mp.weixin.qq.com/s/1pTQ9m3C4ebfSQdyWUAyaQ" target="_blank">-->
<!-- <img src="/assets/images/ad/aiadmin.gif">-->
<!-- </a>-->
<!-- </div>-->
<!-- </template>-->
<template #doc-before>
<div style="margin-bottom: 30px">
<a href="https://gitee.com/aiflowy/aiflowy" target="_blank">
<img src="/assets/images/ad/aiflowy-banner.jpg">
</a>
</div>
</template>
<!-- <template #home-features-after>-->
<!-- <div class="banner-home">-->
<!-- <a href="https://mp.weixin.qq.com/s/1pTQ9m3C4ebfSQdyWUAyaQ" target="_blank">-->
<!-- <img src="/assets/images/ad/aiadmin.gif">-->
<!-- </a>-->
<!-- </div>-->
<!-- </template>-->
<template #home-features-after>
<div class="banner-home">
<a href="https://gitee.com/aiflowy/aiflowy" target="_blank">
<img src="/assets/images/ad/aiflowy-banner.jpg">
</a>
</div>
</template>
<!-- <template #home-features-after>-->
@ -142,10 +142,10 @@ const {Layout} = DefaultTheme
<!-- <a href="https://dromara.gitee.io/fast-request/" target="_blank"><img-->
<!-- src="/assets/images/ad/fast-request-20230828.svg" style="width: 120px;height: 50px"></a>-->
<!-- </div>-->
<div class="banner">
<a href="https://www.5iot.com/source?key=flex" target="_blank"><img
src="/assets/images/ad/iotlink_20240802.png"></a>
</div>
<!-- <div class="banner">-->
<!-- <a href="https://www.5iot.com/source?key=flex" target="_blank"><img-->
<!-- src="/assets/images/ad/iotlink_20240802.png"></a>-->
<!-- </div>-->
<div class="banner">
<a href="http://www.jpress.cn" target="_blank" style="height:50px;
background: rgb(247 247 247);width: 105px;color: #000;font-size: 18px">
@ -159,10 +159,10 @@ const {Layout} = DefaultTheme
<div class="banner">
<a href="http://www.codeformat.cn" target="_blank"><img src="/assets/images/ad/code-format.png"></a>
</div>
<div class="banner">
<a href="https://eiam.topiam.cn" target="_blank"><img
src="/assets/images/ad/topiam_20230909.png" style="width: 105px;height: 50px"></a>
</div>
<!-- <div class="banner">-->
<!-- <a href="https://eiam.topiam.cn" target="_blank"><img-->
<!-- src="/assets/images/ad/topiam_20230909.png" style="width: 105px;height: 50px"></a>-->
<!-- </div>-->
<div class="banner">
虚位以待
</div>
@ -174,10 +174,10 @@ const {Layout} = DefaultTheme
<a href="https://www.orangeforms.com" target="_blank"><img
src="/assets/images/ad/cd_20250620.jpg" data-expired="20250620"></a>
</div>
<div class="banner-bottom">
<a href="https://www.diboot.com/?from=mf" target="_blank"><img
src="https://www.diboot.com/diboot_mf.png" data-expired="20250116"></a>
</div>
<!-- <div class="banner-bottom">-->
<!-- <a href="https://www.diboot.com/?from=mf" target="_blank"><img-->
<!-- src="https://www.diboot.com/diboot_mf.png" data-expired="20250116"></a>-->
<!-- </div>-->
</div>
</template>
</Layout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

View File

@ -181,14 +181,14 @@ Other other = row.toObject(Other.class);
## Row 字段转化为驼峰风格
```java
Row row = Db..selectOneBySql("select * from ....");
Row row = Db.selectOneBySql("select * from ....");
Map result = row.toCamelKeysMap();
```
## Row 字段转换为下划线风格
```java
Row row = Db..selectOneBySql("select * from ....");
Row row = Db.selectOneBySql("select * from ....");
Map result = row.toUnderlineKeysMap();
```

View File

@ -6,6 +6,7 @@
- **`insertWithPk(entity, ignoreNulls)`**:带有主键的插入,此时实体类不会经过主键生成器生成主键。
- **`insertBatch(entities)`**:批量插入实体类数据,只会根据第一条数据来构建插入的字段内容。
- **`insertBatch(entities, size)`**:批量插入实体类数据,按 size 切分。
- **`insertBatchSelective(entities)`**:批量插入实体类数据,忽略 `null` 值。
- **`insertOrUpdate(entity)`**:插入或者更新,若主键有值,则更新,若没有主键值,则插入,插入或者更新都不会忽略 `null` 值。
- **`insertOrUpdateSelective(entity)`**:插入或者更新,若主键有值,则更新,若没有主键值,则插入,插入或者更新都会忽略 `null`
值。

View File

@ -14,7 +14,7 @@ MyBatis-Flex 展示的机会。
| 全站右侧边栏 1 | 图片+链接 | 105*50px | ¥200/月 | 8 |
| 全站右侧边栏 2 | 图片+链接 | 222*50px | ¥400/月 | 1 |
您可以联系微信 `fuh99888` 就展示位的详细事宜。
您可以联系微信 `fuh99777` 就展示位的详细事宜。
## 无偿捐赠

View File

@ -2,9 +2,80 @@
查看 [全部代码贡献者](/zh/intro/what-is-mybatisflex.html#贡献者)。
## v1.11.4 20251113
- 修复:修复 EXISTS、NOT EXISTS 的子 select 语句无法自动附加逻辑删除的问题,感谢 @Arowa_Z
- 修复:@EnumValue 应用在接口方法且返回类型为泛型时失效的问题,感谢 @CShisan
- 修复:人大金仓方言类型判断不准确的问题,感谢 @younger
- 修复RowKeyGenerator 的 autoKeyGeneratorNames 在某些情况下累积导致缓存污染的问题
- 文档:修正示例代码中的语法错误,感谢 @涛声依旧
## v1.11.3 20250926
- 修复QueryColumn.between_(values) 不能为 null 的问题 #ID03CH
## v1.11.2 20250926
- 新增:添加 Assert 方便在执行 update 的时候进行断言
- 新增:添加新函数并增强数据库类型判断能力,感谢 @fangzhengjin
- 新增:添加 stringAgg 和 listAgg 函数的重载方法,感谢 @fangzhengjin
- 新增:添加新函数并增强数据库类型判断能力,感谢 @fangzhengjin
- 新增AuditMessage 添加 stmtId ,感谢 @pbnoyz
- 优化bom 框架版本统一管理,感谢 @ruansheng8
- 优化bom 同步最新版本依赖,感谢 @ruansheng8
- 优化:优化关联查询使用逗号分割时排除空值,感谢 @ruansheng8
- 修复修复自动关联查询功能表信息查找根据Schema+表名,感谢 @ruansheng8
- 文档:更新相关文档 docs/zh/core/id.md感谢 @java-coding
## v1.11.1 20250725
- 新增:添加数据源缺失处理器,方便项目启动后,再通过代码添加数据源
- 新增between 条件遇到 一个参数为 null 时自动转换成 LE 或 GE 逻辑 #ICKPDB
- 新增:添加对 Spring Batch 的支持
- 修复:动态添加数据源第二次切换数据源无效的问题 #ICLQQ3
- 修复Datasource lambda 的 orElse 是方法的话,会在执行 lambda 之前堆栈就调用了,那么 Optional 的逻辑就失去作用了
- 测试:添加对 Spring Batch 的单元测试
## v1.11.0 20250713
- 新增:代码生成器 Column 支持带有范型的类型,感谢 @benshi
- 新增:对于用户常用类,启用代码折叠支持,感谢 @hewei
- 新增Column 添加 setProperty 方法的支持,感谢 @benshi
- 新增:增加 GBASE_8C、GBASE_8S_PG、GOLDENDB、SUNDB、VASTBASE、YASDB、PRESTO 驱动识别,感谢 @fangzhengjin
- 新增:添加 loveqq-framework 启动器,感谢 @kfyty725
- 优化:优化 `>=` 逻辑和 `<=` 逻辑保持一致,感谢 @fyh
- 优化:调整 sqlserver 2008 版本的 DbType 为 SQLSERVER_2005修复分页语句不支持 offset 问题,感谢 @all-around-badass
- 修复:高斯数据库调整为无反义处理,避免严格大小写处理,感谢 @all-around-badass
- 修复:在 join 多次相同的表时, 构建租户条件没能取到正确的别名,感谢 @gzkemays
- 修复:在使用 UpdateChain 更新实体类字段时偶发 ClassCastException 异常问题,感谢 @iminifly
- 修复:多环境导入相同 Mapper 冲突问题,感谢 @wcc1433
- 文档:更新代码生成器的相关文档
## v1.10.9 20250319
- 新增: 代码生成器支持配置 entity 类 lombok 注解生成 (@NoArgsConstructor, @AllArgsConstructor),感谢 @coder-xiaomo
- 新增:增加全局忽略 schema 配置的支持,感谢 @cui
- 修复MultiEntityKeyGenerator 不支持 set 设置的问题,感谢 @zhb
- 修复exists 条件中的表别名和父查询保持一致的问题,感谢 @cybzzz
- 修复:修复在 diaelct 中去调用 Db 工具时可能出现类型转换错误的问题
## v1.10.8 20250217
- 新增:代码生成器 GlobalConfig 添加 setEntityWithBaseClassEnable 设置,感谢 @coder-xiaomo
- 新增:代码生成器生成 entity base 时支持设置是否覆盖已有文件,感谢 @coder-xiaomo
- 新增QueryWrapper 支持常量查询,感谢 @weichangming
- 优化:代码生成器 setAuthor 和 setSince 方法传入空字符串时,不添加注释 @author, @since 部分,感谢 @coder-xiaomo
- 修复:在不使用 mybatis-flex-processor 模块时,会出现 StrUtil 找不到的问题,感谢 @codetangxin
- 修复TenantFactory.withoutTenantCondition 在修改时无效的问题,感谢 @codetangxin
## v1.10.7 20250210
- 修复:在不使用 mybatis-flex-processor 模块时,会出现 StrUtil 找不到的问题
- 修复:代码生成器 Controller 代码生成格式和详情无法生成文档的问题

View File

@ -132,7 +132,9 @@ public class UUIDKeyGenerator implements IKeyGenerator {
第 2 步:注册 UUIDKeyGenerator
```java
KeyGeneratorFactory.register("myUUID", new UUIDKeyGenerator());
static {
KeyGeneratorFactory.register("myUUID", new UUIDKeyGenerator());
}
```
第 3 步:在 Entity 里使用 "myUUID" 生成器:

View File

@ -206,6 +206,43 @@ public class Account {
`DataSourceKey.use()` > `@UseDataSource()在方法上` > `@UseDataSource()在类上` >`@Table(dataSource="...")`
:::
## 数据源缺失处理器
当无法根据 `dataSourceKey` 找到数据源时,默认情况下会抛出 `IllegalStateException` 异常。
数据源缺失处理器(`DataSourceMissingHandler`)提供了更加灵活的处理方式,你可以通过它自定义处理逻辑(如:记录日志、抛出异常或主动初始化新的数据源)。
### 使用示例
我们推荐使用 `MyBatisFlexCustomizer` 来配置数据源缺失处理器,如下所示:
```java
@Configuration
public class MyBatisFlexConfiguration implements MyBatisFlexCustomizer {
@Override
public void customize(FlexGlobalConfig globalConfig) {
// ...
// 配置数据源缺失处理器:此处演示的是以后备逻辑主动初始化数据源
globalConfig.setDataSourceMissingHandler((dataSourceKey, dataSourceMap) -> {
// 根据 key 获取数据源
DataSource ds = customCreateDataSource(dataSourceKey);
// 取不到的时候返回 null后续代码逻辑仍然由 FlexDataSource 处理(即抛出异常)
if (ds == null) return null;
// 添加新的数据源,避免下次再次触发和创建
dataSourceMap.put(dataSourceKey, ds);
return dataSourceMap;
});
// ...
}
}
```
## 更多的 Spring 或 Solon Yaml 配置支持
```yaml
mybatis-flex:

View File

@ -74,7 +74,7 @@ public class Account {
用于监听 Entity 实体类数据被新增到数据库,我们可以在实体类被新增时做一些前置操作。比如:
- 数据填充。
- 默认数据填充:比如插入时间、创建人等等
- 数据修改。
示例代码如下:
@ -109,7 +109,9 @@ public class MyInsertListener implements InsertListener {
## onUpdate
使用方式同 onInsert 一致,用于在数据被更新的时候,设置一些默认数据。
使用方式同 onInsert 一致,用于在数据被更新的时候,设置一些默认数据,比如:更新时间、更新人等等。
也可以用于当前数据的 “权限检查”,比如:更新的数据的用户 id 不是当前登录的用户,则抛出异常,不允许更新等等。
## onSet
@ -121,6 +123,7 @@ onSet 可以用于配置:查询数据 entity (或者 entity 列表、分页
- 场景3一对多一对一查询entity 中定义关联实体,在监听到字段赋值时,主动去查询关联表赋值。
- 场景4字段加密监听到内容被赋值时对内容进行加密处理。
- 场景5字段脱敏出字段内容进行脱敏处理
- 场景6数据验证比如当前用户查询的数据中当前用户没有权限查看则抛出异常等。
示例代码如下:

View File

@ -53,7 +53,7 @@ VALUES (1, '张三', 18, '2020-01-11'),
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
<version>1.10.7</version>
<version>1.11.4</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
@ -81,7 +81,7 @@ VALUES (1, '张三', 18, '2020-01-11'),
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot3-starter</artifactId>
<version>1.10.7</version>
<version>1.11.4</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>

View File

@ -10,7 +10,7 @@
```kotlin
dependencies {
implementation("com.mybatis-flex:mybatis-flex-core:1.10.7")
implementation("com.mybatis-flex:mybatis-flex-core:1.11.4")
}
```
@ -18,7 +18,7 @@ dependencies {
```groovy
dependencies {
implementation 'com.mybatis-flex:mybatis-flex-core:1.10.7'
implementation 'com.mybatis-flex:mybatis-flex-core:1.11.4'
}
```
@ -28,7 +28,7 @@ dependencies {
```kotlin
dependencies {
implementation("com.mybatis-flex:mybatis-flex-spring:1.10.7")
implementation("com.mybatis-flex:mybatis-flex-spring:1.11.4")
}
```
@ -36,7 +36,7 @@ dependencies {
```groovy
dependencies {
implementation 'com.mybatis-flex:mybatis-flex-spring:1.10.7'
implementation 'com.mybatis-flex:mybatis-flex-spring:1.11.4'
}
```
@ -46,7 +46,7 @@ dependencies {
```kotlin
dependencies {
implementation("com.mybatis-flex:mybatis-flex-spring-boot-starter:1.10.7")
implementation("com.mybatis-flex:mybatis-flex-spring-boot-starter:1.11.4")
}
```
@ -54,7 +54,7 @@ dependencies {
```groovy
dependencies {
implementation 'com.mybatis-flex:mybatis-flex-spring-boot-starter:1.10.7'
implementation 'com.mybatis-flex:mybatis-flex-spring-boot-starter:1.11.4'
}
```
@ -65,7 +65,7 @@ dependencies {
```kotlin
dependencies {
implementation("com.mybatis-flex:mybatis-flex-solon-plugin:1.10.7")
implementation("com.mybatis-flex:mybatis-flex-solon-plugin:1.11.4")
}
```
@ -73,7 +73,7 @@ dependencies {
```groovy
dependencies {
implementation 'com.mybatis-flex:mybatis-flex-solon-plugin:1.10.7'
implementation 'com.mybatis-flex:mybatis-flex-solon-plugin:1.11.4'
}
```
@ -91,7 +91,7 @@ dependencies {
```kotlin
dependencies {
annotationProcessor("com.mybatis-flex:mybatis-flex-processor:1.10.7")
annotationProcessor("com.mybatis-flex:mybatis-flex-processor:1.11.4")
}
```
@ -99,6 +99,6 @@ dependencies {
```groovy
dependencies {
annotationProcessor 'com.mybatis-flex:mybatis-flex-processor:1.10.7'
annotationProcessor 'com.mybatis-flex:mybatis-flex-processor:1.11.4'
}
```

View File

@ -12,12 +12,12 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-core</artifactId>
<version>1.10.7</version>
<version>1.11.4</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>1.10.7</version>
<version>1.11.4</version>
<scope>provided</scope>
</dependency>
```
@ -28,12 +28,12 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring</artifactId>
<version>1.10.7</version>
<version>1.11.4</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>1.10.7</version>
<version>1.11.4</version>
<scope>provided</scope>
</dependency>
``````
@ -44,12 +44,12 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
<version>1.10.7</version>
<version>1.11.4</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>1.10.7</version>
<version>1.11.4</version>
<scope>provided</scope>
</dependency>
```
@ -60,12 +60,12 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot3-starter</artifactId>
<version>1.10.7</version>
<version>1.11.4</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>1.10.7</version>
<version>1.11.4</version>
<scope>provided</scope>
</dependency>
```
@ -76,12 +76,12 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-solon-plugin</artifactId>
<version>1.10.7</version>
<version>1.11.4</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>1.10.7</version>
<version>1.11.4</version>
<scope>provided</scope>
</dependency>
```
@ -104,7 +104,7 @@
<path>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>1.10.7</version>
<version>1.11.4</version>
</path>
</annotationProcessorPaths>
</configuration>

View File

@ -1,28 +1,41 @@
| | | | | |
|-----|-----|-----|-----|-----|
|![](https://foruda.gitee.com/avatar/1676898191051702081/61279_fuhai_1578915942.png!avatar30)Michael Yang|![](https://foruda.gitee.com/avatar/1698661375322784129/7984572_suomm_1698661375.png!avatar30)王帅|![](https://foruda.gitee.com/avatar/1691636027051962328/11233353_kamo-sama_1691636027.png!avatar30)卡莫sama|丌冰|![](https://foruda.gitee.com/avatar/1691044597656855579/7563907_lifejwang11_1691044597.png!avatar30)life|
|snyk-bot|lhzsdnu|![](https://foruda.gitee.com/avatar/1683858335519306352/15535_noear_admin_1683858335.png!avatar30)西东|tangxin|Font_C|
|pengpeng|庄佳彬|Ice-samll|guanmengyuan|![](https://foruda.gitee.com/avatar/1697612161781835336/7870258_wchopper_1697612161.png!avatar30)王超|
|笨小孩|bf109f|chenjh3|CloudPlayer|Jerry|
|snow|草语|farukonfly|![](https://foruda.gitee.com/avatar/1694759381586775676/568596_qq925966998_1694759381.png!avatar30)李楠|菜鸟3853|
|mofan|Jerry_Zheng|wujl|Martin7-1|![](https://foruda.gitee.com/avatar/1676895504036051867/8807_piggsoft_1578914592.jpg!avatar30)piggsoft|
|![](https://foruda.gitee.com/avatar/1674286432514482953/4807650_fandai_fandaidzsw_1674286432.png!avatar30)赤兮丷|黄沐鸿|loong0306|沈君锋|![](https://foruda.gitee.com/avatar/1691034002435340221/1920167_qimincow_1691034002.png!avatar30)英雄路|
|natsufumij|BQ60ziOxlFI0R0|tan90|aqnghu|张继续|
|font-C|![](https://foruda.gitee.com/avatar/1677053740056224121/5462387_i_tell_you_1618064317.png!avatar30)liibang|cainiao3853|![](https://foruda.gitee.com/avatar/1702438316292746960/8789215_barql_1702438316.png!avatar30)barql|yangs|
|lcxw|![](https://foruda.gitee.com/avatar/1677086127012961929/7598208_robot-l_1590219712.png!avatar30)Robot.L|![](https://foruda.gitee.com/avatar/1695378372753910643/2130728_lemonbx_1695378372.png!avatar30)落羽er|Faputa|qixy|
|yuanbaolong|zhijieqing|![](https://foruda.gitee.com/avatar/1678377314939642686/1604115_handy-git_1678377314.png!avatar30)handy|![](https://foruda.gitee.com/avatar/1677237805724097193/11485875_bygkn_1660893367.png!avatar30)bygkn|![](https://foruda.gitee.com/avatar/1674121508509280199/9288653_saoforestt_1674121508.png!avatar30)Saoforest|
|![](https://foruda.gitee.com/avatar/1676906219947351575/342237_tangzc_1629796763.png!avatar30)唐振超|Watcher.Wang|![](https://foruda.gitee.com/avatar/1676978624694631546/1600987_youthdream_1592959590.png!avatar30)锟斤拷|zhongyong|XiaoLin|
|![](https://foruda.gitee.com/avatar/1677111694079591934/8088436_yang-zzu_1604969134.png!avatar30)yang_zzu|![](https://foruda.gitee.com/avatar/1676895416224286260/8331_chaosforever_1578914555.png!avatar30)锁力|shaoerkuai|meichenhui|![](https://foruda.gitee.com/avatar/1679885039814030308/5151444_yangbuyi_1679885039.png!avatar30)阿志同学|
|chenjian835|![](https://foruda.gitee.com/avatar/1676896586274105369/20327_cnscoo_1578915320.jpg!avatar30)Haru|![](https://foruda.gitee.com/avatar/1676896562075035262/20021_duxlei_1578915302.png!avatar30)duxlei|![](https://foruda.gitee.com/avatar/1676905453682965545/327218_gm173119755_1648555045.png!avatar30)豌豆粉|涛声依旧|
|matthew|gongzhongqiang|luy|凌尘|Alex|
|EafonYoung|![](https://foruda.gitee.com/avatar/1677170868635098448/9319924_pioneer-sun_1624354686.png!avatar30)Pioneer-Sun|![](https://foruda.gitee.com/avatar/1677166292370951564/9173563_q-alex_1627784508.png!avatar30)Q_Alex|![](https://foruda.gitee.com/avatar/1677052070334379576/5421002_wlf213_1612139033.png!avatar30)wlf|1332987|
|Lionel|winnerself|![](https://foruda.gitee.com/avatar/1676898238064465096/61541_whitedolphin_1578915956.png!avatar30)CrazyAirhead|![](https://foruda.gitee.com/avatar/1677182504887358627/9655223_animal553_1631088642.png!avatar30)她出去赚钱了|![](https://foruda.gitee.com/avatar/1694921912224475489/8702036_dataprince_1694921912.png!avatar30)数据小王子|
|XiaoLin|丿风轻灬云淡|![](https://foruda.gitee.com/avatar/1703832348210958955/7966959_zhang-bo-bo_1703832348.png!avatar30)张博|Freeman Liu|大周|
|欢乐码农|2han9wen71an|shark771|庄佳彬|_FLOW__|
|![](https://foruda.gitee.com/avatar/1677062003782215413/5643954_wei_hua_zhou_1653878946.png!avatar30)weihuazhou|hans|![](https://foruda.gitee.com/avatar/1677162544015233775/9094323_lymph_java_1624796992.png!avatar30)Ikko Eltociear Ashimine|guanmengyuan|dgmico|
|![](https://foruda.gitee.com/avatar/1677173250729036908/9369933_hunnyovo_1650792499.png!avatar30)HunnyOvO|wanggaoquan|![](https://foruda.gitee.com/avatar/1689673717825068611/9856206_aohanaohan_1689673717.png!avatar30)Aohan-Zhang|![](https://foruda.gitee.com/avatar/1691737477130376308/1673084_wang_yong_ji_1691737477.png!avatar30)老吉丶|![](https://foruda.gitee.com/avatar/1684129987239221781/1731138_toycat93_1684129987.png!avatar30)玩具猫|
|meng.liu3|yaochen4|![](https://foruda.gitee.com/avatar/1676959401839738321/1269497_zhy_balck_1578947791.png!avatar30)zhy_black|![](https://foruda.gitee.com/avatar/1676974596171836113/1532463_1395961821_1578953848.png!avatar30)ζั͡ ั͡ ั͡ ั͡Wm|![](https://foruda.gitee.com/avatar/1676894749123859490/2132_hopper_1578914095.jpg!avatar30)陈国正|
|![](https://foruda.gitee.com/avatar/1691805683099463215/8904907_zhuhjay_1691805683.png!avatar30)ZhuHJay|![](https://foruda.gitee.com/avatar/1677071665480088881/6561865_zoufang162_1585144118.png!avatar30)zoufang162|乌鸦笑猪黑|wnp|![](https://foruda.gitee.com/avatar/1676901646505077446/106613_myron_1578917779.png!avatar30)MyronLi|
|norkts|拓宇在思考|张春根|![](https://foruda.gitee.com/avatar/1699925437720003320/5656388_wittplus_1699925437.png!avatar30)witt|![](https://foruda.gitee.com/avatar/1676983827162237415/1697554_xinjump_1654653784.png!avatar30)xinjump|
|![](https://foruda.gitee.com/avatar/1693449200752633970/11209107_jl_0417_1693449200.png!avatar30)疾浪|sppan|![](https://foruda.gitee.com/avatar/1662084101462823713/2079235_djxchi_1662084101.png!avatar30)时间淡忘一切|
|![](https://foruda.gitee.com/avatar/1716893681414311163/61279_fuhai_1716893681.png!avatar30)Michael Yang|![](https://foruda.gitee.com/avatar/1698661375322784129/7984572_suomm_1698661375.png!avatar30)王帅|![](https://foruda.gitee.com/avatar/1683858335519306352/15535_noear_admin_1683858335.png!avatar30)西东|![](https://foruda.gitee.com/avatar/1691636027051962328/11233353_kamo-sama_1691636027.png!avatar30)卡莫sama|丌冰|
|![](https://foruda.gitee.com/avatar/1691044597656855579/7563907_lifejwang11_1691044597.png!avatar30)life|snyk-bot|lhzsdnu|tangxin|![](https://foruda.gitee.com/avatar/1705654661450426134/10777007_font-c_1705654661.png!avatar30)Font_C|
|CloudPlayer|pengpeng|robor.luo|![](https://foruda.gitee.com/avatar/1719543818174909250/7694710_bingbingbing9527_1719543818.png!avatar30)Ice|庄佳彬|
|![](https://foruda.gitee.com/avatar/1695378372753910643/2130728_lemonbx_1695378372.png!avatar30)落羽er|![](https://foruda.gitee.com/avatar/1677050007451380844/5392766_chxlay_1578985930.png!avatar30)Alay|guanmengyuan|chenjh3|![](https://foruda.gitee.com/avatar/1697612161781835336/7870258_wchopper_1697612161.png!avatar30)王超|
|![](https://foruda.gitee.com/avatar/1730251364089836489/2218307_min290_1730251364.png!avatar30)晓华|farukonfly|bf109f|![](https://foruda.gitee.com/avatar/1667638625127647293/1821877_cearnach_1667638624.png!avatar30)ruansheng8|![](https://foruda.gitee.com/avatar/1677007160240647120/2168512_hhggcon_1614250488.png!avatar30)huang__2|
|Jerry|![](https://foruda.gitee.com/avatar/1676906219947351575/342237_tangzc_1629796763.png!avatar30)唐振超|![](https://foruda.gitee.com/avatar/1722841881744628821/10294682_goxiaogle_1722841881.png!avatar30)林钟一六|snow|macy0122|
|![](https://foruda.gitee.com/avatar/1699925437720003320/5656388_wittplus_1699925437.png!avatar30)witt|草语|huangxy|Wudadada|SWQXDBA|
|![](https://foruda.gitee.com/avatar/1694759381586775676/568596_qq925966998_1694759381.png!avatar30)李楠|![](https://foruda.gitee.com/avatar/1677086127012961929/7598208_robot-l_1590219712.png!avatar30)Robot.L|![](https://portrait.gitee.com/static/images/violation.svg)fangzhengjin|lemon|mofan|
|oc|Jerry_Zheng|Aliothmoon|![](https://foruda.gitee.com/avatar/1662530771984927775/11582280_zyinnju_1662530771.png!avatar30)ZhengYi|wujl|
|![](https://foruda.gitee.com/avatar/1676895504036051867/8807_piggsoft_1578914592.jpg!avatar30)piggsoft|![](https://foruda.gitee.com/avatar/1677176420854921626/9461594_cida_1626657356.png!avatar30)cida|![](https://foruda.gitee.com/avatar/1674286432514482953/4807650_fandai_fandaidzsw_1674286432.png!avatar30)赤兮丷|![](https://foruda.gitee.com/avatar/1726218414160215373/10127984_something4arthurw_1726218414.png!avatar30)ArthurWang|![](https://foruda.gitee.com/avatar/1662084101462823713/2079235_djxchi_1662084101.png!avatar30)时间淡忘一切|
|黄沐鸿|loong0306|![](https://foruda.gitee.com/avatar/1676915418782652598/483538_tiankafei_1578925291.png!avatar30)tiankafei|distantSail|wcc1433|
|![](https://foruda.gitee.com/avatar/1710484561956174096/4951941_dh_free_1710484561.png!avatar30)Freedom|zhangyx|codingdragon|jingwei.cao|![](https://foruda.gitee.com/avatar/1676896586274105369/20327_cnscoo_1578915320.jpg!avatar30)Haru|
|![](https://foruda.gitee.com/avatar/1676905453682965545/327218_gm173119755_1648555045.png!avatar30)豌豆粉|沈君锋|![](https://foruda.gitee.com/avatar/1691034002435340221/1920167_qimincow_1691034002.png!avatar30)英雄路|natsufumij|Lionel|
|tan90|张继续|![](https://foruda.gitee.com/avatar/1676898238064465096/61541_whitedolphin_1578915956.png!avatar30)发强-CrazyAirhead|aqnghu|BQ60ziOxlFI0R0|
|font-C|![](https://foruda.gitee.com/avatar/1677053740056224121/5462387_i_tell_you_1618064317.png!avatar30)liibang|wtj|![](https://foruda.gitee.com/avatar/1677017991287160720/3034480_coder-xiaomo_1646647297.png!avatar30)程序员小墨|cainiao3853|
|niann|![](https://foruda.gitee.com/avatar/1702438316292746960/8789215_barql_1702438316.png!avatar30)barql|yangs|lcxw|young|
|cyb|hanjinfeng39|![](https://foruda.gitee.com/avatar/1706089834385383191/56562_kings_1706089834.png!avatar30)kings|Faputa|qixy|
|leizhiyou|黄笑|Leo|![](https://foruda.gitee.com/avatar/1678377314939642686/1604115_handy-git_1678377314.png!avatar30)handy|yuanbaolong|
|![](https://foruda.gitee.com/avatar/1674121508509280199/9288653_saoforestt_1674121508.png!avatar30)Saoforest|![](https://foruda.gitee.com/avatar/1677237805724097193/11485875_bygkn_1660893367.png!avatar30)byg|zhijieqing|PT.|zuojinlong|
|Watcher.Wang|![](https://foruda.gitee.com/avatar/1676978624694631546/1600987_youthdream_1592959590.png!avatar30)锟斤拷|![](https://foruda.gitee.com/avatar/1677111694079591934/8088436_yang-zzu_1604969134.png!avatar30)yang_zzu|宋奇峰|![](https://foruda.gitee.com/avatar/1676895416224286260/8331_chaosforever_1578914555.png!avatar30)锁力|
|meichenhui|shaoerkuai|dream-xi|chenjian835|![](https://foruda.gitee.com/avatar/1676896562075035262/20021_duxlei_1578915302.png!avatar30)duxlei|
|乘黄猿码|看来有点无聊啊|![](https://foruda.gitee.com/avatar/1676902073076876764/112593_caohenghui_1578918069.png!avatar30)Accado|![](https://foruda.gitee.com/avatar/1679885039814030308/5151444_yangbuyi_1679885039.png!avatar30)杨不易呀|XiaoLin|
|![](https://foruda.gitee.com/avatar/1707111957383563814/4877788_shuangtao_1707111957.png!avatar30)涛声依旧|Robot.L|huangaoqin|zhongyong|matthew|
|![](https://foruda.gitee.com/avatar/1706366160973793724/9473873_lingchen_gitee_1706366160.png!avatar30)凌尘|luy|gongzhongqiang|Clownsw|![](https://foruda.gitee.com/avatar/1718845171204865524/5315044_feiyuchuixue_1718845171.png!avatar30)INS6|
|Alex|EafonYoung|![](https://foruda.gitee.com/avatar/1677170868635098448/9319924_pioneer-sun_1624354686.png!avatar30)Pioneer-Sun|![](https://foruda.gitee.com/avatar/1677166292370951564/9173563_q-alex_1627784508.png!avatar30)Q_Alex|Schwi|
|Kming|![](https://foruda.gitee.com/avatar/1677052070334379576/5421002_wlf213_1612139033.png!avatar30)momo|1332987|F3235157|winnerself|
|![](https://foruda.gitee.com/avatar/1677182504887358627/9655223_animal553_1631088642.png!avatar30)她出去赚钱了|![](https://foruda.gitee.com/avatar/1694921912224475489/8702036_dataprince_1694921912.png!avatar30)数据小王子|XiaoLin|RishChen|丿风轻灬云淡|
|生旭鹏|![](https://foruda.gitee.com/avatar/1703832348210958955/7966959_zhang-bo-bo_1703832348.png!avatar30)张博|Freeman Liu|大周|欢乐码农|
|shark771|![](https://foruda.gitee.com/avatar/1676901809020238246/108632_lanrain_1578917874.jpeg!avatar30)lanrain|庄佳彬|_FLOW__|![](https://foruda.gitee.com/avatar/1677062003782215413/5643954_wei_hua_zhou_1653878946.png!avatar30)weihuazhou|
|hans|2han9wen71an|老唐|![](https://foruda.gitee.com/avatar/1677173250729036908/9369933_hunnyovo_1650792499.png!avatar30)HunnyOvO|guanmengyuan|
|dgmico|![](https://foruda.gitee.com/avatar/1677162544015233775/9094323_lymph_java_1624796992.png!avatar30)Ikko Eltociear Ashimine|wanggaoquan|![](https://foruda.gitee.com/avatar/1689673717825068611/9856206_aohanaohan_1689673717.png!avatar30)Aohan-Zhang|![](https://foruda.gitee.com/avatar/1691737477130376308/1673084_wang_yong_ji_1691737477.png!avatar30)老吉丶|
|ToyCat|meng.liu3|yaochen4|![](https://foruda.gitee.com/avatar/1676959401839738321/1269497_zhy_balck_1578947791.png!avatar30)zhy_black|![](https://foruda.gitee.com/avatar/1736233015439986906/113326_qingwei_1736233015.png!avatar30)无名丶小辈|
|jeseee|![](https://foruda.gitee.com/avatar/1676974596171836113/1532463_1395961821_1578953848.png!avatar30)ζั͡ ั͡ ั͡ ั͡Wm|![](https://foruda.gitee.com/avatar/1676894749123859490/2132_hopper_1578914095.jpg!avatar30)陈国正|![](https://foruda.gitee.com/avatar/1691805683099463215/8904907_zhuhjay_1691805683.png!avatar30)ZhuHJay|lin-mt|
|![](https://foruda.gitee.com/avatar/1676910196304190970/395644_yhan219_1578922597.png!avatar30)yhan219|![](https://foruda.gitee.com/avatar/1677071665480088881/6561865_zoufang162_1585144118.png!avatar30)zoufang162|乌鸦笑猪黑|![](https://foruda.gitee.com/avatar/1685523335595388107/5155330_yixiacoco_1685523335.png!avatar30)一夏coco|wnp|
|sheldon-pacvue|![](https://foruda.gitee.com/avatar/1676901646505077446/106613_myron_1578917779.png!avatar30)MyronLi|norkts|StringKe|xiaoxiao|
|![](https://foruda.gitee.com/avatar/1731245648666073735/390404_tycms_1731245648.png!avatar30)拓宇|![](https://foruda.gitee.com/avatar/1676957321934470618/1219829_zuihou111_1578946597.png!avatar30)最后|tanglh|F3235157|lovealiang|
|![](https://foruda.gitee.com/avatar/1699583000606978482/1989048_frank_hl_1699583000.png!avatar30)Frank|张春根|![](https://foruda.gitee.com/avatar/1676944509918531732/1097433_noecs_1578940154.png!avatar30)gswy|![](https://foruda.gitee.com/avatar/1693449200752633970/11209107_jl_0417_1693449200.png!avatar30)疾浪|![](https://foruda.gitee.com/avatar/1676983827162237415/1697554_xinjump_1654653784.png!avatar30)xinjump|
|sppan|

View File

@ -4,7 +4,7 @@
## MyBatis-Flex 微信交流群
![](../../assets/images/wechat-group.png)
![](../../assets/images/wechat-group.jpg)
## MyBatis-Flex QQ 交流群

View File

@ -24,7 +24,7 @@ QueryWrapper<Badge type="tip" text="^亮点" /> 帮助我们极大的减少了 S
## 贡献者
这个项目得以存在,要感谢以下所有做出贡献的人。他们有的是学生,有的 10+ 年开发经验的工程师,也有来**阿里巴巴**、**腾讯**、**科大讯飞**、
这个项目得以存在,要感谢以下所有做出贡献的人。他们有的是学生,有的 10+ 年开发经验的工程师,也有来**阿里巴巴**、**腾讯**、**科大讯飞**、
**网宿科技**、**新东方** 等企业的同学,感谢你们。
>以下贡献者,由程序定时从 [Gitee](https://gitee.com/mybatis-flex/mybatis-flex/contributors?ref=main) 获取:

View File

@ -248,7 +248,7 @@ pom.xml 添加 `annotationProcessorPaths` 配置,
```
dependencies {
...
annotationProcessor 'com.mybatis-flex:mybatis-flex-processor:1.10.7'
annotationProcessor 'com.mybatis-flex:mybatis-flex-processor:1.11.4'
}
```

View File

@ -21,7 +21,7 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-codegen</artifactId>
<version>1.10.7</version>
<version>1.11.4</version>
</dependency>
```
@ -213,8 +213,8 @@ globalConfig.enableEntity()
| 配置 | 描述 | 默认值 |
|----------------------------------|-----------------|---------------------------------|
| setAuthor(String) | 作者 | System.getProperty("user.name") |
| setSince(String) | 自 | 日期yyyy-MM-dd |
| setAuthor(String) | 作者(可填写日期、版本号等,设置为 `""` 则不添加 `@author` | System.getProperty("user.name") |
| setSince(String) | 自(可填写日期、版本号等,设置为 `""` 则不添加 `@since` | `yyyy-MM-dd` 格式的日期 |
| setTableCommentFormat(Function) | 表注释格式化 | 原表注释 |
| setColumnCommentFormat(Function) | 字段注释格式化 | 原字段注释 |
| setEntityPackage(String) | Entity 包注释 | "实体类层Entity软件包。" |
@ -297,13 +297,17 @@ globalConfig.getTemplateConfig()
| 配置 | 描述 | 默认值 |
|----------------------------------------------|---------------------------------------------------|--------------------|
| setEntityWithBaseClassEnable(boolean) | 当开启这个配置后Entity 会生成两个类,自动生成的 getter setter 字段等都在 Base 类里,而开发者可以在 Account.java 中添加自己的业务代码 | false |
| setClassPrefix(String) | Entity 类的前缀 | "" |
| setClassSuffix(String) | Entity 类的后缀 | "" |
| setSuperClass(Class) | Entity 类的父类,可以自定义一些 BaseEntity 类 | null |
| setSuperClassFactory(Function<Table, Class>) | Entity 类的父类工厂,可以用于对特定的 Class 设置父类,而非全部 Entity 的父类 | null |
| setOverwriteEnable(boolean) | 是否覆盖之前生成的文件 | false |
| setEntityBaseOverwriteEnable(boolean) | 生成Base类时是否覆盖之前生成的文件 | false |
| setImplInterfaces(Class[]) | Entity 默认实现的接口 | Serializable.class |
| setWithLombok(boolean) | Entity 是否使用 Lombok 注解 | false |
| lombokNoArgsConstructorEnable(boolean) | 当开启 Lombok 注解且不使用 Active Record 时,是否生成 Entity @NoArgsConstructor 注解 | true |
| lombokAllArgsConstructorEnable(boolean) | 当开启 Lombok 注解且不使用 Active Record 时,是否生成 Entity @AllArgsConstructor 注解 | true |
| setWithSwagger(boolean) | Entity 是否使用 Swagger 注解 | false |
| setSwaggerVersion(EntityConfig.SwaggerVersion) | Swagger 注解版本 | SwaggerVersion.FOX |
| setWithActiveRecord(boolean) | 是否生成 Active Record 模式的 Entity | false |
@ -575,7 +579,7 @@ public class ColumnConfig implements Serializable {
```
## 自定 Entity 的属性类型
## 自定 Entity 的属性类型
**方式 1通过 JdbcTypeMapping**

316
mvnw vendored Normal file
View File

@ -0,0 +1,316 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Maven Start Up Batch script
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# M2_HOME - location of maven2's installed home dir
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /usr/local/etc/mavenrc ] ; then
. /usr/local/etc/mavenrc
fi
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "`uname`" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
export JAVA_HOME="`/usr/libexec/java_home`"
else
export JAVA_HOME="/Library/Java/Home"
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=`java-config --jre-home`
fi
fi
if [ -z "$M2_HOME" ] ; then
## resolve links - $0 may be a link to maven's home
PRG="$0"
# need this for relative symlinks
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
saveddir=`pwd`
M2_HOME=`dirname "$PRG"`/..
# make it fully qualified
M2_HOME=`cd "$M2_HOME" && pwd`
cd "$saveddir"
# echo Using m2 at $M2_HOME
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --unix "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$M2_HOME" ] &&
M2_HOME="`(cd "$M2_HOME"; pwd)`"
[ -n "$JAVA_HOME" ] &&
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="`which javac`"
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=`which readlink`
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
if $darwin ; then
javaHome="`dirname \"$javaExecutable\"`"
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
else
javaExecutable="`readlink -f \"$javaExecutable\"`"
fi
javaHome="`dirname \"$javaExecutable\"`"
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="`\\unset -f command; \\command -v java`"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=`cd "$wdir/.."; pwd`
fi
# end of workaround
done
echo "${basedir}"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
echo "$(tr -s '\n' ' ' < "$1")"
fi
}
BASE_DIR=`find_maven_basedir "$(pwd)"`
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found .mvn/wrapper/maven-wrapper.jar"
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
fi
if [ -n "$MVNW_REPOURL" ]; then
jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
else
jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
fi
while IFS="=" read key value; do
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
esac
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
if [ "$MVNW_VERBOSE" = true ]; then
echo "Downloading from: $jarUrl"
fi
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
if $cygwin; then
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
fi
if command -v wget > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found wget ... using wget"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
else
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
if [ "$MVNW_VERBOSE" = true ]; then
echo "Found curl ... using curl"
fi
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl -o "$wrapperJarPath" "$jarUrl" -f
else
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
fi
else
if [ "$MVNW_VERBOSE" = true ]; then
echo "Falling back to using Java to download"
fi
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaClass=`cygpath --path --windows "$javaClass"`
fi
if [ -e "$javaClass" ]; then
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Compiling MavenWrapperDownloader.java ..."
fi
# Compiling the Java class
("$JAVA_HOME/bin/javac" "$javaClass")
fi
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
# Running the downloader
if [ "$MVNW_VERBOSE" = true ]; then
echo " - Running MavenWrapperDownloader.java ..."
fi
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
if [ "$MVNW_VERBOSE" = true ]; then
echo $MAVEN_PROJECTBASEDIR
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$M2_HOME" ] &&
M2_HOME=`cygpath --path --windows "$M2_HOME"`
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
[ -n "$CLASSPATH" ] &&
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
exec "$JAVACMD" \
$MAVEN_OPTS \
$MAVEN_DEBUG_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.home=${M2_HOME}" \
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

188
mvnw.cmd vendored Normal file
View File

@ -0,0 +1,188 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Maven Start Up Batch script
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM M2_HOME - location of maven2's installed home dir
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %DOWNLOAD_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% ^
%JVM_CONFIG_MAVEN_PROPS% ^
%MAVEN_OPTS% ^
%MAVEN_DEBUG_OPTS% ^
-classpath %WRAPPER_JAR% ^
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%"=="on" pause
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
cmd /C exit /B %ERROR_CODE%

View File

@ -5,10 +5,12 @@
<parent>
<artifactId>parent</artifactId>
<groupId>com.mybatis-flex</groupId>
<version>1.10.7</version>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<name>mybatis-flex-annotation</name>
<artifactId>mybatis-flex-annotation</artifactId>
<packaging>jar</packaging>

View File

@ -5,10 +5,12 @@
<parent>
<artifactId>parent</artifactId>
<groupId>com.mybatis-flex</groupId>
<version>1.10.7</version>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<name>mybatis-flex-codegen</name>
<artifactId>mybatis-flex-codegen</artifactId>
<packaging>jar</packaging>
@ -23,7 +25,7 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-core</artifactId>
<version>1.10.7</version>
<version>${project.version}</version>
<exclusions>
<exclusion>
<groupId>com.mybatis-flex</groupId>
@ -120,7 +122,7 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring</artifactId>
<version>${mybatis-flex.version}</version>
<version>${project.version}</version>
<exclusions>
<exclusion>
<groupId>com.mybatis-flex</groupId>
@ -134,7 +136,7 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-solon-plugin</artifactId>
<version>${mybatis-flex.version}</version>
<version>${project.version}</version>
<exclusions>
<exclusion>
<groupId>com.mybatis-flex</groupId>

View File

@ -60,6 +60,11 @@ public class EntityConfig implements Serializable {
*/
private boolean overwriteEnable;
/**
* 生成Base类时是否覆盖之前生成的文件
*/
private boolean baseOverwriteEnable;
/**
* Entity 默认实现的接口
*/
@ -70,6 +75,16 @@ public class EntityConfig implements Serializable {
*/
private boolean withLombok;
/**
* 当开启 Lombok 注解且不使用 Active Record 是否生成 Entity @NoArgsConstructor 注解
*/
private boolean lombokNoArgsConstructorEnable = true;
/**
* 当开启 Lombok 注解且不使用 Active Record 是否生成 Entity @AllArgsConstructor 注解
*/
private boolean lombokAllArgsConstructorEnable = true;
/**
* Entity 是否使用 Swagger 注解
*/
@ -228,6 +243,21 @@ public class EntityConfig implements Serializable {
return this;
}
/**
* 生成Base类时是否覆盖原有文件
*/
public boolean isBaseOverwriteEnable() {
return baseOverwriteEnable;
}
/**
* 设置生成Base类时是否覆盖原有文件
*/
public EntityConfig setBaseOverwriteEnable(boolean baseOverwriteEnable) {
this.baseOverwriteEnable = baseOverwriteEnable;
return this;
}
/**
* 获取实现接口
*/
@ -258,6 +288,36 @@ public class EntityConfig implements Serializable {
return this;
}
/**
* 当开启 Lombok 注解且不使用 Active Record 是否生成 Entity @NoArgsConstructor 注解
*/
public boolean isLombokNoArgsConstructorEnable() {
return lombokNoArgsConstructorEnable;
}
/**
* 设置当开启 Lombok 注解且不使用 Active Record 是否生成 Entity @NoArgsConstructor 注解
*/
public EntityConfig setLombokNoArgsConstructorEnable(boolean lombokNoArgsConstructorEnable) {
this.lombokNoArgsConstructorEnable = lombokNoArgsConstructorEnable;
return this;
}
/**
* 当开启 Lombok 注解且不使用 Active Record 是否生成 Entity @AllArgsConstructor 注解
*/
public boolean isLombokAllArgsConstructorEnable() {
return lombokAllArgsConstructorEnable;
}
/**
* 设置当开启 Lombok 注解且不使用 Active Record 是否生成 Entity @AllArgsConstructor 注解
*/
public EntityConfig setLombokAllArgsConstructorEnable(boolean lombokAllArgsConstructorEnable) {
this.lombokAllArgsConstructorEnable = lombokAllArgsConstructorEnable;
return this;
}
/**
* 是否启用 Swagger
*/

View File

@ -42,7 +42,7 @@ public class GlobalConfig implements Serializable {
private final FileType fileType;
// === 必须配置 ===
//region === 必须配置 ===
public GlobalConfig() {
this(FileType.JAVA);
@ -52,8 +52,9 @@ public class GlobalConfig implements Serializable {
private final PackageConfig packageConfig;
private final StrategyConfig strategyConfig;
private final TemplateConfig templateConfig;
//endregion === 必须配置 ===
// === 可选配置 ===
//region === 可选配置 ===
private EntityConfig entityConfig;
private MapperConfig mapperConfig;
@ -62,11 +63,13 @@ public class GlobalConfig implements Serializable {
private ControllerConfig controllerConfig;
private TableDefConfig tableDefConfig;
private MapperXmlConfig mapperXmlConfig;
//endregion === 可选配置 ===
// === 其他自定义配置 ===
//region === 其他自定义配置 ===
private Map<String, Object> customConfig = new HashMap<>();
//endregion === 其他自定义配置 ===
// === 是否启用生成 ===
//region === 是否启用生成 ===
private boolean entityGenerateEnable;
private boolean mapperGenerateEnable;
@ -122,8 +125,9 @@ public class GlobalConfig implements Serializable {
}
}
//endregion === 是否启用生成 ===
// === 分类配置 ===
//region === 分类配置 ===
public JavadocConfig getJavadocConfig() {
return javadocConfig;
@ -189,8 +193,9 @@ public class GlobalConfig implements Serializable {
}
return mapperXmlConfig;
}
//endregion === 分类配置 ===
// === 启用配置 ===
//region === 启用配置 ===
public EntityConfig enableEntity() {
entityGenerateEnable = true;
@ -230,8 +235,9 @@ public class GlobalConfig implements Serializable {
public void enablePackageInfo() {
packageInfoGenerateEnable = true;
}
//endregion === 启用配置 ===
// === 禁用配置 ===
//region === 禁用配置 ===
public void disableEntity() {
entityGenerateEnable = false;
@ -264,9 +270,9 @@ public class GlobalConfig implements Serializable {
public void disablePackageInfo() {
packageInfoGenerateEnable = false;
}
//endregion === 禁用配置 ===
// === 自定义配置 ===
//region === 自定义配置 ===
public Object getCustomConfig(String key) {
return customConfig.get(key);
@ -283,7 +289,9 @@ public class GlobalConfig implements Serializable {
public void setCustomConfig(Map<String, Object> customConfig) {
this.customConfig = customConfig;
}
// === 分项配置 ===
//endregion === 自定义配置 ===
//region === 分项配置 ===
/**
* @see JavadocConfig#getAuthor()
@ -888,6 +896,20 @@ public class GlobalConfig implements Serializable {
getEntityConfig().setOverwriteEnable(entityOverwriteEnable);
}
/**
* @see EntityConfig#isBaseOverwriteEnable()
*/
public boolean isEntityBaseOverwriteEnable() {
return getEntityConfig().isBaseOverwriteEnable();
}
/**
* @see EntityConfig#setBaseOverwriteEnable(boolean)
*/
public void setEntityBaseOverwriteEnable(boolean entityBaseOverwriteEnable) {
getEntityConfig().setBaseOverwriteEnable(entityBaseOverwriteEnable);
}
/**
* @see EntityConfig#getClassPrefix()
*/
@ -972,6 +994,34 @@ public class GlobalConfig implements Serializable {
getEntityConfig().setWithLombok(entityWithLombok);
}
/**
* @see EntityConfig#isLombokNoArgsConstructorEnable()
*/
public boolean isEntityLombokNoArgsConstructorEnable() {
return getEntityConfig().isLombokNoArgsConstructorEnable();
}
/**
* @see EntityConfig#setLombokNoArgsConstructorEnable(boolean)
*/
public EntityConfig setEntityLombokNoArgsConstructorEnable(boolean entityLombokNoArgsConstructorEnable) {
return getEntityConfig().setLombokNoArgsConstructorEnable(entityLombokNoArgsConstructorEnable);
}
/**
* @see EntityConfig#isLombokAllArgsConstructorEnable()
*/
public boolean isEntityLombokAllArgsConstructorEnable() {
return getEntityConfig().isLombokAllArgsConstructorEnable();
}
/**
* @see EntityConfig#setLombokAllArgsConstructorEnable(boolean)
*/
public EntityConfig setEntityLombokAllArgsConstructorEnable(boolean entityLombokAllArgsConstructorEnable) {
return getEntityConfig().setLombokAllArgsConstructorEnable(entityLombokAllArgsConstructorEnable);
}
/**
* @see EntityConfig#isWithSwagger()
*/
@ -1035,6 +1085,20 @@ public class GlobalConfig implements Serializable {
getEntityConfig().setJdkVersion(jdkVersion);
}
/**
* @see EntityConfig#isWithBaseClassEnable()
*/
public boolean isEntityWithBaseClassEnable() {
return getEntityConfig().isWithBaseClassEnable();
}
/**
* @see EntityConfig#setWithBaseClassEnable(boolean)
*/
public void setEntityWithBaseClassEnable(boolean withBaseClassEnable) {
getEntityConfig().setWithBaseClassEnable(withBaseClassEnable);
}
public boolean isMapperGenerateEnable() {
return mapperGenerateEnable;
}
@ -1510,5 +1574,5 @@ public class GlobalConfig implements Serializable {
public void setPackageInfoGenerateEnable(boolean packageInfoGenerateEnable) {
this.packageInfoGenerateEnable = packageInfoGenerateEnable;
}
//endregion === 分项配置 ===
}

View File

@ -93,6 +93,10 @@ public class Column {
this.property = buildPropertyName();
}
public void setProperty(String property) {
this.property = property;
}
public String getProperty() {
return property;
}
@ -110,12 +114,58 @@ public class Column {
if (!columnConfig.getPropertyType().contains(".")) {
return columnConfig.getPropertyType();
}
return StringUtil.substringAfterLast(columnConfig.getPropertyType(), ".");
return convertToSimpleGenericType(columnConfig.getPropertyType());
} else {
return StringUtil.substringAfterLast(propertyType, ".");
return convertToSimpleGenericType(propertyType);
}
}
private String convertToSimpleGenericType(String fullType) {
if (fullType == null || fullType.isEmpty()) {
return fullType;
}
// 如果不包含泛型直接处理
if (!fullType.contains("<") && !fullType.endsWith(">")) {
return StringUtil.substringAfterLast(fullType, ".");
}
StringBuilder result = new StringBuilder();
int i = 0;
while (i < fullType.length()) {
char c = fullType.charAt(i);
if (c == '<' || c == ',' || c == '>') {
result.append(c);
if (c == ',' || c == '<') {
// 跳过空格
while (i + 1 < fullType.length() && fullType.charAt(i + 1) == ' ') {
i++;
result.append(' ');
}
}
i++;
} else {
// 提取类型名称
int start = i;
while (i < fullType.length() && fullType.charAt(i) != '<' &&
fullType.charAt(i) != ',' && fullType.charAt(i) != '>') {
i++;
}
String typeName = fullType.substring(start, i).trim();
if (!typeName.isEmpty()) {
// 转换为简单类名
String simpleType = StringUtil.substringAfterLast(typeName, ".");
result.append(simpleType);
}
}
}
return result.toString();
}
public void setPropertyType(String propertyType) {
this.propertyType = propertyType;
}
@ -197,8 +247,8 @@ public class Column {
return "";
} else {
return "/**\n" +
" * " + comment + "\n" +
" */";
" * " + comment + "\n" +
" */";
}
}
@ -212,16 +262,41 @@ public class Column {
*/
private static void addImportClass(Set<String> importClasses, String importClass) {
importClass = importClass.trim();
extractAllTypes(importClasses, importClass);
}
// java.util.List<String> >>>>> java.util.List
if (importClass.contains("<") && importClass.endsWith(">")) {
importClass = importClass.substring(0, importClass.indexOf("<"));
private static void extractAllTypes(Set<String> importClasses, String typeString) {
if (typeString == null || typeString.isEmpty()) {
return;
}
// 不包含.则认为是原始类型不需要import
// lang 包不需要显式导入
if (importClass.contains(".") && !importClass.startsWith("java.lang.")) {
importClasses.add(importClass);
int i = 0;
while (i < typeString.length()) {
// 跳过非字母字符
while (i < typeString.length() && !Character.isLetter(typeString.charAt(i))
&& typeString.charAt(i) != '_') {
i++;
}
if (i >= typeString.length()) {
break;
}
// 提取类名
int start = i;
while (i < typeString.length() &&
(Character.isLetterOrDigit(typeString.charAt(i)) ||
typeString.charAt(i) == '_' ||
typeString.charAt(i) == '.')) {
i++;
}
String className = typeString.substring(start, i);
// 检查是否包含包路径且不是java.lang包
if (className.contains(".") && !className.startsWith("java.lang.")) {
importClasses.add(className);
}
}
}
@ -234,7 +309,7 @@ public class Column {
public String buildAnnotations() {
StringBuilder annotations = new StringBuilder();
//@Id 的注解
// @Id 的注解
if (isPrimaryKey || columnConfig.isPrimaryKey()) {
annotations.append("@Id(");
@ -259,14 +334,13 @@ public class Column {
needComma = true;
}
if (entityConfig != null && entityConfig.isColumnCommentEnable() && StringUtil.hasText(comment)) {
addComma(annotations, needComma);
annotations.append("comment = \"")
.append(this.comment.replace("\n", "")
.replace("\"", "\\\"")
.trim())
.append("\"");
.append(this.comment.replace("\n", "")
.replace("\"", "\\\"")
.trim())
.append("\"");
}
if (annotations.length() == 4) {
@ -281,25 +355,25 @@ public class Column {
}
boolean needGenColumnAnnotation = (entityConfig != null && entityConfig.isAlwaysGenColumnAnnotation())
|| !name.equalsIgnoreCase(StringUtil.camelToUnderline(property))
|| (entityConfig != null && entityConfig.isColumnCommentEnable() && StringUtil.hasText(this.comment) && annotations.length() == 0);
|| !name.equalsIgnoreCase(StringUtil.camelToUnderline(property))
|| (entityConfig != null && entityConfig.isColumnCommentEnable() && StringUtil.hasText(this.comment)
&& annotations.length() == 0);
StringBuilder columnAnnotation = new StringBuilder("@Column(");
//@Column 注解
// @Column 注解
if (columnConfig.getOnInsertValue() != null
|| columnConfig.getOnUpdateValue() != null
|| columnConfig.getLarge() != null
|| columnConfig.getLogicDelete() != null
|| columnConfig.getVersion() != null
|| columnConfig.getJdbcType() != null
|| columnConfig.getTypeHandler() != null
|| columnConfig.getTenantId() != null
|| needGenColumnAnnotation
) {
|| columnConfig.getOnUpdateValue() != null
|| columnConfig.getLarge() != null
|| columnConfig.getLogicDelete() != null
|| columnConfig.getVersion() != null
|| columnConfig.getJdbcType() != null
|| columnConfig.getTypeHandler() != null
|| columnConfig.getTenantId() != null
|| needGenColumnAnnotation) {
boolean needComma = false;
if (entityConfig != null && entityConfig.isAlwaysGenColumnAnnotation()
|| !name.equalsIgnoreCase(StringUtil.camelToUnderline(property))) {
|| !name.equalsIgnoreCase(StringUtil.camelToUnderline(property))) {
columnAnnotation.append("value = \"").append(name).append("\"");
needComma = true;
}
@ -336,7 +410,8 @@ public class Column {
}
if (columnConfig.getTypeHandler() != null) {
addComma(columnAnnotation, needComma);
columnAnnotation.append("typeHandler = ").append(columnConfig.getTypeHandler().getSimpleName()).append(".class");
columnAnnotation.append("typeHandler = ").append(columnConfig.getTypeHandler().getSimpleName())
.append(".class");
needComma = true;
}
if (Boolean.TRUE.equals(columnConfig.getTenantId())) {
@ -347,10 +422,10 @@ public class Column {
if (entityConfig != null && entityConfig.isColumnCommentEnable() && StringUtil.hasText(comment)) {
addComma(columnAnnotation, needComma);
columnAnnotation.append("comment = \"")
.append(this.comment.replace("\n", "")
.replace("\"", "\\\"")
.trim())
.append("\"");
.append(this.comment.replace("\n", "")
.replace("\"", "\\\"")
.trim())
.append("\"");
}
columnAnnotation.append(")");
@ -418,19 +493,19 @@ public class Column {
}
boolean needGenColumnAnnotation = (entityConfig != null && entityConfig.isAlwaysGenColumnAnnotation())
|| !name.equalsIgnoreCase(StringUtil.camelToUnderline(property))
|| (entityConfig != null && entityConfig.isColumnCommentEnable() && StringUtil.hasText(this.comment));
|| !name.equalsIgnoreCase(StringUtil.camelToUnderline(property))
|| (entityConfig != null && entityConfig.isColumnCommentEnable()
&& StringUtil.hasText(this.comment));
if (columnConfig.getOnInsertValue() != null
|| columnConfig.getOnUpdateValue() != null
|| columnConfig.getLarge() != null
|| columnConfig.getLogicDelete() != null
|| columnConfig.getVersion() != null
|| columnConfig.getJdbcType() != null
|| columnConfig.getTypeHandler() != null
|| Boolean.TRUE.equals(columnConfig.getTenantId())
|| needGenColumnAnnotation
) {
|| columnConfig.getOnUpdateValue() != null
|| columnConfig.getLarge() != null
|| columnConfig.getLogicDelete() != null
|| columnConfig.getVersion() != null
|| columnConfig.getJdbcType() != null
|| columnConfig.getTypeHandler() != null
|| Boolean.TRUE.equals(columnConfig.getTenantId())
|| needGenColumnAnnotation) {
addImportClass(importClasses, com.mybatisflex.annotation.Column.class.getName());
}
}
@ -450,11 +525,11 @@ public class Column {
@Override
public String toString() {
return "Column{" +
"name='" + name + '\'' +
", className='" + propertyType + '\'' +
", remarks='" + comment + '\'' +
", isAutoIncrement=" + isAutoIncrement +
'}';
"name='" + name + '\'' +
", className='" + propertyType + '\'' +
", remarks='" + comment + '\'' +
", isAutoIncrement=" + isAutoIncrement +
'}';
}
}

View File

@ -83,7 +83,7 @@ public class EntityGenerator implements IGenerator {
table.getColumns().removeIf(column -> globalConfig.getStrategyConfig().getIgnoreColumns().contains(column.getName().toLowerCase()));
}
Map<String, Object> params = new HashMap<>(6);
Map<String, Object> params = new HashMap<>(7);
params.put("table", table);
params.put("entityPackageName", packageConfig.getEntityPackage());
params.put("entityConfig", entityConfig);
@ -132,20 +132,22 @@ public class EntityGenerator implements IGenerator {
String sourceDir = StringUtil.hasText(entityConfig.getSourceDir()) ? entityConfig.getSourceDir() : packageConfig.getSourceDir();
String baseEntityPackagePath = packageConfig.getEntityPackage().replace(".", "/");
baseEntityPackagePath = StringUtil.hasText(entityConfig.getWithBasePackage()) ? entityConfig.getWithBasePackage().replace(".", "")
baseEntityPackagePath = StringUtil.hasText(entityConfig.getWithBasePackage()) ? entityConfig.getWithBasePackage().replace(".", "/")
: baseEntityPackagePath + "/base";
String baseEntityClassName = table.buildEntityClassName() + entityConfig.getWithBaseClassSuffix();
File baseEntityJavaFile = new File(sourceDir, baseEntityPackagePath + "/" + baseEntityClassName + globalConfig.getFileType());
if (baseEntityJavaFile.exists() && !entityConfig.isBaseOverwriteEnable()) {
return;
}
// 排除忽略列
if (globalConfig.getStrategyConfig().getIgnoreColumns() != null) {
table.getColumns().removeIf(column -> globalConfig.getStrategyConfig().getIgnoreColumns().contains(column.getName().toLowerCase()));
}
Map<String, Object> params = new HashMap<>(6);
Map<String, Object> params = new HashMap<>();
params.put("table", table);
params.put("entityPackageName", baseEntityPackagePath.replace("/", "."));
params.put("entityClassName", baseEntityClassName);

View File

@ -26,8 +26,12 @@ import java.util.List;
/**
* #(tableComment) 控制层。
*
#if(javadocConfig.getAuthor())
* @author #(javadocConfig.getAuthor())
#end
#if(javadocConfig.getSince())
* @since #(javadocConfig.getSince())
#end
*/
@Controller
#if(withSwagger && swaggerVersion.getName() == "FOX")

View File

@ -39,8 +39,12 @@ import java.util.List;
/**
* #(tableComment) 控制层。
*
#if(javadocConfig.getAuthor())
* @author #(javadocConfig.getAuthor())
#end
#if(javadocConfig.getSince())
* @since #(javadocConfig.getSince())
#end
*/
#if(controllerConfig.restStyle)
@RestController
@ -60,10 +64,10 @@ public class #(table.buildControllerClassName()) #if(controllerConfig.superClass
private #(table.buildServiceClassName()) #(serviceVarName);
/**
* 添加#(tableComment)。
* 保存#(tableComment)。
*
* @param #(entityVarName) #(tableComment)
* @return {@code true} 添加成功,{@code false} 添加失败
* @return {@code true} 保存成功,{@code false} 保存失败
*/
@PostMapping("save")
#if(withSwagger && swaggerVersion.getName() == "FOX")
@ -84,10 +88,10 @@ public class #(table.buildControllerClassName()) #if(controllerConfig.superClass
*/
@DeleteMapping("remove/{id}")
#if(withSwagger && swaggerVersion.getName() == "FOX")
@ApiOperation("根据主键#(tableComment)")
@ApiOperation("根据主键删除#(tableComment)")
#end
#if(withSwagger && swaggerVersion.getName() == "DOC")
@Operation(description="根据主键#(tableComment)")
@Operation(description="根据主键删除#(tableComment)")
#end
public boolean remove(@PathVariable #if(withSwagger && swaggerVersion.getName() == "FOX")@ApiParam("#(tableComment)主键") #end #if(withSwagger && swaggerVersion.getName() == "DOC")@Parameter(description="#(tableComment)主键") #end #(primaryKeyType) id) {
return #(serviceVarName).removeById(id);
@ -127,7 +131,7 @@ public class #(table.buildControllerClassName()) #if(controllerConfig.superClass
}
/**
* 根据#(tableComment)主键获取详细信息
* 根据主键获取#(tableComment)。
*
* @param id #(tableComment)主键
* @return #(tableComment)详情

View File

@ -18,12 +18,17 @@ import io.swagger.annotations.ApiModelProperty
#if(withSwagger && swaggerVersion.getName() == "DOC")
import io.swagger.v3.oas.annotations.media.Schema
#end
#if(!isBase)
/**
* #(table.getComment()) 实体类。
*
#if(javadocConfig.getAuthor())
* @author #(javadocConfig.getAuthor())
#end
#if(javadocConfig.getSince())
* @since #(javadocConfig.getSince())
#end
*/
#(table.buildTableAnnotation())
#end

View File

@ -30,10 +30,14 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
#else
#if(entityConfig.isLombokAllArgsConstructorEnable())
import lombok.AllArgsConstructor;
#end
import lombok.Builder;
import lombok.Data;
#if(entityConfig.isLombokNoArgsConstructorEnable())
import lombok.NoArgsConstructor;
#end
#if(entityConfig.getSuperClass(table))
import lombok.EqualsAndHashCode;
#end
@ -43,8 +47,12 @@ import lombok.EqualsAndHashCode;
/**
* #(table.getComment()) 实体类。
*
#if(javadocConfig.getAuthor())
* @author #(javadocConfig.getAuthor())
#end
#if(javadocConfig.getSince())
* @since #(javadocConfig.getSince())
#end
*/
#if(withLombok)
#if(withActiveRecord)
@ -54,8 +62,12 @@ import lombok.EqualsAndHashCode;
#else
@Data
@Builder
#if(entityConfig.isLombokNoArgsConstructorEnable())
@NoArgsConstructor
#end
#if(entityConfig.isLombokAllArgsConstructorEnable())
@AllArgsConstructor
#end
#if(entityConfig.getSuperClass(table))
@EqualsAndHashCode(callSuper = true)
#end

View File

@ -19,11 +19,16 @@ import io.swagger.annotations.ApiModelProperty
#if(withSwagger && swaggerVersion.getName() == "DOC")
import io.swagger.v3.oas.annotations.media.Schema
#end
/**
* #(table.getComment()) 实体类。
*
#if(javadocConfig.getAuthor())
* @author #(javadocConfig.getAuthor())
#end
#if(javadocConfig.getSince())
* @since #(javadocConfig.getSince())
#end
*/
#if(withSwagger && swaggerVersion.getName() == "FOX")
@ApiModel("#(table.getComment())")

View File

@ -26,21 +26,30 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
#else
#if(entityConfig.isLombokAllArgsConstructorEnable())
import lombok.AllArgsConstructor;
#end
import lombok.Builder;
import lombok.Data;
#if(entityConfig.isLombokNoArgsConstructorEnable())
import lombok.NoArgsConstructor;
#end
#end
#end
#if(jdkVersion >= 14)
import java.io.Serial;
#end
#if(!isBase)
/**
* #(table.getComment()) 实体类。
*
#if(javadocConfig.getAuthor())
* @author #(javadocConfig.getAuthor())
#end
#if(javadocConfig.getSince())
* @since #(javadocConfig.getSince())
#end
*/
#end
#if(withLombok)
@ -51,17 +60,20 @@ import java.io.Serial;
#else
@Data
@Builder
#if(entityConfig.isLombokNoArgsConstructorEnable())
@NoArgsConstructor
#end
#if(entityConfig.isLombokAllArgsConstructorEnable())
@AllArgsConstructor
#end
#end
#end
#if(withSwagger && swaggerVersion.getName() == "FOX")
@ApiModel("#(table.getComment())")
#end
#if(withSwagger && swaggerVersion.getName() == "DOC")
@Schema(description = "#(table.getComment())")
#end
#if(!isBase)#(table.buildTableAnnotation())#end
public class #(entityClassName) extends #(baseClassName) {
}

View File

@ -9,8 +9,12 @@ import #(packageConfig.entityPackage).#(table.buildEntityClassName());
/**
* #(table.getComment()) 映射层。
*
#if(javadocConfig.getAuthor())
* @author #(javadocConfig.getAuthor())
#end
#if(javadocConfig.getSince())
* @since #(javadocConfig.getSince())
#end
*/
#if(mapperConfig.isMapperAnnotation())
@Mapper

View File

@ -9,8 +9,12 @@ import #(packageConfig.entityPackage).#(table.buildEntityClassName());
/**
* #(table.getComment()) 映射层。
*
#if(javadocConfig.getAuthor())
* @author #(javadocConfig.getAuthor())
#end
#if(javadocConfig.getSince())
* @since #(javadocConfig.getSince())
#end
*/
#if(mapperConfig.isMapperAnnotation())
@Mapper

View File

@ -1,7 +1,11 @@
/**
* #(packageComment)
*
#if(javadocConfig.getAuthor())
* @author #(javadocConfig.getAuthor())
#end
#if(javadocConfig.getSince())
* @since #(javadocConfig.getSince())
#end
*/
package #(packageName);

View File

@ -6,7 +6,11 @@ import #(packageConfig.entityPackage).#(table.buildEntityClassName());
/**
* #(table.getComment()) 服务层。
*
#if(javadocConfig.getAuthor())
* @author #(javadocConfig.getAuthor())
#end
#if(javadocConfig.getSince())
* @since #(javadocConfig.getSince())
#end
*/
interface #(table.buildServiceClassName()) : #(serviceConfig.buildSuperClassName())<#(table.buildEntityClassName())> {}

View File

@ -6,8 +6,12 @@ import #(packageConfig.entityPackage).#(table.buildEntityClassName());
/**
* #(table.getComment()) 服务层。
*
#if(javadocConfig.getAuthor())
* @author #(javadocConfig.getAuthor())
#end
#if(javadocConfig.getSince())
* @since #(javadocConfig.getSince())
#end
*/
public interface #(table.buildServiceClassName()) extends #(serviceConfig.buildSuperClassName())<#(table.buildEntityClassName())> {

View File

@ -11,8 +11,12 @@ import org.noear.solon.annotation.Component;
/**
* #(table.getComment()) 服务层实现。
*
#if(javadocConfig.getAuthor())
* @author #(javadocConfig.getAuthor())
#end
#if(javadocConfig.getSince())
* @since #(javadocConfig.getSince())
#end
*/
@Component
public class #(table.buildServiceImplClassName()) extends ServiceImpl<#(table.buildMapperClassName()), #(table.buildEntityClassName())> #if(table.getGlobalConfig().isServiceGenerateEnable()) implements #(table.buildServiceClassName()) #end{

View File

@ -11,8 +11,12 @@ import org.springframework.stereotype.Service;
/**
* #(table.getComment()) 服务层实现。
*
#if(javadocConfig.getAuthor())
* @author #(javadocConfig.getAuthor())
#end
#if(javadocConfig.getSince())
* @since #(javadocConfig.getSince())
#end
*/
@Service
class #(table.buildServiceImplClassName()) : #(serviceImplConfig.buildSuperClassName())<#(table.buildMapperClassName()), #(table.buildEntityClassName())>()#if(table.getGlobalConfig().isServiceGenerateEnable()), #(table.buildServiceClassName())#end {}

View File

@ -25,8 +25,12 @@ import java.util.List;
/**
* #(table.getComment()) 服务层实现。
*
#if(javadocConfig.getAuthor())
* @author #(javadocConfig.getAuthor())
#end
#if(javadocConfig.getSince())
* @since #(javadocConfig.getSince())
#end
*/
@Service
#if(isCacheExample)

View File

@ -13,8 +13,12 @@ import java.io.Serial;
/**
* #(table.getComment()) 表定义层。
*
#if(javadocConfig.getAuthor())
* @author #(javadocConfig.getAuthor())
#end
#if(javadocConfig.getSince())
* @since #(javadocConfig.getSince())
#end
*/
public class #(tableDefClassName) extends TableDef {

View File

@ -5,10 +5,12 @@
<parent>
<artifactId>parent</artifactId>
<groupId>com.mybatis-flex</groupId>
<version>1.10.7</version>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<name>mybatis-flex-core</name>
<artifactId>mybatis-flex-core</artifactId>
<packaging>jar</packaging>
@ -23,13 +25,13 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-annotation</artifactId>
<version>${mybatis-flex.version}</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>${mybatis-flex.version}</version>
<version>${project.version}</version>
</dependency>
<dependency>
@ -98,13 +100,6 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-annotation</artifactId>
<version>1.10.7</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View File

@ -74,7 +74,7 @@ public interface BaseMapper<T> {
*/
int DEFAULT_BATCH_SIZE = 1000;
// === insert ===
//region === insert ===
/**
* 插入实体类数据不忽略 {@code null}
@ -253,8 +253,9 @@ public interface BaseMapper<T> {
return update(entity, ignoreNulls);
}
}
//endregion === insert ===
// === delete ===
//region === delete ===
/**
* 根据实体主键来删除数据
@ -343,8 +344,9 @@ public interface BaseMapper<T> {
*/
@DeleteProvider(type = EntitySqlProvider.class, method = "deleteByQuery")
int deleteByQuery(@Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
//endregion === delete ===
// === update ===
//region === update ===
/**
* 根据主键来更新数据若实体类属性数据为 {@code null}该属性不会更新到数据库
@ -439,9 +441,9 @@ public interface BaseMapper<T> {
*/
@UpdateProvider(type = EntitySqlProvider.class, method = "updateByQuery")
int updateByQuery(@Param(FlexConsts.ENTITY) T entity, @Param(FlexConsts.IGNORE_NULLS) boolean ignoreNulls, @Param(FlexConsts.QUERY) QueryWrapper queryWrapper);
//endregion === update ===
// === select ===
//region === update ===
/**
* 根据实体主键查询数据
@ -1264,5 +1266,5 @@ public interface BaseMapper<T> {
}
return page;
}
//endregion === update ===
}

View File

@ -27,7 +27,7 @@ public class FlexConsts {
}
public static final String NAME = "MyBatis-Flex";
public static final String VERSION = "1.10.7";
public static final String VERSION = "1.11.4";
public static final String SQL = "$$sql";

View File

@ -20,6 +20,7 @@ import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.Listener;
import com.mybatisflex.annotation.SetListener;
import com.mybatisflex.annotation.UpdateListener;
import com.mybatisflex.core.datasource.DataSourceMissingHandler;
import com.mybatisflex.core.datasource.FlexDataSource;
import com.mybatisflex.core.dialect.DbType;
import com.mybatisflex.core.exception.FlexAssert;
@ -110,11 +111,21 @@ public class FlexGlobalConfig {
*/
private String versionColumn;
/**
* 全局忽略 @Table 中配置的 schema
*/
private boolean ignoreSchema = false;
/**
* 未匹配列处理器
*/
private UnMappedColumnHandler unMappedColumnHandler;
/**
* 数据源缺失处理器
*/
private DataSourceMissingHandler dataSourceMissingHandler;
public boolean isPrintBanner() {
return printBanner;
}
@ -329,6 +340,14 @@ public class FlexGlobalConfig {
this.versionColumn = versionColumn;
}
public boolean isIgnoreSchema() {
return ignoreSchema;
}
public void setIgnoreSchema(boolean ignoreSchema) {
this.ignoreSchema = ignoreSchema;
}
public UnMappedColumnHandler getUnMappedColumnHandler() {
return unMappedColumnHandler;
}
@ -349,6 +368,21 @@ public class FlexGlobalConfig {
FlexGlobalConfig.globalConfigs = globalConfigs;
}
/**
* 获取数据源缺失处理器
* @return DataSourceMissingHandler 数据源缺失处理器实例用于自定义处理逻辑记录日志抛出异常或提供默认数据源
*/
public DataSourceMissingHandler getDataSourceMissingHandler() {
return dataSourceMissingHandler;
}
/**
* 设置获取数据源缺失处理器
* @param dataSourceMissingHandler 数据源缺失处理器实例用于自定义处理逻辑记录日志抛出异常或提供默认数据源
*/
public void setDataSourceMissingHandler(final DataSourceMissingHandler dataSourceMissingHandler) {
this.dataSourceMissingHandler = dataSourceMissingHandler;
}
/**
* 对应的是 注解 {@link com.mybatisflex.annotation.Id} 的配置
@ -386,7 +420,7 @@ public class FlexGlobalConfig {
}
/////static factory methods/////
/// //static factory methods/////
private static ConcurrentHashMap<String, FlexGlobalConfig> globalConfigs = new ConcurrentHashMap<>();
private static FlexGlobalConfig defaultConfig = new FlexGlobalConfig();

View File

@ -97,11 +97,12 @@ public class AuditManager {
}
@SuppressWarnings("rawtypes")
public static <T> T startAudit(AuditRunnable<T> supplier, Statement statement, BoundSql boundSql, Configuration configuration) throws SQLException {
public static <T> T startAudit(AuditRunnable<T> supplier, String stmtId, Statement statement, BoundSql boundSql, Configuration configuration) throws SQLException {
AuditMessage auditMessage = messageFactory.create();
if (auditMessage == null) {
return supplier.execute();
}
auditMessage.setStmtId(stmtId);
String key = DataSourceKey.get();
if (StringUtil.noText(key)) {
key = FlexGlobalConfig.getDefaultConfig()

View File

@ -95,6 +95,11 @@ public class AuditMessage implements Serializable {
*/
private long elapsedTime;
/**
* MappedStatement ID
*/
private String stmtId;
/**
* 数据库名称
*/
@ -270,6 +275,14 @@ public class AuditMessage implements Serializable {
metas.put(key, value);
}
public String getStmtId() {
return stmtId;
}
public void setStmtId(String stmtId) {
this.stmtId = stmtId;
}
public String getDsName() {
return dsName;
}
@ -293,6 +306,7 @@ public class AuditMessage implements Serializable {
", queryCount=" + queryCount +
", queryTime=" + queryTime +
", elapsedTime=" + elapsedTime +
", stmtId=" + stmtId +
", dsName=" + dsName +
", metas=" + metas +
'}';

View File

@ -144,6 +144,9 @@ public class FuncName {
public static final String WEEKOFYEAR = "WEEKOFYEAR";
public static final String YEAR = "YEAR";
public static final String GROUP_CONCAT = "GROUP_CONCAT";
public static final String STRING_AGG = "STRING_AGG";
public static final String LISTAGG = "LISTAGG";
private FuncName() {
}

View File

@ -56,6 +56,7 @@ public final class SqlConsts {
public static final String THEN = " THEN ";
public static final String ELSE = " ELSE ";
public static final String FROM = " FROM ";
public static final String DUAL = "DUAL";
public static final String WHERE = " WHERE ";
public static final String SELECT = "SELECT ";
public static final String VALUES = " VALUES ";

View File

@ -34,9 +34,11 @@ public class DataSourceKey {
public static void use(String dataSourceKey) {
Deque<String> deque = lookup.get();
if (deque != null) {
deque.push(dataSourceKey);
if (deque == null) {
deque = new ArrayDeque<>(1);
lookup.set(deque);
}
deque.push(dataSourceKey);
}
public static String get() {
@ -95,31 +97,4 @@ public class DataSourceKey {
return shardingDsKey != null ? shardingDsKey : dataSource;
}
// === For Removal ===
@Deprecated
public static String getByManual() {
throw new UnsupportedOperationException("使用 DataSource.get() 代替。");
}
@Deprecated
public static String getByAnnotation() {
throw new UnsupportedOperationException("使用 DataSource.get() 代替。");
}
@Deprecated
public static void useWithAnnotation(String dataSourceKey) {
throw new UnsupportedOperationException("使用 DataSource.use(String) 代替。");
}
@Deprecated
public static void setAnnotationKeyThreadLocal(ThreadLocal<String> annotationKeyThreadLocal) {
throw new UnsupportedOperationException("使用 DataSource.setThreadLocal(ThreadLocal<Deque<String>>) 代替。");
}
@Deprecated
public static void setManualKeyThreadLocal(ThreadLocal<String> manualKeyThreadLocal) {
throw new UnsupportedOperationException("使用 DataSource.setThreadLocal(ThreadLocal<Deque<String>>) 代替。");
}
}

View File

@ -0,0 +1,34 @@
package com.mybatisflex.core.datasource;
import javax.sql.DataSource;
import java.util.Map;
/**
* 数据源缺失处理器接口当尝试获取指定数据源但不存在时通过此接口进行动态处理
*
* <p>
* 该接口被设计为函数式接口可通过Lambda表达式或方法引用实现用于在运行时动态处理缺失的数据源<br/>
* 常见应用场景<br/>
* - 多租户系统中根据租户ID动态创建并缓存数据源<br/>
* - 数据源缺失时的主动初始化
* </p>
*/
@FunctionalInterface
public interface DataSourceMissingHandler {
/**
* 处理缺失数据源的核心方法
*
* @param dataSourceKey 当前请求的数据源键标识符通常用于识别目标数据源
* @param dataSourceMap 当前已存在的数据源集合key: 数据源键value: 数据源实例
* @return 处理后的新数据源集合通常应包含原有数据源及新增处理的数据源
* @implSpec 实现类应通过此方法实现<br/>
* 1. 根据dataSourceKey识别需要补充的数据源<br/>
* 2. 创建/配置新的DataSource实例<br/>
* 3. 将新数据源添加到dataSourceMap中<br/>
* 4. 返回更新后的数据源集合<br/>
* 5. 如返回 null Map 为空后续会抛出异常<br/>
* @example 示例场景
* 当请求"tenant_123"数据源不存在时在此方法中创建对应数据源并放入返回的Map
*/
Map<String, DataSource> handle(String dataSourceKey, Map<String, DataSource> dataSourceMap);
}

View File

@ -15,6 +15,7 @@
*/
package com.mybatisflex.core.datasource;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.dialect.DbType;
import com.mybatisflex.core.dialect.DbTypeUtil;
import com.mybatisflex.core.transaction.TransactionContext;
@ -30,7 +31,12 @@ import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ThreadLocalRandom;
/**
@ -53,16 +59,23 @@ public class FlexDataSource extends AbstractDataSource {
}
public FlexDataSource(String dataSourceKey, DataSource dataSource, boolean needDecryptDataSource) {
this(dataSourceKey, dataSource, DbTypeUtil.getDbType(dataSource), needDecryptDataSource);
}
public FlexDataSource(String dataSourceKey, DataSource dataSource, DbType dbType, boolean needDecryptDataSource) {
if (needDecryptDataSource) {
DataSourceManager.decryptDataSource(dataSource);
}
// 处理dbType
dbType = Optional.ofNullable(dbType).orElseGet(() -> DbTypeUtil.getDbType(dataSource));
this.defaultDataSourceKey = dataSourceKey;
this.defaultDataSource = dataSource;
this.defaultDbType = DbTypeUtil.getDbType(dataSource);
this.defaultDbType = dbType;
dataSourceMap.put(dataSourceKey, dataSource);
dbTypeHashMap.put(dataSourceKey, defaultDbType);
dbTypeHashMap.put(dataSourceKey, dbType);
}
/**
@ -71,26 +84,35 @@ public class FlexDataSource extends AbstractDataSource {
public void setDefaultDataSource(String dataSourceKey) {
DataSource ds = dataSourceMap.get(dataSourceKey);
if (ds != null) {
this.defaultDataSourceKey = dataSourceKey;
this.defaultDataSource = ds;
this.defaultDbType = DbTypeUtil.getDbType(ds);
} else {
if (Objects.isNull(ds)) {
throw new IllegalStateException("DataSource not found by key: \"" + dataSourceKey + "\"");
}
// 优先取缓存否则根据数据源返回数据库类型
DbType dbType = Optional.ofNullable(dbTypeHashMap.get(dataSourceKey)).orElseGet(() -> DbTypeUtil.getDbType(ds));
this.defaultDataSourceKey = dataSourceKey;
this.defaultDataSource = ds;
this.defaultDbType = dbType;
}
public void addDataSource(String dataSourceKey, DataSource dataSource) {
addDataSource(dataSourceKey, dataSource, true);
}
public void addDataSource(String dataSourceKey, DataSource dataSource, boolean needDecryptDataSource) {
addDataSource(dataSourceKey, dataSource, DbTypeUtil.getDbType(dataSource), needDecryptDataSource);
}
public void addDataSource(String dataSourceKey, DataSource dataSource, DbType dbType, boolean needDecryptDataSource) {
if (needDecryptDataSource) {
DataSourceManager.decryptDataSource(dataSource);
}
dbType = Optional.ofNullable(dbType).orElseGet(() -> DbTypeUtil.getDbType(dataSource));
dataSourceMap.put(dataSourceKey, dataSource);
dbTypeHashMap.put(dataSourceKey, DbTypeUtil.getDbType(dataSource));
dbTypeHashMap.put(dataSourceKey, dbType);
}
@ -217,38 +239,75 @@ public class FlexDataSource extends AbstractDataSource {
return (iface.isInstance(this) || getDataSource().isWrapperFor(iface));
}
/**
* 获取数据源缺失处理器
*
* @return DataSourceMissingHandler 数据源缺失处理器实例用于自定义处理逻辑记录日志抛出异常或提供默认数据源
*/
public DataSourceMissingHandler getDataSourceMissingHandler() {
return FlexGlobalConfig.getDefaultConfig().getDataSourceMissingHandler();
}
protected DataSource getDataSource() {
DataSource dataSource = defaultDataSource;
DataSourceMissingHandler dataSourceMissingHandler = getDataSourceMissingHandler();
if (dataSourceMap.size() > 1) {
String dataSourceKey = DataSourceKey.get();
if (StringUtil.hasText(dataSourceKey)) {
//负载均衡 key
// 负载均衡 key
if (dataSourceKey.charAt(dataSourceKey.length() - 1) == LOAD_BALANCE_KEY_SUFFIX) {
String prefix = dataSourceKey.substring(0, dataSourceKey.length() - 1);
List<String> matchedKeys = new ArrayList<>();
for (String key : dataSourceMap.keySet()) {
if (key.startsWith(prefix)) {
matchedKeys.add(key);
}
}
// 当找不到匹配的 key 尝试后备匹配
if (matchedKeys.isEmpty() && dataSourceMissingHandler != null) {
Map<String, DataSource> dsMap = dataSourceMissingHandler.handle(dataSourceKey, dataSourceMap);
if (dsMap != null && !dsMap.isEmpty()) {
for (String key : dsMap.keySet()) {
if (key.startsWith(prefix)) {
matchedKeys.add(key);
}
}
}
}
if (matchedKeys.isEmpty()) {
throw new IllegalStateException("Can not matched dataSource by key: \"" + dataSourceKey + "\"");
}
String randomKey = matchedKeys.get(ThreadLocalRandom.current().nextInt(matchedKeys.size()));
return dataSourceMap.get(randomKey);
}
//非负载均衡 key
// 非负载均衡 key
else {
dataSource = dataSourceMap.get(dataSourceKey);
// 当找不到匹配的 key 尝试后备匹配
if (dataSource == null && dataSourceMissingHandler != null) {
Map<String, DataSource> dsMap = dataSourceMissingHandler.handle(dataSourceKey, dataSourceMap);
if (dsMap != null && !dsMap.isEmpty()) {
dataSource = dsMap.get(dataSourceKey);
}
}
if (dataSource == null) {
throw new IllegalStateException("Cannot get target dataSource by key: \"" + dataSourceKey + "\"");
}
}
}
}
return dataSource;
}
@ -267,11 +326,11 @@ public class FlexDataSource extends AbstractDataSource {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (ArrayUtil.contains(proxyMethods, method.getName())
&& isTransactional()) {
//do nothing
// do nothing
return null;
}
//setAutoCommit: true
// setAutoCommit: true
if ("close".equalsIgnoreCase(method.getName())) {
resetAutoCommit(original);
}

View File

@ -15,246 +15,175 @@
*/
package com.mybatisflex.core.dialect;
import com.mybatisflex.core.util.StringUtil;
import java.util.Arrays;
import java.util.List;
public enum DbType {
/**
* MYSQL
*/
MYSQL("mysql", "MySql 数据库"),
/** ClickHouse */
CLICK_HOUSE("clickhouse", "clickhouse 数据库"),
/**
* MARIADB
*/
MARIADB("mariadb", "MariaDB 数据库"),
/** CSIIDB */
CSIIDB("csiidb", "CSIIDB 数据库"),
/**
* ORACLE
*/
ORACLE("oracle", "Oracle11g 及以下数据库"),
/** CUBRID */
CUBRID("cubrid", "CUBRID 数据库"),
/**
* oracle12c
*/
ORACLE_12C("oracle12c", "Oracle12c 及以上数据库"),
/**
* DB2
*/
/** DB2 */
DB2("db2", "DB2 数据库"),
DB2_1005("db2_1005", "DB2 10.5版本数据库"),
/**
* H2
*/
H2("h2", "H2 数据库"),
/**
* HSQL
*/
HSQL("hsql", "HSQL 数据库"),
/**
* SQLITE
*/
SQLITE("sqlite", "SQLite 数据库"),
/**
* POSTGRE
*/
POSTGRE_SQL("postgresql", "PostgreSQL 数据库"),
/**
* SQLSERVER
*/
SQLSERVER("sqlserver", "SQLServer 数据库"),
/**
* SqlServer 2005 数据库
*/
SQLSERVER_2005("sqlserver_2005", "SQLServer 数据库"),
/**
* DM
*/
DM("dm", "达梦数据库"),
/**
* xugu
*/
XUGU("xugu", "虚谷数据库"),
/**
* Kingbase
*/
KINGBASE_ES("kingbasees", "人大金仓数据库"),
/**
* Phoenix
*/
PHOENIX("phoenix", "Phoenix HBase 数据库"),
/**
* Gauss
*/
GAUSS("gauss", "Gauss 数据库"),
/**
* ClickHouse
*/
CLICK_HOUSE("clickhouse", "clickhouse 数据库"),
/**
* GBase
*/
GBASE("gbase", "南大通用(华库)数据库"),
/**
* GBase-8s
*/
GBASE_8S("gbase-8s", "南大通用数据库 GBase 8s"),
/**
* Oscar
*/
OSCAR("oscar", "神通数据库"),
/**
* Sybase
*/
SYBASE("sybase", "Sybase ASE 数据库"),
/**
* OceanBase
*/
OCEAN_BASE("oceanbase", "OceanBase 数据库"),
/**
* Firebird
*/
FIREBIRD("Firebird", "Firebird 数据库"),
/**
* derby
*/
/** derby */
DERBY("derby", "Derby 数据库"),
/**
* HighGo
*/
HIGH_GO("highgo", "瀚高数据库"),
/** DM */
DM("dm", "达梦数据库"),
/**
* CUBRID
*/
CUBRID("cubrid", "CUBRID 数据库"),
/**
* GOLDILOCKS
*/
GOLDILOCKS("goldilocks", "GOLDILOCKS 数据库"),
/**
* CSIIDB
*/
CSIIDB("csiidb", "CSIIDB 数据库"),
/**
* CSIIDB
*/
SAP_HANA("hana", "SAP_HANA 数据库"),
/**
* Impala
*/
IMPALA("impala", "impala 数据库"),
/**
* Vertica
*/
VERTICA("vertica", "vertica数据库"),
/**
* 东方国信 xcloud
*/
XCloud("xcloud", "行云数据库"),
/**
* redshift
*/
REDSHIFT("redshift", "亚马逊 redshift 数据库"),
/**
* openGauss
*/
OPENGAUSS("openGauss", "华为 openGauss 数据库"),
/**
* TDengine
*/
TDENGINE("TDengine", "TDengine 数据库"),
/**
* Informix
*/
INFORMIX("informix", "Informix 数据库"),
/**
* sinodb
*/
SINODB("sinodb", "SinoDB 数据库"),
/**
* uxdb
*/
UXDB("uxdb", "优炫数据库"),
/**
* greenplum
*/
GREENPLUM("greenplum", "greenplum 数据库"),
/**
* lealone
*/
LEALONE("lealone", "lealone 数据库"),
/**
* Hive SQL
*/
HIVE("Hive", "Hive SQL"),
/**
* Doris 兼容 Mysql使用 MySql 驱动和协议
*/
/** Doris 兼容 Mysql使用 MySql 驱动和协议 */
DORIS("doris", "doris 数据库"),
/**
* Trino
*/
TRINO("trino", "trino 数据库"),
/**
* Duckdb
*/
/** Duckdb */
DUCKDB("duckdb", "duckdb 数据库"),
/**
* UNKNOWN DB
*/
/** Firebird */
FIREBIRD("Firebird", "Firebird 数据库"),
/** Gauss */
GAUSS("gauss", "Gauss 数据库"),
/** GBase */
GBASE("gbase", "南大通用(华库)数据库"),
/** GBase-8c */
GBASE_8C("gbase-8c", "南大通用数据库 GBase 8c"),
/** GBase-8s */
GBASE_8S("gbase-8s", "南大通用数据库 GBase 8s"),
/** GBase-8s-pg */
GBASE_8S_PG("gbase-8s-pg", "南大通用数据库 GBase 8s兼容pg"),
/** GOLDENDB */
GOLDENDB("goldendb", "GoldenDB数据库"),
/** GOLDILOCKS */
GOLDILOCKS("goldilocks", "GOLDILOCKS 数据库"),
/** greenplum */
GREENPLUM("greenplum", "greenplum 数据库"),
/** H2 */
H2("h2", "H2 数据库"),
/** HighGo */
HIGH_GO("highgo", "瀚高数据库"),
/** Hive SQL */
HIVE("Hive", "Hive SQL"),
/** HSQL */
HSQL("hsql", "HSQL 数据库"),
/** Impala */
IMPALA("impala", "impala 数据库"),
/** Informix */
INFORMIX("informix", "Informix 数据库"),
/** Kingbase */
KINGBASE_ES("kingbasees", "人大金仓数据库"),
/** lealone */
LEALONE("lealone", "lealone 数据库"),
/** MARIADB */
MARIADB("mariadb", "MariaDB 数据库"),
/** MYSQL */
MYSQL("mysql", "MySql 数据库"),
/** OceanBase */
OCEAN_BASE("oceanbase", "OceanBase 数据库"),
/** openGauss */
OPENGAUSS("openGauss", "华为 openGauss 数据库"),
/** ORACLE */
ORACLE("oracle", "Oracle11g 及以下数据库"),
/** oracle12c */
ORACLE_12C("oracle12c", "Oracle12c 及以上数据库"),
/** Oscar */
OSCAR("oscar", "神通数据库"),
/** Phoenix */
PHOENIX("phoenix", "Phoenix HBase 数据库"),
/** POSTGRE_SQL */
POSTGRE_SQL("postgresql", "PostgreSQL 数据库"),
/** presto */
PRESTO("presto", "Presto数据库"),
/** redshift */
REDSHIFT("redshift", "亚马逊 redshift 数据库"),
/** SAP_HANA */
SAP_HANA("hana", "SAP_HANA 数据库"),
/** sinodb */
SINODB("sinodb", "SinoDB 数据库"),
/** SQLITE */
SQLITE("sqlite", "SQLite 数据库"),
/** SQLSERVER */
SQLSERVER("sqlserver", "SQLServer 数据库"),
/** SqlServer 2005 数据库 */
SQLSERVER_2005("sqlserver_2005", "SQLServer 数据库"),
/** SUNDB */
SUNDB("sundb", "SUNDB数据库"),
/** Sybase */
SYBASE("sybase", "Sybase ASE 数据库"),
/** TDengine */
TDENGINE("TDengine", "TDengine 数据库"),
/** Trino */
TRINO("trino", "trino 数据库"),
/** uxdb */
UXDB("uxdb", "优炫数据库"),
/** VASTBASE */
VASTBASE("vastbase", "Vastbase数据库"),
/** Vertica */
VERTICA("vertica", "vertica数据库"),
/** XCloud */
XCloud("xcloud", "行云数据库"),
/** xugu */
XUGU("xugu", "虚谷数据库"),
/** yasdb */
YASDB("yasdb", "崖山数据库"),
/** OTHER */
OTHER("other", "其他数据库");
/**
* 数据库名称
*/
/** 数据库名称 */
private final String name;
/**
* 描述
*/
/** 描述 */
private final String remarks;
DbType(String name, String remarks) {
this.name = name;
this.remarks = remarks;
@ -263,4 +192,61 @@ public enum DbType {
public String getName() {
return name;
}
/**
* 根据数据库类型名称自动识别数据库类型
*
* @param name 名称
* @return 数据库类型
*/
public static DbType findByName(String name) {
if (StringUtil.noText(name)) {
return null;
}
return Arrays.stream(values())
.filter(em -> em.getName().equalsIgnoreCase(name))
.findFirst()
.orElse(null);
}
/**
* 获取所有数据库类型
*
* @return 包含所有数据库类型的列表
*/
public static List<DbType> all() {
return Arrays.asList(DbType.values());
}
/**
* 判断当前数据库语法是否与MySQL属于同一类型
*/
public boolean mysqlSameType() {
return this == MYSQL || this == MARIADB || this == GBASE || this == OSCAR || this == XUGU || this == CLICK_HOUSE || this == OCEAN_BASE || this == CUBRID || this == SUNDB || this == GOLDENDB || this == YASDB;
}
/**
* 判断当前数据库语法是否与Oracle属于同一类型
*/
public boolean oracleSameType() {
return this == ORACLE || this == DM;
}
/**
* 判断当前数据库语法是否与PostgreSQL属于同一类型
*/
public boolean postgresqlSameType() {
return this == POSTGRE_SQL || this == H2 || this == LEALONE || this == SQLITE || this == HSQL || this == KINGBASE_ES || this == PHOENIX || this == SAP_HANA || this == IMPALA || this == HIGH_GO || this == VERTICA || this == REDSHIFT || this == GAUSS || this == OPENGAUSS || this == TDENGINE || this == UXDB || this == GBASE_8S_PG || this == GBASE_8C || this == VASTBASE || this == DUCKDB;
}
/**
* 是否为已兼容的数据库类型
* 允许的数据库类型包括MySQL系列Oracle系列和PostgreSQL系列
*
* @return 如果是允许的数据库类型返回true否则返回false
*/
public boolean isSupportDb() {
return mysqlSameType() || oracleSameType() || postgresqlSameType();
}
}

View File

@ -16,6 +16,7 @@
package com.mybatisflex.core.dialect;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.exception.FlexExceptions;
import com.mybatisflex.core.exception.locale.LocalizedFormats;
import com.mybatisflex.core.util.StringUtil;
@ -37,6 +38,20 @@ public class DbTypeUtil {
private DbTypeUtil() {
}
/**
* 获取当前数据库类型
* <p>首先从全局配置中获取数据库类型如果全局配置中未设置则尝试从方言工厂中获取线程局部变量设置的数据库类型
*
* @return 当前数据库类型可能为null
*/
public static DbType getCurrentDbType() {
DbType dbType = FlexGlobalConfig.getDefaultConfig().getDbType();
if (dbType == null) {
dbType = DialectFactory.getHintDbType();
}
return dbType;
}
/**
* 获取当前配置的 DbType
*/
@ -63,20 +78,20 @@ public class DbTypeUtil {
*/
private static DbType getSqlserverDbType(DataSource dataSource) {
try (Connection connection = dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT @@VERSION");
ResultSet resultSet = preparedStatement.executeQuery()) {
PreparedStatement preparedStatement = connection.prepareStatement("SELECT @@VERSION");
ResultSet resultSet = preparedStatement.executeQuery()) {
//SELECT @@VERSION 查询返回信息
/*
Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64)
Sep 24 2019 13:48:23
Copyright (C) 2019 Microsoft Corporation
Enterprise Edition (64-bit) on Windows Server 2019 Datacenter 10.0 <X64> (Build 17763: ) (Hypervisor)
*/
Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64)
Sep 24 2019 13:48:23
Copyright (C) 2019 Microsoft Corporation
Enterprise Edition (64-bit) on Windows Server 2019 Datacenter 10.0 <X64> (Build 17763: ) (Hypervisor)
*/
if (resultSet.next()) {
String version = resultSet.getString(1);
if (StringUtil.hasText(version)) {
String year = version.substring(21, 25);
if (StringUtil.hasText(year) && year.compareTo("2005") <= 0) {
if (StringUtil.hasText(year) && year.compareTo("2008") <= 0) {
return DbType.SQLSERVER_2005;
}
}
@ -124,86 +139,106 @@ public class DbTypeUtil {
*/
public static DbType parseDbType(String jdbcUrl) {
jdbcUrl = jdbcUrl.toLowerCase();
if (jdbcUrl.contains(":mysql:") || jdbcUrl.contains(":cobar:")) {
if (jdbcUrl.contains(":ch:") || jdbcUrl.contains(":clickhouse:")) {
return DbType.CLICK_HOUSE;
} else if (jdbcUrl.contains(":cobar:")) {
return DbType.MYSQL;
} else if (jdbcUrl.contains(":mariadb:")) {
return DbType.MARIADB;
} else if (jdbcUrl.contains(":oracle:")) {
return DbType.ORACLE;
} else if (jdbcUrl.contains(":sqlserver2012:")) {
return DbType.SQLSERVER;
} else if (jdbcUrl.contains(":sqlserver:") || jdbcUrl.contains(":microsoft:")) {
return DbType.SQLSERVER_2005;
} else if (jdbcUrl.contains(":postgresql:")) {
return DbType.POSTGRE_SQL;
} else if (jdbcUrl.contains(":hsqldb:")) {
return DbType.HSQL;
} else if (jdbcUrl.contains(":csiidb:")) {
return DbType.CSIIDB;
} else if (jdbcUrl.contains(":cubrid:")) {
return DbType.CUBRID;
} else if (jdbcUrl.contains(":db2:")) {
return DbType.DB2;
} else if (jdbcUrl.contains(":sqlite:")) {
return DbType.SQLITE;
} else if (jdbcUrl.contains(":h2:")) {
return DbType.H2;
} else if (jdbcUrl.contains(":derby:")) {
return DbType.DERBY;
} else if (isMatchedRegex(":dm\\d*:", jdbcUrl)) {
return DbType.DM;
} else if (jdbcUrl.contains(":xugu:")) {
return DbType.XUGU;
} else if (isMatchedRegex(":kingbase\\d*:", jdbcUrl)) {
return DbType.KINGBASE_ES;
} else if (jdbcUrl.contains(":phoenix:")) {
return DbType.PHOENIX;
} else if (jdbcUrl.contains(":zenith:")) {
} else if (jdbcUrl.contains(":duckdb:")) {
return DbType.DUCKDB;
} else if (jdbcUrl.contains(":firebirdsql:")) {
return DbType.FIREBIRD;
} else if (jdbcUrl.contains(":gaussdb:") || jdbcUrl.contains(":zenith:")) {
return DbType.GAUSS;
} else if (jdbcUrl.contains(":gbase:")) {
return DbType.GBASE;
} else if (jdbcUrl.contains(":gbase8c:")) {
return DbType.GBASE_8C;
} else if (jdbcUrl.contains(":gbase8s-pg:")) {
return DbType.GBASE_8S_PG;
} else if (jdbcUrl.contains(":gbasedbt-sqli:") || jdbcUrl.contains(":informix-sqli:")) {
return DbType.GBASE_8S;
} else if (jdbcUrl.contains(":ch:") || jdbcUrl.contains(":clickhouse:")) {
return DbType.CLICK_HOUSE;
} else if (jdbcUrl.contains(":oscar:")) {
return DbType.OSCAR;
} else if (jdbcUrl.contains(":sybase:")) {
return DbType.SYBASE;
} else if (jdbcUrl.contains(":oceanbase:")) {
return DbType.OCEAN_BASE;
} else if (jdbcUrl.contains(":highgo:")) {
return DbType.HIGH_GO;
} else if (jdbcUrl.contains(":cubrid:")) {
return DbType.CUBRID;
} else if (jdbcUrl.contains(":goldendb:")) {
return DbType.GOLDENDB;
} else if (jdbcUrl.contains(":goldilocks:")) {
return DbType.GOLDILOCKS;
} else if (jdbcUrl.contains(":csiidb:")) {
return DbType.CSIIDB;
} else if (jdbcUrl.contains(":sap:")) {
return DbType.SAP_HANA;
} else if (jdbcUrl.contains(":greenplum:")) {
return DbType.GREENPLUM;
} else if (jdbcUrl.contains(":h2:")) {
return DbType.H2;
} else if (jdbcUrl.contains(":highgo:")) {
return DbType.HIGH_GO;
} else if (jdbcUrl.contains(":hive2:") || jdbcUrl.contains(":inceptor2:")) {
return DbType.HIVE;
} else if (jdbcUrl.contains(":hsqldb:")) {
return DbType.HSQL;
} else if (jdbcUrl.contains(":impala:")) {
return DbType.IMPALA;
} else if (jdbcUrl.contains(":informix")) {
return DbType.INFORMIX;
} else if (isMatchedRegex(":kingbase\\d*:", jdbcUrl)) {
return DbType.KINGBASE_ES;
} else if (jdbcUrl.contains(":lealone:")) {
return DbType.LEALONE;
} else if (jdbcUrl.contains(":mariadb:")) {
return DbType.MARIADB;
} else if (jdbcUrl.contains(":mysql:")) {
return DbType.MYSQL;
} else if (jdbcUrl.contains(":oceanbase:")) {
return DbType.OCEAN_BASE;
} else if (jdbcUrl.contains(":opengauss:")) {
return DbType.OPENGAUSS;
} else if (jdbcUrl.contains(":oracle:")) {
return DbType.ORACLE;
} else if (jdbcUrl.contains(":oscar:")) {
return DbType.OSCAR;
} else if (jdbcUrl.contains(":phoenix:")) {
return DbType.PHOENIX;
} else if (jdbcUrl.contains(":postgresql:")) {
return DbType.POSTGRE_SQL;
} else if (jdbcUrl.contains(":presto:")) {
return DbType.PRESTO;
} else if (jdbcUrl.contains(":redshift:")) {
return DbType.REDSHIFT;
} else if (jdbcUrl.contains(":sap:")) {
return DbType.SAP_HANA;
} else if (jdbcUrl.contains(":sinodb")) {
return DbType.SINODB;
} else if (jdbcUrl.contains(":sqlite:")) {
return DbType.SQLITE;
} else if (jdbcUrl.contains(":sqlserver:")) {
return DbType.SQLSERVER_2005;
} else if (jdbcUrl.contains(":sqlserver2012:")) {
return DbType.SQLSERVER;
} else if (jdbcUrl.contains(":sundb:")) {
return DbType.SUNDB;
} else if (jdbcUrl.contains(":sybase:")) {
return DbType.SYBASE;
} else if (jdbcUrl.contains(":taos:") || jdbcUrl.contains(":taos-rs:")) {
return DbType.TDENGINE;
} else if (jdbcUrl.contains(":trino:")) {
return DbType.TRINO;
} else if (jdbcUrl.contains(":uxdb:")) {
return DbType.UXDB;
} else if (jdbcUrl.contains(":vastbase:")) {
return DbType.VASTBASE;
} else if (jdbcUrl.contains(":vertica:")) {
return DbType.VERTICA;
} else if (jdbcUrl.contains(":xcloud:")) {
return DbType.XCloud;
} else if (jdbcUrl.contains(":firebirdsql:")) {
return DbType.FIREBIRD;
} else if (jdbcUrl.contains(":redshift:")) {
return DbType.REDSHIFT;
} else if (jdbcUrl.contains(":opengauss:")) {
return DbType.OPENGAUSS;
} else if (jdbcUrl.contains(":taos:") || jdbcUrl.contains(":taos-rs:")) {
return DbType.TDENGINE;
} else if (jdbcUrl.contains(":informix")) {
return DbType.INFORMIX;
} else if (jdbcUrl.contains(":sinodb")) {
return DbType.SINODB;
} else if (jdbcUrl.contains(":uxdb:")) {
return DbType.UXDB;
} else if (jdbcUrl.contains(":greenplum:")) {
return DbType.GREENPLUM;
} else if (jdbcUrl.contains(":lealone:")) {
return DbType.LEALONE;
} else if (jdbcUrl.contains(":hive2:")) {
return DbType.HIVE;
} else if (jdbcUrl.contains(":duckdb:")) {
return DbType.DUCKDB;
} else if (jdbcUrl.contains(":xugu:")) {
return DbType.XUGU;
} else if (jdbcUrl.contains(":yasdb:")) {
return DbType.YASDB;
} else {
return DbType.OTHER;
}

View File

@ -106,6 +106,9 @@ public class DialectFactory {
case CSIIDB:
case HIVE:
case DORIS:
case GOLDENDB:
case SUNDB:
case YASDB:
return new CommonsDialectImpl(KeywordWrap.BACK_QUOTE, LimitOffsetProcessor.MYSQL);
case CLICK_HOUSE:
return new ClickhouseDialectImpl(KeywordWrap.NONE, LimitOffsetProcessor.MYSQL);
@ -116,7 +119,7 @@ public class DialectFactory {
case ORACLE:
return new OracleDialect();
case GAUSS:
return new CommonsDialectImpl(KeywordWrap.DOUBLE_QUOTATION, LimitOffsetProcessor.ORACLE);
return new CommonsDialectImpl(KeywordWrap.NONE, LimitOffsetProcessor.ORACLE);
case POSTGRE_SQL:
case SQLITE:
case HSQL:
@ -131,6 +134,11 @@ public class DialectFactory {
case UXDB:
case LEALONE:
case DUCKDB:
case GBASE_8C:
case GBASE_8S_PG:
case VASTBASE:
case TRINO:
case PRESTO:
return new CommonsDialectImpl(KeywordWrap.DOUBLE_QUOTATION, LimitOffsetProcessor.POSTGRESQL);
case TDENGINE:
return new CommonsDialectImpl(KeywordWrap.BACK_QUOTE, LimitOffsetProcessor.POSTGRESQL);
@ -151,8 +159,6 @@ public class DialectFactory {
return new CommonsDialectImpl(KeywordWrap.DOUBLE_QUOTATION, LimitOffsetProcessor.SINODB);
case SYBASE:
return new CommonsDialectImpl(KeywordWrap.DOUBLE_QUOTATION, LimitOffsetProcessor.SYBASE);
case TRINO:
return new CommonsDialectImpl(KeywordWrap.NONE, LimitOffsetProcessor.SQLSERVER);
default:
return new CommonsDialectImpl();
}

View File

@ -15,6 +15,7 @@
*/
package com.mybatisflex.core.dialect;
import com.mybatisflex.core.query.QueryTable;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.Row;
import com.mybatisflex.core.table.TableInfo;
@ -64,6 +65,10 @@ public interface IDialect {
String buildSelectSql(QueryWrapper queryWrapper);
default String buildSelectSql(QueryWrapper queryWrapper, List<QueryTable> contextTables) {
return buildSelectSql(queryWrapper);
}
String buildNoSelectSql(QueryWrapper queryWrapper);
String buildDeleteSql(QueryWrapper queryWrapper);

View File

@ -231,12 +231,14 @@ public class ClickhouseDialectImpl extends CommonsDialectImpl {
}
// 单主键
else {
sql.append(wrap(primaryKeys[0])).append(IN).append(BRACKET_LEFT);
for (int i = 0; i < ids.length; i++) {
if (i > 0) {
sql.append(OR);
sql.append(DELIMITER);
}
sql.append(wrap(primaryKeys[0])).append(EQUALS_PLACEHOLDER);
sql.append(PLACEHOLDER);
}
sql.append(BRACKET_RIGHT);
}
prepareAuth(schema, table, sql, OperateType.DELETE);
return sql.toString();
@ -294,12 +296,14 @@ public class ClickhouseDialectImpl extends CommonsDialectImpl {
}
// 单主键
else {
sql.append(wrap(primaryKeys[0])).append(IN).append(BRACKET_LEFT);
for (int i = 0; i < primaryValues.length; i++) {
if (i > 0) {
sql.append(OR);
sql.append(DELIMITER);
}
sql.append(wrap(primaryKeys[0])).append(EQUALS_PLACEHOLDER);
sql.append(PLACEHOLDER);
}
sql.append(BRACKET_RIGHT);
}
sql.append(BRACKET_RIGHT).append(AND).append(buildLogicNormalCondition(logicDeleteColumn, tableInfo));

View File

@ -19,6 +19,7 @@ import com.mybatisflex.core.dialect.IDialect;
import com.mybatisflex.core.dialect.KeywordWrap;
import com.mybatisflex.core.dialect.LimitOffsetProcessor;
import com.mybatisflex.core.dialect.OperateType;
import com.mybatisflex.core.exception.FlexAssert;
import com.mybatisflex.core.exception.FlexExceptions;
import com.mybatisflex.core.exception.locale.LocalizedFormats;
import com.mybatisflex.core.logicdelete.LogicDeleteManager;
@ -40,17 +41,13 @@ import com.mybatisflex.core.util.CollectionUtil;
import com.mybatisflex.core.util.SqlUtil;
import com.mybatisflex.core.util.StringUtil;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import static com.mybatisflex.core.constant.SqlConsts.AND;
import static com.mybatisflex.core.constant.SqlConsts.IN;
import static com.mybatisflex.core.constant.SqlConsts.ASTERISK;
import static com.mybatisflex.core.constant.SqlConsts.BLANK;
import static com.mybatisflex.core.constant.SqlConsts.BRACKET_LEFT;
@ -58,6 +55,7 @@ import static com.mybatisflex.core.constant.SqlConsts.BRACKET_RIGHT;
import static com.mybatisflex.core.constant.SqlConsts.DELETE;
import static com.mybatisflex.core.constant.SqlConsts.DELETE_FROM;
import static com.mybatisflex.core.constant.SqlConsts.DELIMITER;
import static com.mybatisflex.core.constant.SqlConsts.DUAL;
import static com.mybatisflex.core.constant.SqlConsts.EMPTY;
import static com.mybatisflex.core.constant.SqlConsts.EQUALS;
import static com.mybatisflex.core.constant.SqlConsts.EQUALS_PLACEHOLDER;
@ -102,7 +100,8 @@ public class CommonsDialectImpl implements IDialect {
@Override
public String wrap(String keyword) {
return ASTERISK.equals(keyword) ? keyword : keywordWrap.wrap(keyword);
return ASTERISK.equals(keyword) || DUAL.equalsIgnoreCase(StringUtil.tryTrim(keyword)) ?
keyword : keywordWrap.wrap(keyword);
}
@Override
@ -193,6 +192,7 @@ public class CommonsDialectImpl implements IDialect {
@Override
public String forDeleteById(String schema, String tableName, String[] primaryKeys) {
assertPrimaryKeysNotEmpty(primaryKeys);
String table = getRealTable(tableName, OperateType.DELETE);
StringBuilder sql = new StringBuilder();
sql.append(DELETE_FROM);
@ -214,6 +214,7 @@ public class CommonsDialectImpl implements IDialect {
@Override
public String forDeleteBatchByIds(String schema, String tableName, String[] primaryKeys, Object[] ids) {
assertPrimaryKeysNotEmpty(primaryKeys);
String table = getRealTable(tableName, OperateType.DELETE);
StringBuilder sql = new StringBuilder();
sql.append(DELETE_FROM);
@ -242,12 +243,14 @@ public class CommonsDialectImpl implements IDialect {
}
// 单主键
else {
sql.append(wrap(primaryKeys[0])).append(IN).append(BRACKET_LEFT);
for (int i = 0; i < ids.length; i++) {
if (i > 0) {
sql.append(OR);
sql.append(DELIMITER);
}
sql.append(wrap(primaryKeys[0])).append(EQUALS_PLACEHOLDER);
sql.append(PLACEHOLDER);
}
sql.append(BRACKET_RIGHT);
}
prepareAuth(schema, table, sql, OperateType.DELETE);
return sql.toString();
@ -266,6 +269,7 @@ public class CommonsDialectImpl implements IDialect {
Set<String> modifyAttrs = RowCPI.getModifyAttrs(row);
Map<String, RawValue> rawValueMap = RowCPI.getRawValueMap(row);
String[] primaryKeys = RowCPI.obtainsPrimaryKeyStrings(row);
assertPrimaryKeysNotEmpty(primaryKeys);
sql.append(UPDATE);
if (StringUtil.hasText(schema)) {
@ -367,6 +371,7 @@ public class CommonsDialectImpl implements IDialect {
@Override
public String forSelectOneById(String schema, String tableName, String[] primaryKeys, Object[] primaryValues) {
assertPrimaryKeysNotEmpty(primaryKeys);
String table = getRealTable(tableName, OperateType.SELECT);
StringBuilder sql = new StringBuilder(SELECT_ALL_FROM);
if (StringUtil.hasText(schema)) {
@ -393,10 +398,16 @@ public class CommonsDialectImpl implements IDialect {
////////////build query sql///////
@Override
public String buildSelectSql(QueryWrapper queryWrapper) {
return buildSelectSql(queryWrapper, Collections.emptyList());
}
@Override
public String buildSelectSql(QueryWrapper queryWrapper, List<QueryTable> contextTables) {
List<QueryTable> queryTables = CPI.getQueryTables(queryWrapper);
List<QueryTable> joinTables = CPI.getJoinTables(queryWrapper);
List<QueryTable> allTables = CollectionUtil.merge(queryTables, joinTables);
allTables = CollectionUtil.merge(allTables, contextTables);
List<QueryColumn> selectColumns = CPI.getSelectColumns(queryWrapper);
@ -438,7 +449,9 @@ public class CommonsDialectImpl implements IDialect {
buildSelectColumnSql(sqlBuilder, allTables, selectColumns, CPI.getHint(queryWrapper));
sqlBuilder.append(FROM).append(StringUtil.join(DELIMITER, queryTables, queryTable -> queryTable.toSql(this, OperateType.SELECT)));
if(CollectionUtil.isNotEmpty(queryTables)) {
sqlBuilder.append(FROM).append(StringUtil.join(DELIMITER, queryTables, queryTable -> queryTable.toSql(this, OperateType.SELECT)));
}
buildJoinSql(sqlBuilder, queryWrapper, allTables, OperateType.SELECT);
buildWhereSql(sqlBuilder, queryWrapper, allTables, true);
@ -691,16 +704,17 @@ public class CommonsDialectImpl implements IDialect {
String logicDeleteColumn = tableInfo.getLogicDeleteColumnOrSkip();
Object[] tenantIdArgs = tableInfo.buildTenantIdArgs();
String[] primaryKeys = tableInfo.getPrimaryColumns();
assertPrimaryKeysNotEmpty(primaryKeys);
// 正常删除
if (StringUtil.noText(logicDeleteColumn)) {
String deleteByIdSql = forDeleteById(tableInfo.getSchema(), tableInfo.getTableName(), tableInfo.getPrimaryColumns());
String deleteByIdSql = forDeleteById(tableInfo.getSchema(), tableInfo.getTableName(), primaryKeys);
return tableInfo.buildTenantCondition(deleteByIdSql, tenantIdArgs, this);
}
// 逻辑删除
StringBuilder sql = new StringBuilder();
String[] primaryKeys = tableInfo.getPrimaryColumns();
sql.append(UPDATE).append(tableInfo.getWrapSchemaAndTableName(this, OperateType.UPDATE));
sql.append(SET).append(buildLogicDeletedSet(logicDeleteColumn, tableInfo));
sql.append(WHERE);
@ -725,9 +739,12 @@ public class CommonsDialectImpl implements IDialect {
String logicDeleteColumn = tableInfo.getLogicDeleteColumnOrSkip();
Object[] tenantIdArgs = tableInfo.buildTenantIdArgs();
String[] primaryKeys = tableInfo.getPrimaryColumns();
assertPrimaryKeysNotEmpty(primaryKeys);
// 正常删除
if (StringUtil.noText(logicDeleteColumn)) {
String deleteSQL = forDeleteBatchByIds(tableInfo.getSchema(), tableInfo.getTableName(), tableInfo.getPrimaryColumns(), primaryValues);
String deleteSQL = forDeleteBatchByIds(tableInfo.getSchema(), tableInfo.getTableName(), primaryKeys, primaryValues);
// 多租户
if (ArrayUtil.isNotEmpty(tenantIdArgs)) {
@ -744,8 +761,6 @@ public class CommonsDialectImpl implements IDialect {
sql.append(WHERE);
sql.append(BRACKET_LEFT);
String[] primaryKeys = tableInfo.getPrimaryColumns();
// 多主键的场景
if (primaryKeys.length > 1) {
for (int i = 0; i < primaryValues.length / primaryKeys.length; i++) {
@ -764,12 +779,14 @@ public class CommonsDialectImpl implements IDialect {
}
// 单主键
else {
sql.append(wrap(primaryKeys[0])).append(IN).append(BRACKET_LEFT);
for (int i = 0; i < primaryValues.length; i++) {
if (i > 0) {
sql.append(OR);
sql.append(DELIMITER);
}
sql.append(wrap(primaryKeys[0])).append(EQUALS_PLACEHOLDER);
sql.append(PLACEHOLDER);
}
sql.append(BRACKET_RIGHT);
}
sql.append(BRACKET_RIGHT).append(AND).append(buildLogicNormalCondition(logicDeleteColumn, tableInfo));
@ -822,6 +839,7 @@ public class CommonsDialectImpl implements IDialect {
Set<String> updateColumns = tableInfo.obtainUpdateColumns(entity, ignoreNulls, false);
Map<String, RawValue> rawValueMap = tableInfo.obtainUpdateRawValueMap(entity);
String[] primaryKeys = tableInfo.getPrimaryColumns();
assertPrimaryKeysNotEmpty(primaryKeys);
sql.append(UPDATE).append(tableInfo.getWrapSchemaAndTableName(this, OperateType.UPDATE)).append(SET);
@ -956,6 +974,8 @@ public class CommonsDialectImpl implements IDialect {
sql.append(FROM).append(tableInfo.getWrapSchemaAndTableName(this, OperateType.SELECT));
sql.append(WHERE);
String[] pKeys = tableInfo.getPrimaryColumns();
assertPrimaryKeysNotEmpty(pKeys);
for (int i = 0; i < pKeys.length; i++) {
if (i > 0) {
sql.append(AND);
@ -984,6 +1004,7 @@ public class CommonsDialectImpl implements IDialect {
sql.append(FROM).append(tableInfo.getWrapSchemaAndTableName(this, OperateType.SELECT));
sql.append(WHERE);
String[] primaryKeys = tableInfo.getPrimaryColumns();
assertPrimaryKeysNotEmpty(primaryKeys);
String logicDeleteColumn = tableInfo.getLogicDeleteColumnOrSkip();
Object[] tenantIdArgs = tableInfo.buildTenantIdArgs();
@ -1009,12 +1030,14 @@ public class CommonsDialectImpl implements IDialect {
}
// 单主键
else {
sql.append(wrap(primaryKeys[0])).append(IN).append(BRACKET_LEFT);
for (int i = 0; i < primaryValues.length; i++) {
if (i > 0) {
sql.append(OR);
sql.append(DELIMITER);
}
sql.append(wrap(primaryKeys[0])).append(EQUALS_PLACEHOLDER);
sql.append(PLACEHOLDER);
}
sql.append(BRACKET_RIGHT);
}
if (StringUtil.hasText(logicDeleteColumn) || ArrayUtil.isNotEmpty(tenantIdArgs)) {
@ -1128,5 +1151,14 @@ public class CommonsDialectImpl implements IDialect {
return LogicDeleteManager.getProcessor().buildLogicDeletedSet(logicColumn, tableInfo, this);
}
/**
* 断言主键非空
*
* @param primaryKeys 主键
*/
protected void assertPrimaryKeysNotEmpty(String[] primaryKeys) {
if (Objects.isNull(primaryKeys) || primaryKeys.length == 0 || Arrays.stream(primaryKeys).allMatch(String::isEmpty)) {
throw FlexExceptions.wrap("primary key not recognized! Please check the @com.mybatisflex.annotation.Id annotation");
}
}
}

View File

@ -22,6 +22,7 @@ import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import java.sql.Statement;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@ -38,7 +39,7 @@ public class MultiEntityKeyGenerator implements KeyGenerator {
@Override
public void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {
List<Object> entities = (List<Object>) ((Map) parameter).get(FlexConsts.ENTITIES);
Collection<Object> entities = (Collection<Object>) ((Map) parameter).get(FlexConsts.ENTITIES);
if (CollectionUtil.isNotEmpty(entities)) {
for (Object entity : entities) {
((Map) parameter).put(FlexConsts.ENTITY, entity);

View File

@ -42,8 +42,9 @@ public class RowKeyGenerator implements KeyGenerator, IMultiKeyGenerator {
private static final KeyGenerator[] NO_KEY_GENERATORS = new KeyGenerator[0];
private final MappedStatement ms;
private KeyGenerator[] keyGenerators;
private Set<String> autoKeyGeneratorNames;
private KeyGenerator[] keyGenerators;
public RowKeyGenerator(MappedStatement methodMappedStatement) {
this.ms = methodMappedStatement;
@ -52,6 +53,8 @@ public class RowKeyGenerator implements KeyGenerator, IMultiKeyGenerator {
@Override
public void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter) {
Row row = (Row) ((Map<?, ?>) parameter).get(FlexConsts.ROW);
// 重置 autoKeyGeneratorNames fix https://gitee.com/mybatis-flex/mybatis-flex/issues/ID64KB
autoKeyGeneratorNames = null;
keyGenerators = buildRowKeyGenerators(RowCPI.obtainsPrimaryKeys(row));
for (KeyGenerator keyGenerator : keyGenerators) {
keyGenerator.processBefore(executor, ms, stmt, parameter);
@ -89,7 +92,7 @@ public class RowKeyGenerator implements KeyGenerator, IMultiKeyGenerator {
String keyColumn = rowKey.getKeyColumn();
if (rowKey.getKeyType() == KeyType.Auto) {
if (autoKeyGeneratorNames == null) {
autoKeyGeneratorNames = new HashSet<>();
autoKeyGeneratorNames = new LinkedHashSet<>();
}
autoKeyGeneratorNames.add(keyColumn);
return new RowJdbc3KeyGenerator(keyColumn);

View File

@ -46,9 +46,11 @@ public class FlexStatementHandler implements StatementHandler {
private final BoundSql boundSql;
private final boolean auditEnable = AuditManager.isAuditEnable();
private final Configuration configuration;
private final String stmtId;
public FlexStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
configuration = ms.getConfiguration();
stmtId = ms.getId();
switch (ms.getStatementType()) {
case STATEMENT:
delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
@ -83,7 +85,7 @@ public class FlexStatementHandler implements StatementHandler {
AuditManager.startAudit(() -> {
delegate.batch(statement);
return null;
}, statement, boundSql, configuration);
}, stmtId, statement, boundSql, configuration);
} else {
delegate.batch(statement);
}
@ -91,19 +93,19 @@ public class FlexStatementHandler implements StatementHandler {
@Override
public int update(Statement statement) throws SQLException {
return auditEnable ? AuditManager.startAudit(() -> delegate.update(statement), statement, boundSql, configuration)
return auditEnable ? AuditManager.startAudit(() -> delegate.update(statement), stmtId, statement, boundSql, configuration)
: delegate.update(statement);
}
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
return auditEnable ? AuditManager.startAudit(() -> delegate.query(statement, resultHandler), statement, boundSql, configuration)
return auditEnable ? AuditManager.startAudit(() -> delegate.query(statement, resultHandler), stmtId, statement, boundSql, configuration)
: delegate.query(statement, resultHandler);
}
@Override
public <E> Cursor<E> queryCursor(Statement statement) throws SQLException {
return auditEnable ? AuditManager.startAudit(() -> delegate.queryCursor(statement), statement, boundSql, configuration)
return auditEnable ? AuditManager.startAudit(() -> delegate.queryCursor(statement), stmtId, statement, boundSql, configuration)
: delegate.queryCursor(statement);
}

View File

@ -43,7 +43,7 @@ public class Mappers {
private Mappers() {
}
private static final Map<Class<?>, Object> MAPPER_OBJECTS = new ConcurrentHashMap<>();
private static final Map<String, Map<Class<?>, Object>> MAPPER_OBJECTS_OF_ENV = new ConcurrentHashMap<>();
private static final Map<Class<?>, Class<?>> ENTITY_MAPPER_MAP = new ConcurrentHashMap<>();
@ -79,14 +79,16 @@ public class Mappers {
* @return {@link BaseMapper} 对象
*/
public static <M> M ofMapperClass(Class<M> mapperClass) {
Object mapperObject = MapUtil.computeIfAbsent(MAPPER_OBJECTS, mapperClass, clazz ->
Map<Class<?>, Object> mapperObjects = MapUtil.computeIfAbsent(MAPPER_OBJECTS_OF_ENV, "default", envId -> new ConcurrentHashMap<>());
Object mapperObject = MapUtil.computeIfAbsent(mapperObjects, mapperClass, clazz ->
Proxy.newProxyInstance(mapperClass.getClassLoader()
, new Class[]{mapperClass}
, new MapperHandler(mapperClass)));
return (M) mapperObject;
}
public static <M> M ofMapperClass(String environmentId, Class<M> mapperClass) {
Object mapperObject = MapUtil.computeIfAbsent(MAPPER_OBJECTS, mapperClass, clazz ->
Map<Class<?>, Object> mapperObjects = MapUtil.computeIfAbsent(MAPPER_OBJECTS_OF_ENV, environmentId, envId -> new ConcurrentHashMap<>());
Object mapperObject = MapUtil.computeIfAbsent(mapperObjects, mapperClass, clazz ->
Proxy.newProxyInstance(mapperClass.getClassLoader()
, new Class[]{mapperClass}
, new MapperHandler(environmentId, mapperClass)));

View File

@ -26,7 +26,6 @@ import com.mybatisflex.core.row.RowMapper;
import com.mybatisflex.core.table.TableInfo;
import com.mybatisflex.core.table.TableInfoFactory;
import com.mybatisflex.core.util.StringUtil;
import com.mybatisflex.processor.util.StrUtil;
import org.apache.ibatis.reflection.ExceptionUtil;
import org.apache.ibatis.session.SqlSession;
@ -62,7 +61,7 @@ public class FlexMapperProxy<T> extends MybatisMapperProxy<T> {
// Mapper 方法上获取 UseDataSource的value值
finalDsKey = getMethodDsKey(method, proxy);
// 对数据源取值进行动态取值处理
if (!StrUtil.isBlank(finalDsKey)) {
if (StringUtil.hasText(finalDsKey)) {
finalDsKey = DataSourceKey.processDataSourceKey(finalDsKey, proxy, method, args);
}
}

View File

@ -0,0 +1,107 @@
package com.mybatisflex.core.query;
import com.mybatisflex.core.util.StringUtil;
public class Assert {
private Assert() {
}
/**
* 断言表达式为 true
*
* @param <T> 要返回的值类型
* @param value 要返回的值
* @param expression 断言表达式
* @return 原始值
* @throws IllegalArgumentException 当表达式为 false 时抛出
*/
public static <T> T that(T value, boolean expression) {
if (!expression) {
throw new IllegalArgumentException("Assertion failed");
}
return value;
}
/**
* 断言表达式为 true成功返回指定的值
*
* @param <T> 要返回的值类型
* @param value 要返回的值
* @param expression 断言表达式
* @param message 异常消息
* @return 原始值
* @throws IllegalArgumentException 当表达式为 false 时抛出
*/
public static <T> T that(T value, boolean expression, String message) {
if (!expression) {
throw new IllegalArgumentException(message != null ? message : "Assertion failed");
}
return value;
}
/**
* 断言字符串不为空白延迟计算异常消息
*
* @param text 要验证的字符串
* @param message 异常消息
* @return 原始字符串
* @throws IllegalArgumentException 当字符串为空白时抛出
*/
public static String hasText(String text, String message) {
if (StringUtil.noText(text)) {
throw new IllegalArgumentException(
StringUtil.hasText(message) ? message : "value must have text"
);
}
return text;
}
/**
* 断言字符串不为空白
*
* @param text 要验证的参数
* @return 原始字符串
* @throws IllegalArgumentException 当字符串为空白时抛出
*/
public static boolean hasText(String text) {
if (StringUtil.noText(text)) {
throw new IllegalArgumentException("value must have text");
}
return true;
}
/**
* 断言对象不为空
*
* @param obj 要验证的参数
* @return 原始对象
* @throws IllegalArgumentException 当对象为空时抛出
*/
public static boolean notNull(Object obj) {
if (obj == null) {
throw new IllegalArgumentException("value must not be null");
}
return true;
}
/**
* 断言对象不为空
*
* @param obj 要验证的参数
* @param message 异常消息
* @return 原始对象
* @throws IllegalArgumentException 当对象为空时抛出
*/
public static boolean notNull(Object obj, String message) {
if (obj == null) {
throw new IllegalArgumentException(StringUtil.hasText(message) ? message : "value must not be null");
}
return true;
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2022-2024, Mybatis-Flex (fuhai999@gmail.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mybatisflex.core.query;
import com.mybatisflex.core.FlexConsts;
import com.mybatisflex.core.dialect.IDialect;
import java.util.List;
/**
* CAST函数查询列
*/
public class CastQueryColumn extends QueryColumn implements HasParamsColumn {
private QueryColumn column;
private final String dataType;
public CastQueryColumn(QueryColumn column, String dataType) {
this.column = column;
this.dataType = dataType;
}
public CastQueryColumn(String column, String dataType) {
this.column = new QueryColumn(column);
this.dataType = dataType;
}
@Override
protected String toConditionSql(List<QueryTable> queryTables, IDialect dialect) {
return " CAST(" + column.toConditionSql(queryTables, dialect) + " AS " + dataType + ") ";
}
@Override
protected String toSelectSql(List<QueryTable> queryTables, IDialect dialect) {
return " CAST(" + column.toSelectSql(queryTables, dialect) + " AS " + dataType + ") " + WrapperUtil.buildColumnAlias(alias, dialect);
}
@Override
public CastQueryColumn clone() {
CastQueryColumn clone = (CastQueryColumn) super.clone();
clone.column = column.clone();
return clone;
}
@Override
public String toString() {
return "CastQueryColumn{" +
"column=" + column +
", dataType='" + dataType + '\'' +
", alias='" + alias + '\'' +
'}';
}
@Override
public Object[] getParamValues() {
if (column instanceof HasParamsColumn) {
return ((HasParamsColumn) column).getParamValues();
}
return FlexConsts.EMPTY_ARRAY;
}
}

View File

@ -48,7 +48,7 @@ public class OperatorSelectCondition extends QueryCondition {
//检测是否生效
if (checkEffective()) {
String childSql = dialect.buildSelectSql(queryWrapper);
String childSql = dialect.buildSelectSql(queryWrapper, queryTables);
if (StringUtil.hasText(childSql)) {
QueryCondition prevEffectiveCondition = getPrevEffectiveCondition();
if (prevEffectiveCondition != null && this.connector != null) {
@ -76,7 +76,8 @@ public class OperatorSelectCondition extends QueryCondition {
@Override
boolean containsTable(String... tables) {
QueryCondition condition = queryWrapper.getWhereQueryCondition();
return condition != null && condition.containsTable(tables);
boolean subContains = condition != null && condition.containsTable(tables);
return subContains || nextContainsTable(tables);
}
@Override

View File

@ -510,21 +510,46 @@ public class QueryColumn implements CloneSupport<QueryColumn>, Conditional<Query
}
QueryCondition between_(Object[] values) {
if (values == null || values.length != 2) {
throw new IllegalArgumentException("values is null or length is not 2");
// if (values == null || values.length != 2) {
// throw new IllegalArgumentException("values is null or length is not 2");
// }
if (values == null || values.length == 0) {
return QueryCondition.createEmpty();
}
return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlConsts.BETWEEN, values));
Object start = values[0], end = values.length > 1 ? values[1] : null;
return between_(start, end);
}
QueryCondition between_(Object start, Object end) {
if (start == null && end == null) {
return QueryCondition.createEmpty();
}
boolean smartConvertBetweenToLeOrGe = QueryColumnBehavior.isSmartConvertBetweenToLeOrGe();
if ((start == null || end == null) && !smartConvertBetweenToLeOrGe) {
return QueryCondition.createEmpty();
}
/* && end != null */
if (start == null) {
return le_(end);
}
/* && start != null */
if (end == null) {
return ge_(start);
}
return QueryColumnBehavior.castCondition(QueryCondition.create(this, SqlConsts.BETWEEN, new Object[]{start, end}));
}
@Override
public QueryCondition between(Object[] values) {
if (QueryColumnBehavior.shouldIgnoreValue(values)) {
return QueryCondition.createEmpty();
}
// if (QueryColumnBehavior.shouldIgnoreValue(values)) {
// return QueryCondition.createEmpty();
// }
return between_(values);
}
@ -538,9 +563,9 @@ public class QueryColumn implements CloneSupport<QueryColumn>, Conditional<Query
@Override
public QueryCondition between(Object start, Object end) {
if (QueryColumnBehavior.shouldIgnoreValue(start) || QueryColumnBehavior.shouldIgnoreValue(end)) {
return QueryCondition.createEmpty();
}
// if (QueryColumnBehavior.shouldIgnoreValue(start) || QueryColumnBehavior.shouldIgnoreValue(end)) {
// return QueryCondition.createEmpty();
// }
return between_(start, end);
}
@ -576,9 +601,9 @@ public class QueryColumn implements CloneSupport<QueryColumn>, Conditional<Query
@Override
public QueryCondition notBetween(Object[] values) {
if (QueryColumnBehavior.shouldIgnoreValue(values)) {
return QueryCondition.createEmpty();
}
// if (QueryColumnBehavior.shouldIgnoreValue(values)) {
// return QueryCondition.createEmpty();
// }
return notBetween_(values);
}
@ -592,9 +617,9 @@ public class QueryColumn implements CloneSupport<QueryColumn>, Conditional<Query
@Override
public QueryCondition notBetween(Object start, Object end) {
if (QueryColumnBehavior.shouldIgnoreValue(start) || QueryColumnBehavior.shouldIgnoreValue(end)) {
return QueryCondition.createEmpty();
}
// if (QueryColumnBehavior.shouldIgnoreValue(start) || QueryColumnBehavior.shouldIgnoreValue(end)) {
// return QueryCondition.createEmpty();
// }
return notBetween_(start, end);
}
@ -892,7 +917,7 @@ public class QueryColumn implements CloneSupport<QueryColumn>, Conditional<Query
}
////order by ////
/// /order by ////
public QueryOrderBy asc() {
return new QueryOrderBy(this, SqlConsts.ASC);
}
@ -936,6 +961,10 @@ public class QueryColumn implements CloneSupport<QueryColumn>, Conditional<Query
return new ArithmeticQueryColumn(this).divide(number);
}
public QueryColumn cast(String dataType) {
return new CastQueryColumn(this, dataType);
}
/**
* 生成列用于构建查询条件的 SQL 语句
*

View File

@ -94,7 +94,12 @@ public class QueryColumnBehavior {
/**
* {@code IN(...)} 条件只有 1 个参数时是否自动把的内容转换为相等
*/
private static boolean smartConvertInToEquals = false;
private static boolean smartConvertInToEquals = true;
/**
* {@code BETWEEN ... AND ...} 条件只有 1 个参数时是否自动把的内容转换为小于等于或大于等于
*/
private static boolean smartConvertBetweenToLeOrGe = true;
public static Predicate<Object> getIgnoreFunction() {
return ignoreFunction;
@ -112,6 +117,14 @@ public class QueryColumnBehavior {
QueryColumnBehavior.smartConvertInToEquals = smartConvertInToEquals;
}
public static boolean isSmartConvertBetweenToLeOrGe() {
return smartConvertBetweenToLeOrGe;
}
public static void setSmartConvertBetweenToLeOrGe(boolean smartConvertBetweenToLeOrGe) {
QueryColumnBehavior.smartConvertBetweenToLeOrGe = smartConvertBetweenToLeOrGe;
}
static boolean shouldIgnoreValue(Object value) {
return ignoreFunction.test(value);
}

View File

@ -35,7 +35,7 @@ public class QueryMethods {
private QueryMethods() {
}
// === 数学函数 ===
//region === 数学函数 ===
/**
* 返回 x 的绝对值
@ -680,8 +680,9 @@ public class QueryMethods {
public static <T> QueryColumn cot(LambdaGetter<T> columnX) {
return new FunctionQueryColumn(COT, LambdaUtil.getQueryColumn(columnX));
}
//endregion === 数学函数 ===
// === 字符串函数 ===
//region === 字符串函数 ===
/**
* 返回字符串 s 的字符数
@ -1181,8 +1182,9 @@ public class QueryMethods {
public static <S1, S2> QueryColumn findInSet(LambdaGetter<S1> columnS1, LambdaGetter<S2> columnS2) {
return new FunctionQueryColumn(FIND_IN_SET, LambdaUtil.getQueryColumn(columnS1), LambdaUtil.getQueryColumn(columnS2));
}
//endregion === 字符串函数 ===
// === 日期时间函数 ===
//region === 日期时间函数 ===
/**
* 返回当前日期
@ -1884,8 +1886,9 @@ public class QueryMethods {
public static <T, S> QueryColumn getFormat(LambdaGetter<T> columnType, LambdaGetter<S> columnS) {
return new FunctionQueryColumn(GET_FORMAT, LambdaUtil.getQueryColumn(columnType), LambdaUtil.getQueryColumn(columnS));
}
//endregion === 日期时间函数 ===
// === 系统信息函数 ===
//region === 系统信息函数 ===
/**
* 返回数据库的版本号
@ -1970,8 +1973,9 @@ public class QueryMethods {
public static QueryColumn lastInsertId() {
return new FunctionQueryColumn(LAST_INSERT_ID);
}
//endregion === 系统信息函数 ===
// === 加密函数 ===
//region === 加密函数 ===
/**
* 对字符串 str 进行加密
@ -2056,8 +2060,9 @@ public class QueryMethods {
public static <C, P> QueryColumn decode(LambdaGetter<C> columnCryptStr, LambdaGetter<P> columnPswdStr) {
return new FunctionQueryColumn(DECODE, LambdaUtil.getQueryColumn(columnCryptStr), LambdaUtil.getQueryColumn(columnPswdStr));
}
//endregion === 加密函数 ===
// === 其他函数 ===
//region === 其他函数 ===
/**
* 格式化函数可以将数字 x 进行格式化 x 保留到小数点后 n 这个过程需要进行四舍五入
@ -2226,8 +2231,9 @@ public class QueryMethods {
public static <T> QueryColumn inetNtoa(LambdaGetter<T> columnN) {
return new FunctionQueryColumn(INET_NTOA, LambdaUtil.getQueryColumn(columnN));
}
//endregion === 其他函数 ===
// === 聚合函数 ===
//region === 聚合函数 ===
/**
* 返回指定列的最大值
@ -2312,8 +2318,9 @@ public class QueryMethods {
public static <T> FunctionQueryColumn sum(LambdaGetter<T> column) {
return new FunctionQueryColumn(SUM, LambdaUtil.getQueryColumn(column));
}
//endregion === 聚合函数 ===
// === COUNT ===
//region === COUNT ===
/**
* 返回指定列的总行数
@ -2342,9 +2349,9 @@ public class QueryMethods {
public static <T> FunctionQueryColumn count(LambdaGetter<T> column) {
return new FunctionQueryColumn(COUNT, LambdaUtil.getQueryColumn(column));
}
//endregion === COUNT ===
// === DISTINCT ===
//region === DISTINCT ===
/**
* 对指定列进行去重
@ -2358,8 +2365,9 @@ public class QueryMethods {
return new DistinctQueryColumn(Arrays.stream(columns)
.map(LambdaUtil::getQueryColumn).toArray(QueryColumn[]::new));
}
//endregion === DISTINCT ===
// === CASE THEN ELSE ===
//region === CASE THEN ELSE ===
/**
* 构建 case then when 语句
@ -2374,8 +2382,9 @@ public class QueryMethods {
public static CaseSearchQueryColumn.Builder case_(QueryColumn column) {
return new CaseSearchQueryColumn.Builder(column);
}
//endregion === CASE THEN ELSE ===
// === CONVERT ===
//region === CONVERT ===
/**
* 将所给类型类型转换为另一种类型
@ -2383,8 +2392,9 @@ public class QueryMethods {
public static StringFunctionQueryColumn convert(String... params) {
return new StringFunctionQueryColumn(CONVERT, params);
}
//endregion === CONVERT ===
// === 构建 column ===
//region === 构建 column ===
/**
* 构建 TRUE 常量
@ -2494,8 +2504,9 @@ public class QueryMethods {
}
return queryColumns;
}
//endregion === 构建 column ===
// === IF 函数 ===
//region === IF 函数 ===
/**
* IF 函数
@ -2552,9 +2563,9 @@ public class QueryMethods {
public static <N> QueryColumn ifNull(LambdaGetter<N> nullColumn, String elseColumn) {
return ifNull(nullColumn, new QueryColumn(elseColumn));
}
//endregion === IF 函数 ===
// === 构建 QueryCondition 查询条件 ===
//region === 构建 QueryCondition 查询条件 ===
/**
* EXIST (SELECT ...)
@ -2597,8 +2608,9 @@ public class QueryMethods {
public static QueryCondition bracket(QueryCondition condition) {
return new Brackets(condition);
}
//endregion === 构建 QueryCondition 查询条件 ===
// === 构建 QueryWrapper 查询 ===
//region === 构建 QueryWrapper 查询 ===
/**
* SELECT queryColumns FROM table
@ -2666,6 +2678,51 @@ public class QueryMethods {
return new FunctionQueryColumn(GROUP_CONCAT, columnX);
}
/**
* STRING_AGG 聚合函数
*/
public static QueryColumn stringAgg(QueryColumn columnX, String separator) {
return new FunctionQueryColumn(STRING_AGG, columnX, string(separator));
}
public static QueryColumn stringAgg(String columnX, String separator) {
return new FunctionQueryColumn(STRING_AGG, columnX, separator);
}
public static <T> QueryColumn stringAgg(LambdaGetter<T> columnX, String separator) {
return new FunctionQueryColumn(STRING_AGG, LambdaUtil.getQueryColumn(columnX), string(separator));
}
/**
* LISTAGG 聚合函数
*/
public static QueryColumn listAgg(QueryColumn column, String separator) {
return new FunctionQueryColumn(LISTAGG, column, string(separator));
}
public static QueryColumn listAgg(String column, String separator) {
return new FunctionQueryColumn(STRING_AGG, column, separator);
}
public static <T> QueryColumn listAgg(LambdaGetter<T> column, String separator) {
return new FunctionQueryColumn(STRING_AGG, LambdaUtil.getQueryColumn(column), string(separator));
}
/**
* CAST函数查询列
*/
public static <T> QueryColumn cast(QueryColumn column, String dataType) {
return new CastQueryColumn(column, dataType);
}
public static <T> QueryColumn cast(String column, String dataType) {
return new CastQueryColumn(column, dataType);
}
public static <T> QueryColumn cast(LambdaGetter<T> column, String dataType) {
return new CastQueryColumn(LambdaUtil.getQueryColumn(column), dataType);
}
/**
* date 函数
* @return
@ -2673,5 +2730,5 @@ public class QueryMethods {
public static FunctionQueryColumn date(QueryColumn column) {
return new FunctionQueryColumn("DATE", column);
}
//endregion === 构建 QueryWrapper 查询 ===
}

View File

@ -66,6 +66,13 @@ public class QueryOrderBy implements CloneSupport<QueryOrderBy> {
return this;
}
public QueryColumn getQueryColumn() {
return this.queryColumn;
}
public String getOrderType() {
return this.orderType;
}
public String toSql(List<QueryTable> queryTables, IDialect dialect) {
String sql = queryColumn.toConditionSql(queryTables, dialect) + orderType;

View File

@ -867,7 +867,7 @@ public class QueryWrapperAdapter<R extends QueryWrapperAdapter<R>> extends Query
*/
@Override
public R ge(String column, Object value) {
and(QueryMethods.column(column).ge_(value));
and(QueryMethods.column(column).ge(value));
return (R) this;
}
@ -879,7 +879,7 @@ public class QueryWrapperAdapter<R extends QueryWrapperAdapter<R>> extends Query
*/
@Override
public <T> R ge(LambdaGetter<T> column, Object value) {
and(QueryMethods.column(column).ge_(value));
and(QueryMethods.column(column).ge(value));
return (R) this;
}

View File

@ -50,7 +50,12 @@ class WrapperUtil {
}
}
// not Brackets
else {
else if (condition instanceof OperatorSelectCondition) {
if (list == null) {
list = new ArrayList<>();
}
list.add(((OperatorSelectCondition) condition).getQueryWrapper());
} else {
Object value = condition.getValue();
if (value instanceof QueryWrapper) {
if (list == null) {

View File

@ -86,8 +86,9 @@ public abstract class AbstractRelation<SelfEntity> {
this.selfField = ClassUtil.getFirstField(entityClass, field -> field.getName().equalsIgnoreCase(selfField));
this.selfFieldWrapper = FieldWrapper.of(entityClass, selfField);
String tableNameWithSchema = StringUtil.buildSchemaWithTable(targetSchema, targetTable);
//以使用者注解配置为主
this.targetTableInfo = StringUtil.noText(targetTable) ? TableInfoFactory.ofEntityClass(relationFieldWrapper.getMappingType()) : TableInfoFactory.ofTableName(targetTable);
this.targetTableInfo = StringUtil.noText(targetTable) ? TableInfoFactory.ofEntityClass(relationFieldWrapper.getMappingType()) : TableInfoFactory.ofTableName(tableNameWithSchema);
this.targetSchema = targetTableInfo != null ? targetTableInfo.getSchema() : targetSchema;
this.targetTable = targetTableInfo != null ? targetTableInfo.getTableName() : targetTable;

View File

@ -74,6 +74,10 @@ public class ToManyRelation<SelfEntity> extends AbstractRelation<SelfEntity> {
}
String[] splitValues = ((String) targetValue).split(selfValueSplitBy);
for (String splitValue : splitValues) {
// 排除空值
if (splitValue == null || splitValue.isEmpty()) {
continue;
}
//优化分割后的数据类型(防止在数据库查询时候出现隐式转换)
newTargetValues.add(ConvertUtil.convert(splitValue, targetFieldWrapper.getFieldType()));
}

View File

@ -15,6 +15,7 @@
*/
package com.mybatisflex.core.row;
import com.mybatisflex.core.mybatis.MappedStatementTypes;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import org.apache.ibatis.executor.BatchResult;
@ -36,10 +37,21 @@ public class RowMapperInvoker {
this.sqlSessionFactory = sqlSessionFactory;
}
private <R> R execute(Function<RowMapper, R> function) {
try (SqlSession sqlSession = sqlSessionFactory.openSession(true)) {
RowMapper mapper = sqlSession.getMapper(RowMapper.class);
return function.apply(mapper);
protected <R> R execute(Function<RowMapper, R> function) {
Class<?> currentType = MappedStatementTypes.getCurrentType();
if (currentType == null) {
try (SqlSession sqlSession = sqlSessionFactory.openSession(true)) {
RowMapper mapper = sqlSession.getMapper(RowMapper.class);
return function.apply(mapper);
}
} else {
MappedStatementTypes.clear();
try (SqlSession sqlSession = sqlSessionFactory.openSession(true)) {
RowMapper mapper = sqlSession.getMapper(RowMapper.class);
return function.apply(mapper);
} finally {
MappedStatementTypes.setCurrentType(currentType);
}
}
}
@ -115,7 +127,6 @@ public class RowMapperInvoker {
}
public <M> int[] executeBatch(int totalSize, int batchSize, Class<M> mapperClass, BiConsumer<M, Integer> consumer) {
int[] results = new int[totalSize];
try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, true)) {
@ -189,12 +200,15 @@ public class RowMapperInvoker {
public List<Row> selectAll(String schema, String tableName) {
return execute(mapper -> mapper.selectAll(schema, tableName));
}
public Map selectFirstAndSecondColumnsAsMapByQuery(String schema, String tableName, QueryWrapper queryWrapper) {
return execute(mapper -> mapper.selectFirstAndSecondColumnsAsMapByQuery(schema, tableName, queryWrapper));
}
public Map selectFirstAndSecondColumnsAsMap(String sql, Object... args) {
return execute(mapper -> mapper.selectFirstAndSecondColumnsAsMap(sql, args));
}
public Object selectObjectByQuery(String schema, String tableName, QueryWrapper queryWrapper) {
return execute(mapper -> mapper.selectObjectByQuery(schema, tableName, queryWrapper));
}

View File

@ -51,7 +51,7 @@ public interface IService<T> {
*/
BaseMapper<T> getMapper();
// ===== 保存操作 =====
//region ===== 保存操作 =====
/**
* <p>保存实体类对象数据
@ -128,8 +128,9 @@ public interface IService<T> {
Class<BaseMapper<T>> usefulClass = (Class<BaseMapper<T>>) ClassUtil.getUsefulClass(getMapper().getClass());
return SqlUtil.toBool(Db.executeBatch(entities, batchSize, usefulClass, BaseMapper::insertOrUpdateSelective));
}
//endregion ===== 保存操作 =====
// ===== 删除操作 =====
//region ===== 删除操作 =====
/**
* <p>根据查询条件删除数据
@ -197,8 +198,9 @@ public interface IService<T> {
}
return remove(query().where(query));
}
//endregion ===== 删除操作 =====
// ===== 更新操作 =====
//region ===== 更新操作 =====
/**
* <p>根据数据主键更新数据
@ -313,8 +315,9 @@ public interface IService<T> {
Class<BaseMapper<T>> usefulClass = (Class<BaseMapper<T>>) ClassUtil.getUsefulClass(getMapper().getClass());
return SqlUtil.toBool(Db.executeBatch(entities, batchSize, usefulClass, (mapper, entity) -> mapper.update(entity, ignoreNulls)));
}
//endregion ===== 更新操作 =====
// ===== 查询操作 =====
//region ===== 查询操作 =====
/**
* <p>根据数据主键查询一条数据
@ -546,8 +549,9 @@ public interface IService<T> {
default List<T> listByMap(Map<String, Object> query) {
return list(query().where(query));
}
//endregion ===== 查询操作 =====
// ===== 数量查询操作 =====
//region ===== 数量查询操作 =====
/**
* <p>根据查询条件判断数据是否存在
@ -605,8 +609,9 @@ public interface IService<T> {
default long count(QueryCondition condition) {
return count(query().where(condition));
}
//endregion ===== 数量查询操作 =====
// ===== 分页查询操作 =====
//region ===== 分页查询操作 =====
/**
* <p>分页查询所有数据
@ -651,8 +656,9 @@ public interface IService<T> {
default <R> Page<R> pageAs(Page<R> page, QueryWrapper query, Class<R> asType) {
return getMapper().paginateAs(page, query, asType);
}
//endregion ===== 分页查询操作 =====
// ===== 查询包装器操作 =====
//region ===== 查询包装器操作 =====
/**
* 默认 {@link QueryWrapper} 构建
@ -680,5 +686,5 @@ public interface IService<T> {
default UpdateChain<T> updateChain() {
return UpdateChain.create(getMapper());
}
//endregion ===== 查询包装器操作 =====
}

View File

@ -70,18 +70,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.StringJoiner;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -616,6 +605,7 @@ public class TableInfo {
public Set<String> obtainUpdateColumns(Object entity, boolean ignoreNulls, boolean includePrimary) {
MetaObject metaObject = EntityMetaObject.forObject(entity, reflectorFactory);
Set<String> columns = new LinkedHashSet<>(); // 需使用 LinkedHashSet 保证 columns 的顺序
boolean isIgnoreTenantCondition = TenantManager.isIgnoreTenantCondition();
if (entity instanceof UpdateWrapper) {
Map<String, Object> updates = ((UpdateWrapper) entity).getUpdates();
if (updates.isEmpty()) {
@ -629,8 +619,13 @@ public class TableInfo {
continue;
}
// 过滤乐观锁字段 租户字段
if (ObjectUtil.equalsAny(column, versionColumn, tenantIdColumn)) {
// 忽略租户字段时 不要过滤租户字段
if(isIgnoreTenantCondition){
if (Objects.equals(column, versionColumn)) {
continue;
}
// 过滤乐观锁字段 租户字段
}else if (ObjectUtil.equalsAny(column, versionColumn, tenantIdColumn)) {
continue;
}
@ -654,8 +649,13 @@ public class TableInfo {
continue;
}
// 过滤乐观锁字段 租户字段
if (ObjectUtil.equalsAny(column, versionColumn, tenantIdColumn)) {
// 忽略租户字段时 不要过滤租户字段
if(isIgnoreTenantCondition){
if (Objects.equals(column, versionColumn)) {
continue;
}
// 过滤乐观锁字段 租户字段
}else if (ObjectUtil.equalsAny(column, versionColumn, tenantIdColumn)) {
continue;
}
@ -679,6 +679,7 @@ public class TableInfo {
public Object[] buildUpdateSqlArgs(Object entity, boolean ignoreNulls, boolean includePrimary) {
List<Object> values = new ArrayList<>();
boolean isIgnoreTenantCondition = TenantManager.isIgnoreTenantCondition();
if (entity instanceof UpdateWrapper) {
Map<String, Object> updates = ((UpdateWrapper) entity).getUpdates();
if (updates.isEmpty()) {
@ -691,8 +692,13 @@ public class TableInfo {
if (onUpdateColumns != null && onUpdateColumns.containsKey(column)) {
continue;
}
// 过滤乐观锁字段 租户字段
if (ObjectUtil.equalsAny(column, versionColumn, tenantIdColumn)) {
// 忽略租户字段时 不要过滤租户字段
if(isIgnoreTenantCondition){
if (Objects.equals(column, versionColumn)) {
continue;
}
// 过滤乐观锁字段 租户字段
}else if (ObjectUtil.equalsAny(column, versionColumn, tenantIdColumn)) {
continue;
}
@ -739,8 +745,13 @@ public class TableInfo {
continue;
}
// 过滤乐观锁字段 租户字段
if (ObjectUtil.equalsAny(column, versionColumn, tenantIdColumn)) {
// 忽略租户字段时 不要过滤租户字段
if(isIgnoreTenantCondition){
if (Objects.equals(column, versionColumn)) {
continue;
}
// 过滤乐观锁字段 租户字段
}else if (ObjectUtil.equalsAny(column, versionColumn, tenantIdColumn)) {
continue;
}
@ -845,11 +856,16 @@ public class TableInfo {
public void buildTenantCondition(QueryWrapper queryWrapper) {
Object[] tenantIdArgs = buildTenantIdArgs();
// 优先使用 join 表的 alias
String tableAlias =
Optional.ofNullable(CPI.getContext(queryWrapper).get("joinTableAlias"))
.map(String::valueOf)
.orElse(tableName);
if (ArrayUtil.isNotEmpty(tenantIdArgs)) {
if (tenantIdArgs.length == 1) {
queryWrapper.where(QueryCondition.create(schema, tableName, tenantIdColumn, SqlConsts.EQUALS, tenantIdArgs[0]));
queryWrapper.where(QueryCondition.create(schema, tableAlias, tenantIdColumn, SqlConsts.EQUALS, tenantIdArgs[0]));
} else {
queryWrapper.where(QueryCondition.create(schema, tableName, tenantIdColumn, SqlConsts.IN, tenantIdArgs));
queryWrapper.where(QueryCondition.create(schema, tableAlias, tenantIdColumn, SqlConsts.IN, tenantIdArgs));
}
}
}

View File

@ -235,6 +235,8 @@ public class TableInfoFactory {
Reflector reflector = Reflectors.of(entityClass);
tableInfo.setReflector(reflector);
FlexGlobalConfig config = FlexGlobalConfig.getDefaultConfig();
// 初始化表名
Table table = entityClass.getAnnotation(Table.class);
if (table == null) {
@ -242,7 +244,9 @@ public class TableInfoFactory {
if (vo != null) {
TableInfo refTableInfo = ofEntityClass(vo.value());
// 设置 VO 类对应的真实的表名
tableInfo.setSchema(refTableInfo.getSchema());
if (!config.isIgnoreSchema()) {
tableInfo.setSchema(refTableInfo.getSchema());
}
tableInfo.setTableName(refTableInfo.getTableName());
// @Table 注解的属性复制到 VO 类当中
if (vo.copyTableProps()) {
@ -260,7 +264,9 @@ public class TableInfoFactory {
tableInfo.setTableName(tableName);
}
} else {
tableInfo.setSchema(table.schema());
if (!config.isIgnoreSchema()) {
tableInfo.setSchema(table.schema());
}
tableInfo.setTableName(table.value());
tableInfo.setCamelToUnderline(table.camelToUnderline());
tableInfo.setComment(table.comment());
@ -317,8 +323,6 @@ public class TableInfoFactory {
List<Field> entityFields = getColumnFields(entityClass);
FlexGlobalConfig config = FlexGlobalConfig.getDefaultConfig();
TypeHandlerRegistry typeHandlerRegistry = null;
if (config.getConfiguration() != null) {
typeHandlerRegistry = config.getConfiguration().getTypeHandlerRegistry();

View File

@ -66,6 +66,12 @@ public class TenantManager {
ignoreFlags.set(Boolean.TRUE);
}
/**
* 是否忽略 tenant 条件
*/
public static boolean isIgnoreTenantCondition() {
return Boolean.TRUE.equals(ignoreFlags.get());
}
/**
* 恢复 tenant 条件
@ -83,8 +89,7 @@ public class TenantManager {
}
public static Object[] getTenantIds(String tableName) {
Boolean ignoreFlag = ignoreFlags.get();
if (ignoreFlag != null && ignoreFlag) {
if (isIgnoreTenantCondition()) {
return null;
}
return tenantFactory != null ? tenantFactory.getTenantIds(tableName) : null;

View File

@ -19,30 +19,43 @@ package com.mybatisflex.core.transaction;
* 事务的传递方式参考 spring
*/
public enum Propagation {
//若存在当前事务则加入当前事务若不存在当前事务则创建新的事务
/**
* 若存在当前事务则加入当前事务若不存在当前事务则创建新的事务
*/
REQUIRED(0),
//若存在当前事务则加入当前事务若不存在当前事务则已非事务的方式运行
/**
* 若存在当前事务则加入当前事务若不存在当前事务则已非事务的方式运行
*/
SUPPORTS(1),
//若存在当前事务则加入当前事务若不存在当前事务则抛出异常
/**
* 若存在当前事务则加入当前事务若不存在当前事务则抛出异常
*/
MANDATORY(2),
//始终以新事务的方式运行若存在当前事务则暂停挂起当前事务
/**
* 始终以新事务的方式运行若存在当前事务则暂停挂起当前事务
*/
REQUIRES_NEW(3),
//以非事务的方式运行若存在当前事务则暂停挂起当前事务
/**
* 以非事务的方式运行若存在当前事务则暂停挂起当前事务
*/
NOT_SUPPORTED(4),
//以非事务的方式运行若存在当前事务则抛出异常
/**
* 以非事务的方式运行若存在当前事务则抛出异常
*/
NEVER(5),
//如果存在当前事务则在嵌套事务中执行否则行为类似于 PROPAGATION_REQUIRED
/**
* 如果存在当前事务则在嵌套事务中执行否则行为类似于 PROPAGATION_REQUIRED
*/
NESTED(6),
;
private int value;
private final int value;
Propagation(int value) {
this.value = value;
@ -51,8 +64,4 @@ public enum Propagation {
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}

View File

@ -18,6 +18,7 @@ package com.mybatisflex.core.update;
import com.mybatisflex.core.exception.FlexExceptions;
import com.mybatisflex.core.util.ClassUtil;
import com.mybatisflex.core.util.MapUtil;
import org.apache.ibatis.javassist.util.proxy.Proxy;
import org.apache.ibatis.javassist.util.proxy.ProxyFactory;
import org.apache.ibatis.javassist.util.proxy.ProxyObject;
@ -56,10 +57,16 @@ public class ModifyAttrsRecordProxyFactory {
T proxyObject;
try {
proxyObject = (T) ClassUtil.newInstance(proxyClass);
((ProxyObject) proxyObject).setHandler(new ModifyAttrsRecordHandler());
} catch (Exception e) {
throw FlexExceptions.wrap(e, "请为实体类 %s 添加公开的无参构造器!", target.getCanonicalName());
}
if (proxyObject instanceof ProxyObject) {
((ProxyObject) proxyObject).setHandler(new ModifyAttrsRecordHandler());
} else if (proxyObject instanceof Proxy) {
((Proxy) proxyObject).setHandler(new ModifyAttrsRecordHandler());
} else {
throw FlexExceptions.wrap("为实体类 %s 设置字段更新处理器时出错,获取的实体类代理对象既不是 ProxyObject 的实例,也不是 Proxy 的实例", target.getCanonicalName());
}
return proxyObject;
}

View File

@ -15,12 +15,15 @@
*/
package com.mybatisflex.core.update;
import com.mybatisflex.core.exception.FlexExceptions;
import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.util.LambdaGetter;
import com.mybatisflex.core.util.LambdaUtil;
import com.mybatisflex.core.util.UpdateEntity;
import org.apache.ibatis.javassist.util.proxy.Proxy;
import org.apache.ibatis.javassist.util.proxy.ProxyFactory;
import org.apache.ibatis.javassist.util.proxy.ProxyObject;
import java.io.Serializable;
@ -32,7 +35,14 @@ import java.util.Map;
public interface UpdateWrapper<T> extends PropertySetter<UpdateWrapper<T>>, Serializable {
default Map<String, Object> getUpdates() {
ModifyAttrsRecordHandler handler = (ModifyAttrsRecordHandler) ((ProxyObject) this).getHandler();
ModifyAttrsRecordHandler handler = null;
if (this instanceof ProxyObject) {
handler = (ModifyAttrsRecordHandler) ((ProxyObject) this).getHandler();
} else if (this instanceof Proxy) {
handler = (ModifyAttrsRecordHandler) ProxyFactory.getHandler((Proxy) this);
} else {
throw FlexExceptions.wrap("获取实体类代理对象 %s 的字段更新处理器时出错,该对象既不是 ProxyObject 的实例,也不是 Proxy 的实例", this.getClass().getName());
}
return handler.getUpdates();
}

View File

@ -77,13 +77,22 @@ public class EnumWrapper<E extends Enum<E>> {
if (!(methodName.startsWith("get") && methodName.length() > 3)) {
throw new IllegalStateException("Can not find get method \"" + methodName + "()\" in enum: " + enumClass.getName());
}
String enumValueFieldName;
if (methodName.startsWith("get")) {
enumValueFieldName = StringUtil.firstCharToLowerCase(enumValueMethod.getName().substring(3));
} else {
enumValueFieldName = enumValueMethod.getName().toLowerCase();
}
enumValueField = ClassUtil.getFirstField(enumClass, field -> enumValueFieldName.equals(field.getName()));
if (enumValueField != null) {
propertyType = ClassUtil.getWrapType(enumValueField.getType());
} else {
throw new IllegalStateException("Can not find field \"" + enumValueFieldName + "()\" in enum: " + enumClass.getName());
}
this.getterMethod = enumValueMethod;
this.hasEnumValueAnnotation = true;
Class<?> returnType = enumValueMethod.getReturnType();
if (returnType.isPrimitive()) {
returnType = ConvertUtil.primitiveToBoxed(returnType);
}
this.propertyType = returnType;
}
}
}

View File

@ -35,6 +35,10 @@ public class LambdaUtil {
private static final Map<Class<?>, Class<?>> implClassMap = new ConcurrentHashMap<>();
private static final Map<Class<?>, QueryColumn> queryColumnMap = new ConcurrentHashMap<>();
public static Map<Class<?>, String> getFieldNameMap() {
return fieldNameMap;
}
public static <T> String getFieldName(LambdaGetter<T> getter) {
return MapUtil.computeIfAbsent(fieldNameMap, getter.getClass(), aClass -> {
SerializedLambda lambda = getSerializedLambda(getter);

View File

@ -0,0 +1,18 @@
package com.mybatisflex.core.util;
import org.junit.Assert;
import org.junit.Test;
public class LambdaUtilTest {
@Test
public void testIssue516() {
for (int i = 0; i < 100; i++) {
LambdaUtil.getFieldName(TestAccount::getName);
}
Assert.assertEquals(LambdaUtil.getFieldNameMap().size(), 1);
System.out.println("testIssue516");
}
}

View File

@ -0,0 +1,23 @@
package com.mybatisflex.core.util;
public class TestAccount {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}

View File

@ -400,7 +400,7 @@ public class AccountSqlTester {
Assert.assertEquals("SELECT * FROM `tb_account` " +
"WHERE `id` >= 100 " +
"AND EXISTS (SELECT 1 AS `temp_one` FROM `tb_article` AS `a` WHERE `id` >= 100)"
"AND EXISTS (SELECT 1 AS `temp_one` FROM `tb_article` AS `a` WHERE `a`.`id` >= 100)"
, query.toSQL());
System.out.println(query.toSQL());

View File

@ -0,0 +1,21 @@
package com.mybatisflex.coretest;
import com.mybatisflex.core.query.Assert;
import com.mybatisflex.core.query.QueryWrapper;
import org.junit.Test;
import static com.mybatisflex.core.query.QueryMethods.column;
public class AssertTest {
@Test(expected = IllegalArgumentException.class)
public void testAssert() {
String testArg = null;
QueryWrapper queryWrapper = new QueryWrapper()
.from("account")
.where(column("id").eq(1, Assert::notNull))
.and(column("name").eq(testArg, Assert::hasText));
}
}

View File

@ -259,7 +259,7 @@ public class DynamicConditionTest {
@Test
public void testCastFunction1() {
QueryCondition condition = QueryCondition.create(new QueryColumn("id"), SqlOperator.IN, new Object[]{null});
Assert.assertSame(condition, getConditionCaster().apply(condition));
Assert.assertNotSame(condition, getConditionCaster().apply(condition));
}
@Test

View File

@ -80,4 +80,34 @@ public class QueryWrapperTest {
Assert.assertEquals(CPI.getValueArray(wrapper).length, 3);
}
/**
* https://github.com/mybatis-flex/mybatis-flex/issues/491
*/
@Test
public void testIssues491() {
String demo1 = "SELECT c1 FROM ((SELECT 1 as c1) UNION ALL (SELECT 2 as c1) UNION ALL (SELECT 3 as c1)) AS `t`";
QueryWrapper query1 = QueryWrapper.create()
.select("c1")
.from(QueryWrapper.create().select("1 as c1")
.unionAll(QueryWrapper.create().select("2 as c1"))
.unionAll(QueryWrapper.create().select("3 as c1")))
.as("t");
Assert.assertTrue(query1.toSQL().equals(demo1));
String demo2 = "SELECT c1 FROM ((SELECT 1 as c1 FROM dual) UNION ALL (SELECT 2 as c1 FROM dual) UNION ALL " +
"(SELECT 3 as c1 FROM dual)) AS `t`";
QueryWrapper query2 = QueryWrapper.create()
.select("c1")
.from(QueryWrapper.create().select("1 as c1").from("dual")
.unionAll(QueryWrapper.create().select("2 as c1").from("dual"))
.unionAll(QueryWrapper.create().select("3 as c1").from("dual")))
.as("t");
Assert.assertTrue(query2.toSQL().equals(demo2));
}
}

View File

@ -0,0 +1,14 @@
package com.mybatisflex.coretest;
import com.mybatisflex.core.util.UpdateEntity;
import org.junit.Assert;
import org.junit.Test;
public class UpdateEntityTest {
@Test
public void testIssuesIBYEZ7() {
Article article = UpdateEntity.of(Article.class, 1);
Assert.assertEquals(1, (long) article.getId());
}
}

View File

@ -4,9 +4,14 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mybatis-flex</groupId>
<parent>
<groupId>com.mybatis-flex</groupId>
<artifactId>parent</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>mybatis-flex-dependencies</artifactId>
<version>1.10.7</version>
<packaging>pom</packaging>
@ -48,7 +53,6 @@
</developer>
</developers>
<properties>
<mybatis-flex.version>1.10.7</mybatis-flex.version>
</properties>
<dependencyManagement>
@ -56,46 +60,52 @@
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-annotation</artifactId>
<version>${mybatis-flex.version}</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-codegen</artifactId>
<version>${mybatis-flex.version}</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-core</artifactId>
<version>${mybatis-flex.version}</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-processor</artifactId>
<version>${mybatis-flex.version}</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-solon-plugin</artifactId>
<version>${mybatis-flex.version}</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring</artifactId>
<version>${mybatis-flex.version}</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot-starter</artifactId>
<version>${mybatis-flex.version}</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot3-starter</artifactId>
<version>${mybatis-flex.version}</version>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-spring-boot4-starter</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<resources>
<resource>
@ -107,6 +117,7 @@
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
@ -117,92 +128,201 @@
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- Source -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.4</version>
<configuration>
<windowtitle>MybatisFlex</windowtitle>
<doctitle>MybatisFlex</doctitle>
<show>private</show>
<detectLinks>false</detectLinks>
<detectOfflineLinks>true</detectOfflineLinks>
<linksource>true</linksource>
<additionalparam>-Xdoclint:none</additionalparam>
<detectJavaApiLink>true</detectJavaApiLink>
<source>8</source>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc -->
<!-- Gpg Signature -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonatype.central</groupId>
<artifactId>central-publishing-maven-plugin</artifactId>
<version>0.7.0</version>
<extensions>true</extensions>
<configuration>
<publishingServerId>central</publishingServerId>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>${flatten-maven-plugin.version}</version>
<inherited>false</inherited>
<executions>
<execution>
<!-- Create an effective POM (with versions expanded) for the CLI and
documentation -->
<id>flatten-effective-pom</id>
<phase>process-resources</phase>
<goals>
<goal>flatten</goal>
</goals>
<configuration>
<updatePomFile>false</updatePomFile>
<outputDirectory>${project.build.directory}/effective-pom</outputDirectory>
<flattenMode>resolveCiFriendliesOnly</flattenMode>
<pomElements>
<dependencyManagement>expand</dependencyManagement>
<pluginManagement>expand</pluginManagement>
<properties>remove</properties>
<repositories>remove</repositories>
</pomElements>
</configuration>
</execution>
<execution>
<!-- Flatten and simplify our own POM for install/deploy -->
<id>flatten</id>
<phase>process-resources</phase>
<goals>
<goal>flatten</goal>
</goals>
<configuration>
<updatePomFile>true</updatePomFile>
<flattenMode>bom</flattenMode>
<pomElements>
<pluginManagement>keep</pluginManagement>
<properties>keep</properties>
<repositories>remove</repositories>
</pomElements>
</configuration>
</execution>
<execution>
<id>flatten-clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>xml-maven-plugin</artifactId>
<version>${xml-maven-plugin.version}</version>
<inherited>false</inherited>
<executions>
<execution>
<!-- Cleanup the effective POM -->
<id>post-process-effective-pom</id>
<phase>process-resources</phase>
<goals>
<goal>transform</goal>
</goals>
<configuration>
<transformationSets>
<transformationSet>
<dir>${project.build.directory}/effective-pom</dir>
<outputDir>${project.build.directory}/effective-pom</outputDir>
<stylesheet>src/main/xslt/post-process-flattened-pom.xsl</stylesheet>
<outputProperties>
<outputProperty>
<name>indent</name>
<value>yes</value>
</outputProperty>
</outputProperties>
</transformationSet>
</transformationSets>
</configuration>
</execution>
<execution>
<!-- Cleanup the flattened project POM -->
<id>post-process-flattened-pom</id>
<phase>process-resources</phase>
<goals>
<goal>transform</goal>
</goals>
<configuration>
<transformationSets>
<transformationSet>
<dir>${project.basedir}</dir>
<outputDir>${project.basedir}</outputDir>
<includes>.flattened-pom.xml</includes>
<stylesheet>src/main/xslt/post-process-flattened-pom.xsl</stylesheet>
<outputProperties>
<outputProperty>
<name>indent</name>
<value>yes</value>
</outputProperty>
</outputProperties>
</transformationSet>
</transformationSets>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<!-- 跳过测试mvn package -Dmaven.test.skip=true -->
<!-- 检测依赖最新版本mvn versions:display-dependency-updates -->
<!-- 统一修改版本号mvn versions:set -DnewVersion=3.0 -->
<!-- mvn -N versions:update-child-modules -->
<!-- mvn versions:set -DnewVersion=2.0 -DprocessAllModules=true -DallowSnapshots=true -->
<!-- 跳过测试mvn package -Dmaven.test.skip=true -->
<!-- 检测依赖最新版本mvn versions:display-dependency-updates -->
<!-- 统一修改版本号mvn versions:set -DnewVersion=3.0 -->
<!-- mvn -N versions:update-child-modules -->
<!-- mvn versions:set -DnewVersion=2.0 -DprocessAllModules=true -DallowSnapshots=true -->
<!-- mvn clean source:jar install -->
<!-- mvn deploy -Dmaven.test.skip=true -e -P release -->
<!-- mvn deploy -e -P release -->
<id>release</id>
<build>
<plugins>
<!-- Source -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.4</version>
<configuration>
<windowtitle>Mybatis-Flex</windowtitle>
<doctitle>Mybatis-Flex</doctitle>
<show>private</show>
<detectLinks>false</detectLinks>
<detectOfflineLinks>true</detectOfflineLinks>
<linksource>true</linksource>
<additionalparam>-Xdoclint:none</additionalparam>
<detectJavaApiLink>true</detectJavaApiLink>
<source>8</source>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 以下是GPG -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>sign-artifacts</id>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- mvn clean source:jar install -->
<!-- mvn deploy -Dmaven.test.skip=true -e -P release -->
<!-- mvn deploy -e -->
</plugins>
</build>
<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
</snapshotRepository>
<repository>
<id>ossrh</id>
<url>https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
</profile>
</profiles>
<distributionManagement>
<snapshotRepository>
<id>central</id>
<url>https://central.sonatype.com/</url>
</snapshotRepository>
</distributionManagement>
</project>

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:m="http://maven.apache.org/POM/4.0.0"
exclude-result-prefixes="m">
<xsl:output method="xml" encoding="utf-8" indent="yes"
xslt:indent-amount="2" xmlns:xslt="http://xml.apache.org/xslt" />
<xsl:strip-space elements="*" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="/m:project/m:properties">
<xsl:copy>
<xsl:apply-templates select="node()">
<xsl:sort select="name()" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template
match="/m:project/m:dependencyManagement/m:dependencies/m:dependency/m:version/text()[. = '${revision}']">
<xsl:value-of select="/m:project/m:version/text()" />
</xsl:template>
<xsl:template
match="/m:project/m:build/m:pluginManagement/m:plugins/m:plugin/m:version/text()[. = '${revision}']">
<xsl:value-of select="/m:project/m:version/text()" />
</xsl:template>
<xsl:template match="/m:project/m:properties/m:revision" />
<xsl:template match="/m:project/m:properties/m:main.basedir" />
</xsl:stylesheet>

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.mybatis-flex</groupId>
<artifactId>parent</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<name>mybatis-flex-loveqq-starter</name>
<artifactId>mybatis-flex-loveqq-starter</artifactId>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.kfyty</groupId>
<artifactId>loveqq-boot-starter-mybatis</artifactId>
<version>${loveqq.version}</version>
<exclusions>
<exclusion>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2022-2024, Mybatis-Flex (fuhai999@gmail.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mybatisflex.loveqq.framework.boot.autoconfig;
import com.kfyty.loveqq.framework.boot.data.orm.mybatis.autoconfig.SqlSessionFactoryBean;
import com.kfyty.loveqq.framework.core.autoconfig.annotation.Autowired;
import com.kfyty.loveqq.framework.core.event.ContextRefreshedEvent;
import com.kfyty.loveqq.framework.core.support.Pair;
import com.mybatisflex.core.FlexConsts;
import com.mybatisflex.core.datasource.FlexDataSource;
import com.mybatisflex.core.mybatis.FlexConfiguration;
import com.mybatisflex.core.mybatis.FlexSqlSessionFactoryBuilder;
import com.mybatisflex.loveqq.framework.boot.autoconfig.transaction.FlexTransactionFactory;
import org.apache.ibatis.builder.xml.XMLConfigBuilder;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
/**
* <p>源于 {@link SqlSessionFactoryBean}主要是用于构建 {@link com.mybatisflex.core.mybatis.FlexConfiguration }而不是使用原生的 {@link Configuration}
*
* @author kfyty725
*/
public class FlexSqlSessionFactoryBean extends SqlSessionFactoryBean {
@Autowired
private MybatisFlexProperties mybatisFlexProperties;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
// nothing
}
@Override
protected Class<? extends Configuration> obtainConfigurationClass() {
return FlexConfiguration.class;
}
@Override
protected Pair<Configuration, XMLConfigBuilder> buildConfiguration() {
Pair<Configuration, XMLConfigBuilder> configPair = super.buildConfiguration();
MybatisFlexProperties.CoreConfiguration coreConfiguration = this.mybatisFlexProperties.getConfiguration();
if (coreConfiguration != null && coreConfiguration.getDefaultEnumTypeHandler() != null) {
configPair.getKey().setDefaultEnumTypeHandler(coreConfiguration.getDefaultEnumTypeHandler());
}
return configPair;
}
@Override
protected void buildEnvironment(Configuration configuration) {
FlexDataSource flexDataSource;
if (this.getDataSource() instanceof FlexDataSource) {
flexDataSource = (FlexDataSource) this.getDataSource();
} else {
flexDataSource = new FlexDataSource(FlexConsts.NAME, this.getDataSource());
}
configuration.setEnvironment(
new Environment(
FlexConsts.NAME,
this.getTransactionFactory() == null ? new FlexTransactionFactory() : this.getTransactionFactory(),
flexDataSource
)
);
}
@Override
protected void buildMapperLocations(Configuration configuration) {
// mybatis-flex 要延迟加载
}
/**
* 需先构建 sqlSessionFactory再去初始化 mapperLocations
* 因为 xmlMapperBuilder.parse() 用到 FlexGlobalConfig FlexGlobalConfig 的初始化是在 sqlSessionFactory 的构建方法里进行的
* fixed https://gitee.com/mybatis-flex/mybatis-flex/issues/I6X59V
*/
@Override
protected SqlSessionFactory build(Configuration configuration) {
SqlSessionFactory sqlSessionFactory = new FlexSqlSessionFactoryBuilder().build(configuration);
super.buildMapperLocations(configuration);
return sqlSessionFactory;
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2022-2025, Mybatis-Flex (fuhai999@gmail.com).
* <p>
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mybatisflex.loveqq.framework.boot.autoconfig;
import com.kfyty.loveqq.framework.core.autoconfig.InitializingBean;
import com.kfyty.loveqq.framework.core.autoconfig.annotation.Autowired;
import com.kfyty.loveqq.framework.core.autoconfig.annotation.Component;
import com.kfyty.loveqq.framework.core.autoconfig.condition.annotation.ConditionalOnProperty;
import com.mybatisflex.core.audit.AuditManager;
import com.mybatisflex.core.audit.MessageFactory;
import com.mybatisflex.core.audit.MessageReporter;
import com.mybatisflex.core.audit.http.HttpMessageReporter;
/**
* MyBatis-Flex-Admin 自动配置
*
* @author 王帅
* @author kfyty725
* @since 2023-07-01
*/
@Component
@ConditionalOnProperty(prefix = "mybatis-flex.adminConfig", value = "enable", havingValue = "true")
public class MybatisFlexAdminAutoConfiguration implements InitializingBean {
@Autowired(required = false)
private MessageFactory messageFactory;
@Autowired(required = false)
private MybatisFlexProperties properties;
@Autowired(required = false)
private HttpMessageReporter.JSONFormatter jsonFormatter;
@Override
public void afterPropertiesSet() {
AuditManager.setAuditEnable(true);
if (messageFactory != null) {
AuditManager.setMessageFactory(messageFactory);
}
MybatisFlexProperties.AdminConfig adminConfig = properties.getAdminConfig();
MessageReporter messageReporter = new HttpMessageReporter(
adminConfig.getEndpoint(),
adminConfig.getSecretKey(),
jsonFormatter
);
AuditManager.setMessageReporter(messageReporter);
}
}

Some files were not shown because too many files have changed in this diff Show More