mirror of
https://gitee.com/best_handsome/mybatis-plus-join
synced 2025-07-11 00:02:22 +08:00
Compare commits
184 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
1b72884fcb | ||
|
9463cb6437 | ||
|
7614007346 | ||
|
5c3cd62a5f | ||
|
a8b4f77753 | ||
|
0ffac304b9 | ||
|
399609c9fb | ||
|
28392edd61 | ||
|
8e8eb6afdd | ||
|
0356b4c201 | ||
|
6d847adce5 | ||
|
65e466c0e7 | ||
|
91e0528da5 | ||
|
a1c309949a | ||
|
683d640d81 | ||
|
7b03ca05d4 | ||
|
3bd8a78e6b | ||
|
c056475a12 | ||
|
cd82858357 | ||
|
20b21c6d9d | ||
|
cbedb2f58c | ||
|
0b9577e7c4 | ||
|
bb2c8115e0 | ||
|
6a314b1b70 | ||
|
d27318503e | ||
|
44e5a5e79d | ||
|
609234dd2e | ||
|
40b6eff2cc | ||
|
9eb7aac005 | ||
|
08d3b1cf9b | ||
|
b029065187 | ||
|
46a23bfb99 | ||
|
6327dcd15e | ||
|
c50da64608 | ||
|
e93b72bad7 | ||
|
93c81ab043 | ||
|
9f2a79693e | ||
|
5067324103 | ||
|
b3f56f9292 | ||
|
0b065266a1 | ||
|
7c8afeaa98 | ||
|
0353f972e7 | ||
|
4401ad8ca6 | ||
|
42a63cf4d1 | ||
|
9dd1cfbde7 | ||
|
9173f6e5c8 | ||
|
6abb21a5ee | ||
|
d7f7f19fac | ||
|
8ecc698723 | ||
|
6e1c7945c6 | ||
|
3db7995d34 | ||
|
34d920196f | ||
|
2c5b8678d6 | ||
|
5d16d68d4e | ||
|
0ed4bb2278 | ||
|
034c341f5c | ||
|
ce3548c7d2 | ||
|
eb3cecf626 | ||
|
5b61dfedd8 | ||
|
effdc96299 | ||
|
720934500f | ||
|
56ef6c57f7 | ||
|
4d38516ea2 | ||
|
30629ee12a | ||
|
117f465646 | ||
|
f2b3308d53 | ||
|
1f3a73056d | ||
|
14ea2c45b0 | ||
|
9e65e33301 | ||
|
b4ce33141d | ||
|
0a05f48032 | ||
|
15ec4b86b1 | ||
|
4c4fae44a1 | ||
|
7ee3f52d95 | ||
|
cc08e57540 | ||
|
e562c159d1 | ||
|
7abd8550a3 | ||
|
3c27dc921c | ||
|
484eb831dc | ||
|
bac3938b11 | ||
|
c2dfbf29b4 | ||
|
7e4b778f79 | ||
|
047faf4891 | ||
|
51f39d1129 | ||
|
951316e84f | ||
|
7e3ee68d73 | ||
|
6a5983aad4 | ||
|
8495c7c153 | ||
|
5fd49c83e7 | ||
|
5a7416345a | ||
|
6947d89697 | ||
|
5c587a3bfe | ||
|
27444dda74 | ||
|
52a0eb3cc9 | ||
|
543c987983 | ||
|
ec56620e4d | ||
|
81013e34b7 | ||
|
280e9901ed | ||
|
b6d04d5ea4 | ||
|
7e30322e2b | ||
|
bee3f83dea | ||
|
0519bd47ee | ||
|
31662a6e9e | ||
|
d604be19ac | ||
|
5269f3a535 | ||
|
ae6116ce95 | ||
|
646fefaada | ||
|
754cf726fd | ||
|
c898aa56c4 | ||
|
7a05056e6f | ||
|
8bc94f2038 | ||
|
fd0e559c3a | ||
|
fa95c33847 | ||
|
369ec8db05 | ||
|
01043008f9 | ||
|
9794aa3545 | ||
|
3558d94c68 | ||
|
9c683963cb | ||
|
108ed07bd6 | ||
|
ab92b9811f | ||
|
2ee52e39a6 | ||
|
5767ad4b1e | ||
|
33e35ee1fb | ||
|
19329cfb28 | ||
|
b252c474a1 | ||
|
1a82b74952 | ||
|
e3d5187c35 | ||
|
d291edf026 | ||
|
7e03776471 | ||
|
9f4a7a0ea0 | ||
|
cde5c86518 | ||
|
879cecaca9 | ||
|
ad878e454f | ||
|
bb2b322246 | ||
|
c32988d4b6 | ||
|
6fb8e958f5 | ||
|
5c76932fdc | ||
|
5582305376 | ||
|
1673cfe4c0 | ||
|
24b1d51155 | ||
|
f319e4b7a1 | ||
|
be34118e9d | ||
|
18b2394e7e | ||
|
24212523d7 | ||
|
110e0cf8a3 | ||
|
1ca477a61a | ||
|
7f8723bf0f | ||
|
6be7f0bc21 | ||
|
1b3f294645 | ||
|
0df22e3adf | ||
|
69713b1c39 | ||
|
064f5ccaa9 | ||
|
42211407cd | ||
|
ff63c3c141 | ||
|
adada6870c | ||
|
de49069ccc | ||
|
a3340741f1 | ||
|
c6b781fc72 | ||
|
99a5190f43 | ||
|
ad4df5b939 | ||
|
17936814b0 | ||
|
45b68607a2 | ||
|
e92df45f88 | ||
|
30924c4810 | ||
|
4f3f6dac3f | ||
|
19d67fd1a8 | ||
|
049e54d023 | ||
|
a3de7ec409 | ||
|
ac635a91db | ||
|
2ee265c213 | ||
|
7cd632f1ad | ||
|
30377e4f5e | ||
|
658bb2bb59 | ||
|
f8e51aa958 | ||
|
326bd68ade | ||
|
9d37dd4d7c | ||
|
de3504ed5e | ||
|
7db13fd882 | ||
|
f861b9df9c | ||
|
dd35dce49f | ||
|
22ad7c4232 | ||
|
266d71293f | ||
|
86888633f6 | ||
|
f15d94885a |
@ -1,15 +0,0 @@
|
||||
### 当前使用版本(必填,否则不予处理)
|
||||
|
||||
|
||||
|
||||
### 该问题是如何引起的?(确定最新版也有问题再提!!!)
|
||||
|
||||
|
||||
|
||||
### 重现步骤(如果有就写完整)
|
||||
|
||||
|
||||
|
||||
### 报错信息
|
||||
|
||||
|
@ -1,15 +0,0 @@
|
||||
### 该Pull Request关联的Issue
|
||||
|
||||
|
||||
|
||||
### 修改描述
|
||||
|
||||
|
||||
|
||||
### 测试用例
|
||||
|
||||
|
||||
|
||||
### 修复效果的截屏
|
||||
|
||||
|
15
.github/ISSUE_TEMPLATE.zh-CN
vendored
15
.github/ISSUE_TEMPLATE.zh-CN
vendored
@ -1,15 +0,0 @@
|
||||
### 当前使用版本(必填,否则不予处理)
|
||||
|
||||
|
||||
|
||||
### 该问题是如何引起的?(确定最新版也有问题再提!!!)
|
||||
|
||||
|
||||
|
||||
### 重现步骤(如果有就写完整)
|
||||
|
||||
|
||||
|
||||
### 报错信息
|
||||
|
||||
|
45
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
45
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
name: 错误报告
|
||||
description: File a bug report.
|
||||
title: "[错误报告]: 描述"
|
||||
labels: [""]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
请确认以下信息:
|
||||
1. 请按此模板提交issues, 不按模板提交的问题将直接关闭
|
||||
2. 如果你的问题与该仓库无关或者可以直接在以往 issue 中找到, 那么你的 issue 将会被直接关闭
|
||||
3. 提交问题务必描述清楚、附上日志, 描述不清导致无法理解和分析的问题会被直接关闭
|
||||
- type: checkboxes
|
||||
id: confirm
|
||||
attributes:
|
||||
label: 确认
|
||||
description: 在提交 issue 之前,请确认你已经阅读并确认以下内容
|
||||
options:
|
||||
- label: 我的版本是最新版本, 我的版本号与 [version](https://central.sonatype.com/search?q=g:com.github.yulichang%20%20a:mybatis-plus-join-boot-starter&smo=true) 相同, 并且项目里无依赖冲突
|
||||
required: true
|
||||
- label: 我已经在 [issue](https://github.com/yulichang/mybatis-plus-join/issues) 中搜索过, 确认问题没有被提出过
|
||||
required: true
|
||||
- label: 我已经修改标题, 将标题中的 描述 替换为遇到的问题
|
||||
required: true
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: 当前程序版本
|
||||
description: 遇到问题时程序所在的版本号
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: 问题描述
|
||||
description: 请详细描述你碰到的问题
|
||||
placeholder: "问题描述"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: 详细堆栈日志
|
||||
description: 问题出现时,程序错误堆栈日志。
|
||||
render: bash
|
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 官网
|
||||
url: https://mybatis-plus-join.github.io/
|
||||
about: document.
|
35
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
35
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
name: 功能改进
|
||||
description: Feature Request
|
||||
title: "[功能改进]: 描述"
|
||||
labels: [""]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
请说明你希望添加的功能。
|
||||
- type: checkboxes
|
||||
id: confirm
|
||||
attributes:
|
||||
label: 确认
|
||||
description: 在提交 issue 之前,请确认你已经阅读并确认以下内容
|
||||
options:
|
||||
- label: 我的版本是最新版本, 我的版本号与 [version](https://central.sonatype.com/search?q=g:com.github.yulichang%20%20a:mybatis-plus-join-boot-starter&smo=true) 相同, 并且项目里无依赖冲突
|
||||
required: true
|
||||
- label: 我已经在 [issue](https://github.com/yulichang/mybatis-plus-join/issues) 中搜索过, 确认问题没有被提出过
|
||||
required: true
|
||||
- label: 我已经修改标题, 将标题中的 描述 替换为遇到的问题
|
||||
required: true
|
||||
- type: textarea
|
||||
id: feature-request
|
||||
attributes:
|
||||
label: 功能改进
|
||||
description: 请详细描述需要改进或者添加的功能。
|
||||
placeholder: "功能改进"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: references
|
||||
attributes:
|
||||
label: 参考资料
|
||||
description: 可以列举一些参考资料,但是不要引用同类但商业化软件的任何内容。
|
||||
placeholder: "参考资料"
|
15
.github/PULL_REQUEST_TEMPLATE.zh-CN
vendored
15
.github/PULL_REQUEST_TEMPLATE.zh-CN
vendored
@ -1,15 +0,0 @@
|
||||
### 该Pull Request关联的Issue
|
||||
|
||||
|
||||
|
||||
### 修改描述
|
||||
|
||||
|
||||
|
||||
### 测试用例
|
||||
|
||||
|
||||
|
||||
### 修复效果的截屏
|
||||
|
||||
|
10
.github/dependabot.yml
vendored
10
.github/dependabot.yml
vendored
@ -1,11 +1,13 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "gradle" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
- package-ecosystem: "maven" # See documentation for possible values
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
interval: "weekly"
|
||||
ignore:
|
||||
- dependency-name: "com.baomidou:mybatis-plus*"
|
||||
|
39
.github/workflows/depoly.yml
vendored
Normal file
39
.github/workflows/depoly.yml
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
name: Maven Package
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
|
||||
- name: Build with Maven
|
||||
run: mvn -B package --file pom.xml
|
||||
|
||||
- name: Set up Apache Maven Central
|
||||
uses: actions/setup-java@v4
|
||||
with: # running setup-java again overwrites the settings.xml
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
server-id: maven # Value of the distributionManagement/repository/id field of the pom.xml
|
||||
server-username: MAVEN_USERNAME # env variable for username in deploy
|
||||
server-password: MAVEN_CENTRAL_TOKEN # env variable for token in deploy
|
||||
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import
|
||||
gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase
|
||||
|
||||
- name: Publish to Apache Maven Central
|
||||
run: mvn com.github.yulichang:pom-maven-plugin:pom && mvn clean deploy
|
||||
env:
|
||||
MAVEN_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
|
||||
MAVEN_CENTRAL_TOKEN: ${{ secrets.MAVEN_CENTRAL_TOKEN }}
|
||||
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
|
31
.github/workflows/maven.yml
vendored
Normal file
31
.github/workflows/maven.yml
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven
|
||||
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
|
||||
name: Java CI with Maven
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '21'
|
||||
distribution: 'temurin'
|
||||
cache: maven
|
||||
- name: Build with Maven
|
||||
run: mvn -B package --file pom.xml
|
39
.github/workflows/snapshot.yml
vendored
Normal file
39
.github/workflows/snapshot.yml
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
name: Maven Package
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- snapshot
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
|
||||
- name: Build with Maven
|
||||
run: mvn -B package --file pom.xml
|
||||
|
||||
- name: Set up Apache Maven Central
|
||||
uses: actions/setup-java@v4
|
||||
with: # running setup-java again overwrites the settings.xml
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
server-id: maven # Value of the distributionManagement/repository/id field of the pom.xml
|
||||
server-username: MAVEN_USERNAME # env variable for username in deploy
|
||||
server-password: MAVEN_CENTRAL_TOKEN # env variable for token in deploy
|
||||
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }} # Value of the GPG private key to import
|
||||
gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase
|
||||
|
||||
- name: Publish to Apache Maven Central
|
||||
run: mvn com.github.yulichang:pom-maven-plugin:pom -Dprofile=snapshot && mvn clean deploy
|
||||
env:
|
||||
MAVEN_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
|
||||
MAVEN_CENTRAL_TOKEN: ${{ secrets.MAVEN_CENTRAL_TOKEN }}
|
||||
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
|
71
README-zh.md
71
README-zh.md
@ -10,7 +10,7 @@
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://central.sonatype.com/artifact/com.github.yulichang/mybatis-plus-join-boot-starter">
|
||||
<img alt="maven" src="https://img.shields.io/maven-central/v/com.github.yulichang/mybatis-plus-join-boot-starter.svg?style=flat-square">
|
||||
<img alt="Maven central" src="https://img.shields.io/maven-central/v/com.github.yulichang/mybatis-plus-join-boot-starter.svg?style=flat-square">
|
||||
</a>
|
||||
<a href="https://www.apache.org/licenses/LICENSE-2.0">
|
||||
<img alt="code style" src="https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square">
|
||||
@ -25,18 +25,17 @@
|
||||
<p align="center">
|
||||
对 <a href="https://gitee.com/baomidou/mybatis-plus" target="_blank">MyBatis-Plus</a> 多表查询的扩展 |
|
||||
<a href="https://gitee.com/best_handsome/mybatis-plus-join-demo" target="_blank">演示工程</a> |
|
||||
<a href="https://yulichang.github.io/mybatis-plus-join-doc/" target="_blank">使用文档</a> |
|
||||
<a href="https://mybatis-plus-join.github.io" target="_blank">使用文档</a> |
|
||||
点个Star支持一下吧 (☆▽☆)
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
QQ群:680016987 或者
|
||||
<a href="https://gitee.com/best_handsome/mybatis-plus-join/issues/I65N2M" target="_blank">添加作者微信,备注MPJ,加入微信群</a>
|
||||
<br/>
|
||||
<img width="200px" height="200px" src="https://foruda.gitee.com/images/1714756135330585984/bcc86eb0_2020985.png" alt="添加作者微信,备注MPJ,加入微信群"/>
|
||||
</p>
|
||||
|
||||
### <a href="https://yulichang.github.io/mybatis-plus-join-doc/" target="_blank">使用文档WIKI</a>
|
||||
### <a href="https://mybatis-plus-join.github.io" target="_blank">使用文档WIKI</a>
|
||||
|
||||
## 使用方法
|
||||
|
||||
@ -47,23 +46,21 @@ QQ群:680016987 或者
|
||||
<dependency>
|
||||
<groupId>com.github.yulichang</groupId>
|
||||
<artifactId>mybatis-plus-join-boot-starter</artifactId>
|
||||
<version>1.4.13</version>
|
||||
<version>1.5.4</version>
|
||||
</dependency>
|
||||
```
|
||||
- Gradle
|
||||
```
|
||||
implementation 'com.github.yulichang:mybatis-plus-join-boot-starter:1.4.13'
|
||||
implementation 'com.github.yulichang:mybatis-plus-join-boot-starter:1.5.4'
|
||||
```
|
||||
或者clone代码到本地执行 mvn install, 再引入以上依赖
|
||||
或者clone代码到本地执行 `mvn install`, 再引入以上依赖
|
||||
<br>
|
||||
注意: MyBatis Plus版本需要3.3.0+
|
||||
注意: MyBatis Plus版本需要3.1.2+
|
||||
<br>
|
||||
|
||||
### 使用
|
||||
|
||||
* mapper继承MPJBaseMapper (必选)
|
||||
* service继承MPJBaseService (可选)
|
||||
* serviceImpl继承MPJBaseServiceImpl (可选)
|
||||
* mapper继承MPJBaseMapper
|
||||
|
||||
### Lambda形式用法(MPJLambdaWrapper)
|
||||
|
||||
@ -113,52 +110,10 @@ WHERE (
|
||||
AND t.id > ?)
|
||||
```
|
||||
|
||||
说明:
|
||||
# <a href="https://mybatis-plus-join.github.io" target="_blank">完整使用文档 wiki</a>
|
||||
|
||||
* UserDTO.class 查询结果返回类(resultType)
|
||||
* selectAll() 查询指定实体类的全部字段
|
||||
* select() 查询指定的字段,支持可变参数,同一个select只能查询相同表的字段
|
||||
* selectAs() 字段别名查询,用于数据库字段与业务实体类属性名不一致时使用
|
||||
* leftJoin() 参数说明
|
||||
第一个参数: 参与连表的实体类class
|
||||
第二个参数: 连表的ON字段,这个属性必须是第一个参数实体类的属性
|
||||
第三个参数: 参与连表的ON的另一个实体类属性
|
||||
* 默认主表别名是t,其他的表别名以先后调用的顺序使用t1,t2,t3....
|
||||
* 条件查询,可以查询主表以及参与连接的所有表的字段,全部调用mp原生的方法,正常使用没有sql注入风险
|
||||
|
||||
#### 一对多查询
|
||||
|
||||
```java
|
||||
class test {
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Test
|
||||
void testResultMap() {
|
||||
MPJLambdaWrapper<UserDO> wrapper = new MPJLambdaWrapper<>(User.class)
|
||||
.selectAll(UserDO.class)
|
||||
//对多查询
|
||||
.selectCollection(AddressDO.class, UesrDTO::getAddressList)
|
||||
//对一查询
|
||||
.selectAssociation(AddressDO.class, UesrDTO::getAddress)
|
||||
.leftJoin(AddressDO.class, AddressDO::getUserId, UserDO::getId);
|
||||
|
||||
List<UserDTO> dtoList = userMapper.selectJoinList(UserDTO.class, wrapper);
|
||||
|
||||
//关于对多分页查询
|
||||
//由于嵌套结果方式会导致结果集被折叠,因此分页查询的结果在折叠后总数会减少,所以无法保证分页结果数量正确。
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
MPJLambdaWrapper其他功能
|
||||
|
||||
* <a href="https://yulichang.github.io/mybatis-plus-join-doc/pages/core/lambda/select/selectCollection.html" target="_blank">
|
||||
一对一,一对多使用</a>
|
||||
* <a href="https://yulichang.github.io/mybatis-plus-join-doc/pages/core/lambda/select/selectFunc.html" target="_blank">简单的SQL函数使用</a>
|
||||
* <a href="https://yulichang.github.io/mybatis-plus-join-doc/pages/core/lambda/join/leftJoin.html" target="_blank">ON语句多条件支持</a>
|
||||
* <a href="https://yulichang.github.io/mybatis-plus-join-doc/" target="_blank">其他全部功能请参考使用文档</a>
|
||||
|
||||
# <a href="https://yulichang.github.io/mybatis-plus-join-doc" target="_blank">使用文档 wiki</a>
|
||||
# 用爱发电
|
||||

|
||||
|
||||
<a href="https://mybatis-plus-join.github.io/pages/quickstart/support.html" target="_blank">
|
||||
<img alt="支持一下mybatis-plus-join" src="https://foruda.gitee.com/images/1717191488951888381/8463cfcd_2020985.png">
|
||||
</a>
|
||||
|
75
README.md
75
README.md
@ -10,7 +10,7 @@
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://central.sonatype.com/artifact/com.github.yulichang/mybatis-plus-join-boot-starter">
|
||||
<img alt="maven" src="https://img.shields.io/maven-central/v/com.github.yulichang/mybatis-plus-join-boot-starter.svg?style=flat-square">
|
||||
<img alt="Maven central" src="https://img.shields.io/maven-central/v/com.github.yulichang/mybatis-plus-join-boot-starter.svg?style=flat-square">
|
||||
</a>
|
||||
<a href="https://www.apache.org/licenses/LICENSE-2.0">
|
||||
<img alt="code style" src="https://img.shields.io/badge/license-Apache%202-4EB1BA.svg?style=flat-square">
|
||||
@ -23,20 +23,19 @@
|
||||
</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
对 <a href="https://gitee.com/baomidou/mybatis-plus" target="_blank">MyBatis-Plus</a> 多表查询的扩展 |
|
||||
<a href="https://gitee.com/best_handsome/mybatis-plus-join-demo" target="_blank">演示工程</a> |
|
||||
<a href="https://yulichang.github.io/mybatis-plus-join-doc/" target="_blank">使用文档</a> |
|
||||
对 <a href="https://github.com/baomidou/mybatis-plus" target="_blank">MyBatis-Plus</a> 多表查询的扩展 |
|
||||
<a href="https://github.com/yulichang/mybatis-plus-join-demo" target="_blank">演示工程</a> |
|
||||
<a href="https://mybatis-plus-join.github.io" target="_blank">使用文档</a> |
|
||||
点个Star支持一下吧 (☆▽☆)
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
QQ群:680016987 或者
|
||||
<a href="https://gitee.com/best_handsome/mybatis-plus-join/issues/I65N2M" target="_blank">添加作者微信,备注MPJ,加入微信群</a>
|
||||
<br/>
|
||||
<img width="200px" height="200px" src="https://github.com/yulichang/mybatis-plus-join/assets/33247410/6a2aedfa-c67d-4691-9441-204f28b6c73d" alt="添加作者微信,备注MPJ,加入微信群"/>
|
||||
</p>
|
||||
|
||||
### <a href="https://yulichang.github.io/mybatis-plus-join-doc" target="_blank">使用文档WIKI</a>
|
||||
### <a href="https://mybatis-plus-join.github.io" target="_blank">使用文档WIKI</a>
|
||||
|
||||
## 使用方法
|
||||
|
||||
@ -47,23 +46,21 @@ QQ群:680016987 或者
|
||||
<dependency>
|
||||
<groupId>com.github.yulichang</groupId>
|
||||
<artifactId>mybatis-plus-join-boot-starter</artifactId>
|
||||
<version>1.4.13</version>
|
||||
<version>1.5.4</version>
|
||||
</dependency>
|
||||
```
|
||||
- Gradle
|
||||
```
|
||||
implementation 'com.github.yulichang:mybatis-plus-join-boot-starter:1.4.13'
|
||||
implementation 'com.github.yulichang:mybatis-plus-join-boot-starter:1.5.4'
|
||||
```
|
||||
或者clone代码到本地执行 mvn install, 再引入以上依赖
|
||||
或者clone代码到本地执行 `mvn install`, 再引入以上依赖
|
||||
<br>
|
||||
注意: MyBatis Plus版本需要3.3.0+
|
||||
注意: MyBatis Plus版本需要3.1.2+
|
||||
<br>
|
||||
|
||||
### 使用
|
||||
|
||||
* mapper继承MPJBaseMapper (必选)
|
||||
* service继承MPJBaseService (可选)
|
||||
* serviceImpl继承MPJBaseServiceImpl (可选)
|
||||
* mapper继承MPJBaseMapper
|
||||
|
||||
### Lambda形式用法(MPJLambdaWrapper)
|
||||
|
||||
@ -113,52 +110,8 @@ WHERE (
|
||||
AND t.id > ?)
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
* UserDTO.class 查询结果返回类(resultType)
|
||||
* selectAll() 查询指定实体类的全部字段
|
||||
* select() 查询指定的字段,支持可变参数,同一个select只能查询相同表的字段
|
||||
* selectAs() 字段别名查询,用于数据库字段与业务实体类属性名不一致时使用
|
||||
* leftJoin() 参数说明
|
||||
第一个参数: 参与连表的实体类class
|
||||
第二个参数: 连表的ON字段,这个属性必须是第一个参数实体类的属性
|
||||
第三个参数: 参与连表的ON的另一个实体类属性
|
||||
* 默认主表别名是t,其他的表别名以先后调用的顺序使用t1,t2,t3....
|
||||
* 条件查询,可以查询主表以及参与连接的所有表的字段,全部调用mp原生的方法,正常使用没有sql注入风险
|
||||
|
||||
#### 一对多查询
|
||||
|
||||
```java
|
||||
class test {
|
||||
@Resource
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Test
|
||||
void testResultMap() {
|
||||
MPJLambdaWrapper<UserDO> wrapper = new MPJLambdaWrapper<>(User.class)
|
||||
.selectAll(UserDO.class)
|
||||
//对多查询
|
||||
.selectCollection(AddressDO.class, UesrDTO::getAddressList)
|
||||
//对一查询
|
||||
.selectAssociation(AddressDO.class, UesrDTO::getAddress)
|
||||
.leftJoin(AddressDO.class, AddressDO::getUserId, UserDO::getId);
|
||||
|
||||
List<UserDTO> dtoList = userMapper.selectJoinList(UserDTO.class, wrapper);
|
||||
|
||||
//关于对多分页查询
|
||||
//由于嵌套结果方式会导致结果集被折叠,因此分页查询的结果在折叠后总数会减少,所以无法保证分页结果数量正确。
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
MPJLambdaWrapper其他功能
|
||||
|
||||
* <a href="https://yulichang.github.io/mybatis-plus-join-doc/pages/core/lambda/select/selectCollection.html" target="_blank">
|
||||
一对一,一对多使用</a>
|
||||
* <a href="https://yulichang.github.io/mybatis-plus-join-doc/pages/core/lambda/select/selectFunc.html" target="_blank">简单的SQL函数使用</a>
|
||||
* <a href="https://yulichang.github.io/mybatis-plus-join-doc/pages/core/lambda/join/leftJoin.html" target="_blank">ON语句多条件支持</a>
|
||||
* <a href="https://yulichang.github.io/mybatis-plus-join-doc/" target="_blank">其他全部功能请参考使用文档</a>
|
||||
|
||||
# <a href="https://yulichang.github.io/mybatis-plus-join-doc" target="_blank">使用文档 wiki</a>
|
||||
# <a href="https://mybatis-plus-join.github.io" target="_blank">完整使用文档 wiki</a>
|
||||
# 用爱发电
|
||||

|
||||
<a href="https://mybatis-plus-join.github.io/pages/quickstart/support.html" target="_blank">
|
||||
<img alt="支持一下mybatis-plus-join" src="https://mybatis-plus-join.github.io/support.png">
|
||||
</a>
|
||||
|
@ -35,15 +35,6 @@
|
||||
<url>https://github.com/yulichang/mybatis-plus-join</url>
|
||||
</scm>
|
||||
|
||||
<properties>
|
||||
<jdkVersion>1.8</jdkVersion>
|
||||
<jdkVersion.test>1.8</jdkVersion.test>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<github.global.server>github</github.global.server>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
|
@ -2,7 +2,6 @@ package com.github.yulichang.adapter.jsqlparser.v46;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
||||
import net.sf.jsqlparser.schema.Column;
|
||||
import net.sf.jsqlparser.statement.Statement;
|
||||
@ -41,7 +40,7 @@ public class JSqlParserHelperV46 {
|
||||
} else {
|
||||
col = selectExpressionItem.getAlias().getName();
|
||||
}
|
||||
if (StringUtils.isNotBlank(col)) {
|
||||
if (isNotBlank(col)) {
|
||||
columConsumer.accept(col);
|
||||
}
|
||||
}
|
||||
@ -56,4 +55,9 @@ public class JSqlParserHelperV46 {
|
||||
throw new RuntimeException(throwable);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static boolean isNotBlank(String str) {
|
||||
return str != null && !str.trim().isEmpty();
|
||||
}
|
||||
}
|
||||
|
@ -35,20 +35,17 @@
|
||||
<url>https://github.com/yulichang/mybatis-plus-join</url>
|
||||
</scm>
|
||||
|
||||
<properties>
|
||||
<jdkVersion>1.8</jdkVersion>
|
||||
<jdkVersion.test>1.8</jdkVersion.test>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<github.global.server>github</github.global.server>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-core</artifactId>
|
||||
<version>${mpj.mybatis.plus.version}</version>
|
||||
<version>${mybatis.plus.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-jsqlparser</artifactId>
|
||||
<version>${mybatis.plus.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
@ -2,7 +2,6 @@ package com.github.yulichang.adapter.jsqlparser;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
||||
import net.sf.jsqlparser.schema.Column;
|
||||
import net.sf.jsqlparser.statement.Statement;
|
||||
@ -38,7 +37,7 @@ public class JSqlParserHelper {
|
||||
} else {
|
||||
col = item.getAlias().getName();
|
||||
}
|
||||
if (StringUtils.isNotBlank(col)) {
|
||||
if (isNotBlank(col)) {
|
||||
columConsumer.accept(col);
|
||||
}
|
||||
}
|
||||
@ -51,4 +50,8 @@ public class JSqlParserHelper {
|
||||
throw new RuntimeException(throwable);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isNotBlank(String str) {
|
||||
return str != null && !str.trim().isEmpty();
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,13 @@
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-extension</artifactId>
|
||||
<version>${mpj.mybatis.plus.version}</version>
|
||||
<version>${mybatis.plus.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-jsqlparser</artifactId>
|
||||
<version>${mybatis.plus.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -1,13 +1,26 @@
|
||||
package com.github.yulichang.adapter.base;
|
||||
|
||||
import com.baomidou.mybatisplus.core.handlers.IJsonTypeHandler;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.MybatisUtils;
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import com.github.yulichang.adapter.base.metadata.OrderFieldInfo;
|
||||
import com.github.yulichang.adapter.jsqlparser.JSqlParserHelper;
|
||||
import org.apache.ibatis.plugin.Interceptor;
|
||||
import org.apache.ibatis.session.Configuration;
|
||||
import org.apache.ibatis.type.TypeHandler;
|
||||
import org.apache.ibatis.type.TypeHandlerRegistry;
|
||||
import org.apache.ibatis.type.UnknownTypeHandler;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -25,6 +38,10 @@ public interface IAdapter {
|
||||
return tableFieldInfo.isPrimitive();
|
||||
}
|
||||
|
||||
default boolean isWithUpdateFill(TableFieldInfo tableFieldInfo) {
|
||||
return tableFieldInfo.isWithUpdateFill();
|
||||
}
|
||||
|
||||
default String mpjMapping(TableFieldInfo tableFieldInfo) {
|
||||
return tableFieldInfo.getMapping();
|
||||
}
|
||||
@ -50,5 +67,44 @@ public interface IAdapter {
|
||||
new OrderFieldInfo(f.getColumn(), f.getType(), f.getSort())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
void parserColum(String alias, String from, String selectSql, Consumer<String> columConsumer);
|
||||
default void parserColum(String alias, String from, String selectSql, Consumer<String> columConsumer) {
|
||||
JSqlParserHelper.parserColum(alias, from, selectSql, columConsumer);
|
||||
}
|
||||
|
||||
default TypeHandler<?> getTypeHandler(Configuration configuration, Class<?> propertyType, Class<? extends TypeHandler<?>> typeHandlerClass, Field field) {
|
||||
TypeHandlerRegistry registry = configuration.getTypeHandlerRegistry();
|
||||
TypeHandler<?> typeHandler = registry.getMappingTypeHandler(typeHandlerClass);
|
||||
if (typeHandlerClass != null && typeHandlerClass != UnknownTypeHandler.class) {
|
||||
if (IJsonTypeHandler.class.isAssignableFrom(typeHandlerClass)) {
|
||||
// 保证每次实例化
|
||||
typeHandler = MybatisUtils.newJsonTypeHandler(typeHandlerClass, propertyType, field);
|
||||
} else {
|
||||
if (typeHandler == null) {
|
||||
typeHandler = registry.getInstance(propertyType, typeHandlerClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
return typeHandler;
|
||||
}
|
||||
|
||||
default void wrapperInnerPage(Interceptor interceptor, Predicate<Object> predicate, Function<Object, Object> function) {
|
||||
if (interceptor instanceof MybatisPlusInterceptor) {
|
||||
MybatisPlusInterceptor mybatisPlusInterceptor = (MybatisPlusInterceptor) interceptor;
|
||||
try {
|
||||
Field field = MybatisPlusInterceptor.class.getDeclaredField("interceptors");
|
||||
field.setAccessible(true);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<InnerInterceptor> interceptors = (List<InnerInterceptor>) field.get(mybatisPlusInterceptor);
|
||||
|
||||
interceptors.replaceAll(i -> {
|
||||
if (i instanceof PaginationInnerInterceptor && !predicate.test(i)) {
|
||||
return (InnerInterceptor) function.apply(i);
|
||||
}
|
||||
return i;
|
||||
});
|
||||
} catch (Exception e) {
|
||||
throw ExceptionUtils.mpe(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,12 @@
|
||||
package com.github.yulichang.adapter.base.tookit;
|
||||
|
||||
public class CharSequenceUtils {
|
||||
|
||||
public static boolean isBlank(String str) {
|
||||
return str == null || str.trim().isEmpty();
|
||||
}
|
||||
|
||||
public static boolean isNotBlank(String str) {
|
||||
return !isBlank(str);
|
||||
}
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
package com.github.yulichang.adapter.base.tookit;
|
||||
|
||||
import com.baomidou.mybatisplus.core.MybatisPlusVersion;
|
||||
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
|
||||
|
||||
/**
|
||||
* 版本工具类
|
||||
*
|
||||
@ -8,8 +11,24 @@ package com.github.yulichang.adapter.base.tookit;
|
||||
*/
|
||||
public class VersionUtils {
|
||||
|
||||
public static String version = MybatisPlusVersion.getVersion();
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static void setMybatisPlusVersion(String version) {
|
||||
VersionUtils.version = version;
|
||||
}
|
||||
|
||||
public static String getVersion() {
|
||||
if (version != null) {
|
||||
return version;
|
||||
} else {
|
||||
throw ExceptionUtils.mpe("mybatis-plus version is blank, " +
|
||||
"please add VersionUtils.setMybatisPlusVersion(?) code before running application");
|
||||
}
|
||||
}
|
||||
|
||||
public static int compare(String v1, String v2) {
|
||||
String[] v1s = v1.split("\\.");
|
||||
String[] v1s = v1.split("-")[0].split("\\.");
|
||||
String[] v2s = v2.split("\\.");
|
||||
|
||||
String[] vs = v1s.length > v2s.length ? v2s : v1s;
|
||||
|
@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--suppress ALL -->
|
||||
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.github.yulichang</groupId>
|
||||
<artifactId>mybatis-plus-join-adapter</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<artifactId>mybatis-plus-join-adapter-v312</artifactId>
|
||||
<version>${revision}</version>
|
||||
<name>mybatis-plus-join-adapter-v312</name>
|
||||
|
||||
<description>An enhanced toolkit of Mybatis-Plus to simplify development.</description>
|
||||
<url>https://github.com/yulichang/mybatis-plus-join</url>
|
||||
<licenses>
|
||||
<license>
|
||||
<name>The Apache License, Version 2.0</name>
|
||||
<url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
</license>
|
||||
</licenses>
|
||||
<developers>
|
||||
<developer>
|
||||
<id>mybatis-plus-join</id>
|
||||
<name>yulichang</name>
|
||||
<email>yu_lichang@qq.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
<scm>
|
||||
<connection>scm:git:https://github.com/yulichang/mybatis-plus-join.git</connection>
|
||||
<developerConnection>scm:git:https://github.com/yulichang/mybatis-plus-join.git</developerConnection>
|
||||
<url>https://github.com/yulichang/mybatis-plus-join</url>
|
||||
</scm>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.yulichang</groupId>
|
||||
<artifactId>mybatis-plus-join-adapter-base</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -0,0 +1,98 @@
|
||||
package com.github.yulichang.adapter.v312;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.github.yulichang.adapter.base.IAdapter;
|
||||
import com.github.yulichang.adapter.base.metadata.OrderFieldInfo;
|
||||
import com.github.yulichang.adapter.base.tookit.CharSequenceUtils;
|
||||
import com.github.yulichang.adapter.jsqlparser.v46.JSqlParserHelperV46;
|
||||
import org.apache.ibatis.plugin.Interceptor;
|
||||
import org.apache.ibatis.session.Configuration;
|
||||
import org.apache.ibatis.type.TypeHandler;
|
||||
import org.apache.ibatis.type.TypeHandlerRegistry;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* @author yulichang
|
||||
* @since 1.4.3
|
||||
*/
|
||||
public class Adapter312 implements IAdapter {
|
||||
|
||||
@Override
|
||||
public boolean mpjHasLogic(TableInfo tableInfo) {
|
||||
return tableInfo.isLogicDelete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mpjIsPrimitive(TableFieldInfo tableFieldInfo) {
|
||||
return tableFieldInfo.getPropertyType().isPrimitive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWithUpdateFill(TableFieldInfo tableFieldInfo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String mpjMapping(TableFieldInfo tableFieldInfo) {
|
||||
String el = tableFieldInfo.getEl();
|
||||
if (el != null && el.contains(StringPool.COMMA)) {
|
||||
return el.substring(el.indexOf(StringPool.COMMA) + 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableFieldInfo mpjGetLogicField(TableInfo tableInfo) {
|
||||
return tableInfo.getFieldList().stream().filter(f -> Objects.nonNull(f.getLogicDeleteValue())
|
||||
|| Objects.nonNull(f.getLogicNotDeleteValue())).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mpjHasPK(TableInfo tableInfo) {
|
||||
return CharSequenceUtils.isNotBlank(tableInfo.getKeyProperty()) ||
|
||||
CharSequenceUtils.isNotBlank(tableInfo.getKeyColumn());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Configuration mpjGetConfiguration(TableInfo tableInfo) {
|
||||
return tableInfo.getConfiguration();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Field mpjGetField(TableFieldInfo fieldInfo, Supplier<Field> supplier) {
|
||||
return supplier.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OrderFieldInfo> mpjGetOrderField(TableInfo tableInfo) {
|
||||
throw new UnsupportedOperationException("不支持排序");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parserColum(String alias, String from, String selectSql, Consumer<String> columConsumer) {
|
||||
JSqlParserHelperV46.parserColum(alias, from, selectSql, columConsumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeHandler<?> getTypeHandler(Configuration configuration, Class<?> propertyType, Class<? extends TypeHandler<?>> typeHandlerClass, Field field) {
|
||||
TypeHandlerRegistry registry = configuration.getTypeHandlerRegistry();
|
||||
TypeHandler<?> typeHandler = registry.getMappingTypeHandler(typeHandlerClass);
|
||||
if (typeHandler == null) {
|
||||
typeHandler = registry.getInstance(propertyType, typeHandlerClass);
|
||||
}
|
||||
return typeHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void wrapperInnerPage(Interceptor interceptor, Predicate<Object> predicate, Function<Object, Object> function) {
|
||||
}
|
||||
}
|
@ -33,15 +33,6 @@
|
||||
<url>https://github.com/yulichang/mybatis-plus-join</url>
|
||||
</scm>
|
||||
|
||||
<properties>
|
||||
<jdkVersion>1.8</jdkVersion>
|
||||
<jdkVersion.test>1.8</jdkVersion.test>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<github.global.server>github</github.global.server>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.yulichang</groupId>
|
||||
|
@ -1,29 +1,33 @@
|
||||
package com.github.yulichang.adapter.v33x;
|
||||
|
||||
import com.baomidou.mybatisplus.core.MybatisPlusVersion;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.github.yulichang.adapter.base.IAdapter;
|
||||
import com.github.yulichang.adapter.base.metadata.OrderFieldInfo;
|
||||
import com.github.yulichang.adapter.base.tookit.CharSequenceUtils;
|
||||
import com.github.yulichang.adapter.base.tookit.VersionUtils;
|
||||
import com.github.yulichang.adapter.jsqlparser.v46.JSqlParserHelperV46;
|
||||
import org.apache.ibatis.plugin.Interceptor;
|
||||
import org.apache.ibatis.session.Configuration;
|
||||
import org.apache.ibatis.type.TypeHandler;
|
||||
import org.apache.ibatis.type.TypeHandlerRegistry;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* @author yulichang
|
||||
* @since 1.4.3
|
||||
*/
|
||||
public class AdapterV33x implements IAdapter {
|
||||
public class Adapter33x implements IAdapter {
|
||||
|
||||
private static final boolean is330 = VersionUtils.compare(MybatisPlusVersion.getVersion(), "3.3.0") == 0;
|
||||
private static final boolean is330 = VersionUtils.compare(VersionUtils.getVersion(), "3.3.0") == 0;
|
||||
|
||||
@Override
|
||||
public boolean mpjHasLogic(TableInfo tableInfo) {
|
||||
@ -38,7 +42,7 @@ public class AdapterV33x implements IAdapter {
|
||||
@Override
|
||||
public String mpjMapping(TableFieldInfo tableFieldInfo) {
|
||||
String el = tableFieldInfo.getEl();
|
||||
if (StringUtils.isNotBlank(el) && el.contains(StringPool.COMMA)) {
|
||||
if (el != null && el.contains(StringPool.COMMA)) {
|
||||
return el.substring(el.indexOf(StringPool.COMMA) + 1);
|
||||
}
|
||||
return null;
|
||||
@ -52,8 +56,8 @@ public class AdapterV33x implements IAdapter {
|
||||
|
||||
@Override
|
||||
public boolean mpjHasPK(TableInfo tableInfo) {
|
||||
return StringUtils.isNotBlank(tableInfo.getKeyProperty()) ||
|
||||
StringUtils.isNotBlank(tableInfo.getKeyColumn());
|
||||
return CharSequenceUtils.isNotBlank(tableInfo.getKeyProperty()) ||
|
||||
CharSequenceUtils.isNotBlank(tableInfo.getKeyColumn());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -75,4 +79,18 @@ public class AdapterV33x implements IAdapter {
|
||||
public void parserColum(String alias, String from, String selectSql, Consumer<String> columConsumer) {
|
||||
JSqlParserHelperV46.parserColum(alias, from, selectSql, columConsumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeHandler<?> getTypeHandler(Configuration configuration, Class<?> propertyType, Class<? extends TypeHandler<?>> typeHandlerClass, Field field) {
|
||||
TypeHandlerRegistry registry = configuration.getTypeHandlerRegistry();
|
||||
TypeHandler<?> typeHandler = registry.getMappingTypeHandler(typeHandlerClass);
|
||||
if (typeHandler == null) {
|
||||
typeHandler = registry.getInstance(propertyType, typeHandlerClass);
|
||||
}
|
||||
return typeHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void wrapperInnerPage(Interceptor interceptor, Predicate<Object> predicate, Function<Object, Object> function) {
|
||||
}
|
||||
}
|
@ -33,15 +33,6 @@
|
||||
<url>https://github.com/yulichang/mybatis-plus-join</url>
|
||||
</scm>
|
||||
|
||||
<properties>
|
||||
<jdkVersion>1.8</jdkVersion>
|
||||
<jdkVersion.test>1.8</jdkVersion.test>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<github.global.server>github</github.global.server>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.yulichang</groupId>
|
||||
|
@ -1,18 +1,23 @@
|
||||
package com.github.yulichang.adapter.v3431;
|
||||
|
||||
import com.baomidou.mybatisplus.core.MybatisPlusVersion;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.github.yulichang.adapter.base.IAdapter;
|
||||
import com.github.yulichang.adapter.base.metadata.OrderFieldInfo;
|
||||
import com.github.yulichang.adapter.base.tookit.VersionUtils;
|
||||
import com.github.yulichang.adapter.jsqlparser.v46.JSqlParserHelperV46;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.apache.ibatis.plugin.Interceptor;
|
||||
import org.apache.ibatis.session.Configuration;
|
||||
import org.apache.ibatis.type.TypeHandler;
|
||||
import org.apache.ibatis.type.TypeHandlerRegistry;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -22,13 +27,13 @@ import java.util.stream.Collectors;
|
||||
@AllArgsConstructor
|
||||
public class Adapter3431 implements IAdapter {
|
||||
|
||||
private static final boolean v = VersionUtils.compare(MybatisPlusVersion.getVersion(), "3.4.3") < 0;
|
||||
private static final boolean v = VersionUtils.compare(VersionUtils.getVersion(), "3.4.3") < 0;
|
||||
|
||||
@Override
|
||||
public String mpjMapping(TableFieldInfo tableFieldInfo) {
|
||||
if (v) {
|
||||
String el = tableFieldInfo.getEl();
|
||||
if (StringUtils.isNotBlank(el) && el.contains(StringPool.COMMA)) {
|
||||
if (el != null && el.contains(StringPool.COMMA)) {
|
||||
return el.substring(el.indexOf(StringPool.COMMA) + 1);
|
||||
}
|
||||
return null;
|
||||
@ -46,4 +51,18 @@ public class Adapter3431 implements IAdapter {
|
||||
public void parserColum(String alias, String from, String selectSql, Consumer<String> columConsumer) {
|
||||
JSqlParserHelperV46.parserColum(alias, from, selectSql, columConsumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeHandler<?> getTypeHandler(Configuration configuration, Class<?> propertyType, Class<? extends TypeHandler<?>> typeHandlerClass, Field field) {
|
||||
TypeHandlerRegistry registry = configuration.getTypeHandlerRegistry();
|
||||
TypeHandler<?> typeHandler = registry.getMappingTypeHandler(typeHandlerClass);
|
||||
if (typeHandler == null) {
|
||||
typeHandler = registry.getInstance(propertyType, typeHandlerClass);
|
||||
}
|
||||
return typeHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void wrapperInnerPage(Interceptor interceptor, Predicate<Object> predicate, Function<Object, Object> function) {
|
||||
}
|
||||
}
|
||||
|
@ -33,15 +33,6 @@
|
||||
<url>https://github.com/yulichang/mybatis-plus-join</url>
|
||||
</scm>
|
||||
|
||||
<properties>
|
||||
<jdkVersion>1.8</jdkVersion>
|
||||
<jdkVersion.test>1.8</jdkVersion.test>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<github.global.server>github</github.global.server>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
|
@ -33,15 +33,6 @@
|
||||
<url>https://github.com/yulichang/mybatis-plus-join</url>
|
||||
</scm>
|
||||
|
||||
<properties>
|
||||
<jdkVersion>1.8</jdkVersion>
|
||||
<jdkVersion.test>1.8</jdkVersion.test>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<github.global.server>github</github.global.server>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.yulichang</groupId>
|
||||
|
@ -2,8 +2,15 @@ package com.github.yulichang.adapter.v355;
|
||||
|
||||
import com.github.yulichang.adapter.base.IAdapter;
|
||||
import com.github.yulichang.adapter.jsqlparser.v46.JSqlParserHelperV46;
|
||||
import org.apache.ibatis.plugin.Interceptor;
|
||||
import org.apache.ibatis.session.Configuration;
|
||||
import org.apache.ibatis.type.TypeHandler;
|
||||
import org.apache.ibatis.type.TypeHandlerRegistry;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* @author yulichang
|
||||
@ -15,4 +22,18 @@ public class Adapter355 implements IAdapter {
|
||||
public void parserColum(String alias, String from, String selectSql, Consumer<String> columConsumer) {
|
||||
JSqlParserHelperV46.parserColum(alias, from, selectSql, columConsumer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeHandler<?> getTypeHandler(Configuration configuration, Class<?> propertyType, Class<? extends TypeHandler<?>> typeHandlerClass, Field field) {
|
||||
TypeHandlerRegistry registry = configuration.getTypeHandlerRegistry();
|
||||
TypeHandler<?> typeHandler = registry.getMappingTypeHandler(typeHandlerClass);
|
||||
if (typeHandler == null) {
|
||||
typeHandler = registry.getInstance(propertyType, typeHandlerClass);
|
||||
}
|
||||
return typeHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void wrapperInnerPage(Interceptor interceptor, Predicate<Object> predicate, Function<Object, Object> function) {
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@
|
||||
|
||||
<modules>
|
||||
<module>mybatis-plus-join-adapter-base</module>
|
||||
<module>mybatis-plus-join-adapter-v312</module>
|
||||
<module>mybatis-plus-join-adapter-v33x</module>
|
||||
<module>mybatis-plus-join-adapter-v3431</module>
|
||||
<module>mybatis-plus-join-adapter-v352</module>
|
||||
|
@ -33,13 +33,4 @@
|
||||
<developerConnection>scm:git:https://github.com/yulichang/mybatis-plus-join.git</developerConnection>
|
||||
<url>https://github.com/yulichang/mybatis-plus-join</url>
|
||||
</scm>
|
||||
|
||||
<properties>
|
||||
<jdkVersion>1.8</jdkVersion>
|
||||
<jdkVersion.test>1.8</jdkVersion.test>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<github.global.server>github</github.global.server>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
</project>
|
||||
|
@ -4,10 +4,13 @@ import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 动态表名注解
|
||||
* <p>
|
||||
* 1.5.2及以后无需添加此注解就可实现动态表名
|
||||
*
|
||||
* @author yulichang
|
||||
* @since 1.4.4
|
||||
*/
|
||||
@Deprecated
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
|
@ -0,0 +1,89 @@
|
||||
package com.github.yulichang.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* apt注解
|
||||
* <p>
|
||||
* 默认为String.format
|
||||
* <p>
|
||||
* 举例:
|
||||
* <ul>
|
||||
* <li>全大写 %S</li>
|
||||
* <li>加APT后缀 %sAPT</li>
|
||||
* <li>加APT前缀 APT%s</li>
|
||||
* <li>加APT后缀并且大写 %SAPT</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* 支持Ognl语法,字段说明<br/>
|
||||
* Ognl上下文
|
||||
* <ul>
|
||||
* <li>className 类名</li>
|
||||
* <li>classPackage 包名</li>
|
||||
* <li>
|
||||
* util 工具类 OgnlUtil {@link com.github.yulichang.processor.utils.OgnlUtil} ,
|
||||
* <a href="https://github.com/yulichang/mybatis-plus-join/tree/master/plugin/mybatis-plus-join-processor/src/main/java/com/github/yulichang/processor/utils/OgnlUtil.java">
|
||||
* github link
|
||||
* </a>
|
||||
* </li>
|
||||
* </ul>
|
||||
* 指定开头 Ognl# 这不是ognl语法,这是MPJ规定的 用于区分 ognl还是String.format
|
||||
* <p>
|
||||
* 举例:
|
||||
* <ul>
|
||||
* <li>去掉3长度的后缀并且大写 Ognl#className.substring(0, className.length() - 3).toUpperCase() </li>
|
||||
* <li>以“APT”结尾 Ognl#className + 'APT'</li>
|
||||
* <li>全大写并且以“APT”结尾 Ognl#className.toUpperCase() + 'APT' </li>
|
||||
* <li>"PO"结尾替换为“APT”且全大写 Ognl#util.replaceSuffix(className, 'PO', 'APT').toUpperCase() </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* 支持 三元运算 String所有方法 如lastIndexOf subString toUpperCase等 Ognl语法<p>
|
||||
*
|
||||
* @author yulichang
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface Table {
|
||||
|
||||
/**
|
||||
* APT类名
|
||||
* <p>
|
||||
* 支持Ognl 默认使用String.format()
|
||||
*/
|
||||
String value() default "%sCol";
|
||||
|
||||
/**
|
||||
* 生成类的包名
|
||||
* <p>
|
||||
* 支持Ognl 默认使用String.format()
|
||||
*/
|
||||
String classPackage() default "%s.apt";
|
||||
|
||||
/**
|
||||
* 是否在Tables中生成对应的类字段
|
||||
*/
|
||||
boolean genTables() default true;
|
||||
|
||||
/**
|
||||
* Tables中的字段名 默认大写的类名
|
||||
* <p>
|
||||
* 支持Ognl 默认使用String.format()
|
||||
*/
|
||||
String tablesClassPackage() default "%s.tables";
|
||||
|
||||
/**
|
||||
* Tables中的字段名 默认大写的类名
|
||||
* <p>
|
||||
* 支持Ognl 默认使用String.format()
|
||||
*/
|
||||
String tablesClassName() default "%S";
|
||||
|
||||
/**
|
||||
* 是否缓存
|
||||
*/
|
||||
boolean cache() default true;
|
||||
}
|
@ -46,8 +46,8 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>${mpj.mybatis.plus.version}</version>
|
||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||
<version>${mybatis.plus.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.github.yulichang.autoconfigure;
|
||||
|
||||
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusLanguageDriverAutoConfiguration;
|
||||
import com.baomidou.mybatisplus.core.injector.ISqlInjector;
|
||||
import com.github.yulichang.autoconfigure.conditional.JoinSqlInjectorCondition;
|
||||
import com.github.yulichang.autoconfigure.consumer.MybatisPlusJoinIfExistsConsumer;
|
||||
@ -12,6 +11,7 @@ import com.github.yulichang.injector.MPJSqlInjector;
|
||||
import com.github.yulichang.interceptor.MPJInterceptor;
|
||||
import com.github.yulichang.toolkit.SpringContentUtils;
|
||||
import com.github.yulichang.wrapper.enums.IfExistsSqlKeyWordEnum;
|
||||
import com.github.yulichang.wrapper.interfaces.MBiPredicate;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.mybatis.spring.SqlSessionFactoryBean;
|
||||
import org.slf4j.Logger;
|
||||
@ -19,6 +19,7 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
@ -41,7 +42,6 @@ import org.springframework.core.annotation.Order;
|
||||
import javax.sql.DataSource;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
/**
|
||||
* springboot 自动配置类
|
||||
@ -53,7 +53,7 @@ import java.util.function.BiPredicate;
|
||||
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
|
||||
@ConditionalOnSingleCandidate(DataSource.class)
|
||||
@EnableConfigurationProperties(MybatisPlusJoinProperties.class)
|
||||
@AutoConfigureAfter({DataSourceAutoConfiguration.class, MybatisPlusLanguageDriverAutoConfiguration.class})
|
||||
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
|
||||
public class MybatisPlusJoinAutoConfiguration {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(MybatisPlusJoinAutoConfiguration.class);
|
||||
@ -65,15 +65,17 @@ public class MybatisPlusJoinAutoConfiguration {
|
||||
ObjectProvider<MybatisPlusJoinIfExistsConsumer> IfExistsConsumers) {
|
||||
this.properties = Optional.ofNullable(propertiesConsumers.getIfAvailable()).map(c -> c.config(properties)).orElse(properties);
|
||||
ConfigProperties.banner = this.properties.getBanner();
|
||||
ConfigProperties.subTableLogic = this.properties.getSubTableLogic();
|
||||
ConfigProperties.msCache = this.properties.isMsCache();
|
||||
ConfigProperties.tableAlias = this.properties.getTableAlias();
|
||||
ConfigProperties.joinPrefix = this.properties.getJoinPrefix();
|
||||
ConfigProperties.logicDelType = this.properties.getLogicDelType();
|
||||
ConfigProperties.subQueryAlias = this.properties.getSubQueryAlias();
|
||||
ConfigProperties.subTableLogic = this.properties.getSubTableLogic();
|
||||
ConfigProperties.mappingMaxCount = this.properties.getMappingMaxCount();
|
||||
ConfigProperties.Convert.IfExists = this.properties.getIfExists();
|
||||
ConfigProperties.ifExists = Optional.ofNullable(IfExistsConsumers.getIfAvailable())
|
||||
.map(m -> (BiPredicate<Object, IfExistsSqlKeyWordEnum>) m)
|
||||
.orElse((val, key) -> this.properties.getIfExists().test(val));
|
||||
.map(m -> (MBiPredicate<Object, IfExistsSqlKeyWordEnum>) m)
|
||||
.orElse((val, key) -> ConfigProperties.Convert.IfExists.test(val));
|
||||
info("mybatis plus join properties config complete");
|
||||
}
|
||||
|
||||
@ -134,8 +136,8 @@ public class MybatisPlusJoinAutoConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
private void info(String info) {
|
||||
if (properties.getBanner()) {
|
||||
private static void info(String info) {
|
||||
if (ConfigProperties.banner) {
|
||||
logger.info(info);
|
||||
}
|
||||
}
|
||||
@ -174,6 +176,16 @@ public class MybatisPlusJoinAutoConfiguration {
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||
this.listableBeanFactory = beanFactory;
|
||||
SpringContentUtils.setSpringContext(this);
|
||||
|
||||
try {
|
||||
String[] names = beanFactory.getBeanNamesForType(SqlSessionFactory.class);
|
||||
for (String name : names) {
|
||||
BeanDefinition definition = beanFactory.getBeanDefinition(name);
|
||||
info(String.format("MPJ SqlSessionFactory bean definition: %s factoryBeanName: %s factoryMethodName: %s source: %s",
|
||||
name, definition.getFactoryBeanName(), definition.getFactoryMethodName(), definition.getSource()));
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
package com.github.yulichang.autoconfigure.consumer;
|
||||
|
||||
import com.github.yulichang.wrapper.enums.IfExistsSqlKeyWordEnum;
|
||||
|
||||
import java.util.function.BiPredicate;
|
||||
import com.github.yulichang.wrapper.interfaces.MBiPredicate;
|
||||
|
||||
/**
|
||||
* 自定义IfExists策略
|
||||
@ -10,5 +9,5 @@ import java.util.function.BiPredicate;
|
||||
* @author yulichang
|
||||
* @since 1.4.9
|
||||
*/
|
||||
public interface MybatisPlusJoinIfExistsConsumer extends BiPredicate<Object, IfExistsSqlKeyWordEnum> {
|
||||
public interface MybatisPlusJoinIfExistsConsumer extends MBiPredicate<Object, IfExistsSqlKeyWordEnum> {
|
||||
}
|
||||
|
@ -39,6 +39,11 @@
|
||||
<artifactId>mybatis-plus-join-annotation</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.yulichang</groupId>
|
||||
<artifactId>mybatis-plus-join-adapter-v312</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.yulichang</groupId>
|
||||
<artifactId>mybatis-plus-join-adapter-v33x</artifactId>
|
||||
@ -59,10 +64,27 @@
|
||||
<artifactId>mybatis-plus-join-adapter-v355</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.yulichang</groupId>
|
||||
<artifactId>mybatis-plus-join-wrapper-ext</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-extension</artifactId>
|
||||
<version>${mpj.mybatis.plus.version}</version>
|
||||
<version>${mybatis.plus.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-jsqlparser</artifactId>
|
||||
<version>${mybatis.plus.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-spring</artifactId>
|
||||
<version>${mybatis.plus.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -82,5 +104,19 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
|
||||
</manifest>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
@ -1,9 +1,6 @@
|
||||
package com.github.yulichang.adapter;
|
||||
|
||||
import com.github.yulichang.adapter.base.IAdapter;
|
||||
import com.github.yulichang.adapter.jsqlparser.JSqlParserHelper;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author yulichang
|
||||
@ -11,8 +8,4 @@ import java.util.function.Consumer;
|
||||
*/
|
||||
public class Adapter implements IAdapter {
|
||||
|
||||
@Override
|
||||
public void parserColum(String alias, String from, String selectSql, Consumer<String> columConsumer) {
|
||||
JSqlParserHelper.parserColum(alias, from, selectSql, columConsumer);
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,14 @@
|
||||
package com.github.yulichang.adapter;
|
||||
|
||||
import com.baomidou.mybatisplus.core.MybatisPlusVersion;
|
||||
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
|
||||
import com.github.yulichang.adapter.base.IAdapter;
|
||||
import com.github.yulichang.adapter.base.tookit.VersionUtils;
|
||||
import com.github.yulichang.adapter.v33x.AdapterV33x;
|
||||
import com.github.yulichang.adapter.v312.Adapter312;
|
||||
import com.github.yulichang.adapter.v33x.Adapter33x;
|
||||
import com.github.yulichang.adapter.v3431.Adapter3431;
|
||||
import com.github.yulichang.adapter.v355.Adapter355;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author yulichang
|
||||
* @since 1.4.3
|
||||
@ -22,19 +20,19 @@ public class AdapterHelper {
|
||||
|
||||
|
||||
static {
|
||||
String lastAdapter = "3.5.6";
|
||||
String version = Optional.of(MybatisPlusVersion.getVersion()).orElse(lastAdapter);
|
||||
|
||||
if (VersionUtils.compare(version, lastAdapter) >= 0) {
|
||||
String version = VersionUtils.getVersion();
|
||||
if (VersionUtils.compare(version, "3.5.6") >= 0) {
|
||||
adapter = new Adapter();
|
||||
} else if (VersionUtils.compare(version, "3.5.4") >= 0) {
|
||||
adapter = new Adapter355();
|
||||
} else if (VersionUtils.compare(version, "3.4.0") >= 0) {
|
||||
adapter = new Adapter3431();
|
||||
} else if (VersionUtils.compare(version, "3.3.0") >= 0) {
|
||||
adapter = new AdapterV33x();
|
||||
adapter = new Adapter33x();
|
||||
} else if (VersionUtils.compare(version, "3.1.2") >= 0) {
|
||||
adapter = new Adapter312();
|
||||
} else {
|
||||
throw ExceptionUtils.mpe("MPJ需要MP版本3.3.0+,当前MP版本%s", version);
|
||||
throw ExceptionUtils.mpe("MPJ需要MP版本3.1.2+,当前MP版本%s", version);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,137 @@
|
||||
package com.github.yulichang.base;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.github.yulichang.interfaces.MPJBaseJoin;
|
||||
import com.github.yulichang.toolkit.Constant;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* join相关方法
|
||||
*
|
||||
* @author yulichang
|
||||
*/
|
||||
public interface JoinMapper<T> {
|
||||
|
||||
/**
|
||||
* 根据 Wrapper 条件,连表删除
|
||||
*
|
||||
* @param wrapper joinWrapper
|
||||
*/
|
||||
int deleteJoin(@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);
|
||||
|
||||
/**
|
||||
* 根据 whereEntity 条件,更新记录
|
||||
*
|
||||
* @param entity 实体对象 (set 条件值,可以为 null)
|
||||
* @param wrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
|
||||
*/
|
||||
int updateJoin(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);
|
||||
|
||||
/**
|
||||
* 根据 whereEntity 条件,更新记录 (null字段也会更新 !!!)
|
||||
*
|
||||
* @param entity 实体对象 (set 条件值,可以为 null)
|
||||
* @param wrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
|
||||
*/
|
||||
int updateJoinAndNull(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);
|
||||
|
||||
/**
|
||||
* 根据 Wrapper 条件,查询总记录数
|
||||
*
|
||||
* @param wrapper joinWrapper
|
||||
*/
|
||||
Long selectJoinCount(@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);
|
||||
|
||||
/**
|
||||
* 连表查询返回一条记录
|
||||
*
|
||||
* @param wrapper joinWrapper
|
||||
* @return T
|
||||
*/
|
||||
default T selectJoinOne(@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper) {
|
||||
return selectJoinOne(null, wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 连表查询返回一条记录
|
||||
*
|
||||
* @param wrapper joinWrapper
|
||||
* @param clazz resultType
|
||||
*/
|
||||
<DTO> DTO selectJoinOne(@Param(Constant.CLAZZ) Class<DTO> clazz,
|
||||
@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);
|
||||
|
||||
/**
|
||||
* 连表查询返回Map
|
||||
*
|
||||
* @param wrapper joinWrapper
|
||||
*/
|
||||
default Map<String, Object> selectJoinMap(@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper) {
|
||||
//noinspection unchecked
|
||||
return selectJoinOne(Map.class, wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 连表查询返回记录集合
|
||||
*
|
||||
* @param wrapper joinWrapper
|
||||
* @return List<T>
|
||||
*/
|
||||
default List<T> selectJoinList(@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper) {
|
||||
return selectJoinList(null, wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 连表查询返回记录集合
|
||||
*
|
||||
* @param wrapper joinWrapper
|
||||
* @param clazz resultType
|
||||
*/
|
||||
<DTO> List<DTO> selectJoinList(@Param(Constant.CLAZZ) Class<DTO> clazz,
|
||||
@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);
|
||||
|
||||
/**
|
||||
* 连表查询返回Map集合
|
||||
*
|
||||
* @param wrapper joinWrapper
|
||||
*/
|
||||
default List<Map<String, Object>> selectJoinMaps(@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper) {
|
||||
//noinspection unchecked
|
||||
return (List<Map<String, Object>>) ((Object) selectJoinList(Map.class, wrapper));
|
||||
}
|
||||
|
||||
/**
|
||||
* 连表查询返回记录集合并分页
|
||||
*
|
||||
* @param wrapper joinWrapper
|
||||
*/
|
||||
default <P extends IPage<T>> P selectJoinPage(P page, @Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper) {
|
||||
return selectJoinPage(page, null, wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 连表查询返回记录集合并分页
|
||||
*
|
||||
* @param wrapper joinWrapper
|
||||
* @param clazz resultType
|
||||
* @param <DTO> 分页返回对象
|
||||
*/
|
||||
<DTO, P extends IPage<DTO>> P selectJoinPage(P page,
|
||||
@Param(Constant.CLAZZ) Class<DTO> clazz,
|
||||
@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);
|
||||
|
||||
/**
|
||||
* 连表查询返回Map集合并分页
|
||||
*
|
||||
* @param wrapper joinWrapper
|
||||
*/
|
||||
default <P extends IPage<Map<String, Object>>> P selectJoinMapsPage(P page,
|
||||
@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper) {
|
||||
//noinspection unchecked,rawtypes
|
||||
return (P) selectJoinPage((IPage) page, Map.class, wrapper);
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
package com.github.yulichang.base;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
|
||||
import com.github.yulichang.interfaces.MPJBaseJoin;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@SuppressWarnings({"unchecked", "unused"})
|
||||
public interface JoinService<T> {
|
||||
|
||||
BaseMapper<T> getBaseMapper();
|
||||
|
||||
/**
|
||||
* 根据 Wrapper 条件,连表删除
|
||||
*
|
||||
* @param wrapper joinWrapper
|
||||
*/
|
||||
default boolean deleteJoin(MPJBaseJoin<T> wrapper) {
|
||||
return SqlHelper.retBool(((JoinMapper<T>) getBaseMapper()).deleteJoin(wrapper));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 whereEntity 条件,更新记录
|
||||
*
|
||||
* @param entity 实体对象 (set 条件值,可以为 null)
|
||||
* @param wrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
|
||||
*/
|
||||
default boolean updateJoin(T entity, MPJBaseJoin<T> wrapper) {
|
||||
return SqlHelper.retBool(((JoinMapper<T>) getBaseMapper()).updateJoin(entity, wrapper));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 whereEntity 条件,更新记录 (null字段也会更新 !!!)
|
||||
*
|
||||
* @param entity 实体对象 (set 条件值,可以为 null)
|
||||
* @param wrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
|
||||
*/
|
||||
default boolean updateJoinAndNull(T entity, MPJBaseJoin<T> wrapper) {
|
||||
return SqlHelper.retBool(((JoinMapper<T>) getBaseMapper()).updateJoinAndNull(entity, wrapper));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 Wrapper 条件,查询总记录数
|
||||
*/
|
||||
default Long selectJoinCount(MPJBaseJoin<T> wrapper) {
|
||||
return ((JoinMapper<T>) getBaseMapper()).selectJoinCount(wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接查询返回一条记录
|
||||
*/
|
||||
default <DTO> DTO selectJoinOne(Class<DTO> clazz, MPJBaseJoin<T> wrapper) {
|
||||
return ((JoinMapper<T>) getBaseMapper()).selectJoinOne(clazz, wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接查询返回集合
|
||||
*/
|
||||
default <DTO> List<DTO> selectJoinList(Class<DTO> clazz, MPJBaseJoin<T> wrapper) {
|
||||
return ((JoinMapper<T>) getBaseMapper()).selectJoinList(clazz, wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接查询返回集合并分页
|
||||
*/
|
||||
default <DTO, P extends IPage<DTO>> P selectJoinListPage(P page, Class<DTO> clazz, MPJBaseJoin<T> wrapper) {
|
||||
return ((JoinMapper<T>) getBaseMapper()).selectJoinPage(page, clazz, wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接查询返回Map
|
||||
*/
|
||||
default Map<String, Object> selectJoinMap(MPJBaseJoin<T> wrapper) {
|
||||
return ((JoinMapper<T>) getBaseMapper()).selectJoinMap(wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接查询返回Map集合
|
||||
*/
|
||||
default List<Map<String, Object>> selectJoinMaps(MPJBaseJoin<T> wrapper) {
|
||||
return ((JoinMapper<T>) getBaseMapper()).selectJoinMaps(wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接查询返回Map集合并分页
|
||||
*/
|
||||
default <P extends IPage<Map<String, Object>>> P selectJoinMapsPage(P page, MPJBaseJoin<T> wrapper) {
|
||||
return ((JoinMapper<T>) getBaseMapper()).selectJoinMapsPage(page, wrapper);
|
||||
}
|
||||
}
|
@ -1,99 +1,11 @@
|
||||
package com.github.yulichang.base;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.github.yulichang.interfaces.MPJBaseJoin;
|
||||
import com.github.yulichang.toolkit.Constant;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author yulichang
|
||||
* @see BaseMapper
|
||||
*/
|
||||
public interface MPJBaseMapper<T> extends BaseMapper<T> {
|
||||
public interface MPJBaseMapper<T> extends BaseMapper<T>, JoinMapper<T> {
|
||||
|
||||
/**
|
||||
* 根据 Wrapper 条件,连表删除
|
||||
*
|
||||
* @param wrapper joinWrapper
|
||||
*/
|
||||
int deleteJoin(@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);
|
||||
|
||||
/**
|
||||
* 根据 whereEntity 条件,更新记录
|
||||
*
|
||||
* @param entity 实体对象 (set 条件值,可以为 null)
|
||||
* @param wrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
|
||||
*/
|
||||
int updateJoin(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);
|
||||
|
||||
/**
|
||||
* 根据 whereEntity 条件,更新记录 (null字段也会更新 !!!)
|
||||
*
|
||||
* @param entity 实体对象 (set 条件值,可以为 null)
|
||||
* @param wrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
|
||||
*/
|
||||
int updateJoinAndNull(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);
|
||||
|
||||
/**
|
||||
* 根据 Wrapper 条件,查询总记录数
|
||||
*
|
||||
* @param wrapper joinWrapper
|
||||
*/
|
||||
Long selectJoinCount(@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);
|
||||
|
||||
/**
|
||||
* 连表查询返回一条记录
|
||||
*
|
||||
* @param wrapper joinWrapper
|
||||
* @param clazz resultType
|
||||
*/
|
||||
<DTO> DTO selectJoinOne(@Param(Constant.CLAZZ) Class<DTO> clazz,
|
||||
@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);
|
||||
|
||||
/**
|
||||
* 连表查询返回Map
|
||||
*
|
||||
* @param wrapper joinWrapper
|
||||
*/
|
||||
Map<String, Object> selectJoinMap(@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);
|
||||
|
||||
/**
|
||||
* 连表查询返回记录集合
|
||||
*
|
||||
* @param wrapper joinWrapper
|
||||
* @param clazz resultType
|
||||
*/
|
||||
<DTO> List<DTO> selectJoinList(@Param(Constant.CLAZZ) Class<DTO> clazz,
|
||||
@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);
|
||||
|
||||
/**
|
||||
* 连表查询返回Map集合
|
||||
*
|
||||
* @param wrapper joinWrapper
|
||||
*/
|
||||
List<Map<String, Object>> selectJoinMaps(@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);
|
||||
|
||||
/**
|
||||
* 连表查询返回记录集合并分页
|
||||
*
|
||||
* @param wrapper joinWrapper
|
||||
* @param clazz resultType
|
||||
* @param <DTO> 分页返回对象
|
||||
*/
|
||||
<DTO, P extends IPage<DTO>> P selectJoinPage(P page,
|
||||
@Param(Constant.CLAZZ) Class<DTO> clazz,
|
||||
@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);
|
||||
|
||||
/**
|
||||
* 连表查询返回Map集合并分页
|
||||
*
|
||||
* @param wrapper joinWrapper
|
||||
*/
|
||||
<P extends IPage<Map<String, Object>>> P selectJoinMapsPage(P page,
|
||||
@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);
|
||||
}
|
||||
|
@ -1,12 +1,6 @@
|
||||
package com.github.yulichang.base;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
|
||||
import com.github.yulichang.interfaces.MPJBaseJoin;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 基础service
|
||||
@ -15,84 +9,6 @@ import java.util.Map;
|
||||
* @author yulichang
|
||||
*/
|
||||
@SuppressWarnings({"unused"})
|
||||
public interface MPJBaseService<T> extends IService<T> {
|
||||
public interface MPJBaseService<T> extends IService<T>, JoinService<T> {
|
||||
|
||||
|
||||
/**
|
||||
* 根据 Wrapper 条件,连表删除
|
||||
*
|
||||
* @param wrapper joinWrapper
|
||||
*/
|
||||
default boolean deleteJoin(MPJBaseJoin<T> wrapper) {
|
||||
return SqlHelper.retBool(((MPJBaseMapper<T>) getBaseMapper()).deleteJoin(wrapper));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 whereEntity 条件,更新记录
|
||||
*
|
||||
* @param entity 实体对象 (set 条件值,可以为 null)
|
||||
* @param wrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
|
||||
*/
|
||||
default boolean updateJoin(T entity, MPJBaseJoin<T> wrapper) {
|
||||
return SqlHelper.retBool(((MPJBaseMapper<T>) getBaseMapper()).updateJoin(entity, wrapper));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 whereEntity 条件,更新记录 (null字段也会更新 !!!)
|
||||
*
|
||||
* @param entity 实体对象 (set 条件值,可以为 null)
|
||||
* @param wrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
|
||||
*/
|
||||
default boolean updateJoinAndNull(T entity, MPJBaseJoin<T> wrapper) {
|
||||
return SqlHelper.retBool(((MPJBaseMapper<T>) getBaseMapper()).updateJoinAndNull(entity, wrapper));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 Wrapper 条件,查询总记录数
|
||||
*/
|
||||
default Long selectJoinCount(MPJBaseJoin<T> wrapper) {
|
||||
return ((MPJBaseMapper<T>) getBaseMapper()).selectJoinCount(wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接查询返回一条记录
|
||||
*/
|
||||
default <DTO> DTO selectJoinOne(Class<DTO> clazz, MPJBaseJoin<T> wrapper) {
|
||||
return ((MPJBaseMapper<T>) getBaseMapper()).selectJoinOne(clazz, wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接查询返回集合
|
||||
*/
|
||||
default <DTO> List<DTO> selectJoinList(Class<DTO> clazz, MPJBaseJoin<T> wrapper) {
|
||||
return ((MPJBaseMapper<T>) getBaseMapper()).selectJoinList(clazz, wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接查询返回集合并分页
|
||||
*/
|
||||
default <DTO, P extends IPage<DTO>> P selectJoinListPage(P page, Class<DTO> clazz, MPJBaseJoin<T> wrapper) {
|
||||
return ((MPJBaseMapper<T>) getBaseMapper()).selectJoinPage(page, clazz, wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接查询返回Map
|
||||
*/
|
||||
default Map<String, Object> selectJoinMap(MPJBaseJoin<T> wrapper) {
|
||||
return ((MPJBaseMapper<T>) getBaseMapper()).selectJoinMap(wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接查询返回Map集合
|
||||
*/
|
||||
default List<Map<String, Object>> selectJoinMaps(MPJBaseJoin<T> wrapper) {
|
||||
return ((MPJBaseMapper<T>) getBaseMapper()).selectJoinMaps(wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接查询返回Map集合并分页
|
||||
*/
|
||||
default <P extends IPage<Map<String, Object>>> P selectJoinMapsPage(P page, MPJBaseJoin<T> wrapper) {
|
||||
return ((MPJBaseMapper<T>) getBaseMapper()).selectJoinMapsPage(page, wrapper);
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,7 @@ package com.github.yulichang.config;
|
||||
import com.github.yulichang.config.enums.IfExistsEnum;
|
||||
import com.github.yulichang.config.enums.LogicDelTypeEnum;
|
||||
import com.github.yulichang.wrapper.enums.IfExistsSqlKeyWordEnum;
|
||||
|
||||
import java.util.function.BiPredicate;
|
||||
import com.github.yulichang.wrapper.interfaces.MBiPredicate;
|
||||
|
||||
/**
|
||||
* @author yulichang
|
||||
@ -53,5 +52,13 @@ public class ConfigProperties {
|
||||
* <p>
|
||||
* NOT_BLANK 非空白字符串 例: "" -> false, " " -> false, "\r" -> false, "abc" -> true ...
|
||||
*/
|
||||
public static BiPredicate<Object, IfExistsSqlKeyWordEnum> ifExists = (val, key) -> IfExistsEnum.NOT_EMPTY.test(val);
|
||||
public static MBiPredicate<Object, IfExistsSqlKeyWordEnum> ifExists = (val, key) -> IfExistsEnum.NOT_EMPTY.test(val);
|
||||
|
||||
|
||||
/**
|
||||
* 暂存 不可使用 用于规避starter包中需要序列化
|
||||
*/
|
||||
public static class Convert {
|
||||
public static IfExistsEnum IfExists = IfExistsEnum.NOT_EMPTY;
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package com.github.yulichang.config;
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.github.yulichang.interceptor.MPJInterceptor;
|
||||
import com.github.yulichang.toolkit.InterceptorList;
|
||||
import com.github.yulichang.toolkit.MybatisJoinPlusVersion;
|
||||
import org.apache.ibatis.logging.Log;
|
||||
import org.apache.ibatis.logging.LogFactory;
|
||||
import org.apache.ibatis.plugin.Interceptor;
|
||||
@ -30,11 +31,10 @@ public class MPJInterceptorConfig {
|
||||
System.out.println(" _ _ |_ _ _|_. ___ _ | _ . _ . _ \n" +
|
||||
"| | |\\/|_)(_| | |_\\ |_)||_|_\\ | (_) | | | \n" +
|
||||
" / | /\n" +
|
||||
" 1.4.13");
|
||||
" " + MybatisJoinPlusVersion.getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void replaceInterceptorChain(List<SqlSessionFactory> sqlSessionFactoryList) {
|
||||
if (CollectionUtils.isEmpty(sqlSessionFactoryList)) {
|
||||
return;
|
||||
@ -46,6 +46,7 @@ public class MPJInterceptorConfig {
|
||||
InterceptorChain chain = (InterceptorChain) interceptorChain.get(factory.getConfiguration());
|
||||
Field interceptors = InterceptorChain.class.getDeclaredField("interceptors");
|
||||
interceptors.setAccessible(true);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Interceptor> list = (List<Interceptor>) interceptors.get(chain);
|
||||
if (CollectionUtils.isEmpty(list)) {
|
||||
interceptors.set(chain, new InterceptorList<>());
|
||||
|
@ -1,9 +1,10 @@
|
||||
package com.github.yulichang.config.enums;
|
||||
|
||||
import com.github.yulichang.toolkit.MPJStringUtils;
|
||||
import com.github.yulichang.toolkit.StrUtils;
|
||||
import com.github.yulichang.wrapper.interfaces.MPredicate;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* 条件判断策略
|
||||
@ -11,7 +12,7 @@ import java.util.function.Predicate;
|
||||
* @author yulichang
|
||||
* @since 1.4.9
|
||||
*/
|
||||
public enum IfExistsEnum implements Predicate<Object> {
|
||||
public enum IfExistsEnum implements MPredicate<Object>, Serializable {
|
||||
|
||||
/**
|
||||
* 非null
|
||||
@ -20,15 +21,15 @@ public enum IfExistsEnum implements Predicate<Object> {
|
||||
/**
|
||||
* 非空字符串 例: "" -> false, " " -> true ...
|
||||
*/
|
||||
NOT_EMPTY(val -> NOT_NULL.and(v -> !(v instanceof CharSequence) || MPJStringUtils.isNotEmpty((CharSequence) v)).test(val)),
|
||||
NOT_EMPTY(val -> NOT_NULL.and(v -> !(v instanceof CharSequence) || StrUtils.isNotEmpty((CharSequence) v)).test(val)),
|
||||
/**
|
||||
* NOT_BLANK 非空白字符串 例: "" -> false, " " -> false, "\r" -> false, "abc" -> true ...
|
||||
*/
|
||||
NOT_BLANK(val -> NOT_NULL.and(v -> !(v instanceof CharSequence) || MPJStringUtils.isNotBlank((CharSequence) v)).test(val));
|
||||
NOT_BLANK(val -> NOT_NULL.and(v -> !(v instanceof CharSequence) || StrUtils.isNotBlank((CharSequence) v)).test(val));
|
||||
|
||||
private final Predicate<Object> predicate;
|
||||
private final MPredicate<Object> predicate;
|
||||
|
||||
IfExistsEnum(Predicate<Object> predicate) {
|
||||
IfExistsEnum(MPredicate<Object> predicate) {
|
||||
this.predicate = predicate;
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,13 @@
|
||||
package com.github.yulichang.config.enums;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 逻辑删除位置
|
||||
*
|
||||
* @author yulichang
|
||||
* @since 1.4.4
|
||||
*/
|
||||
public enum LogicDelTypeEnum {
|
||||
public enum LogicDelTypeEnum implements Serializable {
|
||||
WHERE, ON
|
||||
}
|
||||
|
@ -0,0 +1,451 @@
|
||||
package com.github.yulichang.extension.apt;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.OrderBy;
|
||||
import com.baomidou.mybatisplus.core.conditions.SharedString;
|
||||
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.github.yulichang.adapter.AdapterHelper;
|
||||
import com.github.yulichang.config.ConfigProperties;
|
||||
import com.github.yulichang.config.enums.LogicDelTypeEnum;
|
||||
import com.github.yulichang.extension.apt.interfaces.QueryJoin;
|
||||
import com.github.yulichang.extension.apt.matedata.BaseColumn;
|
||||
import com.github.yulichang.extension.apt.matedata.Column;
|
||||
import com.github.yulichang.toolkit.*;
|
||||
import com.github.yulichang.toolkit.support.ColumnCache;
|
||||
import com.github.yulichang.wrapper.interfaces.MFunction;
|
||||
import com.github.yulichang.wrapper.segments.PageInfo;
|
||||
import com.github.yulichang.wrapper.segments.SelectCache;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.baomidou.mybatisplus.core.enums.WrapperKeyword.APPLY;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
/**
|
||||
* 参考 {@link com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper}
|
||||
*
|
||||
* @author yulichang
|
||||
*/
|
||||
@SuppressWarnings({"DuplicatedCode", "unused"})
|
||||
public abstract class AptAbstractWrapper<T, Children extends AptAbstractWrapper<T, Children>>
|
||||
extends JoinAbstractWrapper<T, Children> implements QueryJoin<Children, T> {
|
||||
|
||||
/**
|
||||
* 主表别名
|
||||
*/
|
||||
@Getter
|
||||
protected String alias = ConfigProperties.tableAlias;
|
||||
/**
|
||||
* 副表别名
|
||||
*/
|
||||
protected String subTableAlias = ConfigProperties.tableAlias;
|
||||
/**
|
||||
* 是否构建是否存在一对多
|
||||
*/
|
||||
@Getter
|
||||
protected boolean resultMap = false;
|
||||
@Getter
|
||||
protected boolean resultMapCollection = false;
|
||||
|
||||
@Setter
|
||||
protected PageInfo pageInfo;
|
||||
|
||||
@Getter
|
||||
protected boolean pageByMain = false;
|
||||
/**
|
||||
* 表序号
|
||||
*/
|
||||
protected int tableIndex = 1;
|
||||
|
||||
protected boolean isMain = true;
|
||||
|
||||
/**
|
||||
* 主表 表名处理方法
|
||||
*/
|
||||
protected boolean dynamicTableName = false;
|
||||
|
||||
/**
|
||||
* 主表 表名处理方法
|
||||
*/
|
||||
protected SFunction<String, String> tableFunc;
|
||||
|
||||
/**
|
||||
* 逻辑删除位置
|
||||
*/
|
||||
protected LogicDelTypeEnum logicDelType = ConfigProperties.logicDelType;
|
||||
|
||||
/**
|
||||
* 查询表
|
||||
*/
|
||||
protected final SharedString from = new SharedString();
|
||||
/**
|
||||
* 是否有表别名
|
||||
*/
|
||||
@Getter
|
||||
protected boolean hasAlias;
|
||||
/**
|
||||
* 连表关键字 on 条件 func 使用
|
||||
*/
|
||||
@Getter
|
||||
protected String keyWord;
|
||||
/**
|
||||
* 副表逻辑删除开关
|
||||
*/
|
||||
protected boolean subLogicSql = ConfigProperties.subTableLogic;
|
||||
/**
|
||||
* 主表逻辑删除开关
|
||||
*/
|
||||
protected boolean logicSql = true;
|
||||
|
||||
@Getter
|
||||
protected BaseColumn<T> baseColumn;
|
||||
|
||||
/**
|
||||
* apt别名对应
|
||||
*/
|
||||
@Getter
|
||||
protected TableMap aptIndex;
|
||||
|
||||
/**
|
||||
* 构造方法
|
||||
*/
|
||||
protected AptAbstractWrapper(BaseColumn<T> baseColumn) {
|
||||
this.alias = StrUtils.isNotBlank(baseColumn.getAlias()) ? baseColumn.getAlias() : this.alias;
|
||||
setEntityClass(baseColumn.getColumnClass());
|
||||
this.baseColumn = baseColumn;
|
||||
initNeed();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造方法
|
||||
*
|
||||
* @param entity 主表实体类
|
||||
*/
|
||||
protected AptAbstractWrapper(BaseColumn<T> baseColumn, T entity) {
|
||||
this.alias = StrUtils.isNotBlank(baseColumn.getAlias()) ? baseColumn.getAlias() : this.alias;
|
||||
setEntity(entity);
|
||||
this.baseColumn = baseColumn;
|
||||
initNeed();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据主表分页
|
||||
*/
|
||||
public Children pageByMain() {
|
||||
this.pageByMain = true;
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据主表分页
|
||||
*/
|
||||
public Children pageByMain(MFunction<PageInfo> function) {
|
||||
this.pageByMain = true;
|
||||
function.apply(getPageInfo());
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
public PageInfo getPageInfo() {
|
||||
if (pageInfo == null) {
|
||||
pageInfo = new PageInfo();
|
||||
}
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置表别名
|
||||
* 设置表别名注意sql注入问题
|
||||
*
|
||||
* @return 自定义表别名
|
||||
*/
|
||||
public Children setTableName(SFunction<String, String> tableFunc) {
|
||||
if (isMain) {
|
||||
if (tableFunc != null) {
|
||||
this.dynamicTableName = true;
|
||||
this.tableFunc = tableFunc;
|
||||
}
|
||||
} else {
|
||||
this.tableName = tableFunc.apply(this.tableName);
|
||||
}
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
public String getTableName(String tableName) {
|
||||
if (isMain) {
|
||||
if (dynamicTableName) {
|
||||
return tableFunc.apply(tableName);
|
||||
}
|
||||
return tableName;
|
||||
}
|
||||
return super.getTableName();
|
||||
}
|
||||
|
||||
|
||||
public String getTableNameEnc(String tableName) {
|
||||
Class<T> entityClass = getEntityClass();
|
||||
if (entityClass != null) {
|
||||
TableInfo tableInfo = TableHelper.get(entityClass);
|
||||
if (tableInfo != null) {
|
||||
if (dynamicTableName) {
|
||||
return tableFunc.apply(tableInfo.getTableName());
|
||||
}
|
||||
return tableInfo.getTableName();
|
||||
}
|
||||
}
|
||||
String decode;
|
||||
try {
|
||||
decode = URLDecoder.decode(tableName, StandardCharsets.UTF_8.name());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (dynamicTableName) {
|
||||
return tableFunc.apply(decode);
|
||||
}
|
||||
return decode;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String columnsToString(Column... columns) {
|
||||
return Arrays.stream(columns).map(this::columnToString)
|
||||
.collect(joining(StringPool.COMMA));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String columnToString(Column column) {
|
||||
String pf = column.getAlias().get();
|
||||
if (Objects.nonNull(pf)) {
|
||||
return pf + StringPool.DOT + getCache(column).getColumn();
|
||||
}
|
||||
return this.aptIndex.get(column.getRoot()) + StringPool.DOT + getCache(column).getColumn();
|
||||
}
|
||||
|
||||
protected SelectCache getCache(Column fn) {
|
||||
Map<String, SelectCache> cacheMap = ColumnCache.getMapField(fn.getClazz());
|
||||
return cacheMap.get(fn.getProperty());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 关闭副表逻辑删除
|
||||
* <p>
|
||||
* 副表逻辑删除默认在where语句中
|
||||
* 但有时候需要让它出现在on语句中, 这两种写法区别还是很大的
|
||||
* 所以可以关闭副表逻辑删除, 通过on语句多条件, 自己实现on语句的逻辑删除
|
||||
*/
|
||||
public Children disableSubLogicDel() {
|
||||
this.subLogicSql = false;
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
public Children enableSubLogicDel() {
|
||||
this.subLogicSql = true;
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭主表逻辑删除
|
||||
*/
|
||||
public Children disableLogicDel() {
|
||||
this.logicSql = false;
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
public Children enableLogicDel() {
|
||||
this.logicSql = true;
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
/**
|
||||
* 副表部分逻辑删除支持
|
||||
*/
|
||||
public String getSubLogicSql() {
|
||||
if (subLogicSql && logicDelType == LogicDelTypeEnum.WHERE) {
|
||||
if (aptIndex.isEmpty()) {
|
||||
return StringPool.EMPTY;
|
||||
}
|
||||
return aptIndex.keyList().stream().map(key -> LogicInfoUtils.getLogicInfoApt(key.getColumnClass(), this.aptIndex.get(key)))
|
||||
.collect(Collectors.joining(StringPool.SPACE));
|
||||
}
|
||||
return StringPool.EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* 主表部分逻辑删除支持
|
||||
*/
|
||||
public boolean getLogicSql() {
|
||||
return this.logicSql;
|
||||
}
|
||||
|
||||
/**
|
||||
* 调整逻辑删除位置为ON语句
|
||||
*/
|
||||
public Children logicDelToOn() {
|
||||
this.logicDelType = LogicDelTypeEnum.ON;
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
/**
|
||||
* 调整逻辑删除位置为WHERE语句
|
||||
*/
|
||||
public Children logicDelToWhere() {
|
||||
this.logicDelType = LogicDelTypeEnum.WHERE;
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取连表部分语句
|
||||
*/
|
||||
public String getFrom() {
|
||||
if (StrUtils.isBlank(from.getStringValue())) {
|
||||
StringBuilder value = new StringBuilder();
|
||||
for (Children wrapper : onWrappers) {
|
||||
if (StrUtils.isBlank(wrapper.from.getStringValue())) {
|
||||
if (this.subLogicSql && this.logicDelType == LogicDelTypeEnum.ON) {
|
||||
TableInfo tableInfo = TableHelper.getAssert(wrapper.getJoinClass());
|
||||
if (AdapterHelper.getAdapter().mpjHasLogic(tableInfo)) {
|
||||
wrapper.appendSqlSegments(APPLY, () -> LogicInfoUtils.getLogicInfoNoAnd(
|
||||
wrapper.getIndex(), wrapper.getJoinClass(), wrapper.isHasAlias(), wrapper.getAlias()
|
||||
));
|
||||
}
|
||||
}
|
||||
value.append(StringPool.SPACE)
|
||||
.append(wrapper.getKeyWord())
|
||||
.append(StringPool.SPACE)
|
||||
.append(wrapper.getTableName())
|
||||
.append(StringPool.SPACE)
|
||||
.append(wrapper.hasAlias ? wrapper.alias : (wrapper.alias + wrapper.getIndex()))
|
||||
.append(Constant.ON)
|
||||
.append(wrapper.getExpression().getNormal().getSqlSegment());
|
||||
} else {
|
||||
value.append(StringPool.SPACE)
|
||||
.append(wrapper.getKeyWord())
|
||||
.append(StringPool.SPACE)
|
||||
.append(wrapper.from.getStringValue())
|
||||
.append(StringPool.SPACE);
|
||||
}
|
||||
}
|
||||
from.setStringValue(value.toString());
|
||||
}
|
||||
return from.getStringValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检验表是否已连接
|
||||
*/
|
||||
public boolean checkJoinTable(Class<?> clazz) {
|
||||
return onWrappers.stream().anyMatch(wrapper -> {
|
||||
if (Objects.equals(wrapper.getJoinClass(), clazz)) {
|
||||
return true;
|
||||
} else {
|
||||
TableInfo info = TableHelper.getAssert(clazz);
|
||||
String tableName = info.getTableName();
|
||||
return Optional.ofNullable(wrapper.from.getStringValue())
|
||||
.map(w -> w.contains(Constant.JOIN + StringPool.SPACE + tableName + StringPool.SPACE))
|
||||
.orElse(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部调用, 不建议使用
|
||||
*/
|
||||
@Override
|
||||
public <R> Children join(String keyWord, BaseColumn<R> baseColumn, MFunction<AptAbstractWrapper<T, ?>> function) {
|
||||
Integer oldIndex = this.getIndex();
|
||||
int newIndex = tableIndex;
|
||||
TableInfo info = TableHelper.getAssert(baseColumn.getColumnClass());
|
||||
Children instance = instance(newIndex, keyWord, baseColumn.getColumnClass(), info.getTableName());
|
||||
instance.isMain = false;
|
||||
onWrappers.add(instance);
|
||||
if (StrUtils.isBlank(baseColumn.getAlias())) {
|
||||
aptIndex.put(baseColumn, subTableAlias + newIndex);
|
||||
instance.alias = subTableAlias;
|
||||
instance.hasAlias = false;
|
||||
} else {
|
||||
aptIndex.put(baseColumn, baseColumn.getAlias());
|
||||
instance.alias = baseColumn.getAlias();
|
||||
instance.hasAlias = true;
|
||||
}
|
||||
tableIndex++;
|
||||
function.apply(instance);
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义关键词连接
|
||||
*
|
||||
* @param keyWord 连表关键词
|
||||
* @param condition 条件
|
||||
* @param joinSql sql
|
||||
*/
|
||||
@Override
|
||||
public Children join(String keyWord, boolean condition, String joinSql, Object... objects) {
|
||||
if (condition) {
|
||||
Children wrapper = instanceEmpty();
|
||||
wrapper.from.setStringValue(formatSqlMaybeWithParam(joinSql, objects));
|
||||
wrapper.keyWord = keyWord;
|
||||
onWrappers.add(wrapper);
|
||||
}
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否使用默认注解 {@link OrderBy} 排序
|
||||
*
|
||||
* @return true 使用 false 不使用
|
||||
*/
|
||||
public boolean isUseAnnotationOrderBy() {
|
||||
final String _sqlSegment = this.getSqlSegment();
|
||||
if (StrUtils.isBlank(_sqlSegment)) {
|
||||
return true;
|
||||
}
|
||||
final String _sqlSegmentToUpperCase = _sqlSegment.toUpperCase();
|
||||
return !(_sqlSegmentToUpperCase.contains(Constants.ORDER_BY)
|
||||
|| _sqlSegmentToUpperCase.contains(Constants.LIMIT));
|
||||
}
|
||||
|
||||
/**
|
||||
* 必要的初始化
|
||||
*/
|
||||
protected void initNeed() {
|
||||
paramNameSeq = new AtomicInteger(0);
|
||||
paramNameValuePairs = new HashMap<>(16);
|
||||
expression = new MergeSegments();
|
||||
lastSql = SharedString.emptyString();
|
||||
sqlComment = SharedString.emptyString();
|
||||
sqlFirst = SharedString.emptyString();
|
||||
aptIndex = new TableMap(this.baseColumn, this.alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
this.alias = ConfigProperties.tableAlias;
|
||||
this.resultMap = false;
|
||||
this.resultMapCollection = false;
|
||||
this.pageInfo = null;
|
||||
this.pageByMain = false;
|
||||
this.tableIndex = 1;
|
||||
this.dynamicTableName = false;
|
||||
this.tableFunc = null;
|
||||
this.logicDelType = ConfigProperties.logicDelType;
|
||||
this.from.toEmpty();
|
||||
this.hasAlias = false;
|
||||
this.keyWord = null;
|
||||
this.logicSql = true;
|
||||
this.isMain = true;
|
||||
this.checkSqlInjection = false;
|
||||
this.onWrappers.clear();
|
||||
this.aptIndex.clear();
|
||||
}
|
||||
}
|
@ -0,0 +1,361 @@
|
||||
package com.github.yulichang.extension.apt;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.SharedString;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
|
||||
import com.baomidou.mybatisplus.core.toolkit.*;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.github.yulichang.config.ConfigProperties;
|
||||
import com.github.yulichang.extension.apt.interfaces.Query;
|
||||
import com.github.yulichang.extension.apt.interfaces.QueryLabel;
|
||||
import com.github.yulichang.extension.apt.matedata.BaseColumn;
|
||||
import com.github.yulichang.extension.apt.matedata.Column;
|
||||
import com.github.yulichang.extension.apt.toolkit.AptWrapperUtils;
|
||||
import com.github.yulichang.extension.apt.toolkit.AptWrappers;
|
||||
import com.github.yulichang.toolkit.Constant;
|
||||
import com.github.yulichang.toolkit.LambdaUtils;
|
||||
import com.github.yulichang.toolkit.StrUtils;
|
||||
import com.github.yulichang.toolkit.TableMap;
|
||||
import com.github.yulichang.toolkit.support.ColumnCache;
|
||||
import com.github.yulichang.wrapper.enums.IfExistsSqlKeyWordEnum;
|
||||
import com.github.yulichang.wrapper.interfaces.Chain;
|
||||
import com.github.yulichang.wrapper.interfaces.MBiPredicate;
|
||||
import com.github.yulichang.wrapper.interfaces.MFunction;
|
||||
import com.github.yulichang.wrapper.interfaces.SelectWrapper;
|
||||
import com.github.yulichang.wrapper.resultmap.Label;
|
||||
import com.github.yulichang.wrapper.segments.*;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Lambda 语法使用 Wrapper
|
||||
*
|
||||
* @author yulichang
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class AptQueryWrapper<T> extends AptAbstractWrapper<T, AptQueryWrapper<T>> implements
|
||||
Query<AptQueryWrapper<T>>, QueryLabel<AptQueryWrapper<T>>, Chain<T>, SelectWrapper<T, AptQueryWrapper<T>> {
|
||||
|
||||
/**
|
||||
* 查询字段 sql
|
||||
*/
|
||||
private SharedString sqlSelect = new SharedString();
|
||||
/**
|
||||
* 是否 select distinct
|
||||
*/
|
||||
private boolean selectDistinct = false;
|
||||
/**
|
||||
* 查询的字段
|
||||
*/
|
||||
@Getter
|
||||
private final List<Select> selectColumns = new ArrayList<>();
|
||||
/**
|
||||
* 映射关系
|
||||
*/
|
||||
@Getter
|
||||
private final List<Label<?>> resultMapMybatisLabel = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* union sql
|
||||
*/
|
||||
private SharedString unionSql;
|
||||
|
||||
/**
|
||||
* 自定义wrapper索引
|
||||
*/
|
||||
private AtomicInteger wrapperIndex;
|
||||
|
||||
/**
|
||||
* 自定义wrapper
|
||||
*/
|
||||
@Getter
|
||||
private Map<String, Wrapper<?>> wrapperMap;
|
||||
|
||||
|
||||
/**
|
||||
* 推荐使用此构造方法
|
||||
*/
|
||||
public AptQueryWrapper(BaseColumn<T> baseColumn) {
|
||||
super(baseColumn);
|
||||
}
|
||||
|
||||
|
||||
public AptQueryWrapper(BaseColumn<T> baseColumn, T entity) {
|
||||
super(baseColumn, entity);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 不建议直接 new 该实例,使用 JoinWrappers.lambda(UserDO.class)
|
||||
*/
|
||||
protected AptQueryWrapper(T entity, BaseColumn<T> baseColumn, SharedString sqlSelect, AtomicInteger paramNameSeq,
|
||||
Map<String, Object> paramNameValuePairs, MergeSegments mergeSegments, SharedString paramAlias,
|
||||
SharedString lastSql, SharedString sqlComment, SharedString sqlFirst,
|
||||
TableMap aptIndex, Integer index, String keyWord, Class<?> joinClass, String tableName,
|
||||
MBiPredicate<Object, IfExistsSqlKeyWordEnum> IfExists) {
|
||||
super(baseColumn);
|
||||
super.setEntity(entity);
|
||||
super.setEntityClass(baseColumn.getColumnClass());
|
||||
this.baseColumn = baseColumn;
|
||||
this.paramNameSeq = paramNameSeq;
|
||||
this.paramNameValuePairs = paramNameValuePairs;
|
||||
this.expression = mergeSegments;
|
||||
this.sqlSelect = sqlSelect;
|
||||
this.paramAlias = paramAlias;
|
||||
this.lastSql = lastSql;
|
||||
this.sqlComment = sqlComment;
|
||||
this.sqlFirst = sqlFirst;
|
||||
if (aptIndex != null) {
|
||||
this.aptIndex = aptIndex;
|
||||
}
|
||||
this.index = index;
|
||||
this.keyWord = keyWord;
|
||||
this.joinClass = joinClass;
|
||||
this.tableName = tableName;
|
||||
this.ifExists = IfExists;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sql去重
|
||||
* select distinct
|
||||
*/
|
||||
public AptQueryWrapper<T> distinct() {
|
||||
this.selectDistinct = true;
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Select> getSelectColum() {
|
||||
return this.selectColumns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLabel(Label<?> label, boolean isCollection) {
|
||||
if (isCollection) {
|
||||
this.resultMapCollection = true;
|
||||
}
|
||||
this.resultMap = true;
|
||||
this.resultMapMybatisLabel.add(label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AptQueryWrapper<T> getChildren() {
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置查询字段
|
||||
*
|
||||
* @param columns 字段数组
|
||||
* @return children
|
||||
*/
|
||||
public final AptQueryWrapper<T> select(Column... columns) {
|
||||
if (ArrayUtils.isNotEmpty(columns)) {
|
||||
for (Column s : columns) {
|
||||
Map<String, SelectCache> cacheMap = ColumnCache.getMapField(s.getClazz());
|
||||
SelectCache cache = cacheMap.get(s.getProperty());
|
||||
getSelectColum().add(new SelectApt(cache, s));
|
||||
}
|
||||
}
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询实体类全部字段
|
||||
*/
|
||||
@Override
|
||||
public final <E> AptQueryWrapper<T> selectAll(BaseColumn<E> baseColumn, Column... exclude) {
|
||||
return Query.super.selectAll(baseColumn, exclude);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询主表全部字段
|
||||
* <p>
|
||||
* 需要使用 使用 JoinWrappers.lambda(clazz) 或者 new MPJLambdaQueryWrapper<<(clazz) 构造
|
||||
*
|
||||
* @return children
|
||||
*/
|
||||
@Override
|
||||
public AptQueryWrapper<T> selectAll() {
|
||||
Assert.notNull(getEntityClass(), "使用 AptWrappers.query(clazz) 或者 new JoinAptQueryWrapper<>(BaseColum)");
|
||||
return selectAll(getBaseColumn());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AptQueryWrapper<T> selectFunc(String sql, MFunction<AptConsumer> column, String alias) {
|
||||
AptConsumer apply = column.apply(new AptConsumer());
|
||||
String formatSql;
|
||||
if (ArrayUtils.isEmpty(apply.getValues())) {
|
||||
formatSql = sql;
|
||||
} else {
|
||||
formatSql = formatSqlMaybeWithParam(sql, apply.getValues());
|
||||
}
|
||||
getSelectColum().add(new SelectApt(apply.getColumns(), () -> formatSql, alias));
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
public <E, F> AptQueryWrapper<T> selectSub(BaseColumn<E> baseColumn, Consumer<AptQueryWrapper<E>> consumer, SFunction<F, ?> alias) {
|
||||
return selectSub(baseColumn, consumer, LambdaUtils.getName(alias));
|
||||
}
|
||||
|
||||
/**
|
||||
* 子查询
|
||||
*/
|
||||
public <E, F> AptQueryWrapper<T> selectSub(BaseColumn<E> baseColumn, Consumer<AptQueryWrapper<E>> consumer, String alias) {
|
||||
AptQueryWrapper<E> wrapper = new AptQueryWrapper<E>(null, baseColumn, SharedString.emptyString(),
|
||||
paramNameSeq, paramNameValuePairs, new MergeSegments(), new SharedString(this.paramAlias
|
||||
.getStringValue()), SharedString.emptyString(), SharedString.emptyString(), SharedString.emptyString(),
|
||||
null, null, null, null, null, ifExists) {
|
||||
};
|
||||
wrapper.aptIndex.setParent(this.aptIndex);
|
||||
if (null == baseColumn.getAlias()) {
|
||||
wrapper.alias = ConfigProperties.subQueryAlias;
|
||||
wrapper.aptIndex.setRootAlias(ConfigProperties.subQueryAlias);
|
||||
}
|
||||
wrapper.subTableAlias = ConfigProperties.subQueryAlias;
|
||||
consumer.accept(wrapper);
|
||||
addCustomWrapper(wrapper);
|
||||
this.selectColumns.add(new SelectSub(() -> AptWrapperUtils.buildSubSqlByWrapper(baseColumn.getColumnClass(), wrapper, alias), hasAlias, this.alias, alias));
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* union
|
||||
* <p>
|
||||
* 例: wrapper.union(UserDO.class, union -> union.selectAll(UserDO.class))
|
||||
*
|
||||
* @param baseColumn union语句的主表类型
|
||||
* @since 1.4.8
|
||||
*/
|
||||
public <U> AptQueryWrapper<T> union(BaseColumn<U> baseColumn, Consumer<AptQueryWrapper<U>> consumer) {
|
||||
AptQueryWrapper<U> unionWrapper = AptWrappers.query(baseColumn);
|
||||
addCustomWrapper(unionWrapper);
|
||||
consumer.accept(unionWrapper);
|
||||
|
||||
String sb = " UNION " + AptWrapperUtils.buildUnionSqlByWrapper(baseColumn.getColumnClass(), unionWrapper);
|
||||
|
||||
if (Objects.isNull(unionSql)) {
|
||||
unionSql = SharedString.emptyString();
|
||||
}
|
||||
unionSql.setStringValue(unionSql.getStringValue() + sb);
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
/**
|
||||
* union
|
||||
* <p>
|
||||
* 例: wrapper.unionAll(UserDO.class, union -> union.selectAll(UserDO.class))
|
||||
*
|
||||
* @param baseColumn union语句的主表类型
|
||||
* @since 1.4.8
|
||||
*/
|
||||
public <U> AptQueryWrapper<T> unionAll(BaseColumn<U> baseColumn, Consumer<AptQueryWrapper<U>> consumer) {
|
||||
AptQueryWrapper<U> unionWrapper = AptWrappers.query(baseColumn);
|
||||
addCustomWrapper(unionWrapper);
|
||||
consumer.accept(unionWrapper);
|
||||
|
||||
String sb = " UNION ALL " + AptWrapperUtils.buildUnionSqlByWrapper(baseColumn.getColumnClass(), unionWrapper);
|
||||
|
||||
if (Objects.isNull(unionSql)) {
|
||||
unionSql = SharedString.emptyString();
|
||||
}
|
||||
unionSql.setStringValue(unionSql.getStringValue() + sb);
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
private void addCustomWrapper(AptQueryWrapper<?> wrapper) {
|
||||
if (Objects.isNull(wrapperIndex)) {
|
||||
wrapperIndex = new AtomicInteger(0);
|
||||
}
|
||||
int index = wrapperIndex.incrementAndGet();
|
||||
if (Objects.isNull(wrapperMap)) {
|
||||
wrapperMap = new HashMap<>();
|
||||
}
|
||||
String key = "ew" + index;
|
||||
wrapper.setParamAlias(wrapper.getParamAlias() + ".wrapperMap." + key);
|
||||
wrapperMap.put(key, wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询条件 SQL 片段
|
||||
*/
|
||||
@Override
|
||||
public String getSqlSelect() {
|
||||
if (StrUtils.isBlank(sqlSelect.getStringValue()) && CollectionUtils.isNotEmpty(selectColumns)) {
|
||||
String s = selectColumns.stream().map(i -> {
|
||||
if (i.isStr()) {
|
||||
return i.getColumn();
|
||||
}
|
||||
if (i.isFunc()) {
|
||||
return String.format(i.getFunc().getSql(), Arrays.stream(i.getColumns()).map(c ->
|
||||
this.aptIndex.get(c.getRoot()) + StringPool.DOT + i.getColumn()).toArray()) + Constant.AS + i.getAlias();
|
||||
} else {
|
||||
String prefix;
|
||||
if (null == i.getTableAlias() && null != i.getBaseColumn()) {
|
||||
prefix = this.aptIndex.get(i.getBaseColumn());
|
||||
} else {
|
||||
prefix = i.getTableAlias();
|
||||
}
|
||||
String col = prefix + StringPool.DOT + i.getColumn();
|
||||
return i.isHasAlias() ? col + Constants.AS + i.getAlias() : col;
|
||||
}
|
||||
}).collect(Collectors.joining(StringPool.COMMA));
|
||||
sqlSelect.setStringValue(s);
|
||||
}
|
||||
return sqlSelect.getStringValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUnionSql() {
|
||||
return Optional.ofNullable(unionSql).map(SharedString::getStringValue).orElse(StringPool.EMPTY);
|
||||
}
|
||||
|
||||
public boolean getSelectDistinct() {
|
||||
return selectDistinct;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于生成嵌套 sql
|
||||
* <p>故 sqlSelect 不向下传递</p>
|
||||
*/
|
||||
@Override
|
||||
protected AptQueryWrapper<T> instance() {
|
||||
return instance(index, null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AptQueryWrapper<T> instanceEmpty() {
|
||||
return new AptQueryWrapper<>(getBaseColumn());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AptQueryWrapper<T> instance(Integer index, String keyWord, Class<?> joinClass, String tableName) {
|
||||
return new AptQueryWrapper<>(getEntity(), baseColumn, null, paramNameSeq, paramNameValuePairs,
|
||||
new MergeSegments(), this.paramAlias, SharedString.emptyString(), SharedString.emptyString(), SharedString.emptyString(),
|
||||
this.aptIndex, index, keyWord, joinClass, tableName, ifExists);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
selectDistinct = false;
|
||||
sqlSelect.toNull();
|
||||
selectColumns.clear();
|
||||
wrapperIndex = new AtomicInteger(0);
|
||||
if (Objects.nonNull(wrapperMap)) wrapperMap.clear();
|
||||
if (Objects.nonNull(unionSql)) unionSql.toEmpty();
|
||||
resultMapMybatisLabel.clear();
|
||||
ifExists = ConfigProperties.ifExists;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,98 @@
|
||||
package com.github.yulichang.extension.apt.interfaces;
|
||||
|
||||
import com.github.yulichang.extension.apt.matedata.Column;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 将原来的泛型R改成Column
|
||||
* <p>
|
||||
* {@link com.baomidou.mybatisplus.core.conditions.interfaces.Compare}
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface Compare<Children> extends Serializable {
|
||||
|
||||
default Children eq(Column column, Object val) {
|
||||
return eq(true, column, val);
|
||||
}
|
||||
|
||||
Children eq(boolean condition, Column column, Object val);
|
||||
|
||||
default Children ne(Column column, Object val) {
|
||||
return ne(true, column, val);
|
||||
}
|
||||
|
||||
Children ne(boolean condition, Column column, Object val);
|
||||
|
||||
default Children gt(Column column, Object val) {
|
||||
return gt(true, column, val);
|
||||
}
|
||||
|
||||
Children gt(boolean condition, Column column, Object val);
|
||||
|
||||
default Children ge(Column column, Object val) {
|
||||
return ge(true, column, val);
|
||||
}
|
||||
|
||||
Children ge(boolean condition, Column column, Object val);
|
||||
|
||||
default Children lt(Column column, Object val) {
|
||||
return lt(true, column, val);
|
||||
}
|
||||
|
||||
Children lt(boolean condition, Column column, Object val);
|
||||
|
||||
default Children le(Column column, Object val) {
|
||||
return le(true, column, val);
|
||||
}
|
||||
|
||||
Children le(boolean condition, Column column, Object val);
|
||||
|
||||
default Children between(Column column, Object val1, Object val2) {
|
||||
return between(true, column, val1, val2);
|
||||
}
|
||||
|
||||
Children between(boolean condition, Column column, Object val1, Object val2);
|
||||
|
||||
default Children notBetween(Column column, Object val1, Object val2) {
|
||||
return notBetween(true, column, val1, val2);
|
||||
}
|
||||
|
||||
Children notBetween(boolean condition, Column column, Object val1, Object val2);
|
||||
|
||||
default Children like(Column column, Object val) {
|
||||
return like(true, column, val);
|
||||
}
|
||||
|
||||
Children like(boolean condition, Column column, Object val);
|
||||
|
||||
default Children notLike(Column column, Object val) {
|
||||
return notLike(true, column, val);
|
||||
}
|
||||
|
||||
Children notLike(boolean condition, Column column, Object val);
|
||||
|
||||
default Children likeLeft(Column column, Object val) {
|
||||
return likeLeft(true, column, val);
|
||||
}
|
||||
|
||||
Children likeLeft(boolean condition, Column column, Object val);
|
||||
|
||||
default Children notLikeLeft(Column column, Object val) {
|
||||
return notLikeLeft(true, column, val);
|
||||
}
|
||||
|
||||
Children notLikeLeft(boolean condition, Column column, Object val);
|
||||
|
||||
default Children likeRight(Column column, Object val) {
|
||||
return likeRight(true, column, val);
|
||||
}
|
||||
|
||||
Children likeRight(boolean condition, Column column, Object val);
|
||||
|
||||
default Children notLikeRight(Column column, Object val) {
|
||||
return notLikeRight(true, column, val);
|
||||
}
|
||||
|
||||
Children notLikeRight(boolean condition, Column column, Object val);
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package com.github.yulichang.extension.apt.interfaces;
|
||||
|
||||
import com.github.yulichang.extension.apt.matedata.Column;
|
||||
import com.github.yulichang.wrapper.enums.IfExistsSqlKeyWordEnum;
|
||||
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
/**
|
||||
* {@link com.baomidou.mybatisplus.core.conditions.interfaces.Compare}
|
||||
*
|
||||
* @author yulichang
|
||||
* @since 1.4.9
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface CompareIfExists<Children> extends Compare<Children> {
|
||||
|
||||
BiPredicate<Object, IfExistsSqlKeyWordEnum> getIfExists();
|
||||
|
||||
default Children eqIfExists(Column column, Object val) {
|
||||
return eq(getIfExists().test(val, IfExistsSqlKeyWordEnum.EQ), column, val);
|
||||
}
|
||||
|
||||
default Children neIfExists(Column column, Object val) {
|
||||
return ne(getIfExists().test(val, IfExistsSqlKeyWordEnum.NE), column, val);
|
||||
}
|
||||
|
||||
default Children gtIfExists(Column column, Object val) {
|
||||
return gt(getIfExists().test(val, IfExistsSqlKeyWordEnum.GT), column, val);
|
||||
}
|
||||
|
||||
default Children geIfExists(Column column, Object val) {
|
||||
return ge(getIfExists().test(val, IfExistsSqlKeyWordEnum.GE), column, val);
|
||||
}
|
||||
|
||||
default Children ltIfExists(Column column, Object val) {
|
||||
return lt(getIfExists().test(val, IfExistsSqlKeyWordEnum.LT), column, val);
|
||||
}
|
||||
|
||||
default Children leIfExists(Column column, Object val) {
|
||||
return le(getIfExists().test(val, IfExistsSqlKeyWordEnum.LE), column, val);
|
||||
}
|
||||
|
||||
default Children likeIfExists(Column column, Object val) {
|
||||
return like(getIfExists().test(val, IfExistsSqlKeyWordEnum.LIKE), column, val);
|
||||
}
|
||||
|
||||
default Children notLikeIfExists(Column column, Object val) {
|
||||
return notLike(getIfExists().test(val, IfExistsSqlKeyWordEnum.NOT_LIKE), column, val);
|
||||
}
|
||||
|
||||
default Children likeLeftIfExists(Column column, Object val) {
|
||||
return likeLeft(getIfExists().test(val, IfExistsSqlKeyWordEnum.LIKE_LEFT), column, val);
|
||||
}
|
||||
|
||||
default Children notLikeLeftIfExists(Column column, Object val) {
|
||||
return notLikeLeft(getIfExists().test(val, IfExistsSqlKeyWordEnum.NOT_LIKE_LEFT), column, val);
|
||||
}
|
||||
|
||||
default Children likeRightIfExists(Column column, Object val) {
|
||||
return likeRight(getIfExists().test(val, IfExistsSqlKeyWordEnum.LIKE_RIGHT), column, val);
|
||||
}
|
||||
|
||||
default Children notLikeRightIfExists(Column column, Object val) {
|
||||
return notLikeRight(getIfExists().test(val, IfExistsSqlKeyWordEnum.NOT_LIKE_RIGHT), column, val);
|
||||
}
|
||||
}
|
@ -0,0 +1,191 @@
|
||||
package com.github.yulichang.extension.apt.interfaces;
|
||||
|
||||
import com.github.yulichang.extension.apt.matedata.Column;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* 将原来的泛型R改成Column
|
||||
* <p>
|
||||
* copy {@link com.baomidou.mybatisplus.core.conditions.interfaces.Func}
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface Func<Children> extends FuncLambda<Children> {
|
||||
|
||||
|
||||
default Children isNull(Column column) {
|
||||
return isNull(true, column);
|
||||
}
|
||||
|
||||
Children isNull(boolean condition, Column column);
|
||||
|
||||
|
||||
default Children isNotNull(Column column) {
|
||||
return isNotNull(true, column);
|
||||
}
|
||||
|
||||
Children isNotNull(boolean condition, Column column);
|
||||
|
||||
|
||||
default Children in(Column column, Collection<?> coll) {
|
||||
return in(true, column, coll);
|
||||
}
|
||||
|
||||
Children in(boolean condition, Column column, Collection<?> coll);
|
||||
|
||||
|
||||
default Children in(Column column, Object... values) {
|
||||
return in(true, column, values);
|
||||
}
|
||||
|
||||
Children in(boolean condition, Column column, Object... values);
|
||||
|
||||
|
||||
default Children notIn(Column column, Collection<?> coll) {
|
||||
return notIn(true, column, coll);
|
||||
}
|
||||
|
||||
Children notIn(boolean condition, Column column, Collection<?> coll);
|
||||
|
||||
|
||||
default Children notIn(Column column, Object... values) {
|
||||
return notIn(true, column, values);
|
||||
}
|
||||
|
||||
Children notIn(boolean condition, Column column, Object... values);
|
||||
|
||||
|
||||
default Children inSql(Column column, String inValue) {
|
||||
return inSql(true, column, inValue);
|
||||
}
|
||||
|
||||
Children inSql(boolean condition, Column column, String inValue);
|
||||
|
||||
default Children notInSql(Column column, String inValue) {
|
||||
return notInSql(true, column, inValue);
|
||||
}
|
||||
|
||||
Children notInSql(boolean condition, Column column, String inValue);
|
||||
|
||||
default Children gtSql(Column column, String inValue) {
|
||||
return gtSql(true, column, inValue);
|
||||
}
|
||||
|
||||
Children gtSql(boolean condition, Column column, String inValue);
|
||||
|
||||
default Children geSql(Column column, String inValue) {
|
||||
return geSql(true, column, inValue);
|
||||
}
|
||||
|
||||
Children geSql(boolean condition, Column column, String inValue);
|
||||
|
||||
default Children ltSql(Column column, String inValue) {
|
||||
return ltSql(true, column, inValue);
|
||||
}
|
||||
|
||||
Children ltSql(boolean condition, Column column, String inValue);
|
||||
|
||||
default Children leSql(Column column, String inValue) {
|
||||
return leSql(true, column, inValue);
|
||||
}
|
||||
|
||||
Children leSql(boolean condition, Column column, String inValue);
|
||||
|
||||
default Children eqSql(Column column, String inValue) {
|
||||
return eqSql(true, column, inValue);
|
||||
}
|
||||
|
||||
Children eqSql(boolean condition, Column column, String inValue);
|
||||
|
||||
default Children groupBy(Column column) {
|
||||
return groupBy(true, column);
|
||||
}
|
||||
|
||||
default Children groupBy(List<Column> column) {
|
||||
return groupBy(true, column);
|
||||
}
|
||||
|
||||
Children groupBy(boolean condition, List<Column> columns);
|
||||
|
||||
default Children groupBy(Column column, Column... columns) {
|
||||
return groupBy(true, column, columns);
|
||||
}
|
||||
|
||||
Children groupBy(boolean condition, Column column, Column... columns);
|
||||
|
||||
|
||||
default Children orderByAsc(Column column) {
|
||||
return orderByAsc(true, column);
|
||||
}
|
||||
|
||||
default Children orderByAsc(List<Column> columns) {
|
||||
return orderByAsc(true, columns);
|
||||
}
|
||||
|
||||
Children orderByAsc(boolean condition, List<Column> columns);
|
||||
|
||||
|
||||
default Children orderByAsc(Column column, Column... columns) {
|
||||
return orderByAsc(true, column, columns);
|
||||
}
|
||||
|
||||
default Children orderByAsc(boolean condition, Column column, Column... columns) {
|
||||
return orderBy(condition, true, column, columns);
|
||||
}
|
||||
|
||||
default Children orderByDesc(Column column) {
|
||||
return orderByDesc(true, column);
|
||||
}
|
||||
|
||||
default Children orderByDesc(List<Column> columns) {
|
||||
return orderByDesc(true, columns);
|
||||
}
|
||||
|
||||
Children orderByDesc(boolean condition, List<Column> columns);
|
||||
|
||||
default Children orderByDesc(Column column, Column... columns) {
|
||||
return orderByDesc(true, column, columns);
|
||||
}
|
||||
|
||||
default Children orderByDesc(boolean condition, Column column, Column... columns) {
|
||||
return orderBy(condition, false, column, columns);
|
||||
}
|
||||
|
||||
Children orderBy(boolean condition, boolean isAsc, Column column, Column... columns);
|
||||
|
||||
default Children having(String sqlHaving, Object... params) {
|
||||
return having(true, sqlHaving, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* HAVING ( sql语句 )
|
||||
* <p>例1: having("sum(age) > 10")</p>
|
||||
* <p>例2: having("sum(age) > {0}", 10)</p>
|
||||
*
|
||||
* @param condition 执行条件
|
||||
* @param sqlHaving sql 语句
|
||||
* @param params 参数数组
|
||||
* @return children
|
||||
*/
|
||||
Children having(boolean condition, String sqlHaving, Object... params);
|
||||
|
||||
|
||||
default Children func(Consumer<Children> consumer) {
|
||||
return func(true, consumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 消费函数
|
||||
*
|
||||
* @param consumer 消费函数
|
||||
* @return children
|
||||
* @since 3.3.1
|
||||
*/
|
||||
default Children func(boolean condition, Consumer<Children> consumer) {
|
||||
return func(condition, consumer, null);
|
||||
}
|
||||
|
||||
Children func(boolean condition, Consumer<Children> consumer, Consumer<Children> consumerElse);
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package com.github.yulichang.extension.apt.interfaces;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 将原来的泛型R改成SFunction<X,?>
|
||||
* <p>
|
||||
* copy {@link com.baomidou.mybatisplus.core.conditions.interfaces.Func}
|
||||
*/
|
||||
@SuppressWarnings({"unused", "unchecked"})
|
||||
public interface FuncLambda<Children> extends Serializable {
|
||||
|
||||
default <X> Children groupBy(SFunction<X, ?> column) {
|
||||
return groupBy(true, column);
|
||||
}
|
||||
|
||||
default <X> Children groupByLambda(List<SFunction<X, ?>> column) {
|
||||
return groupByLambda(true, column);
|
||||
}
|
||||
|
||||
<X> Children groupByLambda(boolean condition, List<SFunction<X, ?>> columns);
|
||||
|
||||
<X> Children groupBy(SFunction<X, ?> column, SFunction<X, ?>... columns);
|
||||
|
||||
<X> Children groupBy(boolean condition, SFunction<X, ?> column, SFunction<X, ?>... columns);
|
||||
|
||||
|
||||
default <X> Children orderByAsc(SFunction<X, ?> column) {
|
||||
return orderByAsc(true, column);
|
||||
}
|
||||
|
||||
default <X> Children orderByAscLambda(List<SFunction<X, ?>> columns) {
|
||||
return orderByAscLambda(true, columns);
|
||||
}
|
||||
|
||||
<X> Children orderByAscLambda(boolean condition, List<SFunction<X, ?>> columns);
|
||||
|
||||
|
||||
<X> Children orderByAsc(SFunction<X, ?> column, SFunction<X, ?>... columns);
|
||||
|
||||
<X> Children orderByAsc(boolean condition, SFunction<X, ?> column, SFunction<X, ?>... columns);
|
||||
|
||||
default <X> Children orderByDesc(SFunction<X, ?> column) {
|
||||
return orderByDesc(true, column);
|
||||
}
|
||||
|
||||
default <X> Children orderByDescLambda(List<SFunction<X, ?>> columns) {
|
||||
return orderByDescLambda(true, columns);
|
||||
}
|
||||
|
||||
<X> Children orderByDescLambda(boolean condition, List<SFunction<X, ?>> columns);
|
||||
|
||||
<X> Children orderByDesc(SFunction<X, ?> column, SFunction<X, ?>... columns);
|
||||
|
||||
<X> Children orderByDesc(boolean condition, SFunction<X, ?> column, SFunction<X, ?>... columns);
|
||||
|
||||
<X> Children orderBy(boolean condition, boolean isAsc, SFunction<X, ?> column, SFunction<X, ?>... columns);
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package com.github.yulichang.extension.apt.interfaces;
|
||||
|
||||
import com.github.yulichang.extension.apt.matedata.Column;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 将原来的泛型R改成Column, Object改为Column
|
||||
* 以及移除不会在ON语句中出现的条件 比如like相关 保留原来的like 只是不太可能会出现 on a.id like b.id 所以不会支持这种写法
|
||||
* <p>
|
||||
* {@link com.baomidou.mybatisplus.core.conditions.interfaces.Compare}
|
||||
*
|
||||
* @since 1.1.8
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface OnCompare<Children> extends Serializable {
|
||||
|
||||
default Children eq(Column column, Column val) {
|
||||
return eq(true, column, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* 等于 =
|
||||
*
|
||||
* @param condition 执行条件
|
||||
* @param column 字段
|
||||
* @param val 值
|
||||
* @return children
|
||||
*/
|
||||
Children eq(boolean condition, Column column, Column val);
|
||||
|
||||
default Children ne(Column column, Column val) {
|
||||
return ne(true, column, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* 不等于 <>
|
||||
*
|
||||
* @param condition 执行条件
|
||||
* @param column 字段
|
||||
* @param val 值
|
||||
* @return children
|
||||
*/
|
||||
Children ne(boolean condition, Column column, Column val);
|
||||
|
||||
default Children gt(Column column, Column val) {
|
||||
return gt(true, column, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* 大于 >
|
||||
*
|
||||
* @param condition 执行条件
|
||||
* @param column 字段
|
||||
* @param val 值
|
||||
* @return children
|
||||
*/
|
||||
Children gt(boolean condition, Column column, Column val);
|
||||
|
||||
default Children ge(Column column, Column val) {
|
||||
return ge(true, column, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* 大于等于 >=
|
||||
*
|
||||
* @param condition 执行条件
|
||||
* @param column 字段
|
||||
* @param val 值
|
||||
* @return children
|
||||
*/
|
||||
Children ge(boolean condition, Column column, Column val);
|
||||
|
||||
default Children lt(Column column, Column val) {
|
||||
return lt(true, column, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* 小于 <
|
||||
*
|
||||
* @param condition 执行条件
|
||||
* @param column 字段
|
||||
* @param val 值
|
||||
* @return children
|
||||
*/
|
||||
Children lt(boolean condition, Column column, Column val);
|
||||
|
||||
default Children le(Column column, Column val) {
|
||||
return le(true, column, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* 小于等于 <=
|
||||
*
|
||||
* @param condition 执行条件
|
||||
* @param column 字段
|
||||
* @param val 值
|
||||
* @return children
|
||||
*/
|
||||
Children le(boolean condition, Column column, Column val);
|
||||
}
|
@ -0,0 +1,280 @@
|
||||
package com.github.yulichang.extension.apt.interfaces;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.github.yulichang.extension.apt.matedata.BaseColumn;
|
||||
import com.github.yulichang.extension.apt.matedata.Column;
|
||||
import com.github.yulichang.toolkit.Constant;
|
||||
import com.github.yulichang.toolkit.LambdaUtils;
|
||||
import com.github.yulichang.toolkit.MPJReflectionKit;
|
||||
import com.github.yulichang.toolkit.TableHelper;
|
||||
import com.github.yulichang.toolkit.support.ColumnCache;
|
||||
import com.github.yulichang.toolkit.support.FieldCache;
|
||||
import com.github.yulichang.wrapper.enums.BaseFuncEnum;
|
||||
import com.github.yulichang.wrapper.enums.DefaultFuncEnum;
|
||||
import com.github.yulichang.wrapper.interfaces.MFunction;
|
||||
import com.github.yulichang.wrapper.segments.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 参考 {@link com.baomidou.mybatisplus.core.conditions.query.Query}
|
||||
*
|
||||
* @author yulichang
|
||||
*/
|
||||
@SuppressWarnings({"unused"})
|
||||
public interface Query<Children> extends Serializable {
|
||||
|
||||
List<Select> getSelectColum();
|
||||
|
||||
Children getChildren();
|
||||
|
||||
|
||||
/**
|
||||
* 过滤查询的字段信息
|
||||
* <p>例1: 只要 java 字段名以 "test" 开头的 -> select(i -> i.getProperty().startsWith("test"))</p>
|
||||
* <p>例2: 只要 java 字段属性是 CharSequence 类型的 -> select(TableFieldInfo::isCharSequence)</p>
|
||||
* <p>例3: 只要 java 字段没有填充策略的 -> select(i -> i.getFieldFill() == FieldFill.DEFAULT)</p>
|
||||
* <p>例4: 要全部字段 -> select(i -> true)</p>
|
||||
* <p>例5: 只要主键字段 -> select(i -> false)</p>
|
||||
*
|
||||
* @param predicate 过滤方式
|
||||
* @return children
|
||||
*/
|
||||
default <E> Children selectFilter(BaseColumn<E> baseColumn, Predicate<SelectCache> predicate) {
|
||||
TableInfo info = TableHelper.getAssert(baseColumn.getColumnClass());
|
||||
List<SelectCache> cacheList = ColumnCache.getListField(baseColumn.getColumnClass());
|
||||
cacheList.stream().filter(SelectCache::isSelect).filter(predicate).collect(Collectors.toList()).forEach(
|
||||
i -> getSelectColum().add(new SelectApt(i, baseColumn)));
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
|
||||
<E> Children select(Column... columns);
|
||||
|
||||
/**
|
||||
* String 查询
|
||||
*
|
||||
* @param columns 列
|
||||
*/
|
||||
default Children select(String... columns) {
|
||||
getSelectColum().add(new SelectString(String.join(StringPool.COMMA, columns), null));
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
/**
|
||||
* String 查询
|
||||
*
|
||||
* @param column 列
|
||||
*/
|
||||
default <E> Children selectAs(String column, SFunction<E, ?> alias) {
|
||||
String name = LambdaUtils.getName(alias);
|
||||
getSelectColum().add(new SelectString(column + Constant.AS + name, name));
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
/**
|
||||
* String 查询
|
||||
*
|
||||
* @param column 列
|
||||
*/
|
||||
default <X> Children selectAs(String index, Column column, SFunction<X, ?> alias) {
|
||||
Map<String, SelectCache> cacheMap = ColumnCache.getMapField(column.getClazz());
|
||||
SelectCache cache = cacheMap.get(column.getProperty());
|
||||
String name = LambdaUtils.getName(alias);
|
||||
getSelectColum().add(new SelectApt(cache, column, name));
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
|
||||
default <E> Children selectAsClass(BaseColumn<E> baseColumn, Class<?> tag) {
|
||||
Map<String, SelectCache> normalMap = ColumnCache.getMapField(baseColumn.getColumnClass());
|
||||
List<FieldCache> fieldList = MPJReflectionKit.getFieldList(tag);
|
||||
for (FieldCache cache : fieldList) {
|
||||
if (normalMap.containsKey(cache.getField().getName())) {
|
||||
SelectCache selectCache = normalMap.get(cache.getField().getName());
|
||||
if (selectCache.isSelect()) {
|
||||
getSelectColum().add(new SelectApt(selectCache, baseColumn));
|
||||
}
|
||||
}
|
||||
}
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
/**
|
||||
* ignore
|
||||
*/
|
||||
default <X> Children selectAs(Column column, SFunction<X, ?> alias) {
|
||||
return selectAs(column, LambdaUtils.getName(alias));
|
||||
}
|
||||
|
||||
/**
|
||||
* 别名查询
|
||||
*/
|
||||
default Children selectAs(Column column, String alias) {
|
||||
Map<String, SelectCache> cacheMap = ColumnCache.getMapField(column.getClazz());
|
||||
SelectCache cache = cacheMap.get(column.getProperty());
|
||||
getSelectColum().add(new SelectApt(cache, column, alias));
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询实体类全部字段
|
||||
*/
|
||||
default <E> Children selectAll(BaseColumn<E> baseColumn) {
|
||||
getSelectColum().addAll(ColumnCache.getListField(baseColumn.getColumnClass()).stream().filter(SelectCache::isSelect).map(i ->
|
||||
new SelectApt(i, baseColumn)).collect(Collectors.toList()));
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询实体类全部字段
|
||||
*
|
||||
* @param baseColumn 查询的实体类
|
||||
* @param exclude 排除字段
|
||||
*/
|
||||
default <E> Children selectAll(BaseColumn<E> baseColumn, Column... exclude) {
|
||||
Set<String> excludeSet = Arrays.stream(exclude).map(i ->
|
||||
i.getProperty().toUpperCase(Locale.ENGLISH)).collect(Collectors.toSet());
|
||||
getSelectColum().addAll(ColumnCache.getListField(baseColumn.getColumnClass()).stream().filter(e -> e.isSelect() &&
|
||||
!excludeSet.contains(e.getColumProperty().toUpperCase(Locale.ENGLISH))).map(i ->
|
||||
new SelectApt(i, baseColumn)).collect(Collectors.toList()));
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
/**
|
||||
* select sql 片段
|
||||
*/
|
||||
String getSqlSelect();
|
||||
|
||||
/**
|
||||
* 聚合函数查询
|
||||
* <p>
|
||||
* wrapper.selectFunc(() -> "COUNT(%s)", "t.id", "total");
|
||||
* <p>
|
||||
* lambda
|
||||
* wrapper.selectFunc(() -> "COUNT(%s)", UserDO::getId, UserDTO::getTotal);
|
||||
*
|
||||
* @param funcEnum 函数枚举 {@link DefaultFuncEnum}
|
||||
* @param column 函数作用的字段
|
||||
* @param alias 别名
|
||||
*/
|
||||
default Children selectFunc(BaseFuncEnum funcEnum, Column column, String alias) {
|
||||
Map<String, SelectCache> cacheMap = ColumnCache.getMapField(column.getClazz());
|
||||
getSelectColum().add(new SelectApt(cacheMap.get(column.getProperty()), column, funcEnum, alias));
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
default <X> Children selectFunc(BaseFuncEnum funcEnum, Column column, SFunction<X, ?> alias) {
|
||||
return selectFunc(funcEnum, column, LambdaUtils.getName(alias));
|
||||
}
|
||||
|
||||
default Children selectFunc(BaseFuncEnum funcEnum, Column column) {
|
||||
return selectFunc(funcEnum, column, column.getProperty());
|
||||
}
|
||||
|
||||
|
||||
Children selectFunc(String sql, MFunction<AptConsumer> column, String alias);
|
||||
|
||||
default <S> Children selectFunc(String sql, MFunction<AptConsumer> column, SFunction<S, ?> alias) {
|
||||
return selectFunc(sql, column, LambdaUtils.getName(alias));
|
||||
}
|
||||
|
||||
/* 默认聚合函数扩展 */
|
||||
|
||||
/**
|
||||
* SUM()
|
||||
*/
|
||||
default Children selectSum(Column column) {
|
||||
return selectFunc(DefaultFuncEnum.SUM, column);
|
||||
}
|
||||
|
||||
default <X> Children selectSum(Column column, SFunction<X, ?> alias) {
|
||||
return selectFunc(DefaultFuncEnum.SUM, column, alias);
|
||||
}
|
||||
|
||||
default Children selectSum(Column column, String alias) {
|
||||
return selectFunc(DefaultFuncEnum.SUM, column, alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* COUNT()
|
||||
*/
|
||||
default Children selectCount(Column column) {
|
||||
return selectFunc(DefaultFuncEnum.COUNT, column);
|
||||
}
|
||||
|
||||
default <X> Children selectCount(Column column, SFunction<X, ?> alias) {
|
||||
return selectFunc(DefaultFuncEnum.COUNT, column, alias);
|
||||
}
|
||||
|
||||
default Children selectCount(Column column, String alias) {
|
||||
return selectFunc(DefaultFuncEnum.COUNT, column, alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* MAX()
|
||||
*/
|
||||
default Children selectMax(Column column) {
|
||||
return selectFunc(DefaultFuncEnum.MAX, column);
|
||||
}
|
||||
|
||||
default <X> Children selectMax(Column column, SFunction<X, ?> alias) {
|
||||
return selectFunc(DefaultFuncEnum.MAX, column, alias);
|
||||
}
|
||||
|
||||
default Children selectMax(Column column, String alias) {
|
||||
return selectFunc(DefaultFuncEnum.MAX, column, alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* MIN()
|
||||
*/
|
||||
default Children selectMin(Column column) {
|
||||
return selectFunc(DefaultFuncEnum.MIN, column);
|
||||
}
|
||||
|
||||
default <X> Children selectMin(Column column, SFunction<X, ?> alias) {
|
||||
return selectFunc(DefaultFuncEnum.MIN, column, alias);
|
||||
}
|
||||
|
||||
default Children selectMin(Column column, String alias) {
|
||||
return selectFunc(DefaultFuncEnum.MIN, column, alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* MIN()
|
||||
*/
|
||||
default Children selectAvg(Column column) {
|
||||
return selectFunc(DefaultFuncEnum.AVG, column);
|
||||
}
|
||||
|
||||
default <X> Children selectAvg(Column column, SFunction<X, ?> alias) {
|
||||
return selectFunc(DefaultFuncEnum.AVG, column, alias);
|
||||
}
|
||||
|
||||
default Children selectAvg(Column column, String alias) {
|
||||
return selectFunc(DefaultFuncEnum.AVG, column, alias);
|
||||
}
|
||||
|
||||
/**
|
||||
* LEN()
|
||||
*/
|
||||
default Children selectLen(Column column) {
|
||||
return selectFunc(DefaultFuncEnum.LEN, column);
|
||||
}
|
||||
|
||||
default <X> Children selectLen(Column column, SFunction<X, ?> alias) {
|
||||
return selectFunc(DefaultFuncEnum.LEN, column, alias);
|
||||
}
|
||||
|
||||
default Children selectLen(Column column, String alias) {
|
||||
return selectFunc(DefaultFuncEnum.LEN, column, alias);
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
package com.github.yulichang.extension.apt.interfaces;
|
||||
|
||||
import com.github.yulichang.extension.apt.matedata.BaseColumn;
|
||||
import com.github.yulichang.extension.apt.matedata.Column;
|
||||
import com.github.yulichang.interfaces.MPJBaseJoin;
|
||||
import com.github.yulichang.query.interfaces.StringJoin;
|
||||
import com.github.yulichang.toolkit.Constant;
|
||||
import com.github.yulichang.extension.apt.AptAbstractWrapper;
|
||||
import com.github.yulichang.wrapper.interfaces.MFunction;
|
||||
|
||||
/**
|
||||
* @author yulichang
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public interface QueryJoin<Children, Entity> extends MPJBaseJoin<Entity>, StringJoin<Children, Entity> {
|
||||
|
||||
/**
|
||||
* left join
|
||||
*
|
||||
* @param clazz 关联的实体类
|
||||
* @param left 条件
|
||||
* @param right 条件
|
||||
*/
|
||||
default <T> Children leftJoin(BaseColumn<T> clazz, Column left, Column right) {
|
||||
return join(Constant.LEFT_JOIN, clazz, left, right);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* left join 多条件
|
||||
* <p>
|
||||
* 例 leftJoin(UserDO.class, on -> on.eq(UserDO::getId,UserAddressDO::getUserId).le().gt()...)
|
||||
*
|
||||
* @param clazz 关联实体类
|
||||
* @param function 条件`
|
||||
*/
|
||||
default <T> Children leftJoin(BaseColumn<T> clazz, MFunction<AptAbstractWrapper<Entity, ?>> function) {
|
||||
return join(Constant.LEFT_JOIN, clazz, function);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ignore 参考 left join
|
||||
*/
|
||||
default <T> Children rightJoin(BaseColumn<T> clazz, Column left, Column right) {
|
||||
return join(Constant.RIGHT_JOIN, clazz, left, right);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* ignore 参考 left join
|
||||
*/
|
||||
default <T> Children rightJoin(BaseColumn<T> clazz, MFunction<AptAbstractWrapper<Entity, ?>> function) {
|
||||
return join(Constant.RIGHT_JOIN, clazz, function);
|
||||
}
|
||||
|
||||
/**
|
||||
* ignore 参考 left join
|
||||
*/
|
||||
default <T> Children innerJoin(BaseColumn<T> clazz, Column left, Column right) {
|
||||
return join(Constant.INNER_JOIN, clazz, left, right);
|
||||
}
|
||||
|
||||
/**
|
||||
* ignore 参考 left join
|
||||
*/
|
||||
default <T> Children innerJoin(BaseColumn<T> clazz, MFunction<AptAbstractWrapper<Entity, ?>> function) {
|
||||
return join(Constant.INNER_JOIN, clazz, function);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义连表关键词
|
||||
* 调用此方法 keyword 前后需要带空格 比如 " LEFT JOIN " " RIGHT JOIN "
|
||||
* <p>
|
||||
* 查询基类 可以直接调用此方法实现以上所有功能
|
||||
*
|
||||
* @param keyWord 连表关键字
|
||||
* @param clazz 连表实体类
|
||||
* @param left 关联条件
|
||||
* @param right 扩展 用于关联表的 select 和 where
|
||||
*/
|
||||
default <T> Children join(String keyWord, BaseColumn<T> clazz, Column left, Column right) {
|
||||
return join(keyWord, clazz, on -> on.eq(left, right));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 内部使用, 不建议直接调用
|
||||
*/
|
||||
<T> Children join(String keyWord, BaseColumn<T> clazz, MFunction<AptAbstractWrapper<Entity, ?>> function);
|
||||
}
|
@ -0,0 +1,172 @@
|
||||
package com.github.yulichang.extension.apt.interfaces;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.Assert;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.github.yulichang.extension.apt.matedata.BaseColumn;
|
||||
import com.github.yulichang.toolkit.LambdaUtils;
|
||||
import com.github.yulichang.toolkit.MPJReflectionKit;
|
||||
import com.github.yulichang.toolkit.support.FieldCache;
|
||||
import com.github.yulichang.extension.apt.resultmap.MybatisLabel;
|
||||
import com.github.yulichang.extension.apt.resultmap.MybatisLabelFree;
|
||||
import com.github.yulichang.wrapper.interfaces.MFunction;
|
||||
import com.github.yulichang.wrapper.resultmap.Label;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 对一或对多查询
|
||||
*
|
||||
* @author yulichang
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "unused", "DuplicatedCode"})
|
||||
public interface QueryLabel<Children> {
|
||||
|
||||
void addLabel(Label<?> label, boolean isCollection);
|
||||
|
||||
Children getChildren();
|
||||
|
||||
/**
|
||||
* 一对多查询 调用此方法必需要调用对应的 left join / right join ... 连表方法,否则会报错
|
||||
* <p>
|
||||
* 举例 UserDO AddressDO 为一对多关系 UserDTO 为结果类
|
||||
* <pre>
|
||||
* MPJLambdaWrapper<UserDO> wrapper = new MPJLambdaWrapper<UserDO>();
|
||||
* wrapper.selectAll(UserDO.class)
|
||||
* .selectCollection(AddressDO.class, UserDTO::getAddressListDTO)
|
||||
* .leftJoin(AddressDO.class, ...... )
|
||||
* .eq(...)
|
||||
* ...
|
||||
* <pre/>
|
||||
* 会自动将 AddressDO类中相同属性的字段 以mybatis<collection>的方式映射到UserDTO.addressListDTO属性中
|
||||
*
|
||||
* @since 1.3.0
|
||||
*
|
||||
* @param child 连表数据库实体类
|
||||
* @param dtoField 包装类对应的属性
|
||||
* @param <S> 包装类
|
||||
* @param <C> 对多数据库实体类
|
||||
* @param <Z> 包装类集合泛型
|
||||
* @param <F> 包装类集合字段泛型
|
||||
*/
|
||||
|
||||
default <S, C, Z, F extends Collection<?>> Children selectCollection(BaseColumn<C> child, SFunction<S, F> dtoField) {
|
||||
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||
Class<S> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||
Map<String, FieldCache> fieldMap = MPJReflectionKit.getFieldMap(dtoClass);
|
||||
FieldCache field = fieldMap.get(dtoFieldName);
|
||||
Class<?> genericType = MPJReflectionKit.getGenericType(field.getField());
|
||||
MybatisLabel.Builder<C, Z> builder;
|
||||
if (genericType == null || genericType.isAssignableFrom(child.getColumnClass())) {
|
||||
//找不到集合泛型 List List<?> List<Object> , 直接查询数据库实体
|
||||
builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType());
|
||||
} else {
|
||||
Class<Z> ofType = (Class<Z>) genericType;
|
||||
builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), ofType, true);
|
||||
}
|
||||
addLabel(builder.build(), true);
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
/**
|
||||
* 一对多查询 调用此方法必需要调用对应的 left join / right join ... 连表方法,否则会报错
|
||||
* <p>
|
||||
* 举例 UserDO AddressDO 为一对多关系 UserDTO 为结果类
|
||||
* <pre>
|
||||
* MPJLambdaWrapper<UserDO> wrapper = new MPJLambdaWrapper<UserDO>()
|
||||
* .selectAll(UserDO.class)
|
||||
* .selectCollection(AddressDO.class, UserDTO::getAddressListDTO, map -> map
|
||||
* .id(AddressDO::getId, AddressDTO::getId) //如果属性名一致 可以传一个
|
||||
* .result(AddressDO::getUserId) //如果属性名一致 可以传一个
|
||||
* .result(AddressDO::getAddress, AddressDTO::getAddress)) //如果属性名一致 可以传一个
|
||||
* .leftJoin(AddressDO.class, ...... )
|
||||
* .eq(...)
|
||||
* ...
|
||||
* <pre/>
|
||||
*
|
||||
* 会自动将 AddressDO类中指定的字段 以mybatis<collection>的方式映射到UserDTO.addressListDTO属性中
|
||||
*
|
||||
* @since 1.3.0
|
||||
*
|
||||
* @param child 连表数据库实体类
|
||||
* @param dtoField 包装类对应的属性
|
||||
* @param collection collection标签内容
|
||||
* @param <S> 包装类
|
||||
* @param <C> 对多数据库实体类
|
||||
* @param <Z> 包装类集合泛型
|
||||
* @param <F> 包装类集合字段泛型
|
||||
*/
|
||||
default <S, C, Z, F extends Collection<Z>> Children selectCollection(BaseColumn<C> child,
|
||||
SFunction<S, F> dtoField,
|
||||
MFunction<MybatisLabel.Builder<C, Z>> collection) {
|
||||
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||
Class<S> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||
//获取集合泛型
|
||||
Class<?> genericType = MPJReflectionKit.getGenericType(field.getField());
|
||||
Class<Z> ofType = (Class<Z>) genericType;
|
||||
MybatisLabel.Builder<C, Z> builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), ofType, false);
|
||||
MybatisLabel.Builder<C, Z> czBuilder = collection.apply(builder);
|
||||
addLabel(czBuilder.build(), true);
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
|
||||
default <S, Z, F extends Collection<Z>> Children selectCollection(SFunction<S, F> dtoField,
|
||||
MFunction<MybatisLabelFree.Builder<Z>> collection) {
|
||||
//自由映射必须存在泛型Z
|
||||
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||
Class<S> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||
//获取集合泛型
|
||||
Class<?> genericType = MPJReflectionKit.getGenericType(field.getField());
|
||||
Class<Z> ofType = (Class<Z>) genericType;
|
||||
MybatisLabelFree.Builder<Z> builder = new MybatisLabelFree.Builder<>(dtoFieldName, field.getType(), ofType);
|
||||
MybatisLabelFree.Builder<Z> czBuilder = collection.apply(builder);
|
||||
addLabel(czBuilder.build(), true);
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 对一查询 用法参考 selectCollection
|
||||
*
|
||||
* @since 1.3.0
|
||||
*/
|
||||
default <S, C, F> Children selectAssociation(BaseColumn<C> child, SFunction<S, F> dtoField) {
|
||||
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||
Class<S> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||
Map<String, FieldCache> fieldMap = MPJReflectionKit.getFieldMap(dtoClass);
|
||||
FieldCache field = fieldMap.get(dtoFieldName);
|
||||
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
|
||||
MybatisLabel.Builder<C, F> builder;
|
||||
builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), (Class<F>) field.getType(), true);
|
||||
addLabel(builder.build(), false);
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
default <S, C, F> Children selectAssociation(SFunction<S, F> dtoField,
|
||||
MFunction<MybatisLabelFree.Builder<F>> collection) {
|
||||
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||
Class<S> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
|
||||
MybatisLabelFree.Builder<F> builder = new MybatisLabelFree.Builder<>(dtoFieldName, field.getType(), (Class<F>) field.getType());
|
||||
MybatisLabelFree.Builder<F> cfBuilder = collection.apply(builder);
|
||||
addLabel(cfBuilder.build(), false);
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
default <S, C, F> Children selectAssociation(BaseColumn<C> child, SFunction<S, F> dtoField,
|
||||
MFunction<MybatisLabel.Builder<C, F>> collection) {
|
||||
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||
Class<S> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
|
||||
MybatisLabel.Builder<C, F> builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), (Class<F>) field.getType(), false);
|
||||
MybatisLabel.Builder<C, F> cfBuilder = collection.apply(builder);
|
||||
addLabel(cfBuilder.build(), false);
|
||||
return getChildren();
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package com.github.yulichang.extension.apt.matedata;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author yulichang
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
public abstract class BaseColumn<T> implements Serializable {
|
||||
|
||||
protected String alias;
|
||||
|
||||
abstract public Class<T> getColumnClass();
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.github.yulichang.extension.apt.matedata;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* @author yulichang
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@Getter
|
||||
public class Column implements Serializable {
|
||||
|
||||
private final BaseColumn<?> root;
|
||||
|
||||
private final String property;
|
||||
|
||||
public Column(BaseColumn<?> root, String property) {
|
||||
this.root = root;
|
||||
this.property = property;
|
||||
}
|
||||
|
||||
public Class<?> getClazz() {
|
||||
return root.getColumnClass();
|
||||
}
|
||||
|
||||
public Supplier<String> getAlias() {
|
||||
return root::getAlias;
|
||||
}
|
||||
}
|
@ -0,0 +1,275 @@
|
||||
package com.github.yulichang.extension.apt.resultmap;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Assert;
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.github.yulichang.extension.apt.matedata.BaseColumn;
|
||||
import com.github.yulichang.extension.apt.matedata.Column;
|
||||
import com.github.yulichang.toolkit.LambdaUtils;
|
||||
import com.github.yulichang.toolkit.MPJReflectionKit;
|
||||
import com.github.yulichang.toolkit.TableHelper;
|
||||
import com.github.yulichang.toolkit.support.ColumnCache;
|
||||
import com.github.yulichang.toolkit.support.FieldCache;
|
||||
import com.github.yulichang.wrapper.interfaces.MFunction;
|
||||
import com.github.yulichang.wrapper.resultmap.IResult;
|
||||
import com.github.yulichang.wrapper.resultmap.Label;
|
||||
import com.github.yulichang.wrapper.segments.SelectCache;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* collection 标签 目前先支持这几个属性 后续在扩展
|
||||
*
|
||||
* @author yulichang
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@Getter
|
||||
public class MybatisLabel<E, T> implements Label<T> {
|
||||
|
||||
private String property;
|
||||
|
||||
private BaseColumn<E> baseColumn;
|
||||
|
||||
private Class<?> javaType;
|
||||
|
||||
private Class<T> ofType;
|
||||
|
||||
private List<IResult> resultList;
|
||||
|
||||
/**
|
||||
* wrapper里面的引用
|
||||
*/
|
||||
private List<Label<?>> mybatisLabels;
|
||||
|
||||
private MybatisLabel() {
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unused", "unchecked", "DuplicatedCode"})
|
||||
public static class Builder<E, T> {
|
||||
|
||||
private final MybatisLabel<E, T> mybatisLabel;
|
||||
|
||||
/**
|
||||
* 自动构建
|
||||
*/
|
||||
public Builder(String property, BaseColumn<E> baseColumn, Class<?> javaType) {
|
||||
this.mybatisLabel = new MybatisLabel<>();
|
||||
mybatisLabel.property = property;
|
||||
mybatisLabel.baseColumn = baseColumn;
|
||||
mybatisLabel.javaType = javaType;
|
||||
mybatisLabel.ofType = (Class<T>) baseColumn.getColumnClass();
|
||||
mybatisLabel.resultList = new ArrayList<>();
|
||||
mybatisLabel.mybatisLabels = new ArrayList<>();
|
||||
autoBuild(true, baseColumn.getColumnClass(), (Class<T>) baseColumn.getColumnClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动构建
|
||||
*
|
||||
* @param property property
|
||||
* @param baseColumn 数据库实体类
|
||||
* @param javaType javaType
|
||||
* @param ofType 映射类
|
||||
* @param auto 自动映射数据库实体对应的字段
|
||||
*/
|
||||
public Builder(String property, BaseColumn<E> baseColumn, Class<?> javaType, Class<T> ofType, boolean auto) {
|
||||
this.mybatisLabel = new MybatisLabel<>();
|
||||
mybatisLabel.property = property;
|
||||
mybatisLabel.baseColumn = baseColumn;
|
||||
mybatisLabel.javaType = javaType;
|
||||
mybatisLabel.ofType = ofType;
|
||||
mybatisLabel.resultList = new ArrayList<>();
|
||||
mybatisLabel.mybatisLabels = new ArrayList<>();
|
||||
autoBuild(auto, baseColumn.getColumnClass(), ofType);
|
||||
}
|
||||
|
||||
/**
|
||||
* 映射实体全部字段
|
||||
*/
|
||||
public Builder<E, T> all() {
|
||||
autoBuild(true, mybatisLabel.baseColumn.getColumnClass(), mybatisLabel.ofType);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 映射实体字段过滤(含主键)
|
||||
*/
|
||||
public Builder<E, T> filter(Predicate<SelectCache> predicate) {
|
||||
Map<String, FieldCache> fieldMap = MPJReflectionKit.getFieldMap(mybatisLabel.ofType);
|
||||
ColumnCache.getListField(mybatisLabel.baseColumn.getColumnClass()).stream().filter(predicate)
|
||||
.filter(p -> fieldMap.containsKey(p.getColumProperty())).forEach(c ->
|
||||
mybatisLabel.resultList.add(new Result.Builder<T>(c.isPk(), mybatisLabel.baseColumn, c).build()));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<E, T> id(Column column, SFunction<T, ?> tag) {
|
||||
Result.Builder<T> builder = new Result.Builder<>(true, column);
|
||||
builder.column(column).property(tag);
|
||||
mybatisLabel.resultList.add(builder.build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<E, T> id(Column column) {
|
||||
Result.Builder<T> builder = new Result.Builder<>(true, column);
|
||||
builder.column(column);
|
||||
mybatisLabel.resultList.add(builder.build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<E, T> result(Column column, SFunction<T, ?> tag) {
|
||||
Result.Builder<T> builder = new Result.Builder<>(false, column);
|
||||
builder.column(column).property(tag);
|
||||
mybatisLabel.resultList.add(builder.build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<E, T> result(Column column) {
|
||||
Result.Builder<T> builder = new Result.Builder<>(false, column);
|
||||
builder.column(column);
|
||||
mybatisLabel.resultList.add(builder.build());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 嵌套
|
||||
*/
|
||||
public <A, R, B extends Collection<R>> Builder<E, T> collection(BaseColumn<A> entityClass, SFunction<T, B> func) {
|
||||
String dtoFieldName = LambdaUtils.getName(func);
|
||||
Class<T> dtoClass = LambdaUtils.getEntityClass(func);
|
||||
Map<String, FieldCache> fieldMap = MPJReflectionKit.getFieldMap(dtoClass);
|
||||
FieldCache field = fieldMap.get(dtoFieldName);
|
||||
Class<?> genericType = MPJReflectionKit.getGenericType(field.getField());
|
||||
Builder<A, R> builder;
|
||||
if (genericType == null || genericType.isAssignableFrom(entityClass.getColumnClass())) {
|
||||
//找不到集合泛型 List List<?> List<Object> , 直接查询数据库实体
|
||||
builder = new Builder<>(dtoFieldName, entityClass, field.getType());
|
||||
} else {
|
||||
Class<R> ofType = (Class<R>) genericType;
|
||||
builder = new Builder<>(dtoFieldName, entityClass, field.getType(), ofType, true);
|
||||
}
|
||||
mybatisLabel.mybatisLabels.add(builder.build());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 嵌套
|
||||
*/
|
||||
public <A, R, B extends Collection<R>> Builder<E, T> collection(SFunction<T, B> func,
|
||||
MFunction<MybatisLabelFree.Builder<R>> mFunc) {
|
||||
String dtoFieldName = LambdaUtils.getName(func);
|
||||
Class<T> dtoClass = LambdaUtils.getEntityClass(func);
|
||||
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||
//获取集合泛型
|
||||
Class<?> genericType = MPJReflectionKit.getGenericType(field.getField());
|
||||
Class<R> ofType = (Class<R>) genericType;
|
||||
MybatisLabelFree.Builder<R> builder = new MybatisLabelFree.Builder<>(dtoFieldName, field.getType(), ofType);
|
||||
mybatisLabel.mybatisLabels.add(mFunc.apply(builder).build());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 嵌套
|
||||
*/
|
||||
public <A, R, B extends Collection<R>> Builder<E, T> collection(BaseColumn<A> entityClass,
|
||||
SFunction<T, B> func,
|
||||
MFunction<Builder<A, R>> mFunc) {
|
||||
String dtoFieldName = LambdaUtils.getName(func);
|
||||
Class<T> dtoClass = LambdaUtils.getEntityClass(func);
|
||||
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||
//获取集合泛型
|
||||
Class<?> genericType = MPJReflectionKit.getGenericType(field.getField());
|
||||
Class<R> ofType = (Class<R>) genericType;
|
||||
Builder<A, R> builder = new Builder<>(dtoFieldName, entityClass, field.getType(), ofType, false);
|
||||
mybatisLabel.mybatisLabels.add(mFunc.apply(builder).build());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 嵌套
|
||||
*/
|
||||
public <A, B> Builder<E, T> association(BaseColumn<A> child, SFunction<T, B> dtoField) {
|
||||
Class<T> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||
Map<String, FieldCache> fieldMap = MPJReflectionKit.getFieldMap(dtoClass);
|
||||
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||
FieldCache field = fieldMap.get(dtoFieldName);
|
||||
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
|
||||
Builder<A, B> builder;
|
||||
builder = new Builder<>(dtoFieldName, child, field.getType(), (Class<B>) field.getType(), true);
|
||||
mybatisLabel.mybatisLabels.add(builder.build());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 嵌套
|
||||
*/
|
||||
public <A, B> Builder<E, T> association(SFunction<T, B> dtoField,
|
||||
MFunction<MybatisLabelFree.Builder<B>> collection) {
|
||||
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||
Class<T> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
|
||||
MybatisLabelFree.Builder<B> builder = new MybatisLabelFree.Builder<>(dtoFieldName, field.getType(), (Class<B>) field.getType());
|
||||
mybatisLabel.mybatisLabels.add(collection.apply(builder).build());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 嵌套
|
||||
*/
|
||||
public <A, B> Builder<E, T> association(BaseColumn<A> child, SFunction<T, B> dtoField,
|
||||
MFunction<Builder<A, B>> collection) {
|
||||
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||
Class<T> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
|
||||
Builder<A, B> builder = new Builder<>(dtoFieldName, child, field.getType(), (Class<B>) field.getType(), false);
|
||||
mybatisLabel.mybatisLabels.add(collection.apply(builder).build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public MybatisLabel<E, T> build() {
|
||||
if (CollectionUtils.isEmpty(mybatisLabel.resultList)) {
|
||||
autoBuild(true, mybatisLabel.baseColumn.getColumnClass(), mybatisLabel.ofType);
|
||||
}
|
||||
return mybatisLabel;
|
||||
}
|
||||
|
||||
private void autoBuild(boolean auto, Class<E> entityClass, Class<T> tagClass) {
|
||||
TableInfo tableInfo = TableHelper.getAssert(entityClass);
|
||||
Map<String, FieldCache> tagMap = MPJReflectionKit.getFieldMap(tagClass);
|
||||
if (auto && !tagMap.isEmpty()) {
|
||||
List<SelectCache> listField = ColumnCache.getListField(entityClass);
|
||||
if (entityClass.isAssignableFrom(tagClass)) {
|
||||
mybatisLabel.resultList.addAll(listField.stream().map(i -> {
|
||||
Result result = new Result();
|
||||
result.setId(i.isPk());
|
||||
result.setBaseColumn(mybatisLabel.baseColumn);
|
||||
result.setProperty(i.getColumProperty());
|
||||
result.setJavaType(i.getColumnType());
|
||||
result.setJdbcType(i.getJdbcType());
|
||||
result.setSelectNormal(i);
|
||||
return result;
|
||||
}).collect(Collectors.toList()));
|
||||
} else {
|
||||
for (SelectCache s : listField) {
|
||||
FieldCache field = tagMap.get(s.getColumProperty());
|
||||
if (Objects.nonNull(field)) {
|
||||
Result result = new Result();
|
||||
result.setId(s.isPk());
|
||||
result.setBaseColumn(mybatisLabel.baseColumn);
|
||||
result.setProperty(s.getColumProperty());
|
||||
result.setJavaType(field.getType());
|
||||
result.setSelectNormal(s);
|
||||
mybatisLabel.resultList.add(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,220 @@
|
||||
package com.github.yulichang.extension.apt.resultmap;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.Assert;
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.github.yulichang.extension.apt.matedata.BaseColumn;
|
||||
import com.github.yulichang.extension.apt.matedata.Column;
|
||||
import com.github.yulichang.toolkit.LambdaUtils;
|
||||
import com.github.yulichang.toolkit.MPJReflectionKit;
|
||||
import com.github.yulichang.toolkit.support.ColumnCache;
|
||||
import com.github.yulichang.toolkit.support.FieldCache;
|
||||
import com.github.yulichang.wrapper.interfaces.MFunction;
|
||||
import com.github.yulichang.wrapper.resultmap.IResult;
|
||||
import com.github.yulichang.wrapper.resultmap.Label;
|
||||
import com.github.yulichang.wrapper.resultmap.ResultList;
|
||||
import com.github.yulichang.wrapper.segments.SelectCache;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* 无泛型约束 实现自由映射
|
||||
*
|
||||
* @author yulichang
|
||||
* @since 1.4.4
|
||||
*/
|
||||
@Getter
|
||||
public class MybatisLabelFree<T> implements Label<T> {
|
||||
|
||||
private String property;
|
||||
|
||||
private Class<?> javaType;
|
||||
|
||||
private Class<T> ofType;
|
||||
|
||||
private List<IResult> resultList;
|
||||
|
||||
/**
|
||||
* wrapper里面的引用
|
||||
*/
|
||||
private List<Label<?>> mybatisLabels;
|
||||
|
||||
private MybatisLabelFree() {
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unused", "unchecked", "DuplicatedCode"})
|
||||
public static class Builder<T> {
|
||||
|
||||
private final MybatisLabelFree<T> mybatisLabel;
|
||||
|
||||
/**
|
||||
* 手动构建
|
||||
*
|
||||
* @param property property
|
||||
* @param javaType javaType
|
||||
* @param ofType 映射类
|
||||
*/
|
||||
public Builder(String property, Class<?> javaType, Class<T> ofType) {
|
||||
this.mybatisLabel = new MybatisLabelFree<>();
|
||||
mybatisLabel.property = property;
|
||||
mybatisLabel.javaType = javaType;
|
||||
mybatisLabel.ofType = ofType;
|
||||
mybatisLabel.resultList = new ResultList();
|
||||
mybatisLabel.mybatisLabels = new ArrayList<>();
|
||||
}
|
||||
|
||||
public <E> Builder<T> all(BaseColumn<E> entityClass) {
|
||||
allBuild(entityClass);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 映射实体字段过滤(含主键)
|
||||
*/
|
||||
public <E> Builder<T> filter(BaseColumn<E> baseColumn, Predicate<SelectCache> predicate) {
|
||||
Map<String, FieldCache> fieldMap = MPJReflectionKit.getFieldMap(mybatisLabel.ofType);
|
||||
ColumnCache.getListField(baseColumn.getColumnClass()).stream().filter(predicate)
|
||||
.filter(p -> fieldMap.containsKey(p.getColumProperty())).forEach(c ->
|
||||
mybatisLabel.resultList.add(new Result.Builder<T>(false, baseColumn, c).build()));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<T> id(Column column, SFunction<T, ?> tag) {
|
||||
Result.Builder<T> builder = new Result.Builder<>(true, column);
|
||||
builder.column(column).property(tag);
|
||||
mybatisLabel.resultList.add(builder.build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<T> id(Column column) {
|
||||
Result.Builder<T> builder = new Result.Builder<>(true, column);
|
||||
builder.column(column);
|
||||
mybatisLabel.resultList.add(builder.build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<T> result(Column column, SFunction<T, ?> tag) {
|
||||
Result.Builder<T> builder = new Result.Builder<>(false, column);
|
||||
builder.column(column).property(tag);
|
||||
mybatisLabel.resultList.add(builder.build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<T> result(Column column) {
|
||||
Result.Builder<T> builder = new Result.Builder<>(false, column);
|
||||
builder.column(column);
|
||||
mybatisLabel.resultList.add(builder.build());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 嵌套
|
||||
*/
|
||||
public <A, R, B extends Collection<R>> Builder<T> collection(BaseColumn<A> baseColumn, SFunction<T, B> func) {
|
||||
String dtoFieldName = LambdaUtils.getName(func);
|
||||
Class<T> dtoClass = LambdaUtils.getEntityClass(func);
|
||||
Map<String, FieldCache> fieldMap = MPJReflectionKit.getFieldMap(dtoClass);
|
||||
FieldCache field = fieldMap.get(dtoFieldName);
|
||||
Class<?> genericType = MPJReflectionKit.getGenericType(field.getField());
|
||||
MybatisLabel.Builder<A, R> builder;
|
||||
if (genericType == null || genericType.isAssignableFrom(baseColumn.getColumnClass())) {
|
||||
//找不到集合泛型 List List<?> List<Object> , 直接查询数据库实体
|
||||
builder = new MybatisLabel.Builder<>(dtoFieldName, baseColumn, field.getType());
|
||||
} else {
|
||||
Class<R> ofType = (Class<R>) genericType;
|
||||
builder = new MybatisLabel.Builder<>(dtoFieldName, baseColumn, field.getType(), ofType, true);
|
||||
}
|
||||
mybatisLabel.mybatisLabels.add(builder.build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public <A, R, B extends Collection<R>> Builder<T> collection(SFunction<T, B> func,
|
||||
MFunction<Builder<R>> mFunc) {
|
||||
String dtoFieldName = LambdaUtils.getName(func);
|
||||
Class<T> dtoClass = LambdaUtils.getEntityClass(func);
|
||||
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||
//获取集合泛型
|
||||
Class<?> genericType = MPJReflectionKit.getGenericType(field.getField());
|
||||
Class<R> ofType = (Class<R>) genericType;
|
||||
Builder<R> builder = new Builder<>(dtoFieldName, field.getType(), ofType);
|
||||
mybatisLabel.mybatisLabels.add(mFunc.apply(builder).build());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 嵌套
|
||||
*/
|
||||
public <A, R, B extends Collection<R>> Builder<T> collection(BaseColumn<A> entityClass,
|
||||
SFunction<T, B> func,
|
||||
MFunction<MybatisLabel.Builder<A, R>> mFunc) {
|
||||
String dtoFieldName = LambdaUtils.getName(func);
|
||||
Class<T> dtoClass = LambdaUtils.getEntityClass(func);
|
||||
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||
//获取集合泛型
|
||||
Class<?> genericType = MPJReflectionKit.getGenericType(field.getField());
|
||||
Class<R> ofType = (Class<R>) genericType;
|
||||
MybatisLabel.Builder<A, R> builder = new MybatisLabel.Builder<>(dtoFieldName, entityClass, field.getType(), ofType, false);
|
||||
mybatisLabel.mybatisLabels.add(mFunc.apply(builder).build());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 嵌套
|
||||
*/
|
||||
public <A, B> Builder<T> association(BaseColumn<A> child, SFunction<T, B> dtoField) {
|
||||
Class<T> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||
Map<String, FieldCache> fieldMap = MPJReflectionKit.getFieldMap(dtoClass);
|
||||
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||
FieldCache field = fieldMap.get(dtoFieldName);
|
||||
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
|
||||
MybatisLabel.Builder<A, B> builder;
|
||||
builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), (Class<B>) field.getType(), true);
|
||||
mybatisLabel.mybatisLabels.add(builder.build());
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 嵌套
|
||||
*/
|
||||
public <A, B> Builder<T> association(BaseColumn<A> child, SFunction<T, B> dtoField,
|
||||
MFunction<MybatisLabel.Builder<A, B>> collection) {
|
||||
String dtoFieldName = LambdaUtils.getName(dtoField);
|
||||
Class<T> dtoClass = LambdaUtils.getEntityClass(dtoField);
|
||||
FieldCache field = MPJReflectionKit.getFieldMap(dtoClass).get(dtoFieldName);
|
||||
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
|
||||
MybatisLabel.Builder<A, B> builder = new MybatisLabel.Builder<>(dtoFieldName, child, field.getType(), (Class<B>) field.getType(), false);
|
||||
mybatisLabel.mybatisLabels.add(collection.apply(builder).build());
|
||||
return this;
|
||||
}
|
||||
|
||||
public MybatisLabelFree<T> build() {
|
||||
if (CollectionUtils.isEmpty(mybatisLabel.resultList)) {
|
||||
throw ExceptionUtils.mpe("无法自动映射, 找不到 <%s> 对应的表, 请使用 .all(xxx.class), id()或者result() 手动映射",
|
||||
mybatisLabel.ofType.getSimpleName());
|
||||
}
|
||||
return mybatisLabel;
|
||||
}
|
||||
|
||||
private void allBuild(BaseColumn<?> entityClass) {
|
||||
Map<String, FieldCache> tagMap = MPJReflectionKit.getFieldMap(mybatisLabel.getOfType());
|
||||
List<SelectCache> listField = ColumnCache.getListField(entityClass.getColumnClass());
|
||||
for (SelectCache s : listField) {
|
||||
FieldCache field = tagMap.get(s.getColumProperty());
|
||||
if (Objects.nonNull(field)) {
|
||||
Result result = new Result();
|
||||
result.setBaseColumn(entityClass);
|
||||
result.setId(s.isPk());
|
||||
result.setJavaType(field.getType());
|
||||
result.setProperty(s.getColumProperty());
|
||||
result.setSelectNormal(s);
|
||||
mybatisLabel.resultList.add(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,123 @@
|
||||
package com.github.yulichang.extension.apt.resultmap;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
|
||||
import com.github.yulichang.extension.apt.matedata.BaseColumn;
|
||||
import com.github.yulichang.extension.apt.matedata.Column;
|
||||
import com.github.yulichang.toolkit.LambdaUtils;
|
||||
import com.github.yulichang.toolkit.StrUtils;
|
||||
import com.github.yulichang.toolkit.support.ColumnCache;
|
||||
import com.github.yulichang.wrapper.resultmap.IResult;
|
||||
import com.github.yulichang.wrapper.segments.SelectCache;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* result 标签
|
||||
*
|
||||
* @author yulichang
|
||||
* @since 1.3.0
|
||||
*/
|
||||
@Getter
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
public class Result implements IResult {
|
||||
|
||||
private boolean isId;
|
||||
|
||||
private BaseColumn<?> baseColumn;
|
||||
|
||||
private Column column;
|
||||
|
||||
private SelectCache selectNormal;
|
||||
|
||||
private String property;
|
||||
|
||||
private Class<?> javaType;
|
||||
|
||||
private JdbcType jdbcType;
|
||||
|
||||
public Result() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIndex() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings({"UnusedReturnValue", "unused"})
|
||||
public static class Builder<T> {
|
||||
|
||||
private final Result result;
|
||||
|
||||
public Builder(boolean isId, Column column) {
|
||||
this.result = new Result();
|
||||
result.isId = isId;
|
||||
result.column = column;
|
||||
result.baseColumn = column.getRoot();
|
||||
}
|
||||
|
||||
public Builder(boolean isId, Column column, SelectCache selectCache) {
|
||||
this.result = new Result();
|
||||
result.isId = isId;
|
||||
result.column = column;
|
||||
result.baseColumn = column.getRoot();
|
||||
result.selectNormal = selectCache;
|
||||
result.property = selectCache.getColumProperty();
|
||||
result.javaType = selectCache.getColumnType();
|
||||
result.jdbcType = selectCache.getJdbcType();
|
||||
}
|
||||
|
||||
public Builder(boolean isId, BaseColumn<?> baseColumn, SelectCache selectCache) {
|
||||
this.result = new Result();
|
||||
result.isId = isId;
|
||||
result.column = null;
|
||||
result.baseColumn = baseColumn;
|
||||
result.selectNormal = selectCache;
|
||||
result.property = selectCache.getColumProperty();
|
||||
result.javaType = selectCache.getColumnType();
|
||||
result.jdbcType = selectCache.getJdbcType();
|
||||
}
|
||||
|
||||
public Builder<T> property(SFunction<T, ?> property) {
|
||||
result.property = LambdaUtils.getName(property);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<T> column(Column column) {
|
||||
Map<String, SelectCache> normalMap = ColumnCache.getMapField(column.getClazz());
|
||||
SelectCache normal = normalMap.get(column.getProperty());
|
||||
result.selectNormal = normal;
|
||||
result.column = column;
|
||||
if (StrUtils.isBlank(result.property)) {
|
||||
result.property = normal.getColumProperty();
|
||||
}
|
||||
if (Objects.isNull(result.javaType)) {
|
||||
result.javaType = normal.getColumnType();
|
||||
}
|
||||
if (Objects.isNull(result.jdbcType)) {
|
||||
result.jdbcType = normal.getJdbcType();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<T> javaType(Class<?> javaType) {
|
||||
result.javaType = javaType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder<T> jdbcType(JdbcType jdbcType) {
|
||||
result.jdbcType = jdbcType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Result build() {
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,151 @@
|
||||
package com.github.yulichang.extension.apt.toolkit;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.github.yulichang.adapter.AdapterHelper;
|
||||
import com.github.yulichang.extension.apt.AptQueryWrapper;
|
||||
import com.github.yulichang.toolkit.LogicInfoUtils;
|
||||
import com.github.yulichang.toolkit.StrUtils;
|
||||
import com.github.yulichang.toolkit.TableHelper;
|
||||
import com.github.yulichang.toolkit.sql.SqlScriptUtils;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author yulichang
|
||||
* @since 1.4.5
|
||||
*/
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
public class AptWrapperUtils {
|
||||
|
||||
public static <T> String buildSubSqlByWrapper(Class<T> clazz, AptQueryWrapper<T> wrapper, String alias) {
|
||||
TableInfo tableInfo = TableHelper.getAssert(clazz);
|
||||
String first = Optional.ofNullable(wrapper.getSqlFirst()).orElse(StringPool.EMPTY);
|
||||
boolean hasWhere = false;
|
||||
String entityWhere = getEntitySql(tableInfo, wrapper);
|
||||
if (StrUtils.isNotBlank(entityWhere)) {
|
||||
hasWhere = true;
|
||||
}
|
||||
String mainLogic = mainLogic(hasWhere, clazz, wrapper);
|
||||
if (StrUtils.isNotBlank(mainLogic)) {
|
||||
hasWhere = true;
|
||||
}
|
||||
String subLogic = subLogic(hasWhere, wrapper);
|
||||
if (StrUtils.isNotBlank(subLogic)) {
|
||||
hasWhere = true;
|
||||
}
|
||||
String sqlSegment = (wrapper.getSqlSegment() != null && StrUtils.isNotBlank(wrapper.getSqlSegment())) ?
|
||||
((wrapper.isEmptyOfNormal() ? StringPool.EMPTY : (hasWhere ? " AND " : " WHERE ")) + wrapper.getSqlSegment()) : StringPool.EMPTY;
|
||||
|
||||
String sqlComment = Optional.ofNullable(wrapper.getSqlComment()).orElse(StringPool.EMPTY);
|
||||
return String.format(" (%s SELECT %s FROM %s %s %s %s %s %s %s) AS %s ",
|
||||
first,
|
||||
wrapper.getSqlSelect(),
|
||||
wrapper.getTableName(tableInfo.getTableName()),
|
||||
wrapper.getAlias(),
|
||||
wrapper.getFrom(),
|
||||
mainLogic,
|
||||
subLogic,
|
||||
sqlSegment,
|
||||
sqlComment,
|
||||
alias);
|
||||
}
|
||||
|
||||
public static String buildUnionSqlByWrapper(Class<?> clazz, AptQueryWrapper<?> wrapper) {
|
||||
TableInfo tableInfo = TableHelper.getAssert(clazz);
|
||||
String first = Optional.ofNullable(wrapper.getSqlFirst()).orElse(StringPool.EMPTY);
|
||||
boolean hasWhere = false;
|
||||
String entityWhere = getEntitySql(tableInfo, wrapper);
|
||||
if (StrUtils.isNotBlank(entityWhere)) {
|
||||
hasWhere = true;
|
||||
}
|
||||
String mainLogic = mainLogic(hasWhere, clazz, wrapper);
|
||||
if (StrUtils.isNotBlank(mainLogic)) {
|
||||
hasWhere = true;
|
||||
}
|
||||
String subLogic = subLogic(hasWhere, wrapper);
|
||||
if (StrUtils.isNotBlank(subLogic)) {
|
||||
hasWhere = true;
|
||||
}
|
||||
String sqlSegment = (wrapper.getSqlSegment() != null && StrUtils.isNotBlank(wrapper.getSqlSegment())) ?
|
||||
((wrapper.isEmptyOfNormal() ? StringPool.EMPTY : (hasWhere ? " AND " : " WHERE ")) + wrapper.getSqlSegment()) : StringPool.EMPTY;
|
||||
|
||||
String sqlComment = Optional.ofNullable(wrapper.getSqlComment()).orElse(StringPool.EMPTY);
|
||||
return String.format(" %s SELECT %s FROM %s %s %s %s %s %s %s ",
|
||||
first,
|
||||
wrapper.getSqlSelect(),
|
||||
wrapper.getTableName(tableInfo.getTableName()),
|
||||
wrapper.getAlias(),
|
||||
wrapper.getFrom(),
|
||||
mainLogic,
|
||||
subLogic,
|
||||
sqlSegment,
|
||||
sqlComment);
|
||||
}
|
||||
|
||||
private static <T> String formatParam(AptQueryWrapper<T> wrapper, Object param) {
|
||||
final String genParamName = Constants.WRAPPER_PARAM + wrapper.getParamNameSeq().incrementAndGet();
|
||||
final String paramStr = wrapper.getParamAlias() + ".paramNameValuePairs." + genParamName;
|
||||
wrapper.getParamNameValuePairs().put(genParamName, param);
|
||||
return SqlScriptUtils.safeParam(paramStr, null);
|
||||
}
|
||||
|
||||
private static String getEntitySql(TableInfo tableInfo, AptQueryWrapper<?> wrapper) {
|
||||
Object obj = wrapper.getEntity();
|
||||
if (Objects.isNull(obj)) {
|
||||
return StringPool.EMPTY;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder(StringPool.EMPTY);
|
||||
for (TableFieldInfo fieldInfo : tableInfo.getFieldList()) {
|
||||
if (AdapterHelper.getAdapter().mpjHasLogic(tableInfo) && fieldInfo.isLogicDelete()) {
|
||||
continue;
|
||||
}
|
||||
Object val;
|
||||
try {
|
||||
val = fieldInfo.getField().get(obj);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (Objects.isNull(val)) {
|
||||
continue;
|
||||
}
|
||||
String s = wrapper.getAptIndex().get(wrapper.getBaseColumn());
|
||||
sb.append(" AND ").append(s == null ? wrapper.getAlias() : s).append(Constants.DOT)
|
||||
.append(fieldInfo.getColumn()).append(Constants.EQUALS).append(formatParam(wrapper, val));
|
||||
}
|
||||
//条件不为空 加上 where
|
||||
if (sb.length() > 0) {
|
||||
sb.delete(0, 4);
|
||||
sb.insert(0, " WHERE ");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static String mainLogic(boolean hasWhere, Class<?> clazz, AptQueryWrapper<?> wrapper) {
|
||||
if (!wrapper.getLogicSql()) {
|
||||
return StringPool.EMPTY;
|
||||
}
|
||||
String info = LogicInfoUtils.getLogicInfo(null, clazz, true, wrapper.getAlias());
|
||||
if (StrUtils.isNotBlank(info)) {
|
||||
if (hasWhere) {
|
||||
return " AND " + info;
|
||||
}
|
||||
return " WHERE " + info.substring(4);
|
||||
}
|
||||
return StringPool.EMPTY;
|
||||
}
|
||||
|
||||
private static String subLogic(boolean hasWhere, AptQueryWrapper<?> wrapper) {
|
||||
String sql = wrapper.getSubLogicSql();
|
||||
if (StrUtils.isNotBlank(sql)) {
|
||||
if (hasWhere) {
|
||||
return sql;
|
||||
}
|
||||
return " WHERE " + sql.substring(4);
|
||||
}
|
||||
return StringPool.EMPTY;
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.github.yulichang.extension.apt.toolkit;
|
||||
|
||||
import com.github.yulichang.extension.apt.matedata.BaseColumn;
|
||||
import com.github.yulichang.extension.apt.AptQueryWrapper;
|
||||
|
||||
/**
|
||||
* @author yulichang
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class AptWrappers {
|
||||
|
||||
/**
|
||||
* AptWrappers.query(User.class)
|
||||
*/
|
||||
public static <T> AptQueryWrapper<T> query(BaseColumn<T> baseColumn) {
|
||||
return new AptQueryWrapper<>(baseColumn);
|
||||
}
|
||||
|
||||
/**
|
||||
* AptWrappers.query("t", User.class)
|
||||
*/
|
||||
public static <T> AptQueryWrapper<T> query(BaseColumn<T> baseColumn, T entity) {
|
||||
return new AptQueryWrapper<>(baseColumn, entity);
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.github.yulichang.kt;
|
||||
package com.github.yulichang.extension.kt;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.OrderBy;
|
||||
import com.baomidou.mybatisplus.core.conditions.SharedString;
|
||||
@ -6,17 +6,19 @@ import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.github.yulichang.adapter.AdapterHelper;
|
||||
import com.github.yulichang.config.ConfigProperties;
|
||||
import com.github.yulichang.config.enums.LogicDelTypeEnum;
|
||||
import com.github.yulichang.kt.interfaces.QueryJoin;
|
||||
import com.github.yulichang.extension.kt.interfaces.QueryJoin;
|
||||
import com.github.yulichang.toolkit.*;
|
||||
import com.github.yulichang.toolkit.support.ColumnCache;
|
||||
import com.github.yulichang.wrapper.enums.PrefixEnum;
|
||||
import com.github.yulichang.wrapper.interfaces.MFunction;
|
||||
import com.github.yulichang.wrapper.segments.PageInfo;
|
||||
import com.github.yulichang.wrapper.segments.SelectCache;
|
||||
import kotlin.reflect.KProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
@ -55,6 +57,14 @@ public abstract class KtAbstractLambdaWrapper<T, Children extends KtAbstractLamb
|
||||
*/
|
||||
@Getter
|
||||
protected boolean resultMap = false;
|
||||
@Getter
|
||||
protected boolean resultMapCollection = false;
|
||||
|
||||
@Setter
|
||||
protected PageInfo pageInfo;
|
||||
|
||||
@Getter
|
||||
protected boolean pageByMain = false;
|
||||
/**
|
||||
* 表序号
|
||||
*/
|
||||
@ -166,6 +176,30 @@ public abstract class KtAbstractLambdaWrapper<T, Children extends KtAbstractLamb
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据主表分页
|
||||
*/
|
||||
public Children pageByMain() {
|
||||
this.pageByMain = true;
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据主表分页
|
||||
*/
|
||||
public Children pageByMain(MFunction<PageInfo> function) {
|
||||
this.pageByMain = true;
|
||||
function.apply(getPageInfo());
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
public PageInfo getPageInfo() {
|
||||
if (pageInfo == null) {
|
||||
pageInfo = new PageInfo();
|
||||
}
|
||||
return pageInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置表别名
|
||||
* 设置表别名注意sql注入问题
|
||||
@ -328,10 +362,10 @@ public abstract class KtAbstractLambdaWrapper<T, Children extends KtAbstractLamb
|
||||
* 获取连表部分语句
|
||||
*/
|
||||
public String getFrom() {
|
||||
if (StringUtils.isBlank(from.getStringValue())) {
|
||||
if (StrUtils.isBlank(from.getStringValue())) {
|
||||
StringBuilder value = new StringBuilder();
|
||||
for (Children wrapper : onWrappers) {
|
||||
if (StringUtils.isBlank(wrapper.from.getStringValue())) {
|
||||
if (StrUtils.isBlank(wrapper.from.getStringValue())) {
|
||||
if (this.subLogicSql && this.logicDelType == LogicDelTypeEnum.ON) {
|
||||
TableInfo tableInfo = TableHelper.getAssert(wrapper.getJoinClass());
|
||||
if (AdapterHelper.getAdapter().mpjHasLogic(tableInfo)) {
|
||||
@ -373,7 +407,7 @@ public abstract class KtAbstractLambdaWrapper<T, Children extends KtAbstractLamb
|
||||
instance.isNo = true;
|
||||
instance.isMain = false;
|
||||
onWrappers.add(instance);
|
||||
if (StringUtils.isBlank(tableAlias)) {
|
||||
if (StrUtils.isBlank(tableAlias)) {
|
||||
tableList.put(oldIndex, clazz, false, subTableAlias, newIndex);
|
||||
instance.alias = subTableAlias;
|
||||
instance.hasAlias = false;
|
||||
@ -401,10 +435,10 @@ public abstract class KtAbstractLambdaWrapper<T, Children extends KtAbstractLamb
|
||||
* @param joinSql sql
|
||||
*/
|
||||
@Override
|
||||
public Children join(String keyWord, boolean condition, String joinSql) {
|
||||
public Children join(String keyWord, boolean condition, String joinSql,Object... args) {
|
||||
if (condition) {
|
||||
Children wrapper = instanceEmpty();
|
||||
wrapper.from.setStringValue(joinSql);
|
||||
wrapper.from.setStringValue(formatSqlMaybeWithParam(joinSql,args));
|
||||
wrapper.keyWord = keyWord;
|
||||
onWrappers.add(wrapper);
|
||||
}
|
||||
@ -418,7 +452,7 @@ public abstract class KtAbstractLambdaWrapper<T, Children extends KtAbstractLamb
|
||||
*/
|
||||
public boolean isUseAnnotationOrderBy() {
|
||||
final String _sqlSegment = this.getSqlSegment();
|
||||
if (StringUtils.isBlank(_sqlSegment)) {
|
||||
if (StrUtils.isBlank(_sqlSegment)) {
|
||||
return true;
|
||||
}
|
||||
final String _sqlSegmentToUpperCase = _sqlSegment.toUpperCase();
|
||||
@ -445,6 +479,9 @@ public abstract class KtAbstractLambdaWrapper<T, Children extends KtAbstractLamb
|
||||
super.clear();
|
||||
this.alias = ConfigProperties.tableAlias;
|
||||
this.resultMap = false;
|
||||
this.resultMapCollection = false;
|
||||
this.pageInfo = null;
|
||||
this.pageByMain = false;
|
||||
this.tableIndex = 1;
|
||||
this.dynamicTableName = false;
|
||||
this.tableFunc = null;
|
@ -1,4 +1,4 @@
|
||||
package com.github.yulichang.kt;
|
||||
package com.github.yulichang.extension.kt;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.ISqlSegment;
|
||||
import com.baomidou.mybatisplus.core.conditions.SharedString;
|
||||
@ -12,14 +12,11 @@ import com.baomidou.mybatisplus.core.toolkit.*;
|
||||
import com.baomidou.mybatisplus.core.toolkit.sql.SqlUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.sql.StringEscape;
|
||||
import com.github.yulichang.config.ConfigProperties;
|
||||
import com.github.yulichang.kt.interfaces.CompareIfExists;
|
||||
import com.github.yulichang.kt.interfaces.Func;
|
||||
import com.github.yulichang.kt.interfaces.OnCompare;
|
||||
import com.github.yulichang.kt.segments.FuncArgs;
|
||||
import com.github.yulichang.toolkit.KtUtils;
|
||||
import com.github.yulichang.toolkit.MPJSqlInjectionUtils;
|
||||
import com.github.yulichang.toolkit.Ref;
|
||||
import com.github.yulichang.toolkit.TableList;
|
||||
import com.github.yulichang.extension.kt.interfaces.CompareIfExists;
|
||||
import com.github.yulichang.extension.kt.interfaces.Func;
|
||||
import com.github.yulichang.extension.kt.interfaces.OnCompare;
|
||||
import com.github.yulichang.extension.kt.segments.FuncArgs;
|
||||
import com.github.yulichang.toolkit.*;
|
||||
import com.github.yulichang.toolkit.sql.SqlScriptUtils;
|
||||
import com.github.yulichang.wrapper.enums.IfExistsSqlKeyWordEnum;
|
||||
import com.github.yulichang.wrapper.enums.PrefixEnum;
|
||||
@ -34,6 +31,8 @@ import lombok.Getter;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.baomidou.mybatisplus.core.enums.SqlKeyword.*;
|
||||
import static com.baomidou.mybatisplus.core.enums.WrapperKeyword.APPLY;
|
||||
@ -195,7 +194,7 @@ public abstract class KtAbstractWrapper<T, Children extends KtAbstractWrapper<T,
|
||||
public Children allEq(boolean condition, Map<KProperty<?>, ?> params, boolean null2IsNull) {
|
||||
if (condition && CollectionUtils.isNotEmpty(params)) {
|
||||
params.forEach((k, v) -> {
|
||||
if (StringUtils.checkValNotNull(v)) {
|
||||
if (StrUtils.checkValNotNull(v)) {
|
||||
eq(k, v);
|
||||
} else {
|
||||
if (null2IsNull) {
|
||||
@ -307,7 +306,7 @@ public abstract class KtAbstractWrapper<T, Children extends KtAbstractWrapper<T,
|
||||
@Override
|
||||
public Children apply(boolean condition, String applySql, Object... values) {
|
||||
return maybeDo(condition, () -> appendSqlSegments(APPLY,
|
||||
() -> formatSqlMaybeWithParam(applySql, null, values)));
|
||||
() -> formatSqlMaybeWithParam(applySql, values)));
|
||||
}
|
||||
|
||||
public Children applyFunc(String applySql, Function<FuncArgs, SelectFunc.Arg[]> consumerFunction, Object... values) {
|
||||
@ -319,7 +318,8 @@ public abstract class KtAbstractWrapper<T, Children extends KtAbstractWrapper<T,
|
||||
return maybeDo(condition, () -> appendSqlSegments(APPLY,
|
||||
() -> formatSqlMaybeWithParam(String.format(applySql,
|
||||
Arrays.stream(consumerFunction.apply(new FuncArgs())).map(func ->
|
||||
columnToString(index, null, (KProperty<?>) func.getProperty(), false, PrefixEnum.CD_FIRST)).toArray()), null, values)));
|
||||
columnToString(index, null, (KProperty<?>) func.getProperty(),
|
||||
false, PrefixEnum.CD_FIRST)).toArray()), values)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -356,7 +356,7 @@ public abstract class KtAbstractWrapper<T, Children extends KtAbstractWrapper<T,
|
||||
@Override
|
||||
public Children exists(boolean condition, String existsSql, Object... values) {
|
||||
return maybeDo(condition, () -> appendSqlSegments(EXISTS,
|
||||
() -> String.format("(%s)", formatSqlMaybeWithParam(existsSql, null, values))));
|
||||
() -> String.format("(%s)", formatSqlMaybeWithParam(existsSql, values))));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -495,12 +495,18 @@ public abstract class KtAbstractWrapper<T, Children extends KtAbstractWrapper<T,
|
||||
@Override
|
||||
public Children having(boolean condition, String sqlHaving, Object... params) {
|
||||
return maybeDo(condition, () -> appendSqlSegments(HAVING,
|
||||
() -> formatSqlMaybeWithParam(sqlHaving, null, params)));
|
||||
() -> formatSqlMaybeWithParam(sqlHaving, params)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Children func(boolean condition, Consumer<Children> consumer) {
|
||||
return maybeDo(condition, () -> consumer.accept(typedThis));
|
||||
public Children func(boolean condition, Consumer<Children> consumer, Consumer<Children> consumerElse) {
|
||||
if (condition) {
|
||||
consumer.accept(typedThis);
|
||||
}
|
||||
if (!condition && Objects.nonNull(consumerElse)) {
|
||||
consumerElse.accept(typedThis);
|
||||
}
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -588,21 +594,28 @@ public abstract class KtAbstractWrapper<T, Children extends KtAbstractWrapper<T,
|
||||
* <p>
|
||||
* 支持 "{0}" 这种,或者 "sql {0} sql" 这种
|
||||
*
|
||||
* @param sqlStr 可能是sql片段
|
||||
* @param mapping 例如: "javaType=int,jdbcType=NUMERIC,typeHandler=xxx.xxx.MyTypeHandler" 这种
|
||||
* @param params 参数
|
||||
* @param sqlStr 可能是sql片段
|
||||
* @param params 参数
|
||||
* @return sql片段
|
||||
*/
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
protected final String formatSqlMaybeWithParam(String sqlStr, String mapping, Object... params) {
|
||||
if (StringUtils.isBlank(sqlStr)) {
|
||||
// todo 何时会这样?
|
||||
protected final String formatSqlMaybeWithParam(String sqlStr, Object... params) {
|
||||
if (StrUtils.isBlank(sqlStr)) {
|
||||
return null;
|
||||
}
|
||||
if (ArrayUtils.isNotEmpty(params)) {
|
||||
for (int i = 0; i < params.length; ++i) {
|
||||
final String target = Constants.LEFT_BRACE + i + Constants.RIGHT_BRACE;
|
||||
sqlStr = sqlStr.replace(target, formatParam(mapping, params[i]));
|
||||
String target = Constants.LEFT_BRACE + i + Constants.RIGHT_BRACE;
|
||||
if (sqlStr.contains(target)) {
|
||||
sqlStr = sqlStr.replace(target, formatParam(null, params[i]));
|
||||
} else {
|
||||
Matcher matcher = Pattern.compile("[{]" + i + ",[a-zA-Z0-9.,=]+}").matcher(sqlStr);
|
||||
if (!matcher.find()) {
|
||||
throw ExceptionUtils.mpe("Please check the syntax correctness! sql not contains: \"%s\"", target);
|
||||
}
|
||||
String group = matcher.group();
|
||||
sqlStr = sqlStr.replace(group, formatParam(group.substring(target.length(), group.length() - 1), params[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
return sqlStr;
|
||||
@ -697,7 +710,7 @@ public abstract class KtAbstractWrapper<T, Children extends KtAbstractWrapper<T,
|
||||
|
||||
@Override
|
||||
public String getSqlComment() {
|
||||
if (StringUtils.isNotBlank(sqlComment.getStringValue())) {
|
||||
if (StrUtils.isNotBlank(sqlComment.getStringValue())) {
|
||||
return "/*" + StringEscape.escapeRawString(sqlComment.getStringValue()) + "*/";
|
||||
}
|
||||
return null;
|
||||
@ -705,7 +718,7 @@ public abstract class KtAbstractWrapper<T, Children extends KtAbstractWrapper<T,
|
||||
|
||||
@Override
|
||||
public String getSqlFirst() {
|
||||
if (StringUtils.isNotBlank(sqlFirst.getStringValue())) {
|
||||
if (StrUtils.isNotBlank(sqlFirst.getStringValue())) {
|
||||
return StringEscape.escapeRawString(sqlFirst.getStringValue());
|
||||
}
|
||||
return null;
|
||||
@ -833,7 +846,7 @@ public abstract class KtAbstractWrapper<T, Children extends KtAbstractWrapper<T,
|
||||
public <V> Children allEqStr(boolean condition, Map<String, V> params, boolean null2IsNull) {
|
||||
if (condition && CollectionUtils.isNotEmpty(params)) {
|
||||
params.forEach((k, v) -> {
|
||||
if (StringUtils.checkValNotNull(v)) {
|
||||
if (StrUtils.checkValNotNull(v)) {
|
||||
eq(k, v);
|
||||
} else {
|
||||
if (null2IsNull) {
|
||||
@ -850,7 +863,7 @@ public abstract class KtAbstractWrapper<T, Children extends KtAbstractWrapper<T,
|
||||
if (condition && CollectionUtils.isNotEmpty(params)) {
|
||||
params.forEach((k, v) -> {
|
||||
if (filter.test(k, v)) {
|
||||
if (StringUtils.checkValNotNull(v)) {
|
||||
if (StrUtils.checkValNotNull(v)) {
|
||||
eq(k, v);
|
||||
} else {
|
||||
if (null2IsNull) {
|
@ -1,4 +1,4 @@
|
||||
package com.github.yulichang.kt;
|
||||
package com.github.yulichang.extension.kt;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.SharedString;
|
||||
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
|
||||
@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.*;
|
||||
import com.github.yulichang.adapter.AdapterHelper;
|
||||
import com.github.yulichang.toolkit.LogicInfoUtils;
|
||||
import com.github.yulichang.toolkit.StrUtils;
|
||||
import com.github.yulichang.toolkit.TableHelper;
|
||||
import com.github.yulichang.toolkit.TableList;
|
||||
import com.github.yulichang.wrapper.interfaces.DeleteChain;
|
||||
@ -71,7 +72,7 @@ public class KtDeleteJoinWrapper<T> extends KtAbstractLambdaWrapper<T, KtDeleteJ
|
||||
*/
|
||||
@Override
|
||||
public String getDeleteSql() {
|
||||
if (StringUtils.isNotBlank(this.deleteSql.getStringValue())) {
|
||||
if (StrUtils.isNotBlank(this.deleteSql.getStringValue())) {
|
||||
return this.deleteSql.getStringValue();
|
||||
}
|
||||
String delete = null;
|
||||
@ -89,7 +90,7 @@ public class KtDeleteJoinWrapper<T> extends KtAbstractLambdaWrapper<T, KtDeleteJ
|
||||
if (CollectionUtils.isNotEmpty(deleteTableName)) {
|
||||
delete = delete + StringPool.COMMA + String.join(StringPool.COMMA, deleteTableName);
|
||||
}
|
||||
if (StringUtils.isBlank(delete)) {
|
||||
if (StrUtils.isBlank(delete)) {
|
||||
delete = this.alias;
|
||||
}
|
||||
deleteSql.setStringValue(delete);
|
||||
@ -101,7 +102,7 @@ public class KtDeleteJoinWrapper<T> extends KtAbstractLambdaWrapper<T, KtDeleteJ
|
||||
*/
|
||||
@Override
|
||||
public String getDeleteLogicSql() {
|
||||
if (StringUtils.isNotBlank(this.deleteSql.getStringValue())) {
|
||||
if (StrUtils.isNotBlank(this.deleteSql.getStringValue())) {
|
||||
return this.deleteSql.getStringValue();
|
||||
}
|
||||
String delete = null;
|
||||
@ -119,7 +120,7 @@ public class KtDeleteJoinWrapper<T> extends KtAbstractLambdaWrapper<T, KtDeleteJ
|
||||
if (CollectionUtils.isNotEmpty(deleteTableName)) {
|
||||
delete = delete + StringPool.COMMA + String.join(StringPool.COMMA, deleteTableName);
|
||||
}
|
||||
if (StringUtils.isNotBlank(delete)) {
|
||||
if (StrUtils.isNotBlank(delete)) {
|
||||
delete = StringPool.COMMA + delete;
|
||||
} else {
|
||||
delete = StringPool.EMPTY;
|
@ -1,15 +1,22 @@
|
||||
package com.github.yulichang.kt;
|
||||
package com.github.yulichang.extension.kt;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.SharedString;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
|
||||
import com.baomidou.mybatisplus.core.toolkit.*;
|
||||
import com.github.yulichang.config.ConfigProperties;
|
||||
import com.github.yulichang.kt.interfaces.Query;
|
||||
import com.github.yulichang.kt.interfaces.QueryLabel;
|
||||
import com.github.yulichang.toolkit.*;
|
||||
import com.github.yulichang.extension.kt.interfaces.Query;
|
||||
import com.github.yulichang.extension.kt.interfaces.QueryLabel;
|
||||
import com.github.yulichang.extension.kt.segments.FuncArgs;
|
||||
import com.github.yulichang.extension.kt.toolkit.KtWrapperUtils;
|
||||
import com.github.yulichang.extension.kt.toolkit.KtWrappers;
|
||||
import com.github.yulichang.toolkit.Constant;
|
||||
import com.github.yulichang.toolkit.KtUtils;
|
||||
import com.github.yulichang.toolkit.StrUtils;
|
||||
import com.github.yulichang.toolkit.TableList;
|
||||
import com.github.yulichang.toolkit.support.ColumnCache;
|
||||
import com.github.yulichang.wrapper.interfaces.Chain;
|
||||
import com.github.yulichang.wrapper.interfaces.MFunction;
|
||||
import com.github.yulichang.wrapper.interfaces.SelectWrapper;
|
||||
import com.github.yulichang.wrapper.resultmap.Label;
|
||||
import com.github.yulichang.wrapper.segments.*;
|
||||
@ -159,7 +166,10 @@ public class KtLambdaWrapper<T> extends KtAbstractLambdaWrapper<T, KtLambdaWrapp
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addLabel(Label<?> label) {
|
||||
public void addLabel(Label<?> label, boolean isCollection) {
|
||||
if (isCollection) {
|
||||
this.resultMapCollection = true;
|
||||
}
|
||||
this.resultMap = true;
|
||||
this.resultMapMybatisLabel.add(label);
|
||||
}
|
||||
@ -188,8 +198,8 @@ public class KtLambdaWrapper<T> extends KtAbstractLambdaWrapper<T, KtLambdaWrapp
|
||||
}
|
||||
|
||||
@Override
|
||||
public KtLambdaWrapper<T> selectAll(Class<?> clazz) {
|
||||
return Query.super.selectAll(clazz);
|
||||
public KtLambdaWrapper<T> selectAll() {
|
||||
return Query.super.selectAll(getEntityClass());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -199,11 +209,16 @@ public class KtLambdaWrapper<T> extends KtAbstractLambdaWrapper<T, KtLambdaWrapp
|
||||
return selectSub(clazz, ConfigProperties.subQueryAlias, consumer, alias);
|
||||
}
|
||||
|
||||
|
||||
public <E, F> KtLambdaWrapper<T> selectSub(Class<E> clazz, String st, Consumer<KtLambdaWrapper<?>> consumer, KProperty<?> alias) {
|
||||
return selectSub(clazz, st, consumer, alias.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* 子查询
|
||||
*/
|
||||
public KtLambdaWrapper<T> selectSub(Class<?> clazz, String st,
|
||||
Consumer<KtLambdaWrapper<?>> consumer, KProperty<?> alias) {
|
||||
Consumer<KtLambdaWrapper<?>> consumer, String alias) {
|
||||
KtLambdaWrapper<?> wrapper = new KtLambdaWrapper(null, clazz, SharedString.emptyString(), paramNameSeq,
|
||||
paramNameValuePairs, new MergeSegments(), new SharedString(this.paramAlias.getStringValue()),
|
||||
SharedString.emptyString(), SharedString.emptyString(), SharedString.emptyString(), new TableList(),
|
||||
@ -217,7 +232,21 @@ public class KtLambdaWrapper<T> extends KtAbstractLambdaWrapper<T, KtLambdaWrapp
|
||||
consumer.accept(wrapper);
|
||||
addCustomWrapper(wrapper);
|
||||
this.selectColumns.add(new SelectSub(() -> KtWrapperUtils.buildSubSqlByWrapper(
|
||||
clazz, wrapper, alias.getName()), hasAlias, this.alias, alias.getName()));
|
||||
clazz, wrapper, alias), hasAlias, this.alias, alias));
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KtLambdaWrapper<T> selectFunc(String sql, MFunction<FuncArgs> column, String alias) {
|
||||
FuncArgs apply = column.apply(new FuncArgs());
|
||||
String formatSql;
|
||||
if (ArrayUtils.isEmpty(apply.getValues())) {
|
||||
formatSql = sql;
|
||||
} else {
|
||||
formatSql = formatSqlMaybeWithParam(sql, apply.getValues());
|
||||
}
|
||||
getSelectColum().add(new SelectFunc(alias, getIndex(), () -> formatSql, apply.getFuncArg(),
|
||||
isHasAlias(), getAlias()));
|
||||
return typedThis;
|
||||
}
|
||||
|
||||
@ -335,7 +364,7 @@ public class KtLambdaWrapper<T> extends KtAbstractLambdaWrapper<T, KtLambdaWrapp
|
||||
*/
|
||||
@Override
|
||||
public String getSqlSelect() {
|
||||
if (StringUtils.isBlank(sqlSelect.getStringValue()) && CollectionUtils.isNotEmpty(selectColumns)) {
|
||||
if (StrUtils.isBlank(sqlSelect.getStringValue()) && CollectionUtils.isNotEmpty(selectColumns)) {
|
||||
String s = selectColumns.stream().map(i -> {
|
||||
if (i.isStr()) {
|
||||
return i.getColumn();
|
@ -1,4 +1,4 @@
|
||||
package com.github.yulichang.kt;
|
||||
package com.github.yulichang.extension.kt;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.SharedString;
|
||||
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
|
||||
@ -6,12 +6,9 @@ import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.*;
|
||||
import com.github.yulichang.adapter.AdapterHelper;
|
||||
import com.github.yulichang.kt.interfaces.Update;
|
||||
import com.github.yulichang.toolkit.Constant;
|
||||
import com.github.yulichang.toolkit.KtUtils;
|
||||
import com.github.yulichang.extension.kt.interfaces.Update;
|
||||
import com.github.yulichang.toolkit.*;
|
||||
import com.github.yulichang.toolkit.ReflectionKit;
|
||||
import com.github.yulichang.toolkit.TableHelper;
|
||||
import com.github.yulichang.toolkit.TableList;
|
||||
import com.github.yulichang.wrapper.interfaces.UpdateChain;
|
||||
import kotlin.reflect.KProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
@ -142,7 +139,7 @@ public class KtUpdateJoinWrapper<T> extends KtAbstractLambdaWrapper<T, KtUpdateJ
|
||||
|
||||
@Override
|
||||
public KtUpdateJoinWrapper<T> setSql(boolean condition, String sql) {
|
||||
if (condition && StringUtils.isNotBlank(sql)) {
|
||||
if (condition && StrUtils.isNotBlank(sql)) {
|
||||
if (Objects.isNull(sqlSet)) {
|
||||
sqlSet = new ArrayList<>();
|
||||
}
|
||||
@ -153,7 +150,7 @@ public class KtUpdateJoinWrapper<T> extends KtAbstractLambdaWrapper<T, KtUpdateJ
|
||||
|
||||
@Override
|
||||
public String getSqlSet() {
|
||||
if (StringUtils.isNotBlank(sqlSetStr.getStringValue())) {
|
||||
if (StrUtils.isNotBlank(sqlSetStr.getStringValue())) {
|
||||
return sqlSetStr.getStringValue();
|
||||
}
|
||||
StringBuilder set = new StringBuilder(StringPool.EMPTY);
|
@ -1,4 +1,4 @@
|
||||
package com.github.yulichang.kt.interfaces;
|
||||
package com.github.yulichang.extension.kt.interfaces;
|
||||
|
||||
import kotlin.reflect.KProperty;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.github.yulichang.kt.interfaces;
|
||||
package com.github.yulichang.extension.kt.interfaces;
|
||||
|
||||
import com.github.yulichang.wrapper.enums.IfExistsSqlKeyWordEnum;
|
||||
import kotlin.reflect.KProperty;
|
@ -1,4 +1,4 @@
|
||||
package com.github.yulichang.kt.interfaces;
|
||||
package com.github.yulichang.extension.kt.interfaces;
|
||||
|
||||
import kotlin.reflect.KProperty;
|
||||
|
||||
@ -483,5 +483,9 @@ public interface Func<Children> extends Serializable {
|
||||
* @return children
|
||||
* @since 3.3.1
|
||||
*/
|
||||
Children func(boolean condition, Consumer<Children> consumer);
|
||||
default Children func(boolean condition, Consumer<Children> consumer) {
|
||||
return func(condition, consumer, null);
|
||||
}
|
||||
|
||||
Children func(boolean condition, Consumer<Children> consumer, Consumer<Children> consumerElse);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.github.yulichang.kt.interfaces;
|
||||
package com.github.yulichang.extension.kt.interfaces;
|
||||
|
||||
import kotlin.reflect.KProperty;
|
||||
|
@ -1,9 +1,9 @@
|
||||
package com.github.yulichang.kt.interfaces;
|
||||
package com.github.yulichang.extension.kt.interfaces;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.github.yulichang.kt.segments.FuncArgs;
|
||||
import com.github.yulichang.extension.kt.segments.FuncArgs;
|
||||
import com.github.yulichang.toolkit.Constant;
|
||||
import com.github.yulichang.toolkit.KtUtils;
|
||||
import com.github.yulichang.toolkit.MPJReflectionKit;
|
||||
@ -12,6 +12,7 @@ import com.github.yulichang.toolkit.support.ColumnCache;
|
||||
import com.github.yulichang.toolkit.support.FieldCache;
|
||||
import com.github.yulichang.wrapper.enums.BaseFuncEnum;
|
||||
import com.github.yulichang.wrapper.enums.DefaultFuncEnum;
|
||||
import com.github.yulichang.wrapper.interfaces.MFunction;
|
||||
import com.github.yulichang.wrapper.segments.*;
|
||||
import kotlin.reflect.KProperty;
|
||||
|
||||
@ -19,7 +20,6 @@ import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -216,16 +216,10 @@ public interface Query<Children> extends Serializable {
|
||||
}
|
||||
|
||||
|
||||
default Children selectFunc(String sql, Function<FuncArgs, SelectFunc.Arg[]> column, String alias) {
|
||||
getSelectColum().add(new SelectFunc(alias, getIndex(), () -> sql, column.apply(new FuncArgs()),
|
||||
isHasAlias(), getAlias()));
|
||||
return getChildren();
|
||||
}
|
||||
Children selectFunc(String sql, MFunction<FuncArgs> column, String alias);
|
||||
|
||||
default Children selectFunc(String sql, Function<FuncArgs, SelectFunc.Arg[]> column, KProperty<?> alias) {
|
||||
getSelectColum().add(new SelectFunc(alias.getName(), getIndex(), () -> sql,
|
||||
column.apply(new FuncArgs()), isHasAlias(), getAlias()));
|
||||
return getChildren();
|
||||
default Children selectFunc(String sql, MFunction<FuncArgs> column, KProperty<?> alias) {
|
||||
return selectFunc(sql, column, alias.getName());
|
||||
}
|
||||
|
||||
/* 默认聚合函数扩展 */
|
@ -1,7 +1,7 @@
|
||||
package com.github.yulichang.kt.interfaces;
|
||||
package com.github.yulichang.extension.kt.interfaces;
|
||||
|
||||
import com.github.yulichang.interfaces.MPJBaseJoin;
|
||||
import com.github.yulichang.kt.KtAbstractLambdaWrapper;
|
||||
import com.github.yulichang.extension.kt.KtAbstractLambdaWrapper;
|
||||
import com.github.yulichang.query.interfaces.StringJoin;
|
||||
import com.github.yulichang.toolkit.Constant;
|
||||
import com.github.yulichang.wrapper.interfaces.MFunction;
|
@ -1,11 +1,11 @@
|
||||
package com.github.yulichang.kt.interfaces;
|
||||
package com.github.yulichang.extension.kt.interfaces;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.Assert;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.github.yulichang.kt.resultmap.MybatisLabel;
|
||||
import com.github.yulichang.kt.resultmap.MybatisLabelFree;
|
||||
import com.github.yulichang.extension.kt.resultmap.MybatisLabel;
|
||||
import com.github.yulichang.extension.kt.resultmap.MybatisLabelFree;
|
||||
import com.github.yulichang.toolkit.KtUtils;
|
||||
import com.github.yulichang.toolkit.MPJReflectionKit;
|
||||
import com.github.yulichang.toolkit.StrUtils;
|
||||
import com.github.yulichang.toolkit.support.FieldCache;
|
||||
import com.github.yulichang.wrapper.interfaces.MFunction;
|
||||
import com.github.yulichang.wrapper.resultmap.Label;
|
||||
@ -23,7 +23,7 @@ import java.util.Map;
|
||||
@SuppressWarnings({"unused", "DuplicatedCode"})
|
||||
public interface QueryLabel<Children> {
|
||||
|
||||
void addLabel(Label<?> label);
|
||||
void addLabel(Label<?> label, boolean isCollection);
|
||||
|
||||
Children getChildren();
|
||||
|
||||
@ -62,7 +62,7 @@ public interface QueryLabel<Children> {
|
||||
} else {
|
||||
builder = new MybatisLabel.Builder<>(prefix, dtoFieldName, child, field.getType(), genericType, true);
|
||||
}
|
||||
addLabel(builder.build());
|
||||
addLabel(builder.build(), true);
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
@ -104,7 +104,7 @@ public interface QueryLabel<Children> {
|
||||
Class<?> genericType = MPJReflectionKit.getGenericType(field.getField());
|
||||
MybatisLabelFree.Builder<?> builder = new MybatisLabelFree.Builder<>(dtoFieldName, field.getType(), genericType);
|
||||
MybatisLabelFree.Builder<?> czBuilder = collection.apply(builder);
|
||||
addLabel(czBuilder.build());
|
||||
addLabel(czBuilder.build(), true);
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
@ -118,7 +118,7 @@ public interface QueryLabel<Children> {
|
||||
Class<?> genericType = MPJReflectionKit.getGenericType(field.getField());
|
||||
MybatisLabel.Builder<?, ?> builder = new MybatisLabel.Builder<>(prefix, dtoFieldName, child, field.getType(), genericType, false);
|
||||
MybatisLabel.Builder<?, ?> czBuilder = collection.apply(builder);
|
||||
addLabel(czBuilder.build());
|
||||
addLabel(czBuilder.build(), true);
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
@ -137,9 +137,9 @@ public interface QueryLabel<Children> {
|
||||
FieldCache field = fieldMap.get(dtoFieldName);
|
||||
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
|
||||
MybatisLabel.Builder<?, ?> builder;
|
||||
builder = new MybatisLabel.Builder<>(StringUtils.isBlank(prefix) ? null : prefix,
|
||||
builder = new MybatisLabel.Builder<>(StrUtils.isBlank(prefix) ? null : prefix,
|
||||
dtoFieldName, child, field.getType(), (Class<?>) field.getType(), true);
|
||||
addLabel(builder.build());
|
||||
addLabel(builder.build(), false);
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
@ -160,7 +160,7 @@ public interface QueryLabel<Children> {
|
||||
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
|
||||
MybatisLabelFree.Builder<?> builder = new MybatisLabelFree.Builder<>(dtoFieldName, field.getType(), (Class<?>) field.getType());
|
||||
MybatisLabelFree.Builder<?> cfBuilder = collection.apply(builder);
|
||||
addLabel(cfBuilder.build());
|
||||
addLabel(cfBuilder.build(), false);
|
||||
return getChildren();
|
||||
}
|
||||
|
||||
@ -169,10 +169,10 @@ public interface QueryLabel<Children> {
|
||||
String dtoFieldName = dtoField.getName();
|
||||
FieldCache field = MPJReflectionKit.getFieldMap(KtUtils.ref(dtoField)).get(dtoFieldName);
|
||||
Assert.isFalse(Collection.class.isAssignableFrom(field.getType()), "association 不支持集合类");
|
||||
MybatisLabel.Builder<?, ?> builder = new MybatisLabel.Builder<>(StringUtils.isBlank(prefix) ? null : prefix,
|
||||
MybatisLabel.Builder<?, ?> builder = new MybatisLabel.Builder<>(StrUtils.isBlank(prefix) ? null : prefix,
|
||||
dtoFieldName, child, field.getType(), (Class<?>) field.getType(), false);
|
||||
MybatisLabel.Builder<?, ?> cfBuilder = collection.apply(builder);
|
||||
addLabel(cfBuilder.build());
|
||||
addLabel(cfBuilder.build(), false);
|
||||
return getChildren();
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.github.yulichang.kt.interfaces;
|
||||
package com.github.yulichang.extension.kt.interfaces;
|
||||
|
||||
import kotlin.reflect.KProperty;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.github.yulichang.kt.resultmap;
|
||||
package com.github.yulichang.extension.kt.resultmap;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Assert;
|
||||
@ -264,7 +264,7 @@ public class MybatisLabel<E, T> implements Label<T> {
|
||||
result.setIndex(mybatisLabel.index);
|
||||
result.setProperty(i.getColumProperty());
|
||||
result.setJavaType(i.getColumnType());
|
||||
result.setJdbcType(Objects.isNull(i.getTableFieldInfo()) ? null : i.getTableFieldInfo().getJdbcType());
|
||||
result.setJdbcType(i.getJdbcType());
|
||||
result.setSelectNormal(i);
|
||||
return result;
|
||||
}).collect(Collectors.toList()));
|
@ -1,4 +1,4 @@
|
||||
package com.github.yulichang.kt.resultmap;
|
||||
package com.github.yulichang.extension.kt.resultmap;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Assert;
|
@ -1,8 +1,7 @@
|
||||
package com.github.yulichang.kt.resultmap;
|
||||
package com.github.yulichang.extension.kt.resultmap;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.github.yulichang.toolkit.KtUtils;
|
||||
import com.github.yulichang.toolkit.StrUtils;
|
||||
import com.github.yulichang.toolkit.support.ColumnCache;
|
||||
import com.github.yulichang.wrapper.resultmap.IResult;
|
||||
import com.github.yulichang.wrapper.segments.SelectCache;
|
||||
@ -14,7 +13,6 @@ import org.apache.ibatis.type.JdbcType;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* result 标签
|
||||
@ -60,7 +58,7 @@ public class Result implements IResult {
|
||||
result.selectNormal = selectCache;
|
||||
result.property = selectCache.getColumProperty();
|
||||
result.javaType = selectCache.getColumnType();
|
||||
result.jdbcType = Optional.ofNullable(selectCache.getTableFieldInfo()).map(TableFieldInfo::getJdbcType).orElse(null);
|
||||
result.jdbcType = selectCache.getJdbcType();
|
||||
}
|
||||
|
||||
public Builder<T> property(KProperty<?> property) {
|
||||
@ -73,14 +71,14 @@ public class Result implements IResult {
|
||||
String name = column.getName();
|
||||
SelectCache normal = normalMap.get(name);
|
||||
result.selectNormal = normal;
|
||||
if (StringUtils.isBlank(result.property)) {
|
||||
if (StrUtils.isBlank(result.property)) {
|
||||
result.property = normal.getColumProperty();
|
||||
}
|
||||
if (Objects.isNull(result.javaType)) {
|
||||
result.javaType = normal.getColumnType();
|
||||
}
|
||||
if (Objects.isNull(result.jdbcType)) {
|
||||
result.jdbcType = Objects.isNull(normal.getTableFieldInfo()) ? null : normal.getTableFieldInfo().getJdbcType();
|
||||
result.jdbcType = normal.getJdbcType();
|
||||
}
|
||||
return this;
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.github.yulichang.extension.kt.segments;
|
||||
|
||||
import com.github.yulichang.toolkit.KtUtils;
|
||||
import com.github.yulichang.wrapper.segments.SelectFunc;
|
||||
import kotlin.reflect.KProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 自定义函数列
|
||||
*
|
||||
* @author yulichang
|
||||
* @since 1.4.6
|
||||
*/
|
||||
@Data
|
||||
@SuppressWarnings("unused")
|
||||
public class FuncArgs {
|
||||
|
||||
private KProperty<?>[] args;
|
||||
|
||||
private Object[] values;
|
||||
|
||||
public FuncArgs accept(KProperty<?>... kProperty) {
|
||||
this.args = kProperty;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FuncArgs values(Object... values) {
|
||||
this.values = values;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SelectFunc.Arg[] getFuncArg() {
|
||||
return Arrays.stream(args).map(i ->
|
||||
new SelectFunc.Arg(KtUtils.ref(i), i.getName(), false, null, i,false,null))
|
||||
.toArray(SelectFunc.Arg[]::new);
|
||||
}
|
||||
|
||||
}
|
@ -1,12 +1,14 @@
|
||||
package com.github.yulichang.toolkit;
|
||||
package com.github.yulichang.extension.kt.toolkit;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.github.yulichang.adapter.AdapterHelper;
|
||||
import com.github.yulichang.kt.KtLambdaWrapper;
|
||||
import com.github.yulichang.extension.kt.KtLambdaWrapper;
|
||||
import com.github.yulichang.toolkit.LogicInfoUtils;
|
||||
import com.github.yulichang.toolkit.StrUtils;
|
||||
import com.github.yulichang.toolkit.TableHelper;
|
||||
import com.github.yulichang.toolkit.sql.SqlScriptUtils;
|
||||
|
||||
import java.util.Objects;
|
||||
@ -24,18 +26,18 @@ public class KtWrapperUtils {
|
||||
String first = Optional.ofNullable(wrapper.getSqlFirst()).orElse(StringPool.EMPTY);
|
||||
boolean hasWhere = false;
|
||||
String entityWhere = getEntitySql(tableInfo, wrapper);
|
||||
if (StringUtils.isNotBlank(entityWhere)) {
|
||||
if (StrUtils.isNotBlank(entityWhere)) {
|
||||
hasWhere = true;
|
||||
}
|
||||
String mainLogic = mainLogic(hasWhere, clazz, wrapper);
|
||||
if (StringUtils.isNotBlank(mainLogic)) {
|
||||
if (StrUtils.isNotBlank(mainLogic)) {
|
||||
hasWhere = true;
|
||||
}
|
||||
String subLogic = subLogic(hasWhere, wrapper);
|
||||
if (StringUtils.isNotBlank(subLogic)) {
|
||||
if (StrUtils.isNotBlank(subLogic)) {
|
||||
hasWhere = true;
|
||||
}
|
||||
String sqlSegment = (wrapper.getSqlSegment() != null && StringUtils.isNotBlank(wrapper.getSqlSegment())) ?
|
||||
String sqlSegment = (wrapper.getSqlSegment() != null && StrUtils.isNotBlank(wrapper.getSqlSegment())) ?
|
||||
((wrapper.isEmptyOfNormal() ? StringPool.EMPTY : (hasWhere ? " AND " : " WHERE ")) + wrapper.getSqlSegment()) : StringPool.EMPTY;
|
||||
|
||||
String sqlComment = Optional.ofNullable(wrapper.getSqlComment()).orElse(StringPool.EMPTY);
|
||||
@ -57,18 +59,18 @@ public class KtWrapperUtils {
|
||||
String first = Optional.ofNullable(wrapper.getSqlFirst()).orElse(StringPool.EMPTY);
|
||||
boolean hasWhere = false;
|
||||
String entityWhere = getEntitySql(tableInfo, wrapper);
|
||||
if (StringUtils.isNotBlank(entityWhere)) {
|
||||
if (StrUtils.isNotBlank(entityWhere)) {
|
||||
hasWhere = true;
|
||||
}
|
||||
String mainLogic = mainLogic(hasWhere, clazz, wrapper);
|
||||
if (StringUtils.isNotBlank(mainLogic)) {
|
||||
if (StrUtils.isNotBlank(mainLogic)) {
|
||||
hasWhere = true;
|
||||
}
|
||||
String subLogic = subLogic(hasWhere, wrapper);
|
||||
if (StringUtils.isNotBlank(subLogic)) {
|
||||
if (StrUtils.isNotBlank(subLogic)) {
|
||||
hasWhere = true;
|
||||
}
|
||||
String sqlSegment = (wrapper.getSqlSegment() != null && StringUtils.isNotBlank(wrapper.getSqlSegment())) ?
|
||||
String sqlSegment = (wrapper.getSqlSegment() != null && StrUtils.isNotBlank(wrapper.getSqlSegment())) ?
|
||||
((wrapper.isEmptyOfNormal() ? StringPool.EMPTY : (hasWhere ? " AND " : " WHERE ")) + wrapper.getSqlSegment()) : StringPool.EMPTY;
|
||||
|
||||
String sqlComment = Optional.ofNullable(wrapper.getSqlComment()).orElse(StringPool.EMPTY);
|
||||
@ -126,7 +128,7 @@ public class KtWrapperUtils {
|
||||
return StringPool.EMPTY;
|
||||
}
|
||||
String info = LogicInfoUtils.getLogicInfo(null, clazz, true, wrapper.getAlias());
|
||||
if (StringUtils.isNotBlank(info)) {
|
||||
if (StrUtils.isNotBlank(info)) {
|
||||
if (hasWhere) {
|
||||
return " AND " + info;
|
||||
}
|
||||
@ -137,7 +139,7 @@ public class KtWrapperUtils {
|
||||
|
||||
private static String subLogic(boolean hasWhere, KtLambdaWrapper<?> wrapper) {
|
||||
String sql = wrapper.getSubLogicSql();
|
||||
if (StringUtils.isNotBlank(sql)) {
|
||||
if (StrUtils.isNotBlank(sql)) {
|
||||
if (hasWhere) {
|
||||
return sql;
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
package com.github.yulichang.toolkit;
|
||||
package com.github.yulichang.extension.kt.toolkit;
|
||||
|
||||
import com.github.yulichang.kt.KtDeleteJoinWrapper;
|
||||
import com.github.yulichang.kt.KtLambdaWrapper;
|
||||
import com.github.yulichang.kt.KtUpdateJoinWrapper;
|
||||
import com.github.yulichang.extension.kt.KtDeleteJoinWrapper;
|
||||
import com.github.yulichang.extension.kt.KtLambdaWrapper;
|
||||
import com.github.yulichang.extension.kt.KtUpdateJoinWrapper;
|
||||
|
||||
/**
|
||||
* @author yulichang
|
@ -1,6 +1,5 @@
|
||||
package com.github.yulichang.injector;
|
||||
|
||||
import com.baomidou.mybatisplus.core.MybatisPlusVersion;
|
||||
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
|
||||
import com.baomidou.mybatisplus.core.injector.AbstractSqlInjector;
|
||||
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
|
||||
@ -9,14 +8,13 @@ import com.baomidou.mybatisplus.core.injector.methods.*;
|
||||
import com.baomidou.mybatisplus.core.mapper.Mapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.ClassUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
|
||||
import com.github.yulichang.adapter.base.tookit.VersionUtils;
|
||||
import com.github.yulichang.adapter.v3431.AbstractMethodV3431;
|
||||
import com.github.yulichang.method.*;
|
||||
import com.github.yulichang.toolkit.MPJTableMapperHelper;
|
||||
import com.github.yulichang.toolkit.ReflectionKit;
|
||||
import com.github.yulichang.toolkit.TableHelper;
|
||||
import com.github.yulichang.toolkit.reflect.GenericTypeUtils;
|
||||
import lombok.Getter;
|
||||
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
||||
import org.apache.ibatis.session.Configuration;
|
||||
@ -60,7 +58,7 @@ public class MPJSqlInjector extends DefaultSqlInjector {
|
||||
@Deprecated
|
||||
@SuppressWarnings({"unused", "DeprecatedIsStillUsed"})
|
||||
public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
|
||||
if (VersionUtils.compare(MybatisPlusVersion.getVersion(), "3.4.3.2") >= 0) {
|
||||
if (VersionUtils.compare(VersionUtils.getVersion(), "3.4.3.2") >= 0) {
|
||||
throw ExceptionUtils.mpe("DefaultSqlInjector 的 getMethodList(Class<?> mapperClass) 方法已在 3.4.3.2+ 改为" +
|
||||
"getMethodList(Class<?> mapperClass, TableInfo tableInfo)\n");
|
||||
}
|
||||
@ -92,6 +90,7 @@ public class MPJSqlInjector extends DefaultSqlInjector {
|
||||
*/
|
||||
@Override
|
||||
@Deprecated
|
||||
@SuppressWarnings({"deprecation", "DeprecatedIsStillUsed"})
|
||||
public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
|
||||
if (Objects.nonNull(sqlInjector)) {
|
||||
return methodFilter(sqlInjector.getMethodList(mapperClass, tableInfo));
|
||||
@ -128,7 +127,7 @@ public class MPJSqlInjector extends DefaultSqlInjector {
|
||||
|
||||
private List<AbstractMethod> getJoinMethod() {
|
||||
List<AbstractMethod> list = new ArrayList<>();
|
||||
if (VersionUtils.compare(MybatisPlusVersion.getVersion(), "3.5.0") >= 0) {
|
||||
if (VersionUtils.compare(VersionUtils.getVersion(), "3.5.0") >= 0) {
|
||||
list.add(new DeleteJoin(SqlMethod.DELETE_JOIN.getMethod()));
|
||||
list.add(new UpdateJoin(SqlMethod.UPDATE_JOIN.getMethod()));
|
||||
list.add(new UpdateJoinAndNull(SqlMethod.UPDATE_JOIN_AND_NULL.getMethod()));
|
||||
@ -136,9 +135,6 @@ public class MPJSqlInjector extends DefaultSqlInjector {
|
||||
list.add(new SelectJoinOne(SqlMethod.SELECT_JOIN_ONE.getMethod()));
|
||||
list.add(new SelectJoinList(SqlMethod.SELECT_JOIN_LIST.getMethod()));
|
||||
list.add(new SelectJoinPage(SqlMethod.SELECT_JOIN_PAGE.getMethod()));
|
||||
list.add(new SelectJoinMap(SqlMethod.SELECT_JOIN_MAP.getMethod()));
|
||||
list.add(new SelectJoinMaps(SqlMethod.SELECT_JOIN_MAPS.getMethod()));
|
||||
list.add(new SelectJoinMapsPage(SqlMethod.SELECT_JOIN_MAPS_PAGE.getMethod()));
|
||||
} else {
|
||||
list.add(new DeleteJoin());
|
||||
list.add(new UpdateJoin());
|
||||
@ -147,9 +143,6 @@ public class MPJSqlInjector extends DefaultSqlInjector {
|
||||
list.add(new SelectJoinOne());
|
||||
list.add(new SelectJoinList());
|
||||
list.add(new SelectJoinPage());
|
||||
list.add(new SelectJoinMap());
|
||||
list.add(new SelectJoinMaps());
|
||||
list.add(new SelectJoinMapsPage());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@ -178,7 +171,7 @@ public class MPJSqlInjector extends DefaultSqlInjector {
|
||||
|
||||
@Override
|
||||
public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
|
||||
Class<?> modelClass = getSuperClassGenericType(mapperClass, Mapper.class, 0);
|
||||
Class<?> modelClass = ReflectionKit.getSuperClassGenericType(mapperClass, Mapper.class, 0);
|
||||
super.inspectInject(builderAssistant, mapperClass);
|
||||
MPJTableMapperHelper.init(modelClass, mapperClass);
|
||||
Supplier<Class<?>> supplier = () -> {
|
||||
@ -191,11 +184,6 @@ public class MPJSqlInjector extends DefaultSqlInjector {
|
||||
TableHelper.init(modelClass, supplier.get());
|
||||
}
|
||||
|
||||
public static Class<?> getSuperClassGenericType(final Class<?> clazz, final Class<?> genericIfc, final int index) {
|
||||
Class<?>[] typeArguments = GenericTypeUtils.resolveTypeArguments(ClassUtils.getUserClass(clazz), genericIfc);
|
||||
return null == typeArguments ? null : typeArguments[index];
|
||||
}
|
||||
|
||||
@SuppressWarnings("IfStatementWithIdenticalBranches")
|
||||
protected Class<?> extractModelClassOld(Class<?> mapperClass) {
|
||||
Type[] types = mapperClass.getGenericInterfaces();
|
||||
|
@ -1,16 +1,14 @@
|
||||
package com.github.yulichang.interceptor;
|
||||
|
||||
import com.baomidou.mybatisplus.core.MybatisPlusVersion;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.github.yulichang.adapter.AdapterHelper;
|
||||
import com.github.yulichang.adapter.base.tookit.VersionUtils;
|
||||
import com.github.yulichang.config.ConfigProperties;
|
||||
import com.github.yulichang.interfaces.MPJBaseJoin;
|
||||
import com.github.yulichang.query.MPJQueryWrapper;
|
||||
import com.github.yulichang.toolkit.*;
|
||||
import com.github.yulichang.toolkit.support.FieldCache;
|
||||
import com.github.yulichang.wrapper.interfaces.SelectWrapper;
|
||||
@ -21,12 +19,13 @@ import com.github.yulichang.wrapper.segments.SelectLabel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import org.apache.ibatis.executor.Executor;
|
||||
import org.apache.ibatis.logging.Log;
|
||||
import org.apache.ibatis.logging.LogFactory;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.mapping.ResultFlag;
|
||||
import org.apache.ibatis.mapping.ResultMap;
|
||||
import org.apache.ibatis.mapping.ResultMapping;
|
||||
import org.apache.ibatis.plugin.*;
|
||||
import org.apache.ibatis.session.Configuration;
|
||||
import org.apache.ibatis.session.ResultHandler;
|
||||
import org.apache.ibatis.session.RowBounds;
|
||||
|
||||
@ -36,9 +35,8 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 连表拦截器
|
||||
* <p>
|
||||
* 用于实现动态resultType
|
||||
* 之前的实现方式是mybatis-plus的Interceptor,无法修改args,存在并发问题
|
||||
* 所以将这个拦截器独立出来
|
||||
*
|
||||
* @author yulichang
|
||||
*/
|
||||
@ -46,107 +44,76 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
@Intercepts(@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}))
|
||||
public class MPJInterceptor implements Interceptor {
|
||||
|
||||
private static final boolean v = VersionUtils.compare(MybatisPlusVersion.getVersion(), "3.4.3.1") > 0;
|
||||
private static final boolean v = VersionUtils.compare(VersionUtils.getVersion(), "3.4.3.1") > 0;
|
||||
|
||||
private static final List<ResultMapping> EMPTY_RESULT_MAPPING = new ArrayList<>(0);
|
||||
|
||||
/**
|
||||
* 缓存MappedStatement,不需要每次都去构建MappedStatement
|
||||
*/
|
||||
private static final Map<String, Map<Configuration, MappedStatement>> MS_CACHE = new ConcurrentHashMap<>();
|
||||
|
||||
private static final Map<String, Val> MS_MAPPER_CACHE = new ConcurrentHashMap<>();
|
||||
|
||||
private static final Map<String, Val> RES_MAPPER_CACHE = new ConcurrentHashMap<>();
|
||||
private static final Log log = LogFactory.getLog(MPJInterceptor.class);
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("Java8MapApi")
|
||||
public Object intercept(Invocation invocation) throws Throwable {
|
||||
Object ew = null;
|
||||
Object[] args = invocation.getArgs();
|
||||
if (args[0] instanceof MappedStatement) {
|
||||
MappedStatement ms = (MappedStatement) args[0];
|
||||
if (args[1] instanceof Map) {
|
||||
Map<String, Object> map = (Map<String, Object>) args[1];
|
||||
Object ew = map.containsKey(Constants.WRAPPER) ? map.get(Constants.WRAPPER) : null;
|
||||
ew = map.getOrDefault(Constants.WRAPPER, null);
|
||||
if (Objects.nonNull(ew) && ew instanceof MPJBaseJoin) {
|
||||
if (CollectionUtils.isNotEmpty(map)) {
|
||||
Class<?> rt = null;
|
||||
if (map.containsKey(Constant.CLAZZ)) {
|
||||
rt = (Class<?>) map.get(Constant.CLAZZ);
|
||||
} else {
|
||||
if (CollectionUtils.isNotEmpty(ms.getResultMaps())) {
|
||||
Class<?> entity = MPJTableMapperHelper.getEntity(getMapper(ms.getId(), ms.getResource()));
|
||||
Class<?> type = ms.getResultMaps().get(0).getType();
|
||||
if (Objects.nonNull(entity) && Objects.nonNull(type)
|
||||
&& !MPJReflectionKit.isPrimitiveOrWrapper(type) && entity == type) {
|
||||
rt = type;
|
||||
}
|
||||
Class<?> rt = null;
|
||||
if (map.containsKey(Constant.CLAZZ) && map.get(Constant.CLAZZ) != null) {
|
||||
rt = (Class<?>) map.get(Constant.CLAZZ);
|
||||
} else {
|
||||
if (CollectionUtils.isNotEmpty(ms.getResultMaps())) {
|
||||
Class<?> entity = MPJTableMapperHelper.getEntity(getMapper(ms.getId(), ms.getResource()));
|
||||
Class<?> type = ms.getResultMaps().get(0).getType();
|
||||
if (Objects.nonNull(entity) && Objects.nonNull(type)
|
||||
&& !MPJReflectionKit.isPrimitiveOrWrapper(type) && (entity == type)) {
|
||||
rt = type;
|
||||
}
|
||||
}
|
||||
if (Objects.nonNull(rt)) {
|
||||
args[0] = getMappedStatement(ms, rt, ew);
|
||||
}
|
||||
}
|
||||
if (Objects.nonNull(rt)) {
|
||||
args[0] = getMappedStatement(ms, rt, ew, map);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return invocation.proceed();
|
||||
return fill(ew, invocation.proceed());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取MappedStatement
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public MappedStatement getMappedStatement(MappedStatement ms, Class<?> resultType, Object ew) {
|
||||
String id = ms.getId() + StringPool.DASH + (resultType.getName().replaceAll("\\.", StringPool.DASH));
|
||||
public <E> MappedStatement getMappedStatement(MappedStatement ms, Class<?> resultType, Object ew, Map<String, Object> map) {
|
||||
if (ew instanceof SelectWrapper) {
|
||||
SelectWrapper wrapper = (SelectWrapper) ew;
|
||||
SelectWrapper<E, ?> wrapper = (SelectWrapper<E, ?>) ew;
|
||||
if (wrapper.getEntityClass() == null) {
|
||||
wrapper.setEntityClass(MPJTableMapperHelper.getEntity(getMapper(ms.getId(), ms.getResource())));
|
||||
wrapper.setEntityClass((Class<E>) MPJTableMapperHelper.getEntity(getMapper(ms.getId(), ms.getResource())));
|
||||
}
|
||||
if (wrapper.getSelectColumns().isEmpty() && wrapper.getEntityClass() != null) {
|
||||
wrapper.selectAll(wrapper.getEntityClass());
|
||||
wrapper.selectAll();
|
||||
}
|
||||
//TODO 重构缓存 -> 根据sql缓存
|
||||
//不走缓存
|
||||
}
|
||||
if (ew instanceof MPJQueryWrapper) {
|
||||
MPJQueryWrapper wrapper = (MPJQueryWrapper) ew;
|
||||
if (ConfigProperties.msCache) {
|
||||
return getCache(ms, id + StringPool.UNDERSCORE + removeDot(wrapper.getSqlSelect()), resultType, ew);
|
||||
if (wrapper.isResultMapCollection()) {
|
||||
if (map.values().stream().anyMatch(a -> a instanceof IPage) && !wrapper.isPageByMain()) {
|
||||
// 一对多分页问题警告
|
||||
log.warn("select one to many and page query will result in errors in the total count statistics, please use xml.");
|
||||
}
|
||||
}
|
||||
}
|
||||
return buildMappedStatement(ms, resultType, ew, id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 走缓存
|
||||
*/
|
||||
private MappedStatement getCache(MappedStatement ms, String id, Class<?> resultType, Object ew) {
|
||||
Map<Configuration, MappedStatement> statementMap = MS_CACHE.get(id);
|
||||
if (CollectionUtils.isNotEmpty(statementMap)) {
|
||||
MappedStatement statement = statementMap.get(ms.getConfiguration());
|
||||
if (Objects.nonNull(statement)) {
|
||||
return statement;
|
||||
}
|
||||
}
|
||||
MappedStatement mappedStatement = buildMappedStatement(ms, resultType, ew, id);
|
||||
if (statementMap == null) {
|
||||
statementMap = new ConcurrentHashMap<>();
|
||||
MS_CACHE.put(id, statementMap);
|
||||
}
|
||||
statementMap.put(ms.getConfiguration(), mappedStatement);
|
||||
return mappedStatement;
|
||||
return buildMappedStatement(ms, resultType, ew);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 构建新的MappedStatement
|
||||
*/
|
||||
private MappedStatement buildMappedStatement(MappedStatement ms, Class<?> resultType, Object ew, String id) {
|
||||
MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), id, ms.getSqlSource(), ms.getSqlCommandType())
|
||||
private MappedStatement buildMappedStatement(MappedStatement ms, Class<?> resultType, Object ew) {
|
||||
MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), ms.getId(), ms.getSqlSource(), ms.getSqlCommandType())
|
||||
.resource(ms.getResource())
|
||||
.fetchSize(ms.getFetchSize())
|
||||
.statementType(ms.getStatementType())
|
||||
@ -168,7 +135,6 @@ public class MPJInterceptor implements Interceptor {
|
||||
/**
|
||||
* 构建resultMap TODO 可以用lambda简化代码
|
||||
*/
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
private List<ResultMap> buildResultMap(MappedStatement ms, Class<?> resultType, Object obj) {
|
||||
List<ResultMap> result = new ArrayList<>();
|
||||
TableInfo tableInfo = TableHelper.get(resultType);
|
||||
@ -182,7 +148,7 @@ public class MPJInterceptor implements Interceptor {
|
||||
result.add(getDefaultResultMap(tableInfo, ms, resultType, id));
|
||||
return result;
|
||||
}
|
||||
SelectWrapper wrapper = (SelectWrapper) obj;
|
||||
SelectWrapper<?, ?> wrapper = (SelectWrapper<?, ?>) obj;
|
||||
Map<String, FieldCache> fieldMap = MPJReflectionKit.getFieldMap(resultType);
|
||||
List<Select> columnList = wrapper.getSelectColumns();
|
||||
//移除对多查询列,为了可重复使用wrapper
|
||||
@ -200,7 +166,7 @@ public class MPJInterceptor implements Interceptor {
|
||||
}
|
||||
} else {
|
||||
FieldCache field = fieldMap.get(i.getColumProperty());
|
||||
if (StringUtils.isNotBlank(i.getTagColumn())) {
|
||||
if (StrUtils.isNotBlank(i.getTagColumn())) {
|
||||
columnSet.add(i.getTagColumn());
|
||||
if (Objects.nonNull(field)) {
|
||||
ResultMapping.Builder builder = new ResultMapping.Builder(ms.getConfiguration(), i.getColumProperty(),
|
||||
@ -209,7 +175,7 @@ public class MPJInterceptor implements Interceptor {
|
||||
}
|
||||
} else if (wrapper.isResultMap()) {
|
||||
AdapterHelper.getAdapter().parserColum(wrapper.getAlias(), wrapper.getFrom(), i.getColumn(), col -> {
|
||||
String tagCol = MPJStringUtils.getTargetColumn(col);
|
||||
String tagCol = StrUtils.getTargetColumn(col);
|
||||
FieldCache strField = fieldMap.get(tagCol);
|
||||
columnSet.add(tagCol);
|
||||
if (Objects.nonNull(strField)) {
|
||||
@ -222,9 +188,8 @@ public class MPJInterceptor implements Interceptor {
|
||||
}
|
||||
}
|
||||
if (wrapper.isResultMap()) {
|
||||
for (Object o : wrapper.getResultMapMybatisLabel()) {
|
||||
Label<?> label = (Label<?>) o;
|
||||
resultMappings.add(buildResult(ms, label, columnSet, columnList));
|
||||
for (Label<?> o : wrapper.getResultMapMybatisLabel()) {
|
||||
resultMappings.add(buildResult(ms, o, columnSet, columnList));
|
||||
}
|
||||
}
|
||||
result.add(new ResultMap.Builder(ms.getConfiguration(), id, resultType, resultMappings).build());
|
||||
@ -232,8 +197,13 @@ public class MPJInterceptor implements Interceptor {
|
||||
}
|
||||
|
||||
private ResultMapping selectToResult(Class<?> entity, Select select, Class<?> type, ResultMapping.Builder builder) {
|
||||
if (select.hasTypeHandle() && select.getTableFieldInfo().getPropertyType().isAssignableFrom(type)) {
|
||||
builder.typeHandler(select.getTypeHandle());
|
||||
if (select.hasTypeHandle()) {
|
||||
if (select.getPropertyType().isAssignableFrom(type)) {
|
||||
builder.typeHandler(select.getTypeHandle());
|
||||
} else {
|
||||
throw new ClassCastException(String.format("%s not cast to %s [%s]",
|
||||
select.getPropertyType().getSimpleName(), type.getSimpleName(), entity.getName() + "." + select.getColumProperty()));
|
||||
}
|
||||
}
|
||||
if (select.isPk() && entity == select.getClazz()) {
|
||||
builder.flags(Collections.singletonList(ResultFlag.ID));
|
||||
@ -269,10 +239,10 @@ public class MPJInterceptor implements Interceptor {
|
||||
String index = r.getIndex();
|
||||
if (columnSet.contains(columnName)) {
|
||||
columnName = getColumn(columnSet, columnName, 0);
|
||||
label = new SelectLabel(r.getSelectNormal(), null, mybatisLabel.getOfType(), columnName, StringUtils.isNotBlank(index), index);
|
||||
label = new SelectLabel(r.getSelectNormal(), null, mybatisLabel.getOfType(), columnName, StrUtils.isNotBlank(index), index, r.getBaseColumn());
|
||||
} else {
|
||||
columnSet.add(columnName);
|
||||
label = new SelectLabel(r.getSelectNormal(), null, mybatisLabel.getOfType(), StringUtils.isNotBlank(index), index);
|
||||
label = new SelectLabel(r.getSelectNormal(), null, mybatisLabel.getOfType(), StrUtils.isNotBlank(index), index, r.getBaseColumn());
|
||||
}
|
||||
columnList.add(label);
|
||||
ResultMapping.Builder builder = new ResultMapping.Builder(ms.getConfiguration(), r.getProperty(), columnName, r.getJavaType());
|
||||
@ -389,6 +359,24 @@ public class MPJInterceptor implements Interceptor {
|
||||
}
|
||||
}
|
||||
|
||||
private Object fill(Object ew, Object proceed) {
|
||||
if (Objects.isNull(ew) || !(ew instanceof SelectWrapper<?, ?>) || MPJReflectionKit.isPrimitiveOrWrapper(proceed.getClass())) {
|
||||
return proceed;
|
||||
}
|
||||
if (proceed instanceof List) {
|
||||
List<?> list = (List<?>) proceed;
|
||||
if (!list.isEmpty()) {
|
||||
Object o = list.stream().filter(Objects::nonNull).findFirst().orElse(null);
|
||||
if (o == null || MPJReflectionKit.isPrimitiveOrWrapper(o.getClass())) {
|
||||
return proceed;
|
||||
}
|
||||
}
|
||||
}
|
||||
SelectWrapper<?, ?> selectWrapper = (SelectWrapper<?, ?>) ew;
|
||||
selectWrapper.doFill(proceed);
|
||||
return proceed;
|
||||
}
|
||||
|
||||
private Class<?> getMapper(String id, String resource) {
|
||||
Class<?> clazz = MS_MAPPER_CACHE.computeIfAbsent(id, key -> {
|
||||
try {
|
||||
@ -423,14 +411,6 @@ public class MPJInterceptor implements Interceptor {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
private String removeDot(String str) {
|
||||
if (StringUtils.isBlank(str)) {
|
||||
return str;
|
||||
} else {
|
||||
return str.replaceAll("\\.", StringPool.DASH);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object plugin(Object target) {
|
||||
try {
|
||||
|
@ -0,0 +1,119 @@
|
||||
package com.github.yulichang.interceptor.pagination;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
|
||||
import com.baomidou.mybatisplus.extension.parser.JsqlParserGlobal;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.DialectModel;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.dialects.IDialect;
|
||||
import lombok.Getter;
|
||||
import net.sf.jsqlparser.expression.Alias;
|
||||
import net.sf.jsqlparser.schema.Column;
|
||||
import net.sf.jsqlparser.schema.Table;
|
||||
import net.sf.jsqlparser.statement.select.*;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.mapping.ParameterMapping;
|
||||
import org.apache.ibatis.mapping.SqlSource;
|
||||
import org.apache.ibatis.scripting.xmltags.DynamicSqlSource;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author yulichang
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class DialectWrapper {
|
||||
|
||||
private final IDialect dialect;
|
||||
|
||||
@Getter
|
||||
private final List<ParameterMapping> fullMappings = new ArrayList<>();
|
||||
@Getter
|
||||
private final List<ParameterMapping> pageMappings = new ArrayList<>();
|
||||
|
||||
@Getter
|
||||
private String finallySql;
|
||||
|
||||
public DialectWrapper(IDialect dialect) {
|
||||
this.dialect = dialect;
|
||||
}
|
||||
|
||||
public void buildPaginationSql(String originalSql, List<ParameterMapping> mappings, long offset, long limit,
|
||||
Consumer<DialectModel> consumers, MappedStatement ms, Object parameter) {
|
||||
try {
|
||||
// 解析sql
|
||||
Select select = (Select) JsqlParserGlobal.parse(originalSql);
|
||||
if (select instanceof SetOperationList) {
|
||||
throw ExceptionUtils.mpe("不支持 union 对多分页");
|
||||
}
|
||||
//获取 ? 出现的次数
|
||||
String sourceSql = select.toString();
|
||||
int count = ParseHelper.countChar(sourceSql);
|
||||
String formatSql;
|
||||
if (count == mappings.size()) {
|
||||
formatSql = ParseHelper.decode(sourceSql);
|
||||
} else {
|
||||
SqlSource sqlSource = ms.getSqlSource();
|
||||
if (sqlSource instanceof DynamicSqlSource) {
|
||||
formatSql = ParseHelper.getOriginalSql(parameter, (DynamicSqlSource) sqlSource);
|
||||
} else {
|
||||
throw ExceptionUtils.mpe("unknown type: " + sqlSource.getClass().getName());
|
||||
}
|
||||
}
|
||||
//分页的sql
|
||||
PlainSelect pageSql = (PlainSelect) JsqlParserGlobal.parse(formatSql);
|
||||
|
||||
List<Join> joins = pageSql.getJoins();
|
||||
if (CollectionUtils.isNotEmpty(joins)) {
|
||||
pageSql.setJoins(null);
|
||||
}
|
||||
|
||||
pageSql.setSelectItems(Collections.singletonList(new SelectItem<>(new Column().withColumnName("*"))));
|
||||
|
||||
// 替换回 ? 同步mappings顺序
|
||||
String repSql = pageSql.toString();
|
||||
Map<Integer, ParameterMapping> sortMap = new HashMap<>();
|
||||
repSql = ParseHelper.encode(mappings, count, repSql, sortMap);
|
||||
this.pageMappings.addAll(sortMap.entrySet().stream().sorted(Map.Entry.comparingByKey()).map(Map.Entry::getValue).collect(Collectors.toList()));
|
||||
|
||||
DialectModel dialectModel = dialect.buildPaginationSql(repSql, offset, limit);
|
||||
consumers.accept(dialectModel);
|
||||
|
||||
// 带分页方言的sql
|
||||
String formatDialectSql = ParseHelper.decode(dialectModel.getDialectSql(), i -> "s" + i);
|
||||
|
||||
//完整的sql
|
||||
PlainSelect fullSql = (PlainSelect) JsqlParserGlobal.parse(formatSql);
|
||||
|
||||
PlainSelect finalPlainSelect = new PlainSelect();
|
||||
finalPlainSelect.setSelectItems(fullSql.getSelectItems());
|
||||
finalPlainSelect.setDistinct(fullSql.getDistinct());
|
||||
finalPlainSelect.setFromItem(
|
||||
new Table()
|
||||
.withName("(" + formatDialectSql + ")")
|
||||
.withAlias(new Alias(fullSql.getFromItem().getAlias().getName(), false)));
|
||||
finalPlainSelect.setJoins(fullSql.getJoins());
|
||||
|
||||
String finalSql = finalPlainSelect.toString();
|
||||
Map<Integer, ParameterMapping> finalSortMap = new HashMap<>();
|
||||
//page部分
|
||||
for (int i = 0; i < count; i++) {
|
||||
String repStr = ParseHelper.format.apply("s" + i);
|
||||
int i1 = finalSql.indexOf(repStr);
|
||||
if (i1 != -1) {
|
||||
finalSql = finalSql.replace(repStr, "?");
|
||||
finalSortMap.put(i1, this.pageMappings.get(i));
|
||||
}
|
||||
}
|
||||
//其他部分
|
||||
finalSql = ParseHelper.encode(mappings, count, finalSql, finalSortMap);
|
||||
this.fullMappings.addAll(finalSortMap.entrySet().stream().sorted(Map.Entry.comparingByKey()).map(Map.Entry::getValue).collect(Collectors.toList()));
|
||||
this.finallySql = finalSql;
|
||||
} catch (Exception e) {
|
||||
throw ExceptionUtils.mpe("not support this sql, please use xml. error sql: " + originalSql);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,249 @@
|
||||
package com.github.yulichang.interceptor.pagination;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
||||
import com.baomidou.mybatisplus.core.toolkit.*;
|
||||
import com.baomidou.mybatisplus.extension.parser.JsqlParserGlobal;
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.dialects.IDialect;
|
||||
import com.github.yulichang.wrapper.interfaces.SelectWrapper;
|
||||
import net.sf.jsqlparser.JSQLParserException;
|
||||
import net.sf.jsqlparser.expression.Expression;
|
||||
import net.sf.jsqlparser.schema.Column;
|
||||
import net.sf.jsqlparser.statement.select.*;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.ibatis.cache.CacheKey;
|
||||
import org.apache.ibatis.executor.Executor;
|
||||
import org.apache.ibatis.mapping.BoundSql;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.mapping.ParameterMapping;
|
||||
import org.apache.ibatis.mapping.SqlSource;
|
||||
import org.apache.ibatis.scripting.xmltags.DynamicSqlSource;
|
||||
import org.apache.ibatis.session.Configuration;
|
||||
import org.apache.ibatis.session.ResultHandler;
|
||||
import org.apache.ibatis.session.RowBounds;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author yulichang
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class PageInnerInterceptorWrapper extends PaginationInnerInterceptor {
|
||||
|
||||
private static final Log log = LogFactory.getLog(PageInnerInterceptorWrapper.class);
|
||||
|
||||
private final PaginationInnerInterceptor paginationInnerInterceptor;
|
||||
|
||||
public PageInnerInterceptorWrapper(PaginationInnerInterceptor pagination) {
|
||||
this.paginationInnerInterceptor = pagination;
|
||||
super.setOptimizeJoin(true);
|
||||
super.setDbType(pagination.getDbType());
|
||||
super.setDialect(pagination.getDialect());
|
||||
super.setOverflow(pagination.isOverflow());
|
||||
super.setMaxLimit(pagination.getMaxLimit());
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行count
|
||||
*/
|
||||
@Override
|
||||
public boolean willDoQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
|
||||
if (unusedPage(parameter)) {
|
||||
return paginationInnerInterceptor.willDoQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql);
|
||||
}
|
||||
//没有wrapper 或者 不是对多查询 不做处理
|
||||
SelectWrapper<?, ?> wrapper = findMPJWrapper(parameter).orElseThrow(RuntimeException::new);
|
||||
// copy super
|
||||
IPage<?> page = ParameterUtils.findPage(parameter).orElse(null);
|
||||
if (page == null || page.getSize() < 0 || !page.searchCount() || resultHandler != Executor.NO_RESULT_HANDLER) {
|
||||
return true;
|
||||
}
|
||||
|
||||
BoundSql countSql;
|
||||
MappedStatement countMs = buildCountMappedStatement(ms, page.countId());
|
||||
if (countMs != null) {
|
||||
countSql = countMs.getBoundSql(parameter);
|
||||
} else {
|
||||
countMs = buildAutoCountMappedStatement(ms);
|
||||
ArrayList<ParameterMapping> mappingArrayList = new ArrayList<>(boundSql.getParameterMappings());
|
||||
String countSqlStr = autoCountSql(boundSql.getSql(), mappingArrayList, ms, parameter, wrapper);
|
||||
PluginUtils.MPBoundSql mpBoundSql = PluginUtils.mpBoundSql(boundSql);
|
||||
countSql = new BoundSql(countMs.getConfiguration(), countSqlStr, mappingArrayList, parameter);
|
||||
PluginUtils.setAdditionalParameter(countSql, mpBoundSql.additionalParameters());
|
||||
}
|
||||
|
||||
CacheKey cacheKey = executor.createCacheKey(countMs, parameter, rowBounds, countSql);
|
||||
List<Object> result = executor.query(countMs, parameter, rowBounds, resultHandler, cacheKey, countSql);
|
||||
long total = 0;
|
||||
if (CollectionUtils.isNotEmpty(result)) {
|
||||
// 个别数据库 count 没数据不会返回 0
|
||||
Object o = result.get(0);
|
||||
if (o != null) {
|
||||
total = Long.parseLong(o.toString());
|
||||
}
|
||||
}
|
||||
page.setTotal(total);
|
||||
return continuePage(page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加分页方言
|
||||
*/
|
||||
@Override
|
||||
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
|
||||
if (unusedPage(parameter)) {
|
||||
paginationInnerInterceptor.beforeQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql);
|
||||
return;
|
||||
}
|
||||
// copy super
|
||||
IPage<?> page = ParameterUtils.findPage(parameter).orElse(null);
|
||||
if (null == page) {
|
||||
return;
|
||||
}
|
||||
// 处理 orderBy 拼接
|
||||
boolean addOrdered = false;
|
||||
String buildSql = boundSql.getSql();
|
||||
List<OrderItem> orders = page.orders();
|
||||
if (CollectionUtils.isNotEmpty(orders)) {
|
||||
addOrdered = true;
|
||||
buildSql = this.concatOrderBy(buildSql, orders);
|
||||
}
|
||||
|
||||
// size 小于 0 且不限制返回值则不构造分页sql
|
||||
Long _limit = page.maxLimit() != null ? page.maxLimit() : maxLimit;
|
||||
if (page.getSize() < 0 && null == _limit) {
|
||||
if (addOrdered) {
|
||||
PluginUtils.mpBoundSql(boundSql).sql(buildSql);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
handlerLimit(page, _limit);
|
||||
DialectWrapper dialect = findMPJDialect(executor);
|
||||
|
||||
final Configuration configuration = ms.getConfiguration();
|
||||
PluginUtils.MPBoundSql mpBoundSql = PluginUtils.mpBoundSql(boundSql);
|
||||
Map<String, Object> additionalParameter = mpBoundSql.additionalParameters();
|
||||
dialect.buildPaginationSql(buildSql, boundSql.getParameterMappings(), page.offset(), page.getSize(),
|
||||
c -> c.consumers(dialect.getPageMappings(), configuration, additionalParameter),
|
||||
ms, parameter);
|
||||
mpBoundSql.sql(dialect.getFinallySql());
|
||||
mpBoundSql.parameterMappings(dialect.getFullMappings());
|
||||
}
|
||||
|
||||
private boolean unusedPage(Object parameter) {
|
||||
return !findMPJWrapper(parameter).map(SelectWrapper::isPageByMain).orElse(false);
|
||||
}
|
||||
|
||||
private String autoCountSql(String sql, List<ParameterMapping> mappings, MappedStatement ms, Object parameter, SelectWrapper<?, ?> wrapper) {
|
||||
try {
|
||||
Select select = (Select) JsqlParserGlobal.parse(sql);
|
||||
if (select instanceof SetOperationList) {
|
||||
throw ExceptionUtils.mpe("不支持 union 对多分页");
|
||||
}
|
||||
|
||||
//获取 ? 出现的次数
|
||||
String sourceSql = select.toString();
|
||||
int count = ParseHelper.countChar(sourceSql);
|
||||
|
||||
String formatSql;
|
||||
if (count == mappings.size()) {
|
||||
formatSql = ParseHelper.decode(sourceSql);
|
||||
} else {
|
||||
SqlSource sqlSource = ms.getSqlSource();
|
||||
if (sqlSource instanceof DynamicSqlSource) {
|
||||
formatSql = ParseHelper.getOriginalSql(parameter, (DynamicSqlSource) sqlSource);
|
||||
} else {
|
||||
log.error("unknown type: " + sqlSource.getClass().getName());
|
||||
throw ExceptionUtils.mpe("not support this sql, please use xml. error sql: " + sql);
|
||||
}
|
||||
}
|
||||
|
||||
PlainSelect ps = (PlainSelect) JsqlParserGlobal.parse(formatSql);
|
||||
|
||||
// 优化 order by 在非分组情况下
|
||||
List<OrderByElement> orderBy = ps.getOrderByElements();
|
||||
if (CollectionUtils.isNotEmpty(orderBy)) {
|
||||
boolean canClean = true;
|
||||
for (OrderByElement order : orderBy) {
|
||||
// order by 里带参数,不去除order by
|
||||
Expression expression = order.getExpression();
|
||||
if (!(expression instanceof Column) && expression.toString().contains(StringPool.QUESTION_MARK)) {
|
||||
canClean = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (canClean) {
|
||||
ps.setOrderByElements(null);
|
||||
}
|
||||
}
|
||||
|
||||
List<Join> joins = ps.getJoins();
|
||||
if (CollectionUtils.isNotEmpty(joins)) {
|
||||
ps.setJoins(null);
|
||||
}
|
||||
|
||||
String repSql;
|
||||
Distinct distinct = ps.getDistinct();
|
||||
GroupByElement groupBy = ps.getGroupBy();
|
||||
String mainAlias = Optional.of(ps.getFromItem().getAlias().getName()).orElse("");
|
||||
// 包含 distinct、groupBy 不优化
|
||||
if (null != distinct || null != groupBy) {
|
||||
if (wrapper.getPageInfo().getCountSelectSql() != null) {
|
||||
ps.setSelectItems(Collections.singletonList(new SelectItem<>(new Column().withColumnName(wrapper.getPageInfo().getCountSelectSql()))));
|
||||
} else {
|
||||
ps.getSelectItems().removeIf(s -> {
|
||||
if (s.getExpression() instanceof Column) {
|
||||
Column column = (Column) s.getExpression();
|
||||
return !mainAlias.equals(column.getTable().toString());
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
repSql = lowLevelCountSql(ps.toString());
|
||||
} else {
|
||||
// 优化 SQL
|
||||
ps.setSelectItems(COUNT_SELECT_ITEM);
|
||||
repSql = ps.toString();
|
||||
}
|
||||
|
||||
// 替换回 ? 同步mappings顺序
|
||||
Map<Integer, ParameterMapping> sortMap = new HashMap<>();
|
||||
repSql = ParseHelper.encode(mappings, count, repSql, sortMap);
|
||||
mappings.clear();
|
||||
mappings.addAll(sortMap.entrySet().stream().sorted(Map.Entry.comparingByKey()).map(Map.Entry::getValue).collect(Collectors.toList()));
|
||||
return repSql;
|
||||
} catch (JSQLParserException e) {
|
||||
logger.error("optimize this sql to a count sql has exception, sql:\"" + sql + "\", exception:\n" + e.getCause());
|
||||
} catch (Exception e) {
|
||||
logger.error("optimize this sql to a count sql has error, sql:\"" + sql + "\", exception:\n" + e);
|
||||
}
|
||||
throw ExceptionUtils.mpe("not support this sql, please use xml. error sql: " + sql);
|
||||
}
|
||||
|
||||
private DialectWrapper findMPJDialect(Executor executor) {
|
||||
IDialect dialect = super.findIDialect(executor);
|
||||
return new DialectWrapper(dialect);
|
||||
}
|
||||
|
||||
private static Optional<SelectWrapper<?, ?>> findMPJWrapper(Object parameterObject) {
|
||||
if (parameterObject != null) {
|
||||
if (parameterObject instanceof Map) {
|
||||
Map<?, ?> parameterMap = (Map<?, ?>) parameterObject;
|
||||
for (Map.Entry<?, ?> entry : parameterMap.entrySet()) {
|
||||
if (entry.getValue() != null && entry.getValue() instanceof SelectWrapper) {
|
||||
return Optional.of((SelectWrapper<?, ?>) entry.getValue());
|
||||
}
|
||||
}
|
||||
} else if (parameterObject instanceof SelectWrapper) {
|
||||
return Optional.of((SelectWrapper<?, ?>) parameterObject);
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
package com.github.yulichang.interceptor.pagination;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.Assert;
|
||||
import com.github.yulichang.toolkit.MPJReflectionKit;
|
||||
import org.apache.ibatis.mapping.ParameterMapping;
|
||||
import org.apache.ibatis.mapping.SqlSource;
|
||||
import org.apache.ibatis.scripting.xmltags.DynamicSqlSource;
|
||||
import org.apache.ibatis.scripting.xmltags.SqlNode;
|
||||
import org.apache.ibatis.session.Configuration;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* sql 分页解析工具类
|
||||
*
|
||||
* @author yulichang
|
||||
* @since 1.5.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public final class ParseHelper {
|
||||
|
||||
private static final Map<SqlSource, SqlSourceWrapper> SQL_SOURCE_CACHE = new ConcurrentHashMap<>();
|
||||
|
||||
private static final String prefix = "MPJ_Param_i_";
|
||||
private static final String suffix = "_MPJ_Param_i";
|
||||
private static final char placeholder_char = '?';
|
||||
private static final String placeholder_str = String.valueOf(placeholder_char);
|
||||
|
||||
public static final Function<Object, String> format = index -> prefix + index + suffix;
|
||||
|
||||
public static int countChar(String str) {
|
||||
return countChar(str, placeholder_char);
|
||||
}
|
||||
|
||||
public static int countChar(String str, String tag) {
|
||||
return countChar(str, tag.charAt(0));
|
||||
}
|
||||
|
||||
public static int countChar(String str, char tag) {
|
||||
int count = 0;
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
if (str.charAt(i) == tag) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public static String decode(String str) {
|
||||
return decode(str, null);
|
||||
}
|
||||
|
||||
public static String decode(String str, Function<Object, String> formatter) {
|
||||
return decode(str, formatter, placeholder_char);
|
||||
}
|
||||
|
||||
public static String decode(String str, Function<Object, String> formatter, char placeholder) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int count = 0;
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
if (str.charAt(i) == placeholder) {
|
||||
sb.append(format.apply(formatter == null ? count : formatter.apply(count)));
|
||||
count++;
|
||||
} else {
|
||||
sb.append(str.charAt(i));
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String decode(String str, Function<Object, String> formatter, String placeholder) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String[] split = str.split(placeholder);
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
sb.append(split[i]);
|
||||
if (i < split.length - 1) {
|
||||
sb.append(format.apply(formatter == null ? i : formatter.apply(i)));
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String encode(List<ParameterMapping> mappings, int count, String repSql, Map<Integer, ParameterMapping> sortMap) {
|
||||
return encode(mappings, count, repSql, sortMap, placeholder_str);
|
||||
}
|
||||
|
||||
public static String encode(List<ParameterMapping> mappings, int count, String repSql, Map<Integer, ParameterMapping> sortMap, String placeholder) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
String repStr = ParseHelper.format.apply(i);
|
||||
int i1 = repSql.indexOf(repStr);
|
||||
if (i1 != -1) {
|
||||
repSql = repSql.replace(repStr, placeholder);
|
||||
sortMap.put(i1, mappings.get(i));
|
||||
}
|
||||
}
|
||||
return repSql;
|
||||
}
|
||||
|
||||
public static String getOriginalSql(Object parameter, DynamicSqlSource sqlSource) {
|
||||
Assert.notNull(sqlSource, "sqlSource must not be null");
|
||||
SqlSourceWrapper sqlSourceWrapper = SQL_SOURCE_CACHE.computeIfAbsent(sqlSource, key -> {
|
||||
Configuration configuration = MPJReflectionKit.getFieldValue(sqlSource, "configuration");
|
||||
SqlNode sqlNode = MPJReflectionKit.getFieldValue(sqlSource, "rootSqlNode");
|
||||
return new SqlSourceWrapper(configuration, sqlNode);
|
||||
});
|
||||
return ParseHelper.decode(sqlSourceWrapper.getSql(parameter), null, ParseHelper.format.apply(""));
|
||||
}
|
||||
}
|
@ -0,0 +1,159 @@
|
||||
package com.github.yulichang.interceptor.pagination;
|
||||
|
||||
import org.apache.ibatis.builder.BaseBuilder;
|
||||
import org.apache.ibatis.builder.BuilderException;
|
||||
import org.apache.ibatis.builder.ParameterExpression;
|
||||
import org.apache.ibatis.builder.SqlSourceBuilder;
|
||||
import org.apache.ibatis.mapping.ParameterMapping;
|
||||
import org.apache.ibatis.parsing.GenericTokenParser;
|
||||
import org.apache.ibatis.parsing.TokenHandler;
|
||||
import org.apache.ibatis.reflection.MetaClass;
|
||||
import org.apache.ibatis.reflection.MetaObject;
|
||||
import org.apache.ibatis.scripting.xmltags.DynamicContext;
|
||||
import org.apache.ibatis.scripting.xmltags.SqlNode;
|
||||
import org.apache.ibatis.session.Configuration;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author yulichang
|
||||
* @since 1.5.0
|
||||
*/
|
||||
public class SqlSourceWrapper {
|
||||
|
||||
private static final String PARAMETER_PROPERTIES = "javaType,jdbcType,mode,numericScale,resultMap,typeHandler,jdbcTypeName";
|
||||
|
||||
private final Configuration configuration;
|
||||
private final SqlNode rootSqlNode;
|
||||
|
||||
public SqlSourceWrapper(Configuration configuration, SqlNode rootSqlNode) {
|
||||
this.configuration = configuration;
|
||||
this.rootSqlNode = rootSqlNode;
|
||||
}
|
||||
|
||||
|
||||
public String getSql(Object parameterObject) {
|
||||
DynamicContext context = new DynamicContext(configuration, parameterObject);
|
||||
rootSqlNode.apply(context);
|
||||
Class<?> parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
|
||||
return parse(context.getSql(), parameterType, context.getBindings());
|
||||
}
|
||||
|
||||
public String parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {
|
||||
ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType,
|
||||
additionalParameters) {
|
||||
@Override
|
||||
public String handleToken(String content) {
|
||||
super.handleToken(content);
|
||||
return ParseHelper.format.apply("");
|
||||
}
|
||||
};
|
||||
GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
|
||||
String sql;
|
||||
if (configuration.isShrinkWhitespacesInSql()) {
|
||||
sql = parser.parse(SqlSourceBuilder.removeExtraWhitespaces(originalSql));
|
||||
} else {
|
||||
sql = parser.parse(originalSql);
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* copy {@link org.apache.ibatis.builder.SqlSourceBuilder.ParameterMappingTokenHandler}
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
private static class ParameterMappingTokenHandler extends BaseBuilder implements TokenHandler {
|
||||
|
||||
private final List<ParameterMapping> parameterMappings = new ArrayList<>();
|
||||
private final Class<?> parameterType;
|
||||
private final MetaObject metaParameters;
|
||||
|
||||
public ParameterMappingTokenHandler(Configuration configuration, Class<?> parameterType,
|
||||
Map<String, Object> additionalParameters) {
|
||||
super(configuration);
|
||||
this.parameterType = parameterType;
|
||||
this.metaParameters = configuration.newMetaObject(additionalParameters);
|
||||
}
|
||||
|
||||
public List<ParameterMapping> getParameterMappings() {
|
||||
return parameterMappings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handleToken(String content) {
|
||||
parameterMappings.add(buildParameterMapping(content));
|
||||
return "?";
|
||||
}
|
||||
|
||||
private ParameterMapping buildParameterMapping(String content) {
|
||||
Map<String, String> propertiesMap = parseParameterMapping(content);
|
||||
String property = propertiesMap.get("property");
|
||||
Class<?> propertyType;
|
||||
if (metaParameters.hasGetter(property)) { // issue #448 get type from additional params
|
||||
propertyType = metaParameters.getGetterType(property);
|
||||
} else if (typeHandlerRegistry.hasTypeHandler(parameterType)) {
|
||||
propertyType = parameterType;
|
||||
} else if (JdbcType.CURSOR.name().equals(propertiesMap.get("jdbcType"))) {
|
||||
propertyType = java.sql.ResultSet.class;
|
||||
} else if (property == null || Map.class.isAssignableFrom(parameterType)) {
|
||||
propertyType = Object.class;
|
||||
} else {
|
||||
MetaClass metaClass = MetaClass.forClass(parameterType, configuration.getReflectorFactory());
|
||||
if (metaClass.hasGetter(property)) {
|
||||
propertyType = metaClass.getGetterType(property);
|
||||
} else {
|
||||
propertyType = Object.class;
|
||||
}
|
||||
}
|
||||
ParameterMapping.Builder builder = new ParameterMapping.Builder(configuration, property, propertyType);
|
||||
Class<?> javaType = propertyType;
|
||||
String typeHandlerAlias = null;
|
||||
for (Map.Entry<String, String> entry : propertiesMap.entrySet()) {
|
||||
String name = entry.getKey();
|
||||
String value = entry.getValue();
|
||||
if ("javaType".equals(name)) {
|
||||
javaType = resolveClass(value);
|
||||
builder.javaType(javaType);
|
||||
} else if ("jdbcType".equals(name)) {
|
||||
builder.jdbcType(resolveJdbcType(value));
|
||||
} else if ("mode".equals(name)) {
|
||||
builder.mode(resolveParameterMode(value));
|
||||
} else if ("numericScale".equals(name)) {
|
||||
builder.numericScale(Integer.valueOf(value));
|
||||
} else if ("resultMap".equals(name)) {
|
||||
builder.resultMapId(value);
|
||||
} else if ("typeHandler".equals(name)) {
|
||||
typeHandlerAlias = value;
|
||||
} else if ("jdbcTypeName".equals(name)) {
|
||||
builder.jdbcTypeName(value);
|
||||
} else if ("property".equals(name)) {
|
||||
// Do Nothing
|
||||
} else if ("expression".equals(name)) {
|
||||
throw new BuilderException("Expression based parameters are not supported yet");
|
||||
} else {
|
||||
throw new BuilderException("An invalid property '" + name + "' was found in mapping #{" + content
|
||||
+ "}. Valid properties are " + PARAMETER_PROPERTIES);
|
||||
}
|
||||
}
|
||||
if (typeHandlerAlias != null) {
|
||||
builder.typeHandler(resolveTypeHandler(javaType, typeHandlerAlias));
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private Map<String, String> parseParameterMapping(String content) {
|
||||
try {
|
||||
return new ParameterExpression(content);
|
||||
} catch (BuilderException ex) {
|
||||
throw ex;
|
||||
} catch (Exception ex) {
|
||||
throw new BuilderException("Parsing error was found in mapping #{" + content
|
||||
+ "}. Check syntax #{property|(expression), var1=value1, var2=value2, ...} ", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
package com.github.yulichang.kt.segments;
|
||||
|
||||
import com.github.yulichang.toolkit.KtUtils;
|
||||
import com.github.yulichang.wrapper.segments.SelectFunc;
|
||||
import kotlin.reflect.KProperty;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 自定义函数列
|
||||
*
|
||||
* @author yulichang
|
||||
* @since 1.4.6
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class FuncArgs {
|
||||
|
||||
public SelectFunc.Arg[] accept(KProperty<?>... kProperty) {
|
||||
return Arrays.stream(kProperty).map(i -> new SelectFunc.Arg(KtUtils.ref(i), i.getName(), false, null, i)).toArray(SelectFunc.Arg[]::new);
|
||||
}
|
||||
|
||||
}
|
@ -6,18 +6,18 @@ import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
|
||||
import com.github.yulichang.adapter.AdapterHelper;
|
||||
import com.github.yulichang.adapter.base.metadata.OrderFieldInfo;
|
||||
import com.github.yulichang.annotation.DynamicTableName;
|
||||
import com.github.yulichang.config.ConfigProperties;
|
||||
import com.github.yulichang.toolkit.StrUtils;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
@ -103,7 +103,7 @@ public interface MPJBaseMethod extends Constants {
|
||||
return true;
|
||||
})
|
||||
.map(i -> getSqlWhere(i, newPrefix)).filter(Objects::nonNull).collect(joining(NEWLINE));
|
||||
if (!withId || StringUtils.isBlank(tableInfo.getKeyProperty())) {
|
||||
if (!withId || StrUtils.isBlank(tableInfo.getKeyProperty())) {
|
||||
return filedSqlScript;
|
||||
}
|
||||
String newKeyProperty = newPrefix + tableInfo.getKeyProperty();
|
||||
@ -123,11 +123,15 @@ public interface MPJBaseMethod extends Constants {
|
||||
tableFieldInfo.getWhereStrategy());
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
default String convertIf(TableFieldInfo tableFieldInfo, final String sqlScript, final String property, final FieldStrategy fieldStrategy) {
|
||||
if (fieldStrategy == FieldStrategy.NEVER) {
|
||||
return null;
|
||||
}
|
||||
if (AdapterHelper.getAdapter().mpjIsPrimitive(tableFieldInfo) || fieldStrategy == FieldStrategy.IGNORED) {
|
||||
FieldStrategy strategy = Optional.ofNullable(fieldStrategy).orElse(FieldStrategy.DEFAULT);
|
||||
if (AdapterHelper.getAdapter().mpjIsPrimitive(tableFieldInfo)
|
||||
|| strategy.name().equalsIgnoreCase("ALWAYS")
|
||||
|| strategy.name().equalsIgnoreCase("IGNORED")) {
|
||||
return sqlScript;
|
||||
}
|
||||
if (fieldStrategy == FieldStrategy.NOT_EMPTY && tableFieldInfo.isCharSequence()) {
|
||||
@ -138,7 +142,7 @@ public interface MPJBaseMethod extends Constants {
|
||||
}
|
||||
|
||||
default String convertIfProperty(String prefix, String property) {
|
||||
return StringUtils.isNotBlank(prefix) ? prefix.substring(0, prefix.length() - 1) + "['" + property + "']" : property;
|
||||
return StrUtils.isNotBlank(prefix) ? prefix.substring(0, prefix.length() - 1) + "['" + property + "']" : property;
|
||||
}
|
||||
|
||||
|
||||
@ -183,10 +187,6 @@ public interface MPJBaseMethod extends Constants {
|
||||
* 获取表名
|
||||
*/
|
||||
default String mpjTableName(TableInfo tableInfo) {
|
||||
DynamicTableName dynamicTableName = tableInfo.getEntityType().getAnnotation(DynamicTableName.class);
|
||||
if (Objects.isNull(dynamicTableName)) {
|
||||
return tableInfo.getTableName();
|
||||
}
|
||||
String tableName = tableInfo.getTableName(), encode;
|
||||
try {
|
||||
encode = URLEncoder.encode(tableName, "UTF-8");
|
||||
@ -253,7 +253,7 @@ public interface MPJBaseMethod extends Constants {
|
||||
final String newPrefix = prefix == null ? EMPTY : prefix;
|
||||
// 默认: column=
|
||||
String sqlSet = "${ew.alias}." + tableFieldInfo.getColumn() + EQUALS;
|
||||
if (StringUtils.isNotBlank(tableFieldInfo.getUpdate())) {
|
||||
if (StrUtils.isNotBlank(tableFieldInfo.getUpdate())) {
|
||||
sqlSet += String.format(tableFieldInfo.getUpdate(), tableFieldInfo.getColumn());
|
||||
} else {
|
||||
sqlSet += SqlScriptUtils.safeParam(newPrefix + tableFieldInfo.getEl());
|
||||
@ -262,7 +262,7 @@ public interface MPJBaseMethod extends Constants {
|
||||
if (ignoreIf) {
|
||||
return sqlSet;
|
||||
}
|
||||
if (tableFieldInfo.isWithUpdateFill()) {
|
||||
if (AdapterHelper.getAdapter().isWithUpdateFill(tableFieldInfo)) {
|
||||
// 不进行 if 包裹
|
||||
return sqlSet;
|
||||
}
|
||||
@ -270,7 +270,7 @@ public interface MPJBaseMethod extends Constants {
|
||||
}
|
||||
|
||||
default String mpjConvertIfProperty(String prefix, String property) {
|
||||
return StringUtils.isNotBlank(prefix) ? prefix.substring(0, prefix.length() - 1) + "['" + property + "']" : property;
|
||||
return StrUtils.isNotBlank(prefix) ? prefix.substring(0, prefix.length() - 1) + "['" + property + "']" : property;
|
||||
}
|
||||
|
||||
default String mpjConvertIf(TableFieldInfo tableFieldInfo, final String sqlScript, final String property, final FieldStrategy fieldStrategy) {
|
||||
|
@ -1,11 +0,0 @@
|
||||
package com.github.yulichang.method;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* result type 标识类
|
||||
*
|
||||
* @author yulichang
|
||||
*/
|
||||
public class MPJResultType implements Serializable {
|
||||
}
|
@ -32,7 +32,7 @@ public class SelectJoinList extends MPJAbstractMethod {
|
||||
String sql = String.format(sqlMethod.getSql(), sqlFirst(), sqlDistinct(), sqlSelectColumns(tableInfo, true),
|
||||
mpjTableName(tableInfo), sqlAlias(), sqlFrom(), sqlWhereEntityWrapper(true, tableInfo), mpjSqlOrderBy(tableInfo), sqlComment());
|
||||
SqlSource sqlSource = languageDriver.createSqlSource(configuration, removeExtraWhitespaces(sql), modelClass);
|
||||
return this.addSelectMappedStatementForOther(mapperClass, sqlMethod.getMethod(), sqlSource, MPJResultType.class);
|
||||
return this.addSelectMappedStatementForOther(mapperClass, sqlMethod.getMethod(), sqlSource, tableInfo.getEntityType());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,44 +0,0 @@
|
||||
package com.github.yulichang.method;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
|
||||
import com.github.yulichang.interfaces.MPJBaseJoin;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.mapping.SqlSource;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* copy {@link com.baomidou.mybatisplus.core.injector.methods.SelectMaps}
|
||||
*
|
||||
* @author yulichang
|
||||
*/
|
||||
public class SelectJoinMap extends MPJAbstractMethod {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public SelectJoinMap() {
|
||||
super();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public SelectJoinMap(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
|
||||
SqlMethod sqlMethod = SqlMethod.SELECT_JOIN_MAP;
|
||||
String sql = String.format(sqlMethod.getSql(), sqlFirst(), sqlDistinct(), sqlSelectColumns(tableInfo, true),
|
||||
mpjTableName(tableInfo), sqlAlias(), sqlFrom(), sqlWhereEntityWrapper(true, tableInfo), sqlComment());
|
||||
SqlSource sqlSource = languageDriver.createSqlSource(configuration, removeExtraWhitespaces(sql), modelClass);
|
||||
return this.addSelectMappedStatementForOther(mapperClass, sqlMethod.getMethod(), sqlSource, Map.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String sqlComment() {
|
||||
return super.sqlComment() + StringPool.NEWLINE + SqlScriptUtils.convertIf("${ew.unionSql}", String.format("%s != null and (%s instanceof %s)",
|
||||
Constants.WRAPPER, Constants.WRAPPER, MPJBaseJoin.class.getName()), true);
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package com.github.yulichang.method;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
|
||||
import com.github.yulichang.interfaces.MPJBaseJoin;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.mapping.SqlSource;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* copy {@link com.baomidou.mybatisplus.core.injector.methods.SelectMaps}
|
||||
*
|
||||
* @author yulichang
|
||||
*/
|
||||
public class SelectJoinMaps extends MPJAbstractMethod {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public SelectJoinMaps() {
|
||||
super();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public SelectJoinMaps(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
|
||||
SqlMethod sqlMethod = SqlMethod.SELECT_JOIN_MAPS;
|
||||
String sql = String.format(sqlMethod.getSql(), sqlFirst(), sqlDistinct(), sqlSelectColumns(tableInfo, true),
|
||||
mpjTableName(tableInfo), sqlAlias(), sqlFrom(), sqlWhereEntityWrapper(true, tableInfo), mpjSqlOrderBy(tableInfo), sqlComment());
|
||||
SqlSource sqlSource = languageDriver.createSqlSource(configuration, removeExtraWhitespaces(sql), modelClass);
|
||||
return this.addSelectMappedStatementForOther(mapperClass, sqlMethod.getMethod(), sqlSource, Map.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String sqlComment() {
|
||||
return super.sqlComment() + StringPool.NEWLINE + SqlScriptUtils.convertIf("${ew.unionSql}", String.format("%s != null and (%s instanceof %s)",
|
||||
Constants.WRAPPER, Constants.WRAPPER, MPJBaseJoin.class.getName()), true);
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package com.github.yulichang.method;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.TableInfo;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import com.baomidou.mybatisplus.core.toolkit.StringPool;
|
||||
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
|
||||
import com.github.yulichang.interfaces.MPJBaseJoin;
|
||||
import org.apache.ibatis.mapping.MappedStatement;
|
||||
import org.apache.ibatis.mapping.SqlSource;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* copy {@link com.baomidou.mybatisplus.core.injector.methods.SelectMaps}
|
||||
*
|
||||
* @author yulichang
|
||||
*/
|
||||
public class SelectJoinMapsPage extends MPJAbstractMethod {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public SelectJoinMapsPage() {
|
||||
super();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public SelectJoinMapsPage(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("DuplicatedCode")
|
||||
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
|
||||
SqlMethod sqlMethod = SqlMethod.SELECT_JOIN_MAPS_PAGE;
|
||||
String sql = String.format(sqlMethod.getSql(), sqlFirst(), sqlDistinct(), sqlSelectColumns(tableInfo, true),
|
||||
mpjTableName(tableInfo), sqlAlias(), sqlFrom(), sqlWhereEntityWrapper(true, tableInfo), mpjSqlOrderBy(tableInfo), sqlComment());
|
||||
SqlSource sqlSource = languageDriver.createSqlSource(configuration, removeExtraWhitespaces(sql), modelClass);
|
||||
return this.addSelectMappedStatementForOther(mapperClass, sqlMethod.getMethod(), sqlSource, Map.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String sqlComment() {
|
||||
return super.sqlComment() + StringPool.NEWLINE + SqlScriptUtils.convertIf("${ew.unionSql}", String.format("%s != null and (%s instanceof %s)",
|
||||
Constants.WRAPPER, Constants.WRAPPER, MPJBaseJoin.class.getName()), true);
|
||||
}
|
||||
}
|
@ -31,7 +31,7 @@ public class SelectJoinOne extends MPJAbstractMethod {
|
||||
String sql = String.format(sqlMethod.getSql(), sqlFirst(), sqlDistinct(), sqlSelectColumns(tableInfo, true),
|
||||
mpjTableName(tableInfo), sqlAlias(), sqlFrom(), sqlWhereEntityWrapper(true, tableInfo), sqlComment());
|
||||
SqlSource sqlSource = languageDriver.createSqlSource(configuration, removeExtraWhitespaces(sql), modelClass);
|
||||
return this.addSelectMappedStatementForOther(mapperClass, sqlMethod.getMethod(), sqlSource, MPJResultType.class);
|
||||
return this.addSelectMappedStatementForOther(mapperClass, sqlMethod.getMethod(), sqlSource, tableInfo.getEntityType());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -32,7 +32,7 @@ public class SelectJoinPage extends MPJAbstractMethod {
|
||||
String sql = String.format(sqlMethod.getSql(), sqlFirst(), sqlDistinct(), sqlSelectColumns(tableInfo, true),
|
||||
mpjTableName(tableInfo), sqlAlias(), sqlFrom(), sqlWhereEntityWrapper(true, tableInfo), mpjSqlOrderBy(tableInfo), sqlComment());
|
||||
SqlSource sqlSource = languageDriver.createSqlSource(configuration, removeExtraWhitespaces(sql), modelClass);
|
||||
return this.addSelectMappedStatementForOther(mapperClass, sqlMethod.getMethod(), sqlSource, MPJResultType.class);
|
||||
return this.addSelectMappedStatementForOther(mapperClass, sqlMethod.getMethod(), sqlSource, tableInfo.getEntityType());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
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