mirror of
https://gitee.com/mybatis-flex/mybatis-flex.git
synced 2025-12-06 16:48:24 +08:00
Compare commits
165 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d555a8e289 | ||
|
|
536f4f6058 | ||
|
|
c80284ef68 | ||
|
|
f02b8857d1 | ||
|
|
0e83000168 | ||
|
|
5814d254b8 | ||
|
|
9895a79a5b | ||
|
|
9469a727a2 | ||
|
|
ce23df8b09 | ||
|
|
ed4f30cb2c | ||
|
|
69c80d251d | ||
|
|
04ffb316bf | ||
|
|
f1ba1b2bb9 | ||
|
|
40f98c84d0 | ||
|
|
af3451b43f | ||
|
|
7185d2c79b | ||
|
|
9a83f1b695 | ||
|
|
a5f56db1d0 | ||
|
|
d770b550b2 | ||
|
|
de26c7a668 | ||
|
|
ad154da481 | ||
|
|
c17e747012 | ||
|
|
b78ae2c6c5 | ||
|
|
9343c8eabd | ||
|
|
45ac06ff97 | ||
|
|
ed09906361 | ||
|
|
7cfc1d3432 | ||
|
|
4b022408a5 | ||
|
|
10e595a628 | ||
|
|
4d82711fa8 | ||
|
|
61857a00fe | ||
|
|
25e00c677e | ||
|
|
eefded34f9 | ||
|
|
a4793eaceb | ||
|
|
f7ec9689d6 | ||
|
|
c1cd6dcecd | ||
|
|
66ca2981da | ||
|
|
12e9243934 | ||
|
|
b0ecb07e1d | ||
|
|
23236e6ec2 | ||
|
|
70a97bb0eb | ||
|
|
efd2a442d4 | ||
|
|
d5d7c3e250 | ||
|
|
3c26f72df8 | ||
|
|
3618f70055 | ||
|
|
c7bc207ce7 | ||
|
|
ec768d2423 | ||
|
|
bf05d11d8e | ||
|
|
2e5bde372f | ||
|
|
01ab3023df | ||
|
|
41b52fa6c2 | ||
|
|
29d82efa64 | ||
|
|
9afcb9514d | ||
|
|
c65a3608f8 | ||
|
|
324810803b | ||
|
|
be7d089264 | ||
|
|
c19896750c | ||
|
|
c3346a4aac | ||
|
|
3cb3563508 | ||
|
|
aa08da881a | ||
|
|
aaa2566b12 | ||
|
|
3967aac363 | ||
|
|
4b1e4fa021 | ||
|
|
66c1cd0850 | ||
|
|
7289b15478 | ||
|
|
ecbd87a1ae | ||
|
|
354f9d11a3 | ||
|
|
03f6c28463 | ||
|
|
f786fd64b5 | ||
|
|
bf973f9f06 | ||
|
|
60a30deea2 | ||
|
|
d47465a91e | ||
|
|
4d8c132b8d | ||
|
|
ece2adc0e3 | ||
|
|
acba6066bc | ||
|
|
08d6dae776 | ||
|
|
6e6f6de0f8 | ||
|
|
b196fbb561 | ||
|
|
cc2ca249e0 | ||
|
|
97bf853364 | ||
|
|
19a090c4a5 | ||
|
|
531152e1d4 | ||
|
|
7e09e4eb5e | ||
|
|
6f0444a139 | ||
|
|
b6d35c8513 | ||
|
|
80ebb40481 | ||
|
|
be21245b3c | ||
|
|
37afc9ca5b | ||
|
|
ce86692bcd | ||
|
|
cbb9f55cdf | ||
|
|
46767593a2 | ||
|
|
dcc9dfb187 | ||
|
|
ac5a7bf511 | ||
|
|
62b28a33a4 | ||
|
|
ed2621f71f | ||
|
|
99c277545e | ||
|
|
cc374a6aa2 | ||
|
|
c969ee388d | ||
|
|
15e93168b6 | ||
|
|
0baa61fe03 | ||
|
|
1ed62629c2 | ||
|
|
a37bdaabf1 | ||
|
|
336e938471 | ||
|
|
ea03a5f3df | ||
|
|
82ed8229e2 | ||
|
|
a12f528388 | ||
|
|
0f46023741 | ||
|
|
cd7eb10758 | ||
|
|
ea45ff983c | ||
|
|
d943caaad1 | ||
|
|
af88769761 | ||
|
|
2bd5c039d1 | ||
|
|
06a798eed7 | ||
|
|
848d709140 | ||
|
|
d20377c049 | ||
|
|
3d1bbbf235 | ||
|
|
4bf41c414b | ||
|
|
2a64e3115f | ||
|
|
65b1161651 | ||
|
|
1ddc316f7c | ||
|
|
7ac13da064 | ||
|
|
2fb2582d9b | ||
|
|
366d556bad | ||
|
|
ea1dd46566 | ||
|
|
624ae4d4a0 | ||
|
|
6c75b6e692 | ||
|
|
6fa86a03a5 | ||
|
|
097d93a343 | ||
|
|
ecfea5e683 | ||
|
|
1987df70a5 | ||
|
|
eafe6d338f | ||
|
|
a35ca5cd62 | ||
|
|
5afd03c948 | ||
|
|
cfa7a75205 | ||
|
|
1c9d3f6a96 | ||
|
|
b326a824b8 | ||
|
|
a0db718ed2 | ||
|
|
b1a2980ac5 | ||
|
|
a39fb3d014 | ||
|
|
f6b22c1da7 | ||
|
|
5fccfa6c4b | ||
|
|
77f0d6c173 | ||
|
|
61006c5057 | ||
|
|
2bf1bdb454 | ||
|
|
890e0c3944 | ||
|
|
fc0812228a | ||
|
|
be123d50d0 | ||
|
|
38e74544db | ||
|
|
9cd42b5f14 | ||
|
|
351fd7facd | ||
|
|
3a28c3b3b4 | ||
|
|
2b22bdc015 | ||
|
|
92cc0d8438 | ||
|
|
af8616e371 | ||
|
|
5c851e0b81 | ||
|
|
80a42efb61 | ||
|
|
e74e4044d1 | ||
|
|
7796f970b0 | ||
|
|
138bc6ca1e | ||
|
|
e5501e9e3f | ||
|
|
8e0a2b32e2 | ||
|
|
71f456bc93 | ||
|
|
ea5836ab51 | ||
|
|
0c4b0c2266 | ||
|
|
afa483d606 |
@ -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
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
Binary file not shown.
18
.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
18
.mvn/wrapper/maven-wrapper.properties
vendored
Normal 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
|
||||
73
changes.md
73
changes.md
@ -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 代码生成格式和详情无法生成文档的问题
|
||||
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
BIN
docs/assets/images/ad/aiflowy-banner.jpg
Normal file
BIN
docs/assets/images/ad/aiflowy-banner.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 71 KiB |
BIN
docs/assets/images/wechat-group.jpg
Normal file
BIN
docs/assets/images/wechat-group.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 125 KiB |
@ -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();
|
||||
```
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
- **`insertWithPk(entity, ignoreNulls)`**:带有主键的插入,此时实体类不会经过主键生成器生成主键。
|
||||
- **`insertBatch(entities)`**:批量插入实体类数据,只会根据第一条数据来构建插入的字段内容。
|
||||
- **`insertBatch(entities, size)`**:批量插入实体类数据,按 size 切分。
|
||||
- **`insertBatchSelective(entities)`**:批量插入实体类数据,忽略 `null` 值。
|
||||
- **`insertOrUpdate(entity)`**:插入或者更新,若主键有值,则更新,若没有主键值,则插入,插入或者更新都不会忽略 `null` 值。
|
||||
- **`insertOrUpdateSelective(entity)`**:插入或者更新,若主键有值,则更新,若没有主键值,则插入,插入或者更新都会忽略 `null`
|
||||
值。
|
||||
|
||||
@ -14,7 +14,7 @@ MyBatis-Flex 展示的机会。
|
||||
| 全站右侧边栏 1 | 图片+链接 | 105*50px | ¥200/月 | 8 |
|
||||
| 全站右侧边栏 2 | 图片+链接 | 222*50px | ¥400/月 | 1 |
|
||||
|
||||
您可以联系微信 `fuh99888` 就展示位的详细事宜。
|
||||
您可以联系微信 `fuh99777` 就展示位的详细事宜。
|
||||
|
||||
## 无偿捐赠
|
||||
|
||||
|
||||
@ -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 代码生成格式和详情无法生成文档的问题
|
||||
|
||||
|
||||
|
||||
@ -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" 生成器:
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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:数据验证,比如当前用户查询的数据中,当前用户没有权限查看,则抛出异常等。
|
||||
|
||||
示例代码如下:
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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'
|
||||
}
|
||||
```
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -1,28 +1,41 @@
|
||||
| | | | | |
|
||||
|-----|-----|-----|-----|-----|
|
||||
|Michael Yang|王帅|卡莫sama|丌冰|life|
|
||||
|snyk-bot|lhzsdnu|西东|tangxin|Font_C|
|
||||
|pengpeng|庄佳彬|Ice-samll|guanmengyuan|王超|
|
||||
|笨小孩|bf109f|chenjh3|CloudPlayer|Jerry|
|
||||
|snow|草语|farukonfly|李楠|菜鸟3853|
|
||||
|mofan|Jerry_Zheng|wujl|Martin7-1|piggsoft|
|
||||
|赤兮丷|黄沐鸿|loong0306|沈君锋|英雄路|
|
||||
|natsufumij|BQ60ziOxlFI0R0|tan90|aqnghu|张继续|
|
||||
|font-C|liibang|cainiao3853|barql|yangs|
|
||||
|lcxw|Robot.L|落羽er|Faputa|qixy|
|
||||
|yuanbaolong|zhijieqing|handy|bygkn|Saoforest|
|
||||
|唐振超|Watcher.Wang|锟斤拷|zhongyong|XiaoLin|
|
||||
|yang_zzu|锁力|shaoerkuai|meichenhui|阿志同学|
|
||||
|chenjian835|Haru|duxlei|豌豆粉|涛声依旧|
|
||||
|matthew|gongzhongqiang|luy|凌尘|Alex|
|
||||
|EafonYoung|Pioneer-Sun|Q_Alex|wlf|1332987|
|
||||
|Lionel|winnerself|CrazyAirhead|她出去赚钱了|数据小王子|
|
||||
|XiaoLin|丿风轻灬云淡|张博|Freeman Liu|大周|
|
||||
|欢乐码农|2han9wen71an|shark771|庄佳彬|_FLOW__|
|
||||
|weihuazhou|hans|Ikko Eltociear Ashimine|guanmengyuan|dgmico|
|
||||
|HunnyOvO|wanggaoquan|Aohan-Zhang|老吉丶|玩具猫|
|
||||
|meng.liu3|yaochen4|zhy_black|ζั͡ ั͡ ั͡ ั͡Wm|陈国正|
|
||||
|ZhuHJay|zoufang162|乌鸦笑猪黑|wnp|MyronLi|
|
||||
|norkts|拓宇在思考|张春根|witt|xinjump|
|
||||
|疾浪|sppan|时间淡忘一切|
|
||||
|Michael Yang|王帅|西东|卡莫sama|丌冰|
|
||||
|life|snyk-bot|lhzsdnu|tangxin|Font_C|
|
||||
|CloudPlayer|pengpeng|robor.luo|Ice|庄佳彬|
|
||||
|落羽er|Alay|guanmengyuan|chenjh3|王超|
|
||||
|晓华|farukonfly|bf109f|ruansheng8|huang__2|
|
||||
|Jerry|唐振超|林钟一六|snow|macy0122|
|
||||
|witt|草语|huangxy|Wudadada|SWQXDBA|
|
||||
|李楠|Robot.L|fangzhengjin|lemon|mofan|
|
||||
|oc|Jerry_Zheng|Aliothmoon|ZhengYi|wujl|
|
||||
|piggsoft|cida|赤兮丷|ArthurWang|时间淡忘一切|
|
||||
|黄沐鸿|loong0306|tiankafei|distantSail|wcc1433|
|
||||
|Freedom|zhangyx|codingdragon|jingwei.cao|Haru|
|
||||
|豌豆粉|沈君锋|英雄路|natsufumij|Lionel|
|
||||
|tan90|张继续|发强-CrazyAirhead|aqnghu|BQ60ziOxlFI0R0|
|
||||
|font-C|liibang|wtj|程序员小墨|cainiao3853|
|
||||
|niann|barql|yangs|lcxw|young|
|
||||
|cyb|hanjinfeng39|kings|Faputa|qixy|
|
||||
|leizhiyou|黄笑|Leo|handy|yuanbaolong|
|
||||
|Saoforest|byg|zhijieqing|PT.|zuojinlong|
|
||||
|Watcher.Wang|锟斤拷|yang_zzu|宋奇峰|锁力|
|
||||
|meichenhui|shaoerkuai|dream-xi|chenjian835|duxlei|
|
||||
|乘黄猿码|看来有点无聊啊|Accado|杨不易呀|XiaoLin|
|
||||
|涛声依旧|Robot.L|huangaoqin|zhongyong|matthew|
|
||||
|凌尘|luy|gongzhongqiang|Clownsw|INS6|
|
||||
|Alex|EafonYoung|Pioneer-Sun|Q_Alex|Schwi|
|
||||
|Kming|momo|1332987|F3235157|winnerself|
|
||||
|她出去赚钱了|数据小王子|XiaoLin|RishChen|丿风轻灬云淡|
|
||||
|生旭鹏|张博|Freeman Liu|大周|欢乐码农|
|
||||
|shark771|lanrain|庄佳彬|_FLOW__|weihuazhou|
|
||||
|hans|2han9wen71an|老唐|HunnyOvO|guanmengyuan|
|
||||
|dgmico|Ikko Eltociear Ashimine|wanggaoquan|Aohan-Zhang|老吉丶|
|
||||
|ToyCat|meng.liu3|yaochen4|zhy_black|无名丶小辈|
|
||||
|jeseee|ζั͡ ั͡ ั͡ ั͡Wm|陈国正|ZhuHJay|lin-mt|
|
||||
|yhan219|zoufang162|乌鸦笑猪黑|一夏coco|wnp|
|
||||
|sheldon-pacvue|MyronLi|norkts|StringKe|xiaoxiao|
|
||||
|拓宇|最后|tanglh|F3235157|lovealiang|
|
||||
|Frank|张春根|gswy|疾浪|xinjump|
|
||||
|sppan|
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
## MyBatis-Flex 微信交流群
|
||||
|
||||

|
||||

|
||||
|
||||
## MyBatis-Flex QQ 交流群
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ QueryWrapper<Badge type="tip" text="^亮点" /> 帮助我们极大的减少了 S
|
||||
|
||||
## 贡献者
|
||||
|
||||
这个项目得以存在,要感谢以下所有做出贡献的人。他们有的是学生,有的 10+ 年开发经验的工程师,也有来至于 **阿里巴巴**、**腾讯**、**科大讯飞**、
|
||||
这个项目得以存在,要感谢以下所有做出贡献的人。他们有的是学生,有的 10+ 年开发经验的工程师,也有来自于 **阿里巴巴**、**腾讯**、**科大讯飞**、
|
||||
**网宿科技**、**新东方** 等企业的同学,感谢你们。
|
||||
|
||||
>以下贡献者,由程序定时从 [Gitee](https://gitee.com/mybatis-flex/mybatis-flex/contributors?ref=main) 获取:
|
||||
|
||||
@ -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'
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@ -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
316
mvnw
vendored
Normal 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
188
mvnw.cmd
vendored
Normal 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%
|
||||
@ -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>
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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。
|
||||
*/
|
||||
|
||||
@ -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 === 分项配置 ===
|
||||
}
|
||||
|
||||
@ -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 +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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")
|
||||
|
||||
@ -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)详情
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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())")
|
||||
|
||||
@ -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) {
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -1,7 +1,11 @@
|
||||
/**
|
||||
* #(packageComment)
|
||||
*
|
||||
#if(javadocConfig.getAuthor())
|
||||
* @author #(javadocConfig.getAuthor())
|
||||
#end
|
||||
#if(javadocConfig.getSince())
|
||||
* @since #(javadocConfig.getSince())
|
||||
#end
|
||||
*/
|
||||
package #(packageName);
|
||||
@ -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())> {}
|
||||
|
||||
@ -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())> {
|
||||
|
||||
|
||||
@ -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{
|
||||
|
||||
@ -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 {}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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 {
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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) ===
|
||||
}
|
||||
|
||||
@ -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";
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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 +
|
||||
'}';
|
||||
|
||||
@ -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() {
|
||||
}
|
||||
|
||||
|
||||
@ -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 ";
|
||||
|
||||
@ -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>>) 代替。");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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)));
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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 语句。
|
||||
*
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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 查询 ===
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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()));
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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 ===== 查询包装器操作 =====
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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());
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
48
mybatis-flex-loveqq-starter/pom.xml
Normal file
48
mybatis-flex-loveqq-starter/pom.xml
Normal 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>
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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
Loading…
x
Reference in New Issue
Block a user