├── .all-contributorsrc
├── .github
├── CODEOWNERS
├── dependabot.yml
├── project.yml
└── workflows
│ ├── build.yml
│ ├── pre-release.yml
│ ├── quarkus-snapshot.yaml
│ ├── release-perform.yml
│ └── release-prepare.yml
├── .gitignore
├── LICENSE.txt
├── README.md
├── mybatis-plus
├── deployment
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ └── java
│ │ └── io
│ │ └── quarkiverse
│ │ └── mybatis
│ │ └── plus
│ │ └── deployment
│ │ └── MyBatisPlusProcessor.java
├── docs
│ ├── antora.yml
│ ├── modules
│ │ └── ROOT
│ │ │ ├── nav.adoc
│ │ │ └── pages
│ │ │ ├── includes
│ │ │ ├── attributes.adoc
│ │ │ └── quarkus-mybatis-plus.adoc
│ │ │ └── index.adoc
│ ├── pom.xml
│ └── templates
│ │ └── includes
│ │ └── attributes.adoc
├── integration-tests
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── io
│ │ │ │ └── quarkiverse
│ │ │ │ └── it
│ │ │ │ └── mybatis
│ │ │ │ └── plus
│ │ │ │ ├── CustomBaseMapper.java
│ │ │ │ ├── EasySqlInjector.java
│ │ │ │ ├── MyBatisPlusResource.java
│ │ │ │ ├── MyObjectHandler.java
│ │ │ │ ├── MybatisPlusServiceResource.java
│ │ │ │ ├── User.java
│ │ │ │ ├── UserMapper.java
│ │ │ │ ├── UserServiceImpl.java
│ │ │ │ └── UuidTypeHandler.java
│ │ └── resources
│ │ │ ├── application.properties
│ │ │ └── insert.sql
│ │ └── test
│ │ └── java
│ │ └── io
│ │ └── quarkiverse
│ │ └── it
│ │ └── mybatis
│ │ └── plus
│ │ ├── MyBatisPlusIT.java
│ │ ├── MyBatisPlusTest.java
│ │ ├── MybatisPlusServiceTest.java
│ │ └── TestResources.java
├── pom.xml
└── runtime
│ ├── pom.xml
│ └── src
│ └── main
│ ├── java
│ ├── com
│ │ └── baomidou
│ │ │ └── mybatisplus
│ │ │ └── core
│ │ │ ├── metadata
│ │ │ └── MapperProxyMetadata.java
│ │ │ └── toolkit
│ │ │ └── reflect
│ │ │ └── SpringReflectionHelper.java
│ └── io
│ │ └── quarkiverse
│ │ └── mybatis
│ │ └── plus
│ │ ├── MyBatisPlusConfig.java
│ │ ├── QuarkusCompatibleSet.java
│ │ ├── extension
│ │ ├── repository
│ │ │ └── CrudRepository.java
│ │ └── service
│ │ │ ├── IService.java
│ │ │ └── impl
│ │ │ └── ServiceImpl.java
│ │ └── runtime
│ │ ├── GenericTypeResolverImpl.java
│ │ ├── MyBatisPlusConfigurationFactory.java
│ │ ├── MyBatisPlusRecorder.java
│ │ └── MyBatisPlusXMLConfigDelegateBuilder.java
│ └── resources
│ └── META-INF
│ ├── quarkus-extension.yaml
│ └── services
│ └── com.baomidou.mybatisplus.core.spi.CompatibleSet
├── mybatis
├── README.md
├── deployment
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ └── java
│ │ │ └── io
│ │ │ └── quarkiverse
│ │ │ └── mybatis
│ │ │ └── deployment
│ │ │ ├── ConfigurationCustomizerBuildItem.java
│ │ │ ├── ConfigurationFactoryBuildItem.java
│ │ │ ├── MyBatisMappedJdbcTypeBuildItem.java
│ │ │ ├── MyBatisMappedTypeBuildItem.java
│ │ │ ├── MyBatisMapperBuildItem.java
│ │ │ ├── MyBatisProcessor.java
│ │ │ ├── MyBatisXmlConfigBuildItem.java
│ │ │ ├── SqlSessionFactoryBuildItem.java
│ │ │ ├── SqlSessionFactoryBuilderBuildItem.java
│ │ │ ├── SqlSessionManagerBuildItem.java
│ │ │ └── XMLConfigBuilderBuildItem.java
│ │ └── test
│ │ ├── java
│ │ └── io
│ │ │ └── quarkiverse
│ │ │ └── mybatis
│ │ │ └── test
│ │ │ ├── MyBatisTest.java
│ │ │ ├── TestResources.java
│ │ │ ├── User.java
│ │ │ ├── UserMapper.java
│ │ │ ├── UuidJdbcTypeHandler.java
│ │ │ └── UuidTypeHandler.java
│ │ └── resources
│ │ ├── application.properties
│ │ └── insert.sql
├── docs
│ ├── antora.yml
│ ├── modules
│ │ └── ROOT
│ │ │ ├── nav.adoc
│ │ │ └── pages
│ │ │ ├── includes
│ │ │ ├── attributes.adoc
│ │ │ └── quarkus-mybatis.adoc
│ │ │ └── index.adoc
│ ├── pom.xml
│ └── templates
│ │ └── includes
│ │ └── attributes.adoc
├── integration-tests
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── io
│ │ │ │ └── quarkiverse
│ │ │ │ └── it
│ │ │ │ └── mybatis
│ │ │ │ ├── Book.java
│ │ │ │ ├── BookMapper.java
│ │ │ │ ├── DerbyUserMapper.java
│ │ │ │ ├── MyBatisResource.java
│ │ │ │ ├── PageConfigurationFactory.java
│ │ │ │ ├── SqlProviderAdapter.java
│ │ │ │ ├── User.java
│ │ │ │ ├── UserMapper.java
│ │ │ │ ├── UuidJdbcTypeHandler.java
│ │ │ │ └── UuidTypeHandler.java
│ │ └── resources
│ │ │ ├── application-xml.properties
│ │ │ ├── application.properties
│ │ │ ├── insert-derby.sql
│ │ │ ├── insert.sql
│ │ │ ├── mapper
│ │ │ ├── DerbyUserMapper.xml
│ │ │ └── UserMapper.xml
│ │ │ ├── mybatis-config.xml
│ │ │ └── otherMapper
│ │ │ └── BookMapper.xml
│ │ └── test
│ │ └── java
│ │ └── io
│ │ └── quarkiverse
│ │ └── it
│ │ └── mybatis
│ │ ├── BaseMyBatisTestCase.java
│ │ ├── MultipleDataSourcesTest.java
│ │ ├── MyBatisIT.java
│ │ ├── MyBatisTest.java
│ │ ├── MyBatisXmlConfigIT.java
│ │ ├── MyBatisXmlConfigTest.java
│ │ ├── TestResources.java
│ │ └── XmlConfigProfile.java
├── pom.xml
└── runtime
│ ├── pom.xml
│ └── src
│ └── main
│ ├── java
│ └── io
│ │ └── quarkiverse
│ │ └── mybatis
│ │ └── runtime
│ │ ├── ConfigurationFactory.java
│ │ ├── MyBatisConfigurationFactory.java
│ │ ├── MyBatisRecorder.java
│ │ ├── MyBatisXMLConfigDelegateBuilder.java
│ │ ├── QuarkusDataSourceFactory.java
│ │ ├── QuarkusDatabaseIdProvider.java
│ │ ├── TransactionalSqlSession.java
│ │ ├── XMLConfigDelegateBuilder.java
│ │ ├── config
│ │ ├── MyBatisDataSourceRuntimeConfig.java
│ │ └── MyBatisRuntimeConfig.java
│ │ └── meta
│ │ └── MapperDataSource.java
│ └── resources
│ └── META-INF
│ └── quarkus-extension.yaml
└── pom.xml
/.all-contributorsrc:
--------------------------------------------------------------------------------
1 | {
2 | "files": [
3 | "README.md"
4 | ],
5 | "imageSize": 100,
6 | "commit": false,
7 | "contributors": [
8 | {
9 | "login": "zhfeng",
10 | "name": "Amos Feng",
11 | "avatar_url": "https://avatars2.githubusercontent.com/u/1246139?v=4",
12 | "profile": "https://github.com/zhfeng",
13 | "contributions": [
14 | "code",
15 | "maintenance"
16 | ]
17 | },
18 | {
19 | "login": "362228416",
20 | "name": "Chao",
21 | "avatar_url": "https://avatars.githubusercontent.com/u/5248797?v=4",
22 | "profile": "https://github.com/362228416",
23 | "contributions": [
24 | "code"
25 | ]
26 | },
27 | {
28 | "login": "AndLvovSky",
29 | "name": "Viktor Ilvovskyi",
30 | "avatar_url": "https://avatars.githubusercontent.com/u/46902956?v=4",
31 | "profile": "https://github.com/AndLvovSky",
32 | "contributions": [
33 | "code"
34 | ]
35 | },
36 | {
37 | "login": "igor-dmitriev",
38 | "name": "Igor Dmitriev",
39 | "avatar_url": "https://avatars.githubusercontent.com/u/4592740?v=4",
40 | "profile": "https://github.com/igor-dmitriev",
41 | "contributions": [
42 | "code"
43 | ]
44 | },
45 | {
46 | "login": "kbrumer",
47 | "name": "Ken Brumer",
48 | "avatar_url": "https://avatars.githubusercontent.com/u/244873?v=4",
49 | "profile": "https://github.com/kbrumer",
50 | "contributions": [
51 | "code"
52 | ]
53 | },
54 | {
55 | "login": "zohar-soul",
56 | "name": "Zohar",
57 | "avatar_url": "https://avatars.githubusercontent.com/u/13990539?v=4",
58 | "profile": "https://github.com/zohar-soul",
59 | "contributions": [
60 | "maintenance"
61 | ]
62 | },
63 | {
64 | "login": "y-bowen",
65 | "name": "bowen",
66 | "avatar_url": "https://avatars.githubusercontent.com/u/20274912?v=4",
67 | "profile": "https://github.com/y-bowen",
68 | "contributions": [
69 | "code"
70 | ]
71 | },
72 | {
73 | "login": "kwseeker",
74 | "name": "Arvin Lee",
75 | "avatar_url": "https://avatars.githubusercontent.com/u/7456558?v=4",
76 | "profile": "https://github.com/kwseeker",
77 | "contributions": [
78 | "code"
79 | ]
80 | },
81 | {
82 | "login": "renemarkvard-sosint",
83 | "name": "renemarkvard-sosint",
84 | "avatar_url": "https://avatars.githubusercontent.com/u/194897321?v=4",
85 | "profile": "https://github.com/renemarkvard-sosint",
86 | "contributions": [
87 | "code"
88 | ]
89 | },
90 | {
91 | "login": "Fengxq2014",
92 | "name": "DefNed",
93 | "avatar_url": "https://avatars.githubusercontent.com/u/8519834?v=4",
94 | "profile": "https://blog.dfned.com/",
95 | "contributions": [
96 | "code"
97 | ]
98 | }
99 | ],
100 | "contributorsPerLine": 7,
101 | "projectName": "quarkus-mybatis",
102 | "projectOwner": "quarkiverse",
103 | "repoType": "github",
104 | "repoHost": "https://github.com",
105 | "skipCi": true,
106 | "commitType": "docs",
107 | "commitConvention": "angular"
108 | }
109 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # Lines starting with '#' are comments.
2 | # Each line is a file pattern followed by one or more owners.
3 |
4 | # More details are here: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
5 |
6 | # The '*' pattern is global owners.
7 |
8 | # Order is important. The last matching pattern has the most precedence.
9 | # The folders are ordered as follows:
10 |
11 | # In each subsection folders are ordered first by depth, then alphabetically.
12 | # This should make it easy to add new rules without breaking existing ones.
13 |
14 | * @quarkiverse/quarkiverse-mybatis
15 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "github-actions"
9 | directory: "/"
10 | schedule:
11 | interval: "daily"
12 | - package-ecosystem: "maven"
13 | directory: "/"
14 | schedule:
15 | interval: "daily"
16 | ignore:
17 | - dependency-name: "org.apache.maven.plugins:maven-compiler-plugin"
18 | - dependency-name: "org.springframework:spring-aop"
19 | - package-ecosystem: "maven"
20 | directory: "/"
21 | schedule:
22 | interval: "daily"
23 | target-branch: "1.x"
24 | ignore:
25 | - dependency-name: "org.apache.maven.plugins:maven-compiler-plugin"
26 | - dependency-name: "org.springframework:spring-aop"
27 | - dependency-name: "io.quarkus:*"
28 | versions: "[3.0,)"
29 |
--------------------------------------------------------------------------------
/.github/project.yml:
--------------------------------------------------------------------------------
1 | name: Quarkiverse MyBatis Extension
2 | release:
3 | current-version: 2.4.0
4 | next-version: 999-SNAPSHOT
5 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on:
4 | push:
5 | branches:
6 | - "master"
7 | - "1.x"
8 | paths-ignore:
9 | - '.gitignore'
10 | - 'CODEOWNERS'
11 | - 'LICENSE'
12 | - 'README*'
13 | pull_request:
14 |
15 | jobs:
16 | build:
17 |
18 | runs-on: ubuntu-latest
19 |
20 | steps:
21 | - uses: actions/checkout@v4
22 |
23 | - name: Set up JDK 17
24 | uses: actions/setup-java@v4
25 | with:
26 | distribution: temurin
27 | java-version: 17
28 |
29 | - name: Cache local Maven repository
30 | uses: actions/cache@v4
31 | with:
32 | path: ~/.m2/repository
33 | key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
34 | restore-keys: |
35 | ${{ runner.os }}-maven-
36 |
37 | - name: Build with Maven
38 | run: mvn -B formatter:validate verify --file pom.xml
39 |
40 | - name: Run Native Check (if maven build success)
41 | if: success()
42 | run: mvn -Dnative -Dquarkus.native.container-build=true -B verify --file pom.xml
43 |
44 |
--------------------------------------------------------------------------------
/.github/workflows/pre-release.yml:
--------------------------------------------------------------------------------
1 | name: Quarkiverse Pre Release
2 |
3 | on:
4 | pull_request:
5 | paths:
6 | - '.github/project.yml'
7 |
8 | concurrency:
9 | group: ${{ github.workflow }}-${{ github.ref }}
10 | cancel-in-progress: true
11 |
12 | jobs:
13 | pre-release:
14 | name: Pre-Release
15 | uses: quarkiverse/.github/.github/workflows/pre-release.yml@main
16 | secrets: inherit
17 |
--------------------------------------------------------------------------------
/.github/workflows/quarkus-snapshot.yaml:
--------------------------------------------------------------------------------
1 | name: "Quarkus ecosystem CI"
2 | on:
3 | watch:
4 | types: [started]
5 |
6 | # For this CI to work, ECOSYSTEM_CI_TOKEN needs to contain a GitHub with rights to close the Quarkus issue that the user/bot has opened,
7 | # while 'ECOSYSTEM_CI_REPO_PATH' needs to be set to the corresponding path in the 'quarkusio/quarkus-ecosystem-ci' repository
8 |
9 | env:
10 | ECOSYSTEM_CI_REPO: quarkusio/quarkus-ecosystem-ci
11 | ECOSYSTEM_CI_REPO_FILE: context.yaml
12 | JAVA_VERSION: 17
13 |
14 | #########################
15 | # Repo specific setting #
16 | #########################
17 |
18 | ECOSYSTEM_CI_REPO_PATH: quarkiverse-mybatis
19 |
20 | jobs:
21 | build:
22 | name: "Build against latest Quarkus snapshot"
23 | runs-on: ubuntu-latest
24 | if: github.actor == 'quarkusbot' || github.actor == 'quarkiversebot'
25 |
26 | steps:
27 | - name: Set up Java
28 | uses: actions/setup-java@v4
29 | with:
30 | distribution: temurin
31 | java-version: ${{ env.JAVA_VERSION }}
32 |
33 | - name: Checkout repo
34 | uses: actions/checkout@v4
35 | with:
36 | path: current-repo
37 |
38 | - name: Checkout Ecosystem
39 | uses: actions/checkout@v4
40 | with:
41 | repository: ${{ env.ECOSYSTEM_CI_REPO }}
42 | path: ecosystem-ci
43 |
44 | - name: Setup and Run Tests
45 | run: ./ecosystem-ci/setup-and-test
46 | env:
47 | ECOSYSTEM_CI_TOKEN: ${{ secrets.ECOSYSTEM_CI_TOKEN }}
48 |
--------------------------------------------------------------------------------
/.github/workflows/release-perform.yml:
--------------------------------------------------------------------------------
1 | name: Quarkiverse Perform Release
2 | run-name: Perform ${{github.event.inputs.tag || github.ref_name}} Release
3 | on:
4 | push:
5 | tags:
6 | - '*'
7 | workflow_dispatch:
8 | inputs:
9 | tag:
10 | description: 'Tag to release'
11 | required: true
12 |
13 | permissions:
14 | attestations: write
15 | id-token: write
16 | contents: read
17 |
18 | concurrency:
19 | group: ${{ github.workflow }}-${{ github.ref }}
20 | cancel-in-progress: true
21 |
22 | jobs:
23 | perform-release:
24 | name: Perform Release
25 | uses: quarkiverse/.github/.github/workflows/perform-release.yml@main
26 | secrets: inherit
27 | with:
28 | version: ${{github.event.inputs.tag || github.ref_name}}
29 |
--------------------------------------------------------------------------------
/.github/workflows/release-prepare.yml:
--------------------------------------------------------------------------------
1 | name: Quarkiverse Prepare Release
2 |
3 | on:
4 | pull_request:
5 | types: [ closed ]
6 | paths:
7 | - '.github/project.yml'
8 |
9 | concurrency:
10 | group: ${{ github.workflow }}-${{ github.ref }}
11 | cancel-in-progress: true
12 |
13 | jobs:
14 | prepare-release:
15 | name: Prepare Release
16 | if: ${{ github.event.pull_request.merged == true}}
17 | uses: quarkiverse/.github/.github/workflows/prepare-release.yml@main
18 | secrets: inherit
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.nar
17 | *.ear
18 | *.zip
19 | *.tar.gz
20 | *.rar
21 |
22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
23 | hs_err_pid*
24 |
25 | # Eclipse
26 | .project
27 | .classpath
28 | .settings/
29 | bin/
30 |
31 | # IntelliJ
32 | .idea
33 | *.ipr
34 | *.iml
35 | *.iws
36 |
37 | # NetBeans
38 | nb-configuration.xml
39 |
40 | # Visual Studio Code
41 | .vscode
42 | .factorypath
43 |
44 | # OSX
45 | .DS_Store
46 |
47 | # Vim
48 | *.swp
49 | *.swo
50 |
51 | # patch
52 | *.orig
53 | *.rej
54 |
55 | # Gradle
56 | .gradle/
57 | build/
58 |
59 | # Maven
60 | target/
61 | pom.xml.tag
62 | pom.xml.releaseBackup
63 | pom.xml.versionsBackup
64 | release.properties
65 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Quarkus MyBatis Extension
2 | [](https://github.com/quarkiverse/quarkus-mybatis/actions?query=workflow%3ABuild)
3 | [](http://www.apache.org/licenses/LICENSE-2.0)
4 | [](https://search.maven.org/search?q=g:io.quarkiverse.mybatis%20AND%20a:quarkus-mybatis-parent)
5 |
6 | [](#contributors-)
7 |
8 |
9 | MyBatis is a first class persistence framework with support for custom SQL, stored procedures and advanced mappings. This extension provides the developers ease of configuration and native support. Add the following dependency in your pom.xml to get started,
10 |
11 | ```xml
12 |
13 | io.quarkiverse.mybatis
14 | quarkus-mybatis
15 |
16 | ```
17 |
18 | And then your can use the ```@Mapper``` in your application just like
19 |
20 | ```java
21 | @Mapper
22 | public interface UserMapper {
23 |
24 | @Select("SELECT * FROM USERS WHERE id = #{id}")
25 | User getUser(Integer id);
26 |
27 | @Insert("INSERT INTO USERS (id, name) VALUES (#{id}, #{name})")
28 | Integer createUser(@Param("id") Integer id, @Param("name") String name);
29 |
30 | @Delete("DELETE FROM USERS WHERE id = #{id}")
31 | Integer removeUser(Integer id);
32 | }
33 | ```
34 |
35 | For more information and quickstart, you can check the complete [documentation](https://quarkiverse.github.io/quarkiverse-docs/quarkus-mybatis/dev/index.html).
36 |
37 | ## Contributors ✨
38 |
39 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
40 |
41 |
42 |
43 |
44 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
69 |
--------------------------------------------------------------------------------
/mybatis-plus/deployment/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | io.quarkiverse.mybatis
5 | quarkus-mybatis-plus-parent
6 | 999-SNAPSHOT
7 | ../
8 |
9 | 4.0.0
10 |
11 | quarkus-mybatis-plus-deployment
12 | Quarkus - Mybatis Plus - Deployment
13 |
14 |
15 |
16 | io.quarkiverse.mybatis
17 | quarkus-mybatis-deployment
18 | ${project.version}
19 |
20 |
21 | io.quarkiverse.mybatis
22 | quarkus-mybatis-plus
23 | ${project.version}
24 |
25 |
26 |
27 | io.quarkus
28 | quarkus-junit5-internal
29 | test
30 |
31 |
32 | io.quarkus
33 | quarkus-test-h2
34 | test
35 |
36 |
37 | io.quarkus
38 | quarkus-test-derby
39 | test
40 |
41 |
42 | io.quarkus
43 | quarkus-jdbc-h2-deployment
44 | test
45 |
46 |
47 | io.quarkus
48 | quarkus-jdbc-derby
49 | test
50 |
51 |
52 |
53 |
54 |
55 |
56 | maven-compiler-plugin
57 |
58 |
59 |
60 | io.quarkus
61 | quarkus-extension-processor
62 | ${quarkus.version}
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/mybatis-plus/deployment/src/main/java/io/quarkiverse/mybatis/plus/deployment/MyBatisPlusProcessor.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.plus.deployment;
2 |
3 | import java.util.List;
4 |
5 | import org.apache.ibatis.executor.Executor;
6 | import org.apache.ibatis.executor.statement.StatementHandler;
7 | import org.apache.ibatis.mapping.BoundSql;
8 | import org.jboss.jandex.AnnotationInstance;
9 | import org.jboss.jandex.AnnotationTarget;
10 | import org.jboss.jandex.ClassInfo;
11 | import org.jboss.jandex.DotName;
12 | import org.jboss.logging.Logger;
13 |
14 | import com.baomidou.mybatisplus.annotation.TableName;
15 | import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder;
16 | import com.baomidou.mybatisplus.core.conditions.Wrapper;
17 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
18 |
19 | import io.quarkiverse.mybatis.deployment.ConfigurationCustomizerBuildItem;
20 | import io.quarkiverse.mybatis.deployment.ConfigurationFactoryBuildItem;
21 | import io.quarkiverse.mybatis.deployment.SqlSessionFactoryBuildItem;
22 | import io.quarkiverse.mybatis.deployment.SqlSessionFactoryBuilderBuildItem;
23 | import io.quarkiverse.mybatis.deployment.XMLConfigBuilderBuildItem;
24 | import io.quarkiverse.mybatis.plus.MyBatisPlusConfig;
25 | import io.quarkiverse.mybatis.plus.runtime.MyBatisPlusConfigurationFactory;
26 | import io.quarkiverse.mybatis.plus.runtime.MyBatisPlusRecorder;
27 | import io.quarkiverse.mybatis.plus.runtime.MyBatisPlusXMLConfigDelegateBuilder;
28 | import io.quarkiverse.mybatis.runtime.meta.MapperDataSource;
29 | import io.quarkus.deployment.annotations.BuildProducer;
30 | import io.quarkus.deployment.annotations.BuildStep;
31 | import io.quarkus.deployment.annotations.ExecutionTime;
32 | import io.quarkus.deployment.annotations.Record;
33 | import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
34 | import io.quarkus.deployment.builditem.FeatureBuildItem;
35 | import io.quarkus.deployment.builditem.IndexDependencyBuildItem;
36 | import io.quarkus.deployment.builditem.nativeimage.NativeImageProxyDefinitionBuildItem;
37 | import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
38 |
39 | public class MyBatisPlusProcessor {
40 |
41 | private static final String FEATURE = "mybatis-plus";
42 | private static final DotName MYBATIS_PLUS_MAPPER = DotName.createSimple(BaseMapper.class.getName());
43 | private static final DotName MYBATIS_MAPPER_DATA_SOURCE = DotName.createSimple(MapperDataSource.class.getName());
44 | private static final DotName MYBATIS_PLUS_WRAPPER = DotName.createSimple(Wrapper.class.getName());
45 | private static final Logger LOG = Logger.getLogger(MyBatisPlusProcessor.class);
46 |
47 | @BuildStep
48 | FeatureBuildItem feature() {
49 | return new FeatureBuildItem(FEATURE);
50 | }
51 |
52 | @BuildStep
53 | ConfigurationFactoryBuildItem createConfigurationFactory() {
54 | return new ConfigurationFactoryBuildItem(new MyBatisPlusConfigurationFactory());
55 | }
56 |
57 | @BuildStep
58 | SqlSessionFactoryBuilderBuildItem createSqlSessionFactoryBuilder() {
59 | return new SqlSessionFactoryBuilderBuildItem(new MybatisSqlSessionFactoryBuilder());
60 | }
61 |
62 | @BuildStep
63 | XMLConfigBuilderBuildItem createXMLConfigBuilder() throws Exception {
64 | return new XMLConfigBuilderBuildItem(new MyBatisPlusXMLConfigDelegateBuilder());
65 | }
66 |
67 | @BuildStep
68 | void addDependencies(BuildProducer indexDependency) {
69 | indexDependency.produce(new IndexDependencyBuildItem("com.baomidou", "mybatis-plus-core"));
70 | }
71 |
72 | @BuildStep
73 | void reflectiveClasses(BuildProducer reflectiveClass,
74 | BuildProducer proxyClass,
75 | CombinedIndexBuildItem indexBuildItem) {
76 | reflectiveClass.produce(ReflectiveClassBuildItem.builder(StatementHandler.class,
77 | Executor.class).methods(true).fields(false).build());
78 | reflectiveClass.produce(ReflectiveClassBuildItem.builder(BoundSql.class).methods(true).fields(true).build());
79 | proxyClass.produce(new NativeImageProxyDefinitionBuildItem(StatementHandler.class.getName()));
80 | proxyClass.produce(new NativeImageProxyDefinitionBuildItem(Executor.class.getName()));
81 |
82 | for (AnnotationInstance i : indexBuildItem.getIndex().getAnnotations(DotName.createSimple(TableName.class.getName()))) {
83 | if (i.target().kind() == AnnotationTarget.Kind.CLASS) {
84 | DotName dotName = i.target().asClass().name();
85 | reflectiveClass
86 | .produce(ReflectiveClassBuildItem.builder(dotName.toString()).methods(true).fields(false).build());
87 | }
88 | }
89 | reflectiveClass
90 | .produce(ReflectiveClassBuildItem.builder(MYBATIS_PLUS_WRAPPER.toString()).methods(true).fields(true).build());
91 | for (ClassInfo classInfo : indexBuildItem.getIndex().getAllKnownSubclasses(MYBATIS_PLUS_WRAPPER)) {
92 | reflectiveClass
93 | .produce(ReflectiveClassBuildItem.builder(classInfo.name().toString()).methods(true).fields(true).build());
94 | }
95 | }
96 |
97 | @BuildStep
98 | @Record(ExecutionTime.STATIC_INIT)
99 | void init(List sqlSessionFactoryBuildItems,
100 | MyBatisPlusConfig config,
101 | MyBatisPlusRecorder recorder) {
102 | sqlSessionFactoryBuildItems
103 | .forEach(sqlSessionFactory -> recorder.initSqlSession(sqlSessionFactory.getSqlSessionFactory(), config));
104 | }
105 |
106 | @BuildStep
107 | @Record(ExecutionTime.STATIC_INIT)
108 | ConfigurationCustomizerBuildItem addCustomSqlInjector(MyBatisPlusRecorder recorder, MyBatisPlusConfig config) {
109 | return new ConfigurationCustomizerBuildItem(recorder.addCustomSqlInjector(config));
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/mybatis-plus/docs/antora.yml:
--------------------------------------------------------------------------------
1 | name: quarkus-mybatis-plus
2 | title: Quarkus MyBatis Plus
3 | version: dev
4 | nav:
5 | - modules/ROOT/nav.adoc
6 |
--------------------------------------------------------------------------------
/mybatis-plus/docs/modules/ROOT/nav.adoc:
--------------------------------------------------------------------------------
1 | * xref:index.adoc[Introduction]
2 |
--------------------------------------------------------------------------------
/mybatis-plus/docs/modules/ROOT/pages/includes/attributes.adoc:
--------------------------------------------------------------------------------
1 | :quarkus-version: 3.18.2
2 | :quarkus-mybatis-plus-version: 2.2.4
3 |
4 | :mybatis-root-url: https://mybatis.org/mybatis-3/
5 | :mybatis-plus-root-url: https://mybatis.plus/
6 |
--------------------------------------------------------------------------------
/mybatis-plus/docs/modules/ROOT/pages/includes/quarkus-mybatis-plus.adoc:
--------------------------------------------------------------------------------
1 |
2 | :summaryTableId: quarkus-mybatis-plus
3 | [.configuration-legend]
4 | icon:lock[title=Fixed at build time] Configuration property fixed at build time - All other configuration properties are overridable at runtime
5 | [.configuration-reference.searchable, cols="80,.^10,.^10"]
6 | |===
7 |
8 | h|[[quarkus-mybatis-plus_configuration]]link:#quarkus-mybatis-plus_configuration[Configuration property]
9 |
10 | h|Type
11 | h|Default
12 |
13 | a|icon:lock[title=Fixed at build time] [[quarkus-mybatis-plus_quarkus.mybatis-plus.pagination.enabled]]`link:#quarkus-mybatis-plus_quarkus.mybatis-plus.pagination.enabled[quarkus.mybatis-plus.pagination.enabled]`
14 |
15 | [.description]
16 | --
17 | MyBatis-plus PaginationInnerInterceptor
18 |
19 | ifdef::add-copy-button-to-env-var[]
20 | Environment variable: env_var_with_copy_button:+++QUARKUS_MYBATIS_PLUS_PAGINATION_ENABLED+++[]
21 | endif::add-copy-button-to-env-var[]
22 | ifndef::add-copy-button-to-env-var[]
23 | Environment variable: `+++QUARKUS_MYBATIS_PLUS_PAGINATION_ENABLED+++`
24 | endif::add-copy-button-to-env-var[]
25 | --|boolean
26 | |`true`
27 |
28 |
29 | a|icon:lock[title=Fixed at build time] [[quarkus-mybatis-plus_quarkus.mybatis-plus.sql-injector]]`link:#quarkus-mybatis-plus_quarkus.mybatis-plus.sql-injector[quarkus.mybatis-plus.sql-injector]`
30 |
31 | [.description]
32 | --
33 | MyBatis-plus SqlInjector Class
34 |
35 | ifdef::add-copy-button-to-env-var[]
36 | Environment variable: env_var_with_copy_button:+++QUARKUS_MYBATIS_PLUS_SQL_INJECTOR+++[]
37 | endif::add-copy-button-to-env-var[]
38 | ifndef::add-copy-button-to-env-var[]
39 | Environment variable: `+++QUARKUS_MYBATIS_PLUS_SQL_INJECTOR+++`
40 | endif::add-copy-button-to-env-var[]
41 | --|string
42 | |
43 |
44 |
45 | a|icon:lock[title=Fixed at build time] [[quarkus-mybatis-plus_quarkus.mybatis-plus.meta-object-handler]]`link:#quarkus-mybatis-plus_quarkus.mybatis-plus.meta-object-handler[quarkus.mybatis-plus.meta-object-handler]`
46 |
47 | [.description]
48 | --
49 | MyBatis-plus globalConfig metaObjectHandler
50 |
51 | ifdef::add-copy-button-to-env-var[]
52 | Environment variable: env_var_with_copy_button:+++QUARKUS_MYBATIS_PLUS_META_OBJECT_HANDLER+++[]
53 | endif::add-copy-button-to-env-var[]
54 | ifndef::add-copy-button-to-env-var[]
55 | Environment variable: `+++QUARKUS_MYBATIS_PLUS_META_OBJECT_HANDLER+++`
56 | endif::add-copy-button-to-env-var[]
57 | --|string
58 | |
59 |
60 | |===
--------------------------------------------------------------------------------
/mybatis-plus/docs/modules/ROOT/pages/index.adoc:
--------------------------------------------------------------------------------
1 | include::./includes/attributes.adoc[]
2 | = Quarkus - Using MyBatis Plus
3 |
4 | :extension-status: preview
5 |
6 | This guide demonstrates how your Quarkus application can use link:{mybatis-plus-root-url}[MyBatis Plus] to provide some efficient, useful, out-of-the-box features for link:{mybatis-root-url}[MyBatis], use it can effectively save your development time.
7 |
--------------------------------------------------------------------------------
/mybatis-plus/docs/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | io.quarkiverse.mybatis
6 | quarkus-mybatis-plus-parent
7 | 999-SNAPSHOT
8 | ../pom.xml
9 |
10 |
11 | quarkus-mybatis-plus-docs
12 | Quarkus - MyBatis Plus - Documentation
13 |
14 |
15 | 3.0.0
16 | 3.2.0
17 | 1.1.3
18 |
19 |
20 |
21 |
22 |
23 | io.quarkiverse.mybatis
24 | quarkus-mybatis-plus-deployment
25 | ${project.version}
26 |
27 |
28 |
29 |
30 |
31 |
32 | it.ozimov
33 | yaml-properties-maven-plugin
34 | ${yaml-properties-maven-plugin.version}
35 |
36 |
37 | initialize
38 |
39 | read-project-properties
40 |
41 |
42 |
43 | ${project.basedir}/../../.github/project.yml
44 |
45 |
46 |
47 |
48 |
49 |
50 | maven-resources-plugin
51 |
52 |
53 | copy-resources
54 | generate-resources
55 |
56 | copy-resources
57 |
58 |
59 | ${project.basedir}/modules/ROOT/pages/includes/
60 |
61 |
62 | ${project.basedir}/../target/asciidoc/generated/config/
63 | quarkus-mybatis-plus.adoc
64 | false
65 |
66 |
67 | ${project.basedir}/templates/includes
68 | attributes.adoc
69 | true
70 |
71 |
72 |
73 |
74 |
75 | copy-images
76 | generate-resources
77 |
78 | copy-resources
79 |
80 |
81 | ${project.build.directory}/generated-docs/_images/
82 |
83 |
84 | ${project.basedir}/modules/ROOT/assets/images/
85 | false
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | org.asciidoctor
94 | asciidoctor-maven-plugin
95 | ${asciidoctor-maven-plugin.version}
96 |
97 | ${skipDocs}
98 | true
99 |
100 |
101 | WARN
102 |
103 |
104 | ${project.basedir}/modules/ROOT/pages/
105 | true
106 |
107 | font
108 |
109 | ./_images/
110 | true
111 |
112 |
113 | -
114 | true
115 |
116 | true
117 |
118 |
119 |
120 |
121 | output-html
122 | prepare-package
123 |
124 | process-asciidoc
125 |
126 |
127 | ${skipDocs}
128 | html5
129 |
130 | coderay
131 |
132 | true
133 | true
134 |
135 |
136 |
137 |
138 |
139 |
140 | org.asciidoctor
141 | asciidoctorj
142 | ${asciidoctorj.version}
143 |
144 |
145 |
146 |
147 |
148 |
149 |
--------------------------------------------------------------------------------
/mybatis-plus/docs/templates/includes/attributes.adoc:
--------------------------------------------------------------------------------
1 | :quarkus-version: ${quarkus.version}
2 | :quarkus-mybatis-plus-version: ${release.current-version}
3 |
4 | :mybatis-root-url: https://mybatis.org/mybatis-3/
5 | :mybatis-plus-root-url: https://mybatis.plus/
6 |
--------------------------------------------------------------------------------
/mybatis-plus/integration-tests/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | io.quarkiverse.mybatis
5 | quarkus-mybatis-plus-parent
6 | 999-SNAPSHOT
7 | ../
8 |
9 | 4.0.0
10 |
11 | quarkus-mybatis-plus-integration-tests
12 | Quarkus - MyBatis Plus - Integration Tests
13 | The mybatis integration tests module
14 |
15 |
16 | 17
17 | 17
18 | true
19 | true
20 | ${skipTests}
21 | ${skipTests}
22 |
23 |
24 |
25 |
26 | io.quarkus
27 | quarkus-resteasy
28 |
29 |
30 | io.quarkus
31 | quarkus-resteasy-jackson
32 |
33 |
34 | io.quarkiverse.mybatis
35 | quarkus-mybatis-plus
36 | ${project.version}
37 |
38 |
39 | io.quarkus
40 | quarkus-jdbc-h2
41 |
42 |
43 | io.quarkus
44 | quarkus-jdbc-derby
45 |
46 |
47 |
48 |
49 | io.quarkus
50 | quarkus-junit5
51 | test
52 |
53 |
54 | io.rest-assured
55 | rest-assured
56 | test
57 |
58 |
59 | io.quarkus
60 | quarkus-test-h2
61 | test
62 |
63 | io.quarkus
64 | quarkus-test-derby
65 | test
66 |
67 |
68 |
69 |
70 |
71 |
72 | io.quarkus
73 | quarkus-maven-plugin
74 | ${quarkus.version}
75 |
76 | true
77 | ${quarkus.build.skip}
78 |
79 |
80 |
81 |
82 | build
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 | native-image
93 |
94 |
95 | native
96 |
97 |
98 |
99 | native
100 |
101 |
102 |
103 |
104 | org.apache.maven.plugins
105 | maven-failsafe-plugin
106 |
107 |
108 |
109 | integration-test
110 | verify
111 |
112 |
113 |
114 | ${project.build.directory}/${project.build.finalName}-runner
115 | org.jboss.logmanager.LogManager
116 | ${maven.home}
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
--------------------------------------------------------------------------------
/mybatis-plus/integration-tests/src/main/java/io/quarkiverse/it/mybatis/plus/CustomBaseMapper.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis.plus;
2 |
3 | import java.util.Collection;
4 |
5 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
6 |
7 | public interface CustomBaseMapper extends BaseMapper {
8 |
9 | Integer insertBatchSomeColumn(Collection entityList);
10 | }
11 |
--------------------------------------------------------------------------------
/mybatis-plus/integration-tests/src/main/java/io/quarkiverse/it/mybatis/plus/EasySqlInjector.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis.plus;
2 |
3 | import java.util.List;
4 |
5 | import com.baomidou.mybatisplus.core.injector.AbstractMethod;
6 | import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
7 | import com.baomidou.mybatisplus.core.metadata.TableInfo;
8 | import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
9 |
10 | public class EasySqlInjector extends DefaultSqlInjector {
11 | @Override
12 | public List getMethodList(Class> mapperClass, TableInfo tableInfo) {
13 | List methodList = super.getMethodList(mapperClass, tableInfo);
14 | methodList.add(new InsertBatchSomeColumn());
15 | return methodList;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/mybatis-plus/integration-tests/src/main/java/io/quarkiverse/it/mybatis/plus/MyBatisPlusResource.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis.plus;
2 |
3 | import java.util.List;
4 | import java.util.UUID;
5 |
6 | import jakarta.inject.Inject;
7 | import jakarta.ws.rs.*;
8 | import jakarta.ws.rs.core.MediaType;
9 |
10 | import org.slf4j.Logger;
11 | import org.slf4j.LoggerFactory;
12 |
13 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
14 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
15 |
16 | @Path("/mybatis/plus")
17 | public class MyBatisPlusResource {
18 | private Logger logger = LoggerFactory.getLogger(MyBatisPlusResource.class);
19 | @Inject
20 | UserMapper userMapper;
21 |
22 | @Path("/user/{id}")
23 | @GET
24 | @Produces(MediaType.APPLICATION_JSON)
25 | public User getUser(@PathParam("id") Integer id) {
26 | return userMapper.selectById(id);
27 | }
28 |
29 | @Path("/user")
30 | @POST
31 | @Produces(MediaType.TEXT_PLAIN)
32 | @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
33 | public Integer createUser(@FormParam("id") Integer id, @FormParam("name") String name,
34 | @FormParam("externalId") UUID externalId) {
35 | User user = new User();
36 | user.setId(id);
37 | user.setName(name);
38 | user.setExternalId(externalId);
39 | return userMapper.insert(user);
40 | }
41 |
42 | @Path("/users")
43 | @POST
44 | @Consumes(MediaType.APPLICATION_JSON)
45 | public Integer createUsers(List users) {
46 | return userMapper.insertBatchSomeColumn(users);
47 | }
48 |
49 | @Path("/user/{id}")
50 | @DELETE
51 | @Produces(MediaType.TEXT_PLAIN)
52 | public Integer removeUser(@PathParam("id") Integer id) {
53 | return userMapper.deleteById(id);
54 | }
55 |
56 | @Path("/user/count/h2")
57 | @GET
58 | @Produces(MediaType.APPLICATION_JSON)
59 | public Long getUserCount() {
60 | return userMapper.selectCount(new QueryWrapper<>(new User()));
61 | }
62 |
63 | @Path("/user/page/{page}/{pageSize}")
64 | @GET
65 | public Page list(@PathParam("page") Integer page, @PathParam("pageSize") Integer pageSize) {
66 | return userMapper.selectPage(new Page(page, pageSize), null);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/mybatis-plus/integration-tests/src/main/java/io/quarkiverse/it/mybatis/plus/MyObjectHandler.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis.plus;
2 |
3 | import java.util.Date;
4 |
5 | import org.apache.ibatis.reflection.MetaObject;
6 | import org.jboss.logging.Logger;
7 |
8 | import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
9 |
10 | public class MyObjectHandler implements MetaObjectHandler {
11 | private static final Logger LOG = Logger.getLogger(MyObjectHandler.class);
12 |
13 | @Override
14 | public void insertFill(final MetaObject metaObject) {
15 | this.setFieldValByName("createTime", new Date().getTime(), metaObject);
16 | this.setFieldValByName("updateTime", new Date().getTime(), metaObject);
17 | }
18 |
19 | @Override
20 | public void updateFill(final MetaObject metaObject) {
21 | this.setFieldValByName("updateTime", new Date().getTime(), metaObject);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/mybatis-plus/integration-tests/src/main/java/io/quarkiverse/it/mybatis/plus/MybatisPlusServiceResource.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis.plus;
2 |
3 | import java.util.List;
4 | import java.util.UUID;
5 |
6 | import jakarta.inject.Inject;
7 | import jakarta.ws.rs.*;
8 | import jakarta.ws.rs.core.MediaType;
9 |
10 | import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
11 |
12 | @Path("/mybatis/plus/service")
13 | public class MybatisPlusServiceResource {
14 | @Inject
15 | UserServiceImpl userService;
16 |
17 | @Path("/user/{id}")
18 | @GET
19 | @Produces(MediaType.APPLICATION_JSON)
20 | public User getUser(@PathParam("id") Integer id) {
21 | return userService.getById(id);
22 | }
23 |
24 | @Path("/user")
25 | @POST
26 | @Produces(MediaType.TEXT_PLAIN)
27 | @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
28 | public Boolean createUser(@FormParam("id") Integer id, @FormParam("name") String name,
29 | @FormParam("externalId") UUID externalId) {
30 | User user = new User();
31 | user.setId(id);
32 | user.setName(name);
33 | user.setExternalId(externalId);
34 | return userService.save(user);
35 | }
36 |
37 | @Path("/users")
38 | @POST
39 | @Consumes(MediaType.APPLICATION_JSON)
40 | public Boolean createUsers(List users) {
41 | return userService.saveBatch(users);
42 | }
43 |
44 | @Path("/user/{id}")
45 | @DELETE
46 | @Produces(MediaType.TEXT_PLAIN)
47 | public Boolean removeUser(@PathParam("id") Integer id) {
48 | return userService.removeById(id);
49 | }
50 |
51 | @Path("/user/count/h2")
52 | @GET
53 | @Produces(MediaType.APPLICATION_JSON)
54 | public Long getUserCount() {
55 | return userService.count();
56 | }
57 |
58 | @Path("/user/page/{page}/{pageSize}")
59 | @GET
60 | public Page list(@PathParam("page") Integer page, @PathParam("pageSize") Integer pageSize) {
61 | return userService.page(new Page(page, pageSize), null);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/mybatis-plus/integration-tests/src/main/java/io/quarkiverse/it/mybatis/plus/User.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis.plus;
2 |
3 | import java.io.Serializable;
4 | import java.util.UUID;
5 |
6 | import com.baomidou.mybatisplus.annotation.FieldFill;
7 | import com.baomidou.mybatisplus.annotation.TableField;
8 | import com.baomidou.mybatisplus.annotation.TableName;
9 | import com.fasterxml.jackson.annotation.JsonInclude;
10 |
11 | @TableName("USERS")
12 | @JsonInclude(JsonInclude.Include.NON_NULL)
13 | public class User implements Serializable {
14 | private Integer id;
15 | private String name;
16 | private UUID externalId;
17 | @TableField(value = "create_time", fill = FieldFill.INSERT)
18 | private Long createTime;
19 | @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
20 | private Long updateTime;
21 |
22 | public Integer getId() {
23 | return id;
24 | }
25 |
26 | public void setId(Integer id) {
27 | this.id = id;
28 | }
29 |
30 | public String getName() {
31 | return name;
32 | }
33 |
34 | public void setName(String name) {
35 | this.name = name;
36 | }
37 |
38 | public UUID getExternalId() {
39 | return externalId;
40 | }
41 |
42 | public void setExternalId(UUID externalId) {
43 | this.externalId = externalId;
44 | }
45 |
46 | public Long getCreateTime() {
47 | return createTime;
48 | }
49 |
50 | public void setCreateTime(final Long createTime) {
51 | this.createTime = createTime;
52 | }
53 |
54 | public Long getUpdateTime() {
55 | return updateTime;
56 | }
57 |
58 | public void setUpdateTime(final Long updateTime) {
59 | this.updateTime = updateTime;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/mybatis-plus/integration-tests/src/main/java/io/quarkiverse/it/mybatis/plus/UserMapper.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis.plus;
2 |
3 | import org.apache.ibatis.annotations.Mapper;
4 |
5 | @Mapper
6 | public interface UserMapper extends CustomBaseMapper {
7 | }
8 |
--------------------------------------------------------------------------------
/mybatis-plus/integration-tests/src/main/java/io/quarkiverse/it/mybatis/plus/UserServiceImpl.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis.plus;
2 |
3 | import jakarta.enterprise.context.ApplicationScoped;
4 |
5 | import io.quarkiverse.mybatis.plus.extension.service.impl.ServiceImpl;
6 |
7 | @ApplicationScoped
8 | public class UserServiceImpl extends ServiceImpl {
9 | }
10 |
--------------------------------------------------------------------------------
/mybatis-plus/integration-tests/src/main/java/io/quarkiverse/it/mybatis/plus/UuidTypeHandler.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis.plus;
2 |
3 | import java.sql.*;
4 | import java.util.UUID;
5 |
6 | import org.apache.ibatis.type.BaseTypeHandler;
7 | import org.apache.ibatis.type.JdbcType;
8 | import org.apache.ibatis.type.MappedTypes;
9 |
10 | @MappedTypes(UUID.class)
11 | public class UuidTypeHandler extends BaseTypeHandler {
12 |
13 | public static UUID fromStringAllowNulls(String uuid) {
14 | if (uuid == null || uuid.trim().equals("")) {
15 | return null;
16 | } else {
17 | return UUID.fromString(uuid);
18 | }
19 | }
20 |
21 | @Override
22 | public void setNonNullParameter(PreparedStatement ps, int i, UUID parameter, JdbcType jdbcType) throws SQLException {
23 | // note the difference in how H2 wants to persist a UUID
24 | ps.setObject(i, parameter);
25 | }
26 |
27 | @Override
28 | public UUID getNullableResult(ResultSet rs, String columnName) throws SQLException {
29 | return fromStringAllowNulls(rs.getString(columnName));
30 | }
31 |
32 | @Override
33 | public UUID getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
34 | return fromStringAllowNulls(rs.getString(columnIndex));
35 | }
36 |
37 | @Override
38 | public UUID getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
39 | return fromStringAllowNulls(cs.getString(columnIndex));
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/mybatis-plus/integration-tests/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | # H2
2 | quarkus.datasource.db-kind=h2
3 | quarkus.datasource.username=username-default
4 | quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:default
5 | quarkus.mybatis.initial-sql=insert.sql
6 | quarkus.mybatis-plus.meta-object-handler=io.quarkiverse.it.mybatis.plus.MyObjectHandler
7 | quarkus.mybatis-plus.sql-injector=io.quarkiverse.it.mybatis.plus.EasySqlInjector
8 |
9 |
--------------------------------------------------------------------------------
/mybatis-plus/integration-tests/src/main/resources/insert.sql:
--------------------------------------------------------------------------------
1 | DROP TABLE USERS IF EXISTS;
2 | DROP TABLE BOOKS IF EXISTS;
3 |
4 | CREATE TABLE USERS (
5 | id integer not null primary key,
6 | name varchar(80) not null,
7 | externalId uuid not null,
8 | create_time long,
9 | update_time long
10 | );
11 |
12 | CREATE TABLE BOOKS (
13 | id integer not null primary key,
14 | title varchar(80) not null,
15 | author_id integer not null,
16 |
17 | foreign key(author_id) references USERS(id)
18 | );
19 |
20 | DELETE FROM users;
21 | insert into users (id, name, externalId) values (1, 'Test User1', 'ccb16b65-8924-4c3f-8c55-681d85a16e79');
22 | insert into users (id, name, externalId) values (2, 'Test User2', 'ae43f233-0b69-4c4e-bfa9-656c475150ad');
23 | insert into users (id, name, externalId) values (3, 'Test User3', '5640e179-466c-427e-9747-4cfac09a2f9a');
24 |
25 | DELETE from books;
26 | insert into books(id, title, author_id) values (1, 'Test Title', 1);
27 |
--------------------------------------------------------------------------------
/mybatis-plus/integration-tests/src/test/java/io/quarkiverse/it/mybatis/plus/MyBatisPlusIT.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis.plus;
2 |
3 | import io.quarkus.test.junit.QuarkusIntegrationTest;
4 |
5 | @QuarkusIntegrationTest
6 | public class MyBatisPlusIT extends MyBatisPlusTest {
7 | }
8 |
--------------------------------------------------------------------------------
/mybatis-plus/integration-tests/src/test/java/io/quarkiverse/it/mybatis/plus/MyBatisPlusTest.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis.plus;
2 |
3 | import static org.hamcrest.core.Is.is;
4 | import static org.hamcrest.core.IsNot.not;
5 |
6 | import java.util.List;
7 | import java.util.UUID;
8 |
9 | import org.junit.jupiter.api.Test;
10 |
11 | import io.quarkus.test.junit.QuarkusTest;
12 | import io.restassured.RestAssured;
13 | import io.restassured.http.ContentType;
14 |
15 | @QuarkusTest
16 | public class MyBatisPlusTest {
17 |
18 | @Test
19 | public void test() {
20 | RestAssured.when().get("/mybatis/plus/user/1").then()
21 | .body(is("{\"id\":1,\"name\":\"Test User1\",\"externalId\":\"ccb16b65-8924-4c3f-8c55-681d85a16e79\"}"));
22 |
23 | RestAssured.when().get("/mybatis/plus/user/page/1/2").then().assertThat()
24 | .body("records[0].name", is("Test User1"))
25 | .body("records[1].name", is("Test User2"))
26 | .body("total", is(3))
27 | .body("size", is(2))
28 | .body("current", is(1))
29 | .body("pages", is(2));
30 |
31 | RestAssured.given().param("id", "5")
32 | .param("name", "New User")
33 | .param("externalId", UUID.fromString("9b036c98-eb1d-4580-a8bb-1115d7a3cd44"))
34 | .post("/mybatis/plus/user")
35 | .then().body(is("1"));
36 |
37 | RestAssured.when().get("/mybatis/plus/user/5").then()
38 | .body("createTime", not(0))
39 | .body("updateTime", not(0));
40 |
41 | RestAssured.when().delete("/mybatis/plus/user/3").then()
42 | .body(is("1"));
43 |
44 | RestAssured.when().get("/mybatis/plus/user/count/h2").then()
45 | .body(is("3"));
46 |
47 | User user1 = new User();
48 | user1.setId(100);
49 | user1.setName("Test User 100");
50 | user1.setExternalId(UUID.randomUUID());
51 |
52 | User user2 = new User();
53 | user2.setId(101);
54 | user2.setName("Test User 101");
55 | user2.setExternalId(UUID.randomUUID());
56 |
57 | List users = List.of(user1, user2);
58 | RestAssured.given()
59 | .contentType(ContentType.JSON)
60 | .body(users)
61 | .post("/mybatis/plus/users")
62 | .then().body(is("2"));
63 |
64 | RestAssured.when().get("/mybatis/plus/user/count/h2").then()
65 | .body(is("5"));
66 |
67 | RestAssured.when().delete("/mybatis/plus/user/100").then()
68 | .body(is("1"));
69 |
70 | RestAssured.when().delete("/mybatis/plus/user/101").then()
71 | .body(is("1"));
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/mybatis-plus/integration-tests/src/test/java/io/quarkiverse/it/mybatis/plus/MybatisPlusServiceTest.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis.plus;
2 |
3 | import static io.restassured.RestAssured.given;
4 | import static io.restassured.RestAssured.when;
5 | import static org.hamcrest.core.Is.is;
6 | import static org.hamcrest.core.IsNot.not;
7 |
8 | import java.net.URL;
9 | import java.util.List;
10 | import java.util.UUID;
11 |
12 | import org.junit.jupiter.api.Test;
13 |
14 | import io.quarkus.test.common.http.TestHTTPEndpoint;
15 | import io.quarkus.test.common.http.TestHTTPResource;
16 | import io.quarkus.test.junit.QuarkusTest;
17 | import io.restassured.http.ContentType;
18 |
19 | @QuarkusTest
20 | public class MybatisPlusServiceTest {
21 |
22 | @TestHTTPEndpoint(MybatisPlusServiceResource.class)
23 | @TestHTTPResource
24 | URL apiUrl;
25 |
26 | @Test
27 | public void test() {
28 | when().get(apiUrl + "/user/1").then()
29 | .statusCode(200)
30 | .body(is("{\"id\":1,\"name\":\"Test User1\",\"externalId\":\"ccb16b65-8924-4c3f-8c55-681d85a16e79\"}"));
31 |
32 | when().get(apiUrl + "/user/page/1/2").then().assertThat()
33 | .body("records[0].name", is("Test User1"))
34 | .body("records[1].name", is("Test User2"))
35 | .body("total", is(3))
36 | .body("size", is(2))
37 | .body("current", is(1))
38 | .body("pages", is(2));
39 |
40 | given().param("id", "205")
41 | .param("name", "New User")
42 | .param("externalId", UUID.fromString("9b036c98-eb1d-4580-a8bb-1115d7a3cd44"))
43 | .post(apiUrl + "/user")
44 | .then().body(is("true"));
45 |
46 | when().get(apiUrl + "/user/205").then()
47 | .body("createTime", not(0))
48 | .body("updateTime", not(0));
49 |
50 | when().delete(apiUrl + "/user/205").then()
51 | .body(is("true"));
52 |
53 | when().get(apiUrl + "/user/count/h2").then()
54 | .body(is("3"));
55 |
56 | User user1 = new User();
57 | user1.setId(200);
58 | user1.setName("Test User 200");
59 | user1.setExternalId(UUID.randomUUID());
60 |
61 | User user2 = new User();
62 | user2.setId(201);
63 | user2.setName("Test User 201");
64 | user2.setExternalId(UUID.randomUUID());
65 |
66 | List users = List.of(user1, user2);
67 | given()
68 | .contentType(ContentType.JSON)
69 | .body(users)
70 | .post(apiUrl + "/users")
71 | .then().body(is("true"));
72 |
73 | when().get(apiUrl + "/user/count/h2").then()
74 | .body(is("5"));
75 |
76 | when().delete(apiUrl + "/user/200").then()
77 | .body(is("true"));
78 |
79 | when().delete(apiUrl + "/user/201").then()
80 | .body(is("true"));
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/mybatis-plus/integration-tests/src/test/java/io/quarkiverse/it/mybatis/plus/TestResources.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis.plus;
2 |
3 | import io.quarkus.test.common.QuarkusTestResource;
4 | import io.quarkus.test.h2.H2DatabaseTestResource;
5 |
6 | @QuarkusTestResource(H2DatabaseTestResource.class)
7 | public class TestResources {
8 | }
9 |
--------------------------------------------------------------------------------
/mybatis-plus/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 |
6 | io.quarkiverse.mybatis
7 | quarkus-parent
8 | 999-SNAPSHOT
9 |
10 |
11 | quarkus-mybatis-plus-parent
12 | Quarkus - Mybatis Plus - Parent
13 | pom
14 |
15 |
16 | deployment
17 | runtime
18 | docs
19 |
20 |
21 |
22 |
23 | it
24 |
25 |
26 | performRelease
27 | !true
28 |
29 |
30 |
31 | integration-tests
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/mybatis-plus/runtime/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | io.quarkiverse.mybatis
5 | quarkus-mybatis-plus-parent
6 | 999-SNAPSHOT
7 | ../
8 |
9 | 4.0.0
10 |
11 | quarkus-mybatis-plus
12 | Quarkus - Mybatis Plus - Runtime
13 | A powerful enhanced toolkit of MyBatis to simplify development
14 |
15 |
16 |
17 | io.quarkiverse.mybatis
18 | quarkus-mybatis
19 | ${project.version}
20 |
21 |
22 | com.baomidou
23 | mybatis-plus
24 |
25 |
26 | com.baomidou
27 | mybatis-plus-spring
28 |
29 |
30 |
31 |
32 | com.baomidou
33 | mybatis-plus-jsqlparser
34 |
35 |
36 | org.graalvm.sdk
37 | nativeimage
38 |
39 |
40 | ru.vyarus
41 | generics-resolver
42 |
43 |
44 |
45 |
46 |
47 |
48 | io.quarkus
49 | quarkus-extension-maven-plugin
50 | ${quarkus.version}
51 |
52 |
53 |
54 | extension-descriptor
55 |
56 | compile
57 |
58 | ${project.groupId}:${project.artifactId}-deployment:${project.version}
59 |
60 |
61 |
62 |
63 |
64 |
65 | maven-compiler-plugin
66 |
67 |
68 |
69 | io.quarkus
70 | quarkus-extension-processor
71 | ${quarkus.version}
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/mybatis-plus/runtime/src/main/java/com/baomidou/mybatisplus/core/metadata/MapperProxyMetadata.java:
--------------------------------------------------------------------------------
1 | package com.baomidou.mybatisplus.core.metadata;
2 |
3 | import org.apache.ibatis.reflection.MetaObject;
4 | import org.apache.ibatis.session.SqlSession;
5 |
6 | import com.baomidou.mybatisplus.core.override.MybatisMapperProxy;
7 |
8 | public class MapperProxyMetadata {
9 | private final SqlSession sqlSession;
10 |
11 | private final Class> mapperInterface;
12 |
13 | public MapperProxyMetadata(MetaObject metaObject) {
14 | MybatisMapperProxy> mapperProxy = (MybatisMapperProxy) metaObject.getOriginalObject();
15 | this.mapperInterface = mapperProxy.getMapperInterface();
16 | this.sqlSession = mapperProxy.getSqlSession();
17 | }
18 |
19 | public Class> getMapperInterface() {
20 | return mapperInterface;
21 | }
22 |
23 | public SqlSession getSqlSession() {
24 | return sqlSession;
25 | }
26 |
27 | @Override
28 | public String toString() {
29 | return "MapperProxy{" +
30 | "mapperInterface=" + mapperInterface +
31 | ", sqlSession=" + sqlSession +
32 | '}';
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/mybatis-plus/runtime/src/main/java/com/baomidou/mybatisplus/core/toolkit/reflect/SpringReflectionHelper.java:
--------------------------------------------------------------------------------
1 | package com.baomidou.mybatisplus.core.toolkit.reflect;
2 |
3 | public class SpringReflectionHelper {
4 |
5 | public static Class>[] resolveTypeArguments(Class> clazz, Class> genericIfc) {
6 | throw new RuntimeException("Not Supported");
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/mybatis-plus/runtime/src/main/java/io/quarkiverse/mybatis/plus/MyBatisPlusConfig.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.plus;
2 |
3 | import java.util.Optional;
4 |
5 | import io.quarkus.runtime.annotations.ConfigPhase;
6 | import io.quarkus.runtime.annotations.ConfigRoot;
7 | import io.smallrye.config.ConfigMapping;
8 | import io.smallrye.config.WithDefault;
9 | import io.smallrye.config.WithName;
10 |
11 | @ConfigRoot(phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED)
12 | @ConfigMapping(prefix = "quarkus.mybatis-plus")
13 | public interface MyBatisPlusConfig {
14 |
15 | /**
16 | * MyBatis-plus PaginationInnerInterceptor
17 | */
18 | @WithName("pagination.enabled")
19 | @WithDefault("true")
20 | boolean pageEnabled();
21 |
22 | /**
23 | * MyBatis-plus SqlInjector Class
24 | */
25 | @WithName("sql-injector")
26 | Optional sqlInjector();
27 |
28 | /**
29 | * MyBatis-plus globalConfig metaObjectHandler
30 | */
31 | @WithName("meta-object-handler")
32 | Optional metaObjectHandler();
33 | }
34 |
--------------------------------------------------------------------------------
/mybatis-plus/runtime/src/main/java/io/quarkiverse/mybatis/plus/QuarkusCompatibleSet.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.plus;
2 |
3 | import java.util.function.Consumer;
4 |
5 | import org.apache.ibatis.exceptions.PersistenceException;
6 | import org.apache.ibatis.logging.Log;
7 | import org.apache.ibatis.reflection.ExceptionUtil;
8 | import org.apache.ibatis.session.ExecutorType;
9 | import org.apache.ibatis.session.SqlSession;
10 | import org.apache.ibatis.session.SqlSessionFactory;
11 |
12 | import com.baomidou.mybatisplus.core.spi.CompatibleSet;
13 | import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
14 |
15 | import io.quarkus.arc.Arc;
16 | import io.quarkus.arc.ClientProxy;
17 | import io.quarkus.runtime.annotations.RegisterForReflection;
18 |
19 | @RegisterForReflection
20 | public class QuarkusCompatibleSet implements CompatibleSet {
21 |
22 | @Override
23 | public SqlSession getSqlSession(SqlSessionFactory sessionFactory) {
24 | return Arc.container().instance(SqlSession.class).get();
25 | }
26 |
27 | @Override
28 | public void closeSqlSession(SqlSession session, SqlSessionFactory sessionFactory) {
29 | if (session != null) {
30 | session.close();
31 | }
32 | }
33 |
34 | @Override
35 | public boolean executeBatch(SqlSessionFactory sqlSessionFactory, Log log, Consumer consumer) {
36 | SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
37 | try {
38 | consumer.accept(sqlSession);
39 | sqlSession.commit(true);
40 | return true;
41 | } catch (Throwable t) {
42 | sqlSession.rollback();
43 | Throwable unwrapped = ExceptionUtil.unwrapThrowable(t);
44 | if (unwrapped instanceof PersistenceException) {
45 | throw ExceptionUtils.mpe(unwrapped);
46 | }
47 | throw ExceptionUtils.mpe(unwrapped);
48 | } finally {
49 | sqlSession.close();
50 | }
51 | }
52 |
53 | @Override
54 | public T getBean(Class clz) {
55 | if (Arc.container() == null || !Arc.container().isRunning()) {
56 | return null;
57 | }
58 | return Arc.container().instance(clz).get();
59 | }
60 |
61 | @Override
62 | public Object getProxyTargetObject(Object mapper) {
63 | Object result = mapper;
64 | //Quarkus's proxy detection
65 | while (result instanceof ClientProxy) {
66 | result = ((ClientProxy) result).arc_contextualInstance();
67 | }
68 | return result;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/mybatis-plus/runtime/src/main/java/io/quarkiverse/mybatis/plus/extension/repository/CrudRepository.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.plus.extension.repository;
2 |
3 | import java.util.Collection;
4 |
5 | import jakarta.inject.Inject;
6 | import jakarta.transaction.Transactional;
7 |
8 | import org.apache.ibatis.binding.MapperMethod;
9 |
10 | import com.baomidou.mybatisplus.core.enums.SqlMethod;
11 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
12 | import com.baomidou.mybatisplus.core.metadata.TableInfo;
13 | import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
14 | import com.baomidou.mybatisplus.core.toolkit.Assert;
15 | import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
16 | import com.baomidou.mybatisplus.core.toolkit.Constants;
17 | import com.baomidou.mybatisplus.core.toolkit.StringUtils;
18 | import com.baomidou.mybatisplus.extension.repository.AbstractRepository;
19 | import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
20 |
21 | public abstract class CrudRepository, T> extends AbstractRepository {
22 | @Inject
23 | protected M baseMapper;
24 |
25 | @Override
26 | public M getBaseMapper() {
27 | Assert.notNull(this.baseMapper, "baseMapper can not be null");
28 | return this.baseMapper;
29 | }
30 |
31 | @Transactional(rollbackOn = Exception.class)
32 | @Override
33 | public boolean saveBatch(Collection entityList, int batchSize) {
34 | String sqlStatement = getSqlStatement(SqlMethod.INSERT_ONE);
35 | return executeBatch(entityList, batchSize, (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity));
36 | }
37 |
38 | protected String getSqlStatement(SqlMethod sqlMethod) {
39 | return SqlHelper.getSqlStatement(this.getMapperClass(), sqlMethod);
40 | }
41 |
42 | @Transactional(rollbackOn = Exception.class)
43 | @Override
44 | public boolean saveOrUpdateBatch(Collection entityList, int batchSize) {
45 | TableInfo tableInfo = TableInfoHelper.getTableInfo(this.getEntityClass());
46 | Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!");
47 | String keyProperty = tableInfo.getKeyProperty();
48 | Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!");
49 | return SqlHelper.saveOrUpdateBatch(getSqlSessionFactory(), this.getMapperClass(), this.log, entityList, batchSize,
50 | (sqlSession, entity) -> {
51 | Object idVal = tableInfo.getPropertyValue(entity, keyProperty);
52 | return StringUtils.checkValNull(idVal)
53 | || CollectionUtils.isEmpty(sqlSession.selectList(getSqlStatement(SqlMethod.SELECT_BY_ID), entity));
54 | }, (sqlSession, entity) -> {
55 | MapperMethod.ParamMap param = new MapperMethod.ParamMap<>();
56 | param.put(Constants.ENTITY, entity);
57 | sqlSession.update(getSqlStatement(SqlMethod.UPDATE_BY_ID), param);
58 | });
59 | }
60 |
61 | @Transactional(rollbackOn = Exception.class)
62 | @Override
63 | public boolean updateBatchById(Collection entityList, int batchSize) {
64 | String sqlStatement = getSqlStatement(SqlMethod.UPDATE_BY_ID);
65 | return executeBatch(entityList, batchSize, (sqlSession, entity) -> {
66 | MapperMethod.ParamMap param = new MapperMethod.ParamMap<>();
67 | param.put(Constants.ENTITY, entity);
68 | sqlSession.update(sqlStatement, param);
69 | });
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/mybatis-plus/runtime/src/main/java/io/quarkiverse/mybatis/plus/extension/service/IService.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.plus.extension.service;
2 |
3 | import java.util.Collection;
4 |
5 | import jakarta.transaction.Transactional;
6 |
7 | import com.baomidou.mybatisplus.extension.repository.IRepository;
8 |
9 | public interface IService extends IRepository {
10 |
11 | @Transactional(rollbackOn = Exception.class)
12 | default boolean saveBatch(Collection entityList) {
13 | return saveBatch(entityList, DEFAULT_BATCH_SIZE);
14 | }
15 |
16 | @Transactional(rollbackOn = Exception.class)
17 | default boolean saveOrUpdateBatch(Collection entityList) {
18 | return saveOrUpdateBatch(entityList, DEFAULT_BATCH_SIZE);
19 | }
20 |
21 | @Transactional(rollbackOn = Exception.class)
22 | default boolean removeBatchByIds(Collection> list) {
23 | return removeByIds(list);
24 | }
25 |
26 | @Transactional(rollbackOn = Exception.class)
27 | default boolean updateBatchById(Collection entityList) {
28 | return updateBatchById(entityList, DEFAULT_BATCH_SIZE);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/mybatis-plus/runtime/src/main/java/io/quarkiverse/mybatis/plus/extension/service/impl/ServiceImpl.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.plus.extension.service.impl;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 |
5 | import io.quarkiverse.mybatis.plus.extension.repository.CrudRepository;
6 | import io.quarkiverse.mybatis.plus.extension.service.IService;
7 |
8 | public class ServiceImpl, T> extends CrudRepository implements IService {
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/mybatis-plus/runtime/src/main/java/io/quarkiverse/mybatis/plus/runtime/GenericTypeResolverImpl.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.plus.runtime;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 | import com.baomidou.mybatisplus.core.toolkit.reflect.IGenericTypeResolver;
7 |
8 | import ru.vyarus.java.generics.resolver.GenericsResolver;
9 | import ru.vyarus.java.generics.resolver.context.GenericsContext;
10 |
11 | public class GenericTypeResolverImpl implements IGenericTypeResolver {
12 | private final Logger logger = LoggerFactory.getLogger(GenericTypeResolverImpl.class);
13 |
14 | @Override
15 | public Class>[] resolveTypeArguments(Class> clazz, Class> genericIfc) {
16 | GenericsContext context = GenericsResolver.resolve(clazz)
17 | .type(genericIfc);
18 | return context.generics().toArray(new Class[] {});
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/mybatis-plus/runtime/src/main/java/io/quarkiverse/mybatis/plus/runtime/MyBatisPlusConfigurationFactory.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.plus.runtime;
2 |
3 | import org.apache.ibatis.session.Configuration;
4 | import org.jboss.logging.Logger;
5 |
6 | import com.baomidou.mybatisplus.core.MybatisConfiguration;
7 | import com.baomidou.mybatisplus.core.toolkit.reflect.GenericTypeUtils;
8 |
9 | import io.quarkiverse.mybatis.runtime.ConfigurationFactory;
10 |
11 | public class MyBatisPlusConfigurationFactory implements ConfigurationFactory {
12 | private static final Logger LOG = Logger.getLogger(MyBatisPlusConfigurationFactory.class);
13 |
14 | @Override
15 | public Configuration createConfiguration() {
16 | GenericTypeUtils.setGenericTypeResolver(new GenericTypeResolverImpl());
17 | return new MybatisConfiguration();
18 | }
19 |
20 | @Override
21 | public boolean isOverrideSetting() {
22 | return true;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/mybatis-plus/runtime/src/main/java/io/quarkiverse/mybatis/plus/runtime/MyBatisPlusRecorder.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.plus.runtime;
2 |
3 | import java.util.function.Consumer;
4 |
5 | import org.apache.ibatis.io.Resources;
6 | import org.apache.ibatis.session.Configuration;
7 | import org.apache.ibatis.session.SqlSessionFactory;
8 | import org.jboss.logging.Logger;
9 |
10 | import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
11 | import com.baomidou.mybatisplus.core.injector.ISqlInjector;
12 | import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
13 | import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
14 | import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
15 |
16 | import io.quarkiverse.mybatis.plus.MyBatisPlusConfig;
17 | import io.quarkus.runtime.RuntimeValue;
18 | import io.quarkus.runtime.annotations.Recorder;
19 |
20 | @Recorder
21 | public class MyBatisPlusRecorder {
22 | private static final Logger LOG = Logger.getLogger(MyBatisPlusRecorder.class);
23 |
24 | public void initSqlSession(RuntimeValue sqlSessionFactory, MyBatisPlusConfig config) {
25 | Configuration configuration = sqlSessionFactory.getValue().getConfiguration();
26 |
27 | if (config.pageEnabled()) {
28 | MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
29 | interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
30 | configuration.addInterceptor(interceptor);
31 | }
32 |
33 | if (config.metaObjectHandler().isPresent()) {
34 | try {
35 | String classMetaObjectHandler = config.metaObjectHandler().get();
36 | MetaObjectHandler handler = (MetaObjectHandler) Resources.classForName(classMetaObjectHandler)
37 | .getDeclaredConstructor().newInstance();
38 | GlobalConfigUtils.getGlobalConfig(configuration).setMetaObjectHandler(handler);
39 | } catch (Exception e) {
40 | LOG.warn("Can not initialize metaObjectHandler " + config.metaObjectHandler().get());
41 | }
42 | }
43 | }
44 |
45 | public Consumer addCustomSqlInjector(MyBatisPlusConfig config) {
46 | return configuration -> {
47 | if (config.sqlInjector().isPresent()) {
48 | try {
49 | String classSqlInjector = config.sqlInjector().get();
50 | ISqlInjector sqlInjector = (ISqlInjector) Resources.classForName(classSqlInjector)
51 | .getDeclaredConstructor().newInstance();
52 | GlobalConfigUtils.getGlobalConfig(configuration).setSqlInjector(sqlInjector);
53 | } catch (Exception e) {
54 | LOG.warn("Can not initialize sqlInjector " + config.sqlInjector().get());
55 | }
56 | }
57 | };
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/mybatis-plus/runtime/src/main/java/io/quarkiverse/mybatis/plus/runtime/MyBatisPlusXMLConfigDelegateBuilder.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.plus.runtime;
2 |
3 | import java.io.Reader;
4 |
5 | import org.apache.ibatis.io.Resources;
6 | import org.apache.ibatis.session.Configuration;
7 |
8 | import com.baomidou.mybatisplus.core.MybatisXMLConfigBuilder;
9 |
10 | import io.quarkiverse.mybatis.runtime.XMLConfigDelegateBuilder;
11 | import io.quarkiverse.mybatis.runtime.config.MyBatisRuntimeConfig;
12 |
13 | public class MyBatisPlusXMLConfigDelegateBuilder implements XMLConfigDelegateBuilder {
14 | private MybatisXMLConfigBuilder builder;
15 | private MyBatisRuntimeConfig config;
16 |
17 | public MyBatisPlusXMLConfigDelegateBuilder() {
18 |
19 | }
20 |
21 | @Override
22 | public void setConfig(MyBatisRuntimeConfig config) {
23 | this.config = config;
24 | }
25 |
26 | @Override
27 | public Configuration getConfiguration() throws Exception {
28 | return getBuilder().getConfiguration();
29 | }
30 |
31 | @Override
32 | public Configuration parse() throws Exception {
33 | return getBuilder().parse();
34 | }
35 |
36 | private MybatisXMLConfigBuilder getBuilder() throws Exception {
37 | if (builder == null) {
38 | Reader reader = Resources.getResourceAsReader(config.xmlconfig().path());
39 | builder = new MybatisXMLConfigBuilder(reader, config.environment());
40 | }
41 | return builder;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/mybatis-plus/runtime/src/main/resources/META-INF/quarkus-extension.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | name: "MyBatis Plus"
3 | metadata:
4 | icon-url: "https://mybatis.plus/img/logo.svg"
5 | keywords:
6 | - "mybatis-plus"
7 | guide: "https://quarkiverse.github.io/quarkiverse-docs/quarkus-mybatis/dev/"
8 | categories:
9 | - "data"
10 | status: "stable"
11 |
--------------------------------------------------------------------------------
/mybatis-plus/runtime/src/main/resources/META-INF/services/com.baomidou.mybatisplus.core.spi.CompatibleSet:
--------------------------------------------------------------------------------
1 | io.quarkiverse.mybatis.plus.QuarkusCompatibleSet
--------------------------------------------------------------------------------
/mybatis/README.md:
--------------------------------------------------------------------------------
1 | # Quarkus MyBatis Extension
2 | [](https://github.com/quarkiverse/quarkus-mybatis/actions?query=workflow%3ABuild)
3 | [](http://www.apache.org/licenses/LICENSE-2.0)
4 | [](https://search.maven.org/search?q=g:io.quarkiverse.mybatis%20AND%20a:quarkus-mybatis-parent)
5 |
6 | [](#contributors-)
7 |
8 |
9 | MyBatis is a first class persistence framework with support for custom SQL, stored procedures and advanced mappings. This extension provides the developers ease of configuration and native support. Add the following dependency in your pom.xml to get started,
10 |
11 | ```xml
12 |
13 | io.quarkiverse.mybatis
14 | quarkus-mybatis
15 |
16 | ```
17 |
18 | And then your can use the ```@Mapper``` in your application just like
19 |
20 | ```java
21 | @Mapper
22 | public interface UserMapper {
23 |
24 | @Select("SELECT * FROM USERS WHERE id = #{id}")
25 | User getUser(Integer id);
26 |
27 | @Insert("INSERT INTO USERS (id, name) VALUES (#{id}, #{name})")
28 | Integer createUser(@Param("id") Integer id, @Param("name") String name);
29 |
30 | @Delete("DELETE FROM USERS WHERE id = #{id}")
31 | Integer removeUser(Integer id);
32 | }
33 | ```
34 |
35 | For more information and quickstart, you can check the complete [documentation](https://quarkiverse.github.io/quarkiverse-docs/quarkus-mybatis/dev/index.html).
36 |
37 | ## Contributors ✨
38 |
39 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
40 |
41 |
42 |
43 |
44 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
60 |
--------------------------------------------------------------------------------
/mybatis/deployment/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | io.quarkiverse.mybatis
5 | quarkus-mybatis-parent
6 | 999-SNAPSHOT
7 | ../
8 |
9 | 4.0.0
10 |
11 | quarkus-mybatis-deployment
12 | Quarkus - Mybatis - Deployment
13 |
14 |
15 |
16 | io.quarkus
17 | quarkus-arc-deployment
18 |
19 |
20 | io.quarkus
21 | quarkus-agroal-deployment
22 |
23 |
24 | io.quarkiverse.mybatis
25 | quarkus-mybatis
26 | ${project.version}
27 |
28 |
29 |
30 | io.quarkus
31 | quarkus-junit5-internal
32 | test
33 |
34 |
35 | io.quarkus
36 | quarkus-test-h2
37 | test
38 |
39 |
40 | io.quarkus
41 | quarkus-test-derby
42 | test
43 |
44 |
45 | io.quarkus
46 | quarkus-jdbc-h2-deployment
47 | test
48 |
49 |
50 | io.quarkus
51 | quarkus-jdbc-derby
52 | test
53 |
54 |
55 |
56 |
57 |
58 |
59 | maven-compiler-plugin
60 |
61 |
62 |
63 | io.quarkus
64 | quarkus-extension-processor
65 | ${quarkus.version}
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/mybatis/deployment/src/main/java/io/quarkiverse/mybatis/deployment/ConfigurationCustomizerBuildItem.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.deployment;
2 |
3 | import java.util.function.Consumer;
4 |
5 | import org.apache.ibatis.session.Configuration;
6 |
7 | import io.quarkus.builder.item.MultiBuildItem;
8 |
9 | public final class ConfigurationCustomizerBuildItem extends MultiBuildItem {
10 | private Consumer customizer;
11 |
12 | public ConfigurationCustomizerBuildItem(Consumer customizer) {
13 | this.customizer = customizer;
14 | }
15 |
16 | public Consumer getCustomizer() {
17 | return customizer;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/mybatis/deployment/src/main/java/io/quarkiverse/mybatis/deployment/ConfigurationFactoryBuildItem.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.deployment;
2 |
3 | import io.quarkiverse.mybatis.runtime.ConfigurationFactory;
4 | import io.quarkus.builder.item.SimpleBuildItem;
5 |
6 | public final class ConfigurationFactoryBuildItem extends SimpleBuildItem {
7 | private final ConfigurationFactory factory;
8 |
9 | public ConfigurationFactoryBuildItem(ConfigurationFactory factory) {
10 | this.factory = factory;
11 | }
12 |
13 | public ConfigurationFactory getFactory() {
14 | return factory;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/mybatis/deployment/src/main/java/io/quarkiverse/mybatis/deployment/MyBatisMappedJdbcTypeBuildItem.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.deployment;
2 |
3 | import org.jboss.jandex.DotName;
4 |
5 | import io.quarkus.builder.item.MultiBuildItem;
6 |
7 | public final class MyBatisMappedJdbcTypeBuildItem extends MultiBuildItem {
8 | private final DotName mappedJdbcTypeName;
9 |
10 | public MyBatisMappedJdbcTypeBuildItem(DotName mappedJdbcTypeName) {
11 | this.mappedJdbcTypeName = mappedJdbcTypeName;
12 | }
13 |
14 | public DotName getMappedJdbcTypeName() {
15 | return mappedJdbcTypeName;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/mybatis/deployment/src/main/java/io/quarkiverse/mybatis/deployment/MyBatisMappedTypeBuildItem.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.deployment;
2 |
3 | import org.jboss.jandex.DotName;
4 |
5 | import io.quarkus.builder.item.MultiBuildItem;
6 |
7 | public final class MyBatisMappedTypeBuildItem extends MultiBuildItem {
8 | private final DotName mappedTypeName;
9 |
10 | public MyBatisMappedTypeBuildItem(DotName mappedTypeName) {
11 | this.mappedTypeName = mappedTypeName;
12 | }
13 |
14 | public DotName getMappedTypeName() {
15 | return mappedTypeName;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/mybatis/deployment/src/main/java/io/quarkiverse/mybatis/deployment/MyBatisMapperBuildItem.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.deployment;
2 |
3 | import org.jboss.jandex.DotName;
4 |
5 | import io.quarkus.builder.item.MultiBuildItem;
6 |
7 | public final class MyBatisMapperBuildItem extends MultiBuildItem {
8 | private final DotName mapperName;
9 | private final String dataSourceName;
10 |
11 | public MyBatisMapperBuildItem(DotName mapperName, String dataSourceName) {
12 | this.mapperName = mapperName;
13 | this.dataSourceName = dataSourceName;
14 | }
15 |
16 | public DotName getMapperName() {
17 | return mapperName;
18 | }
19 |
20 | public String getDataSourceName() {
21 | return dataSourceName;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/mybatis/deployment/src/main/java/io/quarkiverse/mybatis/deployment/MyBatisXmlConfigBuildItem.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.deployment;
2 |
3 | import io.quarkus.builder.item.SimpleBuildItem;
4 |
5 | public final class MyBatisXmlConfigBuildItem extends SimpleBuildItem {
6 | private final boolean enabled;
7 | private final String name;
8 |
9 | public MyBatisXmlConfigBuildItem(String name, boolean enabled) {
10 | this.name = name;
11 | this.enabled = enabled;
12 | }
13 |
14 | public boolean isEnabled() {
15 | return enabled;
16 | }
17 |
18 | public String getName() {
19 | return name;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/mybatis/deployment/src/main/java/io/quarkiverse/mybatis/deployment/SqlSessionFactoryBuildItem.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.deployment;
2 |
3 | import org.apache.ibatis.session.SqlSessionFactory;
4 |
5 | import io.quarkus.builder.item.MultiBuildItem;
6 | import io.quarkus.runtime.RuntimeValue;
7 |
8 | /**
9 | * Hold the RuntimeValue of {@link SqlSessionFactory}
10 | */
11 | public final class SqlSessionFactoryBuildItem extends MultiBuildItem {
12 | private final RuntimeValue sqlSessionFactory;
13 | private final String dataSourceName;
14 | private final boolean defaultDataSource;
15 | private final boolean fromXmlConfig;
16 |
17 | public SqlSessionFactoryBuildItem(
18 | RuntimeValue sqlSessionFactory,
19 | String dataSourceName,
20 | boolean isDefaultDataSource,
21 | boolean isFromXmlConfig) {
22 | this.sqlSessionFactory = sqlSessionFactory;
23 | this.dataSourceName = dataSourceName;
24 | this.defaultDataSource = isDefaultDataSource;
25 | this.fromXmlConfig = isFromXmlConfig;
26 | }
27 |
28 | public RuntimeValue getSqlSessionFactory() {
29 | return sqlSessionFactory;
30 | }
31 |
32 | public String getDataSourceName() {
33 | return dataSourceName;
34 | }
35 |
36 | public boolean isDefaultDataSource() {
37 | return defaultDataSource;
38 | }
39 |
40 | public boolean isFromXmlConfig() {
41 | return fromXmlConfig;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/mybatis/deployment/src/main/java/io/quarkiverse/mybatis/deployment/SqlSessionFactoryBuilderBuildItem.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.deployment;
2 |
3 | import org.apache.ibatis.session.SqlSessionFactoryBuilder;
4 |
5 | import io.quarkus.builder.item.SimpleBuildItem;
6 |
7 | public final class SqlSessionFactoryBuilderBuildItem extends SimpleBuildItem {
8 | private final SqlSessionFactoryBuilder builder;
9 |
10 | public SqlSessionFactoryBuilderBuildItem(SqlSessionFactoryBuilder builder) {
11 | this.builder = builder;
12 | }
13 |
14 | public SqlSessionFactoryBuilder getBuilder() {
15 | return builder;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/mybatis/deployment/src/main/java/io/quarkiverse/mybatis/deployment/SqlSessionManagerBuildItem.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.deployment;
2 |
3 | import io.quarkiverse.mybatis.runtime.TransactionalSqlSession;
4 | import io.quarkus.builder.item.MultiBuildItem;
5 | import io.quarkus.runtime.RuntimeValue;
6 |
7 | /**
8 | * Hold the RuntimeValue of {@link TransactionalSqlSession}
9 | */
10 | public final class SqlSessionManagerBuildItem extends MultiBuildItem {
11 | private final RuntimeValue sqlSessionManager;
12 | private final String dataSourceName;
13 | private final boolean defaultDataSource;
14 |
15 | public SqlSessionManagerBuildItem(
16 | RuntimeValue sqlSessionManager,
17 | String dataSourceName,
18 | Boolean defaultDataSource) {
19 | this.sqlSessionManager = sqlSessionManager;
20 | this.dataSourceName = dataSourceName;
21 | this.defaultDataSource = defaultDataSource;
22 | }
23 |
24 | public RuntimeValue getSqlSessionManager() {
25 | return sqlSessionManager;
26 | }
27 |
28 | public String getDataSourceName() {
29 | return dataSourceName;
30 | }
31 |
32 | public boolean isDefaultDataSource() {
33 | return defaultDataSource;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/mybatis/deployment/src/main/java/io/quarkiverse/mybatis/deployment/XMLConfigBuilderBuildItem.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.deployment;
2 |
3 | import io.quarkiverse.mybatis.runtime.XMLConfigDelegateBuilder;
4 | import io.quarkus.builder.item.SimpleBuildItem;
5 |
6 | public final class XMLConfigBuilderBuildItem extends SimpleBuildItem {
7 | private final XMLConfigDelegateBuilder builder;
8 |
9 | public XMLConfigBuilderBuildItem(XMLConfigDelegateBuilder builder) {
10 | this.builder = builder;
11 | }
12 |
13 | public XMLConfigDelegateBuilder getBuilder() {
14 | return builder;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/mybatis/deployment/src/test/java/io/quarkiverse/mybatis/test/MyBatisTest.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.test;
2 |
3 | import static org.junit.jupiter.api.Assertions.assertEquals;
4 | import static org.junit.jupiter.api.Assertions.assertTrue;
5 |
6 | import java.util.UUID;
7 |
8 | import jakarta.inject.Inject;
9 | import jakarta.inject.Named;
10 |
11 | import org.apache.ibatis.session.SqlSessionFactory;
12 | import org.jboss.shrinkwrap.api.ShrinkWrap;
13 | import org.jboss.shrinkwrap.api.spec.JavaArchive;
14 | import org.junit.jupiter.api.Test;
15 | import org.junit.jupiter.api.extension.RegisterExtension;
16 |
17 | import io.quarkus.test.QuarkusUnitTest;
18 |
19 | public class MyBatisTest {
20 | @RegisterExtension
21 | static final QuarkusUnitTest config = new QuarkusUnitTest().withConfigurationResource("application.properties")
22 | .setArchiveProducer(
23 | () -> ShrinkWrap.create(JavaArchive.class)
24 | .addClasses(UserMapper.class, User.class, UuidTypeHandler.class, UuidJdbcTypeHandler.class));
25 |
26 | @Inject
27 | UserMapper userMapper;
28 |
29 | @Inject
30 | SqlSessionFactory h2SqlSessionFactory;
31 |
32 | @Named("derby")
33 | SqlSessionFactory derbySqlSessionFactory;
34 |
35 | @Test
36 | public void test() throws Exception {
37 | assertTrue(h2SqlSessionFactory.getConfiguration().getMapperRegistry().hasMapper(UserMapper.class));
38 | assertEquals("H2", h2SqlSessionFactory.openSession().getConnection().getMetaData().getDatabaseProductName());
39 | User user = userMapper.getUser(1);
40 | assertEquals(user.getId(), 1);
41 | assertEquals(user.getName(), "Test User1");
42 | assertEquals(user.getExternalId(), UUID.fromString("8c5034fe-1a00-43b7-9c75-f83ef14e3507"));
43 |
44 | assertEquals("Apache Derby",
45 | derbySqlSessionFactory.openSession().getConnection().getMetaData().getDatabaseProductName());
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/mybatis/deployment/src/test/java/io/quarkiverse/mybatis/test/TestResources.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.test;
2 |
3 | import io.quarkus.test.common.QuarkusTestResource;
4 | import io.quarkus.test.derby.DerbyDatabaseTestResource;
5 | import io.quarkus.test.h2.H2DatabaseTestResource;
6 |
7 | @QuarkusTestResource(H2DatabaseTestResource.class)
8 | @QuarkusTestResource(DerbyDatabaseTestResource.class)
9 | public class TestResources {
10 | }
11 |
--------------------------------------------------------------------------------
/mybatis/deployment/src/test/java/io/quarkiverse/mybatis/test/User.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.test;
2 |
3 | import java.util.UUID;
4 |
5 | public class User {
6 | private Integer id;
7 | private String name;
8 | private UUID externalId;
9 |
10 | public Integer getId() {
11 | return id;
12 | }
13 |
14 | public void setId(Integer id) {
15 | this.id = id;
16 | }
17 |
18 | public String getName() {
19 | return name;
20 | }
21 |
22 | public void setName(String name) {
23 | this.name = name;
24 | }
25 |
26 | public UUID getExternalId() {
27 | return externalId;
28 | }
29 |
30 | public void setExternalId(UUID externalId) {
31 | this.externalId = externalId;
32 | }
33 |
34 | @Override
35 | public String toString() {
36 | return "User{" +
37 | "id=" + id +
38 | ", name='" + name + '\'' +
39 | ", externalId=" + externalId +
40 | '}';
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/mybatis/deployment/src/test/java/io/quarkiverse/mybatis/test/UserMapper.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.test;
2 |
3 | import org.apache.ibatis.annotations.Mapper;
4 | import org.apache.ibatis.annotations.Select;
5 |
6 | @Mapper
7 | public interface UserMapper {
8 |
9 | @Select("select * from users where id = #{id}")
10 | User getUser(Integer id);
11 | }
12 |
--------------------------------------------------------------------------------
/mybatis/deployment/src/test/java/io/quarkiverse/mybatis/test/UuidJdbcTypeHandler.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.test;
2 |
3 | import java.sql.*;
4 | import java.util.UUID;
5 |
6 | import org.apache.ibatis.type.BaseTypeHandler;
7 | import org.apache.ibatis.type.JdbcType;
8 | import org.apache.ibatis.type.MappedJdbcTypes;
9 |
10 | @MappedJdbcTypes(value = JdbcType.OTHER, includeNullJdbcType = true)
11 | public class UuidJdbcTypeHandler extends BaseTypeHandler {
12 |
13 | public static UUID fromStringAllowNulls(String uuid) {
14 | if (uuid == null || uuid.trim().equals("")) {
15 | return null;
16 | } else {
17 | return UUID.fromString(uuid);
18 | }
19 | }
20 |
21 | @Override
22 | public void setNonNullParameter(PreparedStatement ps, int i, UUID parameter, JdbcType jdbcType) throws SQLException {
23 | ps.setObject(i, parameter.toString(), Types.OTHER);
24 | }
25 |
26 | @Override
27 | public UUID getNullableResult(ResultSet rs, String columnName) throws SQLException {
28 | return fromStringAllowNulls(rs.getString(columnName));
29 | }
30 |
31 | @Override
32 | public UUID getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
33 | return fromStringAllowNulls(rs.getString(columnIndex));
34 | }
35 |
36 | @Override
37 | public UUID getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
38 | return fromStringAllowNulls(cs.getString(columnIndex));
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/mybatis/deployment/src/test/java/io/quarkiverse/mybatis/test/UuidTypeHandler.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.test;
2 |
3 | import java.sql.*;
4 | import java.util.UUID;
5 |
6 | import org.apache.ibatis.type.BaseTypeHandler;
7 | import org.apache.ibatis.type.JdbcType;
8 | import org.apache.ibatis.type.MappedTypes;
9 |
10 | @MappedTypes(UUID.class)
11 | public class UuidTypeHandler extends BaseTypeHandler {
12 |
13 | public static UUID fromStringAllowNulls(String uuid) {
14 | if (uuid == null || uuid.trim().equals("")) {
15 | return null;
16 | } else {
17 | return UUID.fromString(uuid);
18 | }
19 | }
20 |
21 | @Override
22 | public void setNonNullParameter(PreparedStatement ps, int i, UUID parameter, JdbcType jdbcType) throws SQLException {
23 | ps.setObject(i, parameter.toString(), Types.OTHER);
24 | }
25 |
26 | @Override
27 | public UUID getNullableResult(ResultSet rs, String columnName) throws SQLException {
28 | return fromStringAllowNulls(rs.getString(columnName));
29 | }
30 |
31 | @Override
32 | public UUID getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
33 | return fromStringAllowNulls(rs.getString(columnIndex));
34 | }
35 |
36 | @Override
37 | public UUID getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
38 | return fromStringAllowNulls(cs.getString(columnIndex));
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/mybatis/deployment/src/test/resources/application.properties:
--------------------------------------------------------------------------------
1 | # H2
2 | quarkus.datasource.db-kind=h2
3 | quarkus.datasource.username=username-default
4 | quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:default
5 | quarkus.mybatis.initial-sql=insert.sql
6 |
7 | # Derby
8 | quarkus.datasource.derby.db-kind=derby
9 | quarkus.datasource.derby.jdbc.url=jdbc:derby://localhost:1527/memory:testDB;create=true
10 |
--------------------------------------------------------------------------------
/mybatis/deployment/src/test/resources/insert.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE USERS (
2 | id integer not null primary key,
3 | name varchar(80) not null,
4 | externalId uuid not null
5 | );
6 |
7 | DELETE FROM users;
8 | insert into users (id, name, externalId) values (1, 'Test User1', '8c5034fe-1a00-43b7-9c75-f83ef14e3507');
9 | insert into users (id, name, externalId) values (2, 'Test User2', '0a197020-e05a-41ab-9c46-649cd432feb4');
10 | insert into users (id, name, externalId) values (3, 'Test User3', '9b54c1b1-5e7d-4a64-a06c-9a5b9531e2ee');
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/mybatis/docs/antora.yml:
--------------------------------------------------------------------------------
1 | name: quarkus-mybatis
2 | title: MyBatis
3 | version: dev
4 | nav:
5 | - modules/ROOT/nav.adoc
6 |
--------------------------------------------------------------------------------
/mybatis/docs/modules/ROOT/nav.adoc:
--------------------------------------------------------------------------------
1 | * xref:index.adoc[Introduction]
2 |
--------------------------------------------------------------------------------
/mybatis/docs/modules/ROOT/pages/includes/attributes.adoc:
--------------------------------------------------------------------------------
1 | :quarkus-version: 3.18.2
2 | :quarkus-mybatis-version: 2.2.4
3 |
4 | :mybatis-root-url: https://mybatis.org/mybatis-3/
5 |
--------------------------------------------------------------------------------
/mybatis/docs/modules/ROOT/pages/index.adoc:
--------------------------------------------------------------------------------
1 | include::./includes/attributes.adoc[]
2 | = Quarkus - Using MyBatis
3 |
4 | :extension-status: preview
5 |
6 | This guide demonstrates how your Quarkus application can use link:{mybatis-root-url}[MyBatis] to support custom SQL, stored procedures and advanced mappings.
7 |
8 | == Prerequisites
9 |
10 | To complete this guide, you need:
11 |
12 | * less than 15 minutes
13 | * an IDE
14 | * JDK 11+ installed with `JAVA_HOME` configured appropriately
15 | * Apache Maven
16 | * A running Mysql Database server
17 | * GraalVM, or Docker, installed if you want to run in native mode.
18 |
19 | == Architecture
20 |
21 | The application built in this guide is quite simple: the user can get, add and remove a record through the RESTful API by using the MyBatis Mapper.
22 |
23 |
24 | == Solution
25 |
26 | We recommend that you follow the instructions in the next sections and create the application step by step.
27 |
28 | == Creating the Maven Project
29 |
30 | First, we need a new project. Create a new project with the following command:
31 |
32 | [source, bash, subs=attributes+]
33 | ----
34 | mvn io.quarkus:quarkus-maven-plugin:{quarkus-version}:create \
35 | -DprojectGroupId=org.acme \
36 | -DprojectArtifactId=mybatis-quickstart \
37 | -Dextensions="resteasy-jackson,jdbc-mysql,io.quarkiverse.mybatis:quarkus-mybatis:{quarkus-mybatis-version}" \
38 | -DnoExamples
39 | cd mybatis-quickstart
40 | ----
41 |
42 | [TIP]
43 | ====
44 | Maven 3.6.2+ is required for this to work.
45 | ====
46 |
47 | This command generates a Maven project, with its pom.xml importing the quarkus-mybatis extension.
48 |
49 | If you already have your Quarkus project configured, you can add the `quarkus-mybatis` extension
50 | to your project by adding the following dependency in your `pom.xml`:
51 |
52 | [source, subs=attributes+]
53 | ----
54 |
55 | io.quarkiverse.mybatis
56 | quarkus-mybatis
57 | {quarkus-mybatis-version}
58 |
59 | ----
60 |
61 | == Creating the User POJO
62 | We are going to create a `User` POJO to access to the data in the backend mysql server.
63 | Create the `src/main/java/org/acme/mybatis/User.java` file, with the following content:
64 |
65 | [source, java]
66 | ----
67 | package org.acme.mybatis;
68 |
69 | public class User {
70 | private Integer id;
71 | private String name;
72 |
73 | public Integer getId() {
74 | return id;
75 | }
76 |
77 | public void setId(Integer id) {
78 | this.id = id;
79 | }
80 |
81 | public String getName() {
82 | return name;
83 | }
84 |
85 | public void setName(String name) {
86 | this.name = name;
87 | }
88 | }
89 | ----
90 |
91 | == Creating the User Mapper
92 | We are going to create a `UserMapper` class which will use the MyBatis annotations to inject the SQL.
93 | Create the `src/main/java/org/acme/mybatis/UserMapper.java` file, with the following content:
94 |
95 | [source, java]
96 | ----
97 | package org.acme.mybatis;
98 |
99 | import org.apache.ibatis.annotations.Delete;
100 | import org.apache.ibatis.annotations.Insert;
101 | import org.apache.ibatis.annotations.Mapper;
102 | import org.apache.ibatis.annotations.Param;
103 | import org.apache.ibatis.annotations.Select;
104 |
105 | @Mapper
106 | public interface UserMapper {
107 |
108 | @Select("SELECT * FROM USERS WHERE id = #{id}")
109 | User getUser(Integer id); // <1>
110 |
111 | @Insert("INSERT INTO USERS (id, name) VALUES (#{id}, #{name})")
112 | Integer createUser(@Param("id") Integer id, @Param("name") String name); // <2>
113 |
114 | @Delete("DELETE FROM USERS WHERE id = #{id}")
115 | Integer removeUser(Integer id); // <3>
116 | }
117 | ----
118 |
119 | 1. Get a user from the database.
120 | 2. Insert a user into the database. We should use the `@Param` to bind the parameters.
121 | 3. Delete a user from the databse.
122 |
123 | == Creating the MyBatisResource to handle the requests
124 | We are going to create a `MyBatisResource` class which will handle all the requests to create, query or remove the data
125 | from the database.
126 |
127 | [source, java]
128 | ----
129 | package org.acme.mybatis;
130 |
131 | import jakarta.inject.Inject;
132 | import jakarta.ws.rs.Consumes;
133 | import jakarta.ws.rs.DELETE;
134 | import jakarta.ws.rs.FormParam;
135 | import jakarta.ws.rs.GET;
136 | import jakarta.ws.rs.POST;
137 | import jakarta.ws.rs.Path;
138 | import jakarta.ws.rs.PathParam;
139 | import jakarta.ws.rs.Produces;
140 | import jakarta.ws.rs.core.MediaType;
141 |
142 | @Path("/mybatis")
143 | public class MyBatisResource {
144 |
145 | @Inject
146 | UserMapper userMapper; // <1>
147 |
148 | @Path("/user/{id}")
149 | @GET
150 | @Produces(MediaType.APPLICATION_JSON)
151 | public User getUser(@PathParam("id") Integer id) {
152 | return userMapper.getUser(id);
153 | }
154 |
155 | @Path("/user")
156 | @POST
157 | @Produces(MediaType.TEXT_PLAIN)
158 | @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
159 | public Integer createUser(@FormParam("id") Integer id, @FormParam("name") String name) {
160 | return userMapper.createUser(id, name);
161 | }
162 |
163 | @Path("/user/{id}")
164 | @DELETE
165 | @Produces(MediaType.TEXT_PLAIN)
166 | public Integer removeUser(@PathParam("id") Integer id) {
167 | return userMapper.removeUser(id);
168 | }
169 | }
170 | ----
171 | 1. It uses the UserMapper which should be injected by the Quarkus to access the database.
172 |
173 | == Configure the properties
174 |
175 | We need to config the datasource used to connect to the database and the mybatis will choose the default one. Also you
176 | can use ```quarkus.mybatis.datasource``` for the specific database.
177 |
178 | [source]
179 | ----
180 | quarkus.datasource.db-kind=mysql
181 | quarkus.datasource.username=
182 |
183 | quarkus.datasource.jdbc.url=jdbc:mysql://localhost/test #<1>
184 | quarkus.mybatis.initial-sql=insert.sql #<2>
185 | ----
186 |
187 | 1. The datasource used by the mybatis to connect the database.
188 | 2. The SQL file which should be executed just after the application is started.
189 |
190 | We could keep the following content in the `insert.sql` to add some data:
191 | [source, sql]
192 | ----
193 | DROP TABLE IF EXISTS USERS;
194 |
195 | CREATE TABLE USERS (
196 | id integer not null primary key,
197 | name varchar(80) not null
198 | );
199 |
200 | INSERT INTO USERS (id, name) values(1, 'Test User1');
201 | INSERT INTO USERS (id, name) values(2, 'Test User2');
202 | INSERT INTO USERS (id, name) values(3, 'Test User3');
203 | ----
204 |
205 | == Running with the JVM mode
206 | At first, you should make sure the Mysql Server is running and the `test` database has been created.
207 | Then, you just need to run:
208 |
209 | [source, shell]
210 | ----
211 | ./mvnw compile quarkus:dev
212 | ----
213 |
214 | You can get the user by using the following command:
215 |
216 | [source, shell]
217 | ----
218 | curl http://localhost:8080/mybatis/user/1
219 | ----
220 |
221 | Or create a new user:
222 |
223 | [source, shell]
224 | ----
225 | curl -X POST http://localhost:8080/mybatis/user -d 'id=4&name=test'
226 | ----
227 |
228 | Or remove a user:
229 |
230 | [source, shell]
231 | ----
232 | curl -X DELETE http://localhost:8080/mybatis/user/1
233 | ----
234 |
235 | == Running Native
236 | You can build the native executable with:
237 |
238 | [source, shell]
239 | ----
240 | ./mvnw package -Pnative
241 | ----
242 |
243 | and then run with:
244 |
245 | [source, shell]
246 | ----
247 | ./target/mybatis-quickstart-1.0-SNAPSHOT-runner
248 | ----
249 |
250 | == Support for multiple data sources
251 | You can choose a specific data source for MyBatis mapper using the annotation `@MapperDataSource`.
252 | Query in the next example will be running against data source with name `user`.
253 | If there is no such annotation on the mapper, the default data source will be used.
254 |
255 | [source, java]
256 | ----
257 | @Mapper
258 | @MapperDataSource("user")
259 | public interface UserMapper {
260 | @Select("SELECT * FROM USERS WHERE id = #{id}")
261 | User getUser(Integer id);
262 | }
263 | ----
264 |
265 | == CDI integration
266 | Injects default session factory:
267 |
268 | [source, java]
269 | ----
270 | @Inject
271 | SqlSessionFactory sqlSessionFactory;
272 | ----
273 |
274 | Injects session factory for data source `user`:
275 |
276 | [source, java]
277 | ----
278 | @Named("user")
279 | SqlSessionFactory sqlSessionFactory;
280 | ----
281 |
282 | == XML Configuration Support
283 |
284 | You need to set ```quarkus.mybatis.xmlconfig.enable``` to ```true``` and set ```quarkus.mybatis.xmlconfig.path``` to the
285 | mybatis xml configuration which the default value is ```mybatis-config.xml```.
286 | Aslo ```quarkus.mybatis.environment``` is relevant to the element of ```environment``` in the xml configuration file.
287 |
288 | [source, text]
289 | ----
290 | # H2
291 | quarkus.datasource.h2.db-kind=h2
292 | quarkus.datasource.h2.username=sa
293 | quarkus.datasource.h2.password=sa
294 | quarkus.datasource.h2.jdbc.url=jdbc:h2:tcp://localhost/mem:default
295 |
296 | # MyBatis
297 | quarkus.mybatis.xmlconfig.enable=true
298 | quarkus.mybatis.xmlconfig.path=mybatis-config.xml
299 | quarkus.mybatis.environment=development
300 | quarkus.mybatis.h2.initial-sql=insert-h2.sql
301 | ----
302 |
303 | [source, xml]
304 | ----
305 |
308 |
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 | ----
329 |
330 | The dataSource type must be ```QUARKUS``` and the property ```db``` could be specified to the datasource name in the
331 | quarkus configuration.
332 |
333 |
334 | == Configuration References
335 | include::includes/quarkus-mybatis.adoc[opts=optional, leveloffset=+1]
336 |
--------------------------------------------------------------------------------
/mybatis/docs/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | io.quarkiverse.mybatis
6 | quarkus-mybatis-parent
7 | 999-SNAPSHOT
8 | ../pom.xml
9 |
10 |
11 | quarkus-mybatis-docs
12 | Quarkus - MyBatis - Documentation
13 |
14 |
15 | 3.0.0
16 | 3.2.0
17 | 1.1.3
18 |
19 |
20 |
21 |
22 |
23 | io.quarkiverse.mybatis
24 | quarkus-mybatis-deployment
25 | ${project.version}
26 |
27 |
28 |
29 |
30 |
31 |
32 | it.ozimov
33 | yaml-properties-maven-plugin
34 | ${yaml-properties-maven-plugin.version}
35 |
36 |
37 | initialize
38 |
39 | read-project-properties
40 |
41 |
42 |
43 | ${project.basedir}/../../.github/project.yml
44 |
45 |
46 |
47 |
48 |
49 |
50 | maven-resources-plugin
51 |
52 |
53 | copy-resources
54 | generate-resources
55 |
56 | copy-resources
57 |
58 |
59 | ${project.basedir}/modules/ROOT/pages/includes/
60 |
61 |
62 | ${project.basedir}/../target/asciidoc/generated/config/
63 | quarkus-mybatis.adoc
64 | false
65 |
66 |
67 | ${project.basedir}/templates/includes
68 | attributes.adoc
69 | true
70 |
71 |
72 |
73 |
74 |
75 | copy-images
76 | generate-resources
77 |
78 | copy-resources
79 |
80 |
81 | ${project.build.directory}/generated-docs/_images/
82 |
83 |
84 | ${project.basedir}/modules/ROOT/assets/images/
85 | false
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | org.asciidoctor
94 | asciidoctor-maven-plugin
95 | ${asciidoctor-maven-plugin.version}
96 |
97 | ${skipDocs}
98 | true
99 |
100 |
101 | WARN
102 |
103 |
104 | ${project.basedir}/modules/ROOT/pages/
105 | true
106 |
107 | font
108 |
109 | ./_images/
110 | true
111 |
112 |
113 | -
114 | true
115 |
116 | true
117 |
118 |
119 |
120 |
121 | output-html
122 | prepare-package
123 |
124 | process-asciidoc
125 |
126 |
127 | ${skipDocs}
128 | html5
129 |
130 | coderay
131 |
132 | true
133 | true
134 |
135 |
136 |
137 |
138 |
139 |
140 | org.asciidoctor
141 | asciidoctorj
142 | ${asciidoctorj.version}
143 |
144 |
145 |
146 |
147 |
148 |
149 |
--------------------------------------------------------------------------------
/mybatis/docs/templates/includes/attributes.adoc:
--------------------------------------------------------------------------------
1 | :quarkus-version: ${quarkus.version}
2 | :quarkus-mybatis-version: ${release.current-version}
3 |
4 | :mybatis-root-url: https://mybatis.org/mybatis-3/
5 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | io.quarkiverse.mybatis
5 | quarkus-mybatis-parent
6 | 999-SNAPSHOT
7 | ../
8 |
9 | 4.0.0
10 |
11 | quarkus-mybatis-integration-tests
12 | Quarkus - MyBatis - Integration Tests
13 | The mybatis integration tests module
14 |
15 |
16 | true
17 | true
18 | ${skipTests}
19 | ${skipTests}
20 |
21 |
22 |
23 |
24 | io.quarkus
25 | quarkus-resteasy
26 |
27 |
28 | io.quarkus
29 | quarkus-resteasy-jackson
30 |
31 |
32 | io.quarkiverse.mybatis
33 | quarkus-mybatis
34 | ${project.version}
35 |
36 |
37 | io.quarkus
38 | quarkus-jdbc-h2
39 |
40 |
41 | io.quarkus
42 | quarkus-jdbc-derby
43 |
44 |
45 |
46 |
47 | io.quarkus
48 | quarkus-junit5
49 | test
50 |
51 |
52 | io.rest-assured
53 | rest-assured
54 | test
55 |
56 |
57 | io.quarkus
58 | quarkus-test-h2
59 | test
60 |
61 | io.quarkus
62 | quarkus-test-derby
63 | test
64 |
65 |
66 |
67 |
68 |
69 |
70 | io.quarkus
71 | quarkus-maven-plugin
72 | ${quarkus.version}
73 |
74 | true
75 | ${quarkus.build.skip}
76 |
77 |
78 |
79 |
80 | build
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | native-image
91 |
92 |
93 | native
94 |
95 |
96 |
97 | native
98 |
99 |
100 |
101 |
102 | org.apache.maven.plugins
103 | maven-failsafe-plugin
104 |
105 |
106 |
107 | integration-test
108 | verify
109 |
110 |
111 |
112 | ${project.build.directory}/${project.build.finalName}-runner
113 | org.jboss.logmanager.LogManager
114 | ${maven.home}
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/main/java/io/quarkiverse/it/mybatis/Book.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis;
2 |
3 | import java.io.Serializable;
4 |
5 | public class Book implements Serializable {
6 | private Integer id;
7 | private User author;
8 | private String title;
9 |
10 | public Integer getId() {
11 | return id;
12 | }
13 |
14 | public void setId(Integer id) {
15 | this.id = id;
16 | }
17 |
18 | public User getAuthor() {
19 | return author;
20 | }
21 |
22 | public void setAuthor(User author) {
23 | this.author = author;
24 | }
25 |
26 | public String getTitle() {
27 | return title;
28 | }
29 |
30 | public void setTitle(String title) {
31 | this.title = title;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/main/java/io/quarkiverse/it/mybatis/BookMapper.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis;
2 |
3 | import org.apache.ibatis.annotations.CacheNamespace;
4 | import org.apache.ibatis.annotations.Mapper;
5 | import org.apache.ibatis.annotations.One;
6 | import org.apache.ibatis.annotations.Result;
7 | import org.apache.ibatis.annotations.Results;
8 | import org.apache.ibatis.annotations.Select;
9 |
10 | @Mapper
11 | @CacheNamespace
12 | public interface BookMapper {
13 | @Select("SELECT id, author_id, title from books where id = #{id}")
14 | @Results(value = {
15 | @Result(property = "id", column = "id"),
16 | @Result(property = "author", column = "author_id", javaType = User.class, one = @One(select = "getUser"))
17 | })
18 | Book getBook(Integer id);
19 |
20 | @Select("select * from users where id = #{id}")
21 | User getUser(Integer id);
22 |
23 | Book findById(Integer id);
24 | }
25 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/main/java/io/quarkiverse/it/mybatis/DerbyUserMapper.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis;
2 |
3 | import org.apache.ibatis.annotations.Mapper;
4 | import org.apache.ibatis.annotations.Select;
5 |
6 | import io.quarkiverse.mybatis.runtime.meta.MapperDataSource;
7 |
8 | @Mapper
9 | @MapperDataSource("derby")
10 | public interface DerbyUserMapper {
11 | @Select("select count(*) from users")
12 | int getUserCount();
13 |
14 | User findById(Integer id);
15 | }
16 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/main/java/io/quarkiverse/it/mybatis/MyBatisResource.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 | import java.util.UUID;
6 |
7 | import jakarta.inject.Inject;
8 | import jakarta.transaction.Transactional;
9 | import jakarta.ws.rs.Consumes;
10 | import jakarta.ws.rs.DELETE;
11 | import jakarta.ws.rs.FormParam;
12 | import jakarta.ws.rs.GET;
13 | import jakarta.ws.rs.POST;
14 | import jakarta.ws.rs.Path;
15 | import jakarta.ws.rs.PathParam;
16 | import jakarta.ws.rs.Produces;
17 | import jakarta.ws.rs.core.MediaType;
18 |
19 | import org.apache.ibatis.cursor.Cursor;
20 |
21 | @Path("/mybatis")
22 | public class MyBatisResource {
23 |
24 | @Inject
25 | UserMapper userMapper;
26 |
27 | @Inject
28 | BookMapper bookMapper;
29 |
30 | @Inject
31 | DerbyUserMapper derbyUserMapper;
32 |
33 | @Path("/user/{id}")
34 | @GET
35 | @Produces(MediaType.APPLICATION_JSON)
36 | @Transactional
37 | public User getUser(@PathParam("id") Integer id) {
38 | return userMapper.getUser(id);
39 | }
40 |
41 | @Path("/user/dynamic/{id}")
42 | @GET
43 | @Produces(MediaType.APPLICATION_JSON)
44 | public User getDynamicUser(@PathParam("id") Integer id) {
45 | return userMapper.selectOne(id);
46 | }
47 |
48 | @Path("/user")
49 | @POST
50 | @Produces(MediaType.TEXT_PLAIN)
51 | @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
52 | public Integer createUser(@FormParam("id") Integer id, @FormParam("name") String name,
53 | @FormParam("externalId") UUID externalId) {
54 | return userMapper.createUser(id, name, externalId);
55 | }
56 |
57 | @Path("/user/{id}")
58 | @DELETE
59 | @Produces(MediaType.TEXT_PLAIN)
60 | public Integer removeUser(@PathParam("id") Integer id) {
61 | return userMapper.removeUser(id);
62 | }
63 |
64 | @Path("/user/count/h2")
65 | @GET
66 | @Produces(MediaType.APPLICATION_JSON)
67 | public int getUserCount() {
68 | return userMapper.getUserCount();
69 | }
70 |
71 | @Path("/user/count/derby")
72 | @GET
73 | @Produces(MediaType.APPLICATION_JSON)
74 | public int getDerbyUserCount() {
75 | return derbyUserMapper.getUserCount();
76 | }
77 |
78 | @Path("/user/cursor")
79 | @GET
80 | @Produces(MediaType.APPLICATION_JSON)
81 | @Transactional
82 | public List getUserCursor() throws Exception {
83 | List result = new ArrayList<>();
84 | try (Cursor cursor = userMapper.selectCursor()) {
85 | for (String name : cursor) {
86 | result.add(name);
87 | }
88 | }
89 | return result;
90 | }
91 |
92 | @Path("/book/{id}")
93 | @GET
94 | @Produces(MediaType.APPLICATION_JSON)
95 | public Book getBook(@PathParam("id") Integer id) {
96 | return bookMapper.getBook(id);
97 | }
98 |
99 | @Path("/book/xmlMapper/{id}")
100 | @GET
101 | @Produces(MediaType.APPLICATION_JSON)
102 | public Book findBookById(@PathParam("id") Integer id) {
103 | return bookMapper.findById(id);
104 | }
105 |
106 | @Path("/user/xmlMapper/{id}")
107 | @GET
108 | @Produces(MediaType.APPLICATION_JSON)
109 | public User findUserById(@PathParam("id") Integer id) {
110 | return userMapper.findById(id);
111 | }
112 |
113 | @Path("/user/xmlMapper/derby/{id}")
114 | @GET
115 | @Produces(MediaType.APPLICATION_JSON)
116 | public User findDerbyUserById(@PathParam("id") Integer id) {
117 | return derbyUserMapper.findById(id);
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/main/java/io/quarkiverse/it/mybatis/PageConfigurationFactory.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis;
2 |
3 | import org.apache.ibatis.plugin.Interceptor;
4 | import org.apache.ibatis.plugin.Invocation;
5 | import org.apache.ibatis.session.Configuration;
6 |
7 | public class PageConfigurationFactory {
8 | public Configuration getConfiguration() {
9 | Configuration configuration = new Configuration();
10 | configuration.addInterceptor(new PageInterceptor());
11 | return configuration;
12 | }
13 | }
14 |
15 | class PageInterceptor implements Interceptor {
16 |
17 | @Override
18 | public Object intercept(Invocation invocation) throws Throwable {
19 | return invocation.proceed();
20 | }
21 | }
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/main/java/io/quarkiverse/it/mybatis/SqlProviderAdapter.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis;
2 |
3 | public class SqlProviderAdapter {
4 | public static String select() {
5 | return "select * from users where id = #{id}";
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/main/java/io/quarkiverse/it/mybatis/User.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis;
2 |
3 | import java.io.Serializable;
4 | import java.util.UUID;
5 |
6 | public class User implements Serializable {
7 | private Integer id;
8 | private String name;
9 | private UUID externalId;
10 |
11 | public Integer getId() {
12 | return id;
13 | }
14 |
15 | public void setId(Integer id) {
16 | this.id = id;
17 | }
18 |
19 | public String getName() {
20 | return name;
21 | }
22 |
23 | public void setName(String name) {
24 | this.name = name;
25 | }
26 |
27 | public UUID getExternalId() {
28 | return externalId;
29 | }
30 |
31 | public void setExternalId(UUID externalId) {
32 | this.externalId = externalId;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/main/java/io/quarkiverse/it/mybatis/UserMapper.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis;
2 |
3 | import java.util.UUID;
4 |
5 | import org.apache.ibatis.annotations.CacheNamespace;
6 | import org.apache.ibatis.annotations.Delete;
7 | import org.apache.ibatis.annotations.Insert;
8 | import org.apache.ibatis.annotations.Mapper;
9 | import org.apache.ibatis.annotations.Param;
10 | import org.apache.ibatis.annotations.Select;
11 | import org.apache.ibatis.annotations.SelectProvider;
12 | import org.apache.ibatis.cursor.Cursor;
13 |
14 | @Mapper
15 | @CacheNamespace(readWrite = false)
16 | public interface UserMapper {
17 |
18 | @Select("select * from users where id = #{id}")
19 | User getUser(Integer id);
20 |
21 | @Insert("insert into users (id, name, externalId) values (#{id}, #{name}, #{externalId,jdbcType=OTHER})")
22 | Integer createUser(@Param("id") Integer id, @Param("name") String name, @Param("externalId") UUID externalId);
23 |
24 | @Delete("delete from users where id = #{id}")
25 | Integer removeUser(Integer id);
26 |
27 | @SelectProvider(type = SqlProviderAdapter.class, method = "select")
28 | User selectOne(Integer id);
29 |
30 | @Select("select count(*) from users")
31 | int getUserCount();
32 |
33 | @Select("select name from users")
34 | Cursor selectCursor();
35 |
36 | User findById(Integer id);
37 | }
38 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/main/java/io/quarkiverse/it/mybatis/UuidJdbcTypeHandler.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis;
2 |
3 | import java.sql.*;
4 | import java.util.UUID;
5 |
6 | import org.apache.ibatis.type.BaseTypeHandler;
7 | import org.apache.ibatis.type.JdbcType;
8 | import org.apache.ibatis.type.MappedJdbcTypes;
9 |
10 | @MappedJdbcTypes(value = JdbcType.OTHER, includeNullJdbcType = true)
11 | public class UuidJdbcTypeHandler extends BaseTypeHandler {
12 |
13 | public static UUID fromStringAllowNulls(String uuid) {
14 | if (uuid == null || uuid.trim().equals("")) {
15 | return null;
16 | } else {
17 | return UUID.fromString(uuid);
18 | }
19 | }
20 |
21 | @Override
22 | public void setNonNullParameter(PreparedStatement ps, int i, UUID parameter, JdbcType jdbcType) throws SQLException {
23 | // note the difference in how H2 wants to persist a UUID
24 | ps.setObject(i, parameter);
25 | }
26 |
27 | @Override
28 | public UUID getNullableResult(ResultSet rs, String columnName) throws SQLException {
29 | return fromStringAllowNulls(rs.getString(columnName));
30 | }
31 |
32 | @Override
33 | public UUID getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
34 | return fromStringAllowNulls(rs.getString(columnIndex));
35 | }
36 |
37 | @Override
38 | public UUID getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
39 | return fromStringAllowNulls(cs.getString(columnIndex));
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/main/java/io/quarkiverse/it/mybatis/UuidTypeHandler.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis;
2 |
3 | import java.sql.*;
4 | import java.util.UUID;
5 |
6 | import org.apache.ibatis.type.BaseTypeHandler;
7 | import org.apache.ibatis.type.JdbcType;
8 | import org.apache.ibatis.type.MappedTypes;
9 |
10 | @MappedTypes(UUID.class)
11 | public class UuidTypeHandler extends BaseTypeHandler {
12 |
13 | public static UUID fromStringAllowNulls(String uuid) {
14 | if (uuid == null || uuid.trim().equals("")) {
15 | return null;
16 | } else {
17 | return UUID.fromString(uuid);
18 | }
19 | }
20 |
21 | @Override
22 | public void setNonNullParameter(PreparedStatement ps, int i, UUID parameter, JdbcType jdbcType) throws SQLException {
23 | // note the difference in how H2 wants to persist a UUID
24 | ps.setObject(i, parameter);
25 | }
26 |
27 | @Override
28 | public UUID getNullableResult(ResultSet rs, String columnName) throws SQLException {
29 | return fromStringAllowNulls(rs.getString(columnName));
30 | }
31 |
32 | @Override
33 | public UUID getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
34 | return fromStringAllowNulls(rs.getString(columnIndex));
35 | }
36 |
37 | @Override
38 | public UUID getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
39 | return fromStringAllowNulls(cs.getString(columnIndex));
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/main/resources/application-xml.properties:
--------------------------------------------------------------------------------
1 | quarkus.mybatis.xmlconfig.enable=true
2 | quarkus.mybatis.environment=development
3 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | # H2
2 | quarkus.datasource.db-kind=h2
3 | quarkus.datasource.username=username-default
4 | quarkus.datasource.jdbc.url=jdbc:h2:tcp://localhost/mem:default
5 | quarkus.mybatis.initial-sql=insert.sql
6 | quarkus.mybatis.configuration-factory=io.quarkiverse.it.mybatis.PageConfigurationFactory
7 |
8 | # Derby
9 | quarkus.datasource.derby.db-kind=derby
10 | quarkus.datasource.derby.jdbc.url=jdbc:derby://localhost:1527/memory:testDB;create=true
11 | quarkus.mybatis.derby.initial-sql=insert-derby.sql
12 |
13 | quarkus.mybatis.mapper-locations=mapper,otherMapper/
14 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/main/resources/insert-derby.sql:
--------------------------------------------------------------------------------
1 | CREATE TABLE USERS (
2 | id integer not null primary key,
3 | name varchar(80) not null,
4 | external_id varchar(50) not null
5 | );
6 |
7 | DELETE FROM users;
8 | insert into users (id, name, external_id) values (1, 'Test User1', 'ccb16b65-8924-4c3f-8c55-681d85a16e79');
9 | insert into users (id, name, external_id) values (2, 'Test User2', 'ae43f233-0b69-4c4e-bfa9-656c475150ad');
10 | insert into users (id, name, external_id) values (3, 'Test User3', '5640e179-466c-427e-9747-4cfac09a2f9a');
11 | insert into users (id, name, external_id) values (4, 'Test User4', '5640e179-466c-427e-9747-4cfacsfdsdfd');
12 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/main/resources/insert.sql:
--------------------------------------------------------------------------------
1 | DROP TABLE USERS IF EXISTS;
2 | DROP TABLE BOOKS IF EXISTS;
3 |
4 | CREATE TABLE USERS (
5 | id integer not null primary key,
6 | name varchar(80) not null,
7 | externalId uuid not null
8 | );
9 |
10 | CREATE TABLE BOOKS (
11 | id integer not null primary key,
12 | title varchar(80) not null,
13 | author_id integer not null,
14 |
15 | foreign key(author_id) references USERS(id)
16 | );
17 |
18 | DELETE FROM users;
19 | insert into users (id, name, externalId) values (1, 'Test User1', 'ccb16b65-8924-4c3f-8c55-681d85a16e79');
20 | insert into users (id, name, externalId) values (2, 'Test User2', 'ae43f233-0b69-4c4e-bfa9-656c475150ad');
21 | insert into users (id, name, externalId) values (3, 'Test User3', '5640e179-466c-427e-9747-4cfac09a2f9a');
22 |
23 | DELETE from books;
24 | insert into books(id, title, author_id) values (1, 'Test Title', 1);
25 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/main/resources/mapper/DerbyUserMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | select * from users where id=#{id}
11 |
12 |
13 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/main/resources/mapper/UserMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | select * from users where id=#{id}
11 |
12 |
13 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/main/resources/mybatis-config.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/main/resources/otherMapper/BookMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | select b.id as book_id,
16 | b.title,
17 | u.id,
18 | u.name,
19 | u.externalId
20 | from books as b left join users as u on b.author_id=u.id where b.id=#{id}
21 |
22 |
23 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/test/java/io/quarkiverse/it/mybatis/BaseMyBatisTestCase.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis;
2 |
3 | import static org.hamcrest.core.Is.is;
4 |
5 | import java.util.UUID;
6 |
7 | import io.restassured.RestAssured;
8 |
9 | public class BaseMyBatisTestCase {
10 |
11 | public void runTest() {
12 | RestAssured.when().get("/mybatis/user/1").then()
13 | .body(is("{\"id\":1,\"name\":\"Test User1\",\"externalId\":\"ccb16b65-8924-4c3f-8c55-681d85a16e79\"}"));
14 |
15 | RestAssured.when().get("/mybatis/user/dynamic/1").then()
16 | .body(is("{\"id\":1,\"name\":\"Test User1\",\"externalId\":\"ccb16b65-8924-4c3f-8c55-681d85a16e79\"}"));
17 |
18 | RestAssured.given().param("id", "5")
19 | .param("name", "New User")
20 | .param("externalId", UUID.fromString("9b036c98-eb1d-4580-a8bb-1115d7a3cd44"))
21 | .post("/mybatis/user")
22 | .then().body(is("1"));
23 |
24 | RestAssured.when().delete("/mybatis/user/3").then()
25 | .body(is("1"));
26 |
27 | RestAssured.when().get("/mybatis/book/1").then()
28 | .body(is(
29 | "{\"id\":1,\"author\":{\"id\":1,\"name\":\"Test User1\",\"externalId\":\"ccb16b65-8924-4c3f-8c55-681d85a16e79\"},\"title\":\"Test Title\"}"));
30 |
31 | RestAssured.when().get("/mybatis/book/xmlMapper/1").then()
32 | .body(is(
33 | "{\"id\":1,\"author\":{\"id\":1,\"name\":\"Test User1\",\"externalId\":\"ccb16b65-8924-4c3f-8c55-681d85a16e79\"},\"title\":\"Test Title\"}"));
34 |
35 | RestAssured.when().get("/mybatis/user/xmlMapper/1").then()
36 | .body(is("{\"id\":1,\"name\":\"Test User1\",\"externalId\":\"ccb16b65-8924-4c3f-8c55-681d85a16e79\"}"));
37 |
38 | RestAssured.when().get("/mybatis/user/xmlMapper/derby/1").then()
39 | .body(is("{\"id\":1,\"name\":\"Test User1\",\"externalId\":\"ccb16b65-8924-4c3f-8c55-681d85a16e79\"}"));
40 |
41 | RestAssured.when().get("/mybatis/user/cursor").then()
42 | .body(is("[\"Test User1\",\"Test User2\",\"New User\"]"));
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/test/java/io/quarkiverse/it/mybatis/MultipleDataSourcesTest.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis;
2 |
3 | import static org.hamcrest.core.Is.is;
4 |
5 | import org.junit.jupiter.api.Test;
6 |
7 | import io.quarkus.test.junit.QuarkusTest;
8 | import io.restassured.RestAssured;
9 |
10 | @QuarkusTest
11 | class MultipleDataSourcesTest {
12 | @Test
13 | public void test() {
14 | RestAssured.when().get("/mybatis/user/count/h2").then()
15 | .body(is("3"));
16 |
17 | RestAssured.when().get("/mybatis/user/count/derby").then()
18 | .body(is("4"));
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/test/java/io/quarkiverse/it/mybatis/MyBatisIT.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis;
2 |
3 | import io.quarkus.test.junit.QuarkusIntegrationTest;
4 |
5 | @QuarkusIntegrationTest
6 | class MyBatisIT extends MyBatisTest {
7 |
8 | }
9 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/test/java/io/quarkiverse/it/mybatis/MyBatisTest.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis;
2 |
3 | import org.junit.jupiter.api.Test;
4 |
5 | import io.quarkus.test.junit.QuarkusTest;
6 |
7 | @QuarkusTest
8 | class MyBatisTest extends BaseMyBatisTestCase {
9 |
10 | @Test
11 | void test() {
12 | runTest();
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/test/java/io/quarkiverse/it/mybatis/MyBatisXmlConfigIT.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis;
2 |
3 | import io.quarkus.test.junit.QuarkusIntegrationTest;
4 |
5 | @QuarkusIntegrationTest
6 | public class MyBatisXmlConfigIT extends MyBatisXmlConfigTest {
7 | }
8 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/test/java/io/quarkiverse/it/mybatis/MyBatisXmlConfigTest.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis;
2 |
3 | import org.junit.jupiter.api.Test;
4 |
5 | import io.quarkus.test.junit.QuarkusTest;
6 | import io.quarkus.test.junit.TestProfile;
7 |
8 | @QuarkusTest
9 | @TestProfile(XmlConfigProfile.class)
10 | public class MyBatisXmlConfigTest extends BaseMyBatisTestCase {
11 |
12 | @Test
13 | void test() {
14 | runTest();
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/test/java/io/quarkiverse/it/mybatis/TestResources.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis;
2 |
3 | import io.quarkus.test.common.QuarkusTestResource;
4 | import io.quarkus.test.derby.DerbyDatabaseTestResource;
5 | import io.quarkus.test.h2.H2DatabaseTestResource;
6 |
7 | @QuarkusTestResource(H2DatabaseTestResource.class)
8 | @QuarkusTestResource(DerbyDatabaseTestResource.class)
9 | public class TestResources {
10 | }
11 |
--------------------------------------------------------------------------------
/mybatis/integration-tests/src/test/java/io/quarkiverse/it/mybatis/XmlConfigProfile.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.it.mybatis;
2 |
3 | import io.quarkus.test.junit.QuarkusTestProfile;
4 |
5 | public class XmlConfigProfile implements QuarkusTestProfile {
6 | @Override
7 | public String getConfigProfile() {
8 | return "xml";
9 | }
10 | }
--------------------------------------------------------------------------------
/mybatis/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 |
6 | io.quarkiverse.mybatis
7 | quarkus-parent
8 | 999-SNAPSHOT
9 |
10 |
11 | quarkus-mybatis-parent
12 | Quarkus - Mybatis - Parent
13 | pom
14 |
15 |
16 | deployment
17 | runtime
18 | docs
19 |
20 |
21 |
22 |
23 | it
24 |
25 |
26 | performRelease
27 | !true
28 |
29 |
30 |
31 | integration-tests
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/mybatis/runtime/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | io.quarkiverse.mybatis
5 | quarkus-mybatis-parent
6 | 999-SNAPSHOT
7 | ../
8 |
9 | 4.0.0
10 |
11 | quarkus-mybatis
12 | Quarkus - Mybatis - Runtime
13 | MyBatis SQL mapper framework for Java
14 |
15 |
16 |
17 | io.quarkus
18 | quarkus-arc
19 |
20 |
21 | io.quarkus
22 | quarkus-agroal
23 |
24 |
25 | org.mybatis
26 | mybatis
27 |
28 |
29 | org.graalvm.sdk
30 | nativeimage
31 |
32 |
33 |
34 |
35 |
36 |
37 | io.quarkus
38 | quarkus-extension-maven-plugin
39 | ${quarkus.version}
40 |
41 |
42 |
43 | extension-descriptor
44 |
45 | compile
46 |
47 | ${project.groupId}:${project.artifactId}-deployment:${project.version}
48 |
49 |
50 |
51 |
52 |
53 |
54 | maven-compiler-plugin
55 |
56 |
57 |
58 | io.quarkus
59 | quarkus-extension-processor
60 | ${quarkus.version}
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/mybatis/runtime/src/main/java/io/quarkiverse/mybatis/runtime/ConfigurationFactory.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.runtime;
2 |
3 | import org.apache.ibatis.session.Configuration;
4 |
5 | public interface ConfigurationFactory {
6 | Configuration createConfiguration();
7 |
8 | default boolean isOverrideSetting() {
9 | return false;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/mybatis/runtime/src/main/java/io/quarkiverse/mybatis/runtime/MyBatisConfigurationFactory.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.runtime;
2 |
3 | import org.apache.ibatis.session.Configuration;
4 |
5 | public class MyBatisConfigurationFactory implements ConfigurationFactory {
6 | @Override
7 | public Configuration createConfiguration() {
8 | return new Configuration();
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/mybatis/runtime/src/main/java/io/quarkiverse/mybatis/runtime/MyBatisXMLConfigDelegateBuilder.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.runtime;
2 |
3 | import java.io.Reader;
4 |
5 | import org.apache.ibatis.builder.xml.XMLConfigBuilder;
6 | import org.apache.ibatis.io.Resources;
7 | import org.apache.ibatis.session.Configuration;
8 |
9 | import io.quarkiverse.mybatis.runtime.config.MyBatisRuntimeConfig;
10 |
11 | public class MyBatisXMLConfigDelegateBuilder implements XMLConfigDelegateBuilder {
12 | private XMLConfigBuilder builder;
13 | private MyBatisRuntimeConfig config;
14 |
15 | public MyBatisXMLConfigDelegateBuilder() {
16 |
17 | }
18 |
19 | @Override
20 | public void setConfig(MyBatisRuntimeConfig config) {
21 | this.config = config;
22 | }
23 |
24 | @Override
25 | public Configuration getConfiguration() throws Exception {
26 | return getBuilder().getConfiguration();
27 | }
28 |
29 | @Override
30 | public Configuration parse() throws Exception {
31 | return getBuilder().parse();
32 | }
33 |
34 | private XMLConfigBuilder getBuilder() throws Exception {
35 | if (builder == null) {
36 | Reader reader = Resources.getResourceAsReader(config.xmlconfig().path());
37 | builder = new XMLConfigBuilder(reader, config.environment());
38 | }
39 | return builder;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/mybatis/runtime/src/main/java/io/quarkiverse/mybatis/runtime/QuarkusDataSourceFactory.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.runtime;
2 |
3 | import java.util.Properties;
4 |
5 | import javax.sql.DataSource;
6 |
7 | import org.apache.ibatis.datasource.DataSourceFactory;
8 |
9 | public class QuarkusDataSourceFactory implements DataSourceFactory {
10 | private Properties properties;
11 | private QuarkusDataSource dataSource;
12 |
13 | public QuarkusDataSourceFactory() {
14 | }
15 |
16 | @Override
17 | public void setProperties(Properties properties) {
18 | this.properties = properties;
19 | if (dataSource == null) {
20 | dataSource = new QuarkusDataSource(properties.getProperty("db", ""));
21 | }
22 | }
23 |
24 | @Override
25 | public DataSource getDataSource() {
26 | return dataSource;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/mybatis/runtime/src/main/java/io/quarkiverse/mybatis/runtime/QuarkusDatabaseIdProvider.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.runtime;
2 |
3 | import java.sql.SQLException;
4 |
5 | import javax.sql.DataSource;
6 |
7 | import org.apache.ibatis.mapping.DatabaseIdProvider;
8 | import org.eclipse.microprofile.config.ConfigProvider;
9 |
10 | public class QuarkusDatabaseIdProvider implements DatabaseIdProvider {
11 | @Override
12 | public String getDatabaseId(final DataSource dataSource) throws SQLException {
13 | if (dataSource instanceof QuarkusDataSource ds) {
14 | String name = ds.getDataSourceName();
15 | return ConfigProvider.getConfig().getOptionalValue(
16 | "quarkus.mybatis." + ("".equals(name) ? "" : name + ".") + "database-id", String.class)
17 | .orElse(null);
18 | }
19 | return null;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/mybatis/runtime/src/main/java/io/quarkiverse/mybatis/runtime/TransactionalSqlSession.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.runtime;
2 |
3 | import static java.lang.reflect.Proxy.newProxyInstance;
4 |
5 | import java.lang.reflect.InvocationHandler;
6 | import java.lang.reflect.Method;
7 | import java.sql.Connection;
8 | import java.util.List;
9 | import java.util.Map;
10 | import java.util.concurrent.ConcurrentHashMap;
11 |
12 | import jakarta.transaction.Status;
13 | import jakarta.transaction.Synchronization;
14 | import jakarta.transaction.Transaction;
15 | import jakarta.transaction.TransactionManager;
16 |
17 | import org.apache.ibatis.cursor.Cursor;
18 | import org.apache.ibatis.executor.BatchResult;
19 | import org.apache.ibatis.reflection.ExceptionUtil;
20 | import org.apache.ibatis.session.Configuration;
21 | import org.apache.ibatis.session.ResultHandler;
22 | import org.apache.ibatis.session.RowBounds;
23 | import org.apache.ibatis.session.SqlSession;
24 | import org.apache.ibatis.session.SqlSessionFactory;
25 |
26 | public class TransactionalSqlSession implements SqlSession {
27 | private final SqlSessionFactory sqlSessionFactory;
28 | private final TransactionManager transactionManager;
29 |
30 | private final SqlSession sqlSessionProxy;
31 |
32 | public TransactionalSqlSession(SqlSessionFactory sqlSessionFactory, TransactionManager transactionManager) {
33 | this.sqlSessionFactory = sqlSessionFactory;
34 | this.transactionManager = transactionManager;
35 | this.sqlSessionProxy = (SqlSession) newProxyInstance(SqlSession.class.getClassLoader(),
36 | new Class[] { SqlSession.class }, new TransactionalSqlSessionInterceptor());
37 | }
38 |
39 | @Override
40 | public T selectOne(String statement) {
41 | return this.sqlSessionProxy.selectOne(statement);
42 | }
43 |
44 | @Override
45 | public T selectOne(String statement, Object parameter) {
46 | return this.sqlSessionProxy.selectOne(statement, parameter);
47 | }
48 |
49 | @Override
50 | public List selectList(String statement) {
51 | return this.sqlSessionProxy.selectList(statement);
52 | }
53 |
54 | @Override
55 | public List selectList(String statement, Object parameter) {
56 | return this.sqlSessionProxy.selectList(statement, parameter);
57 | }
58 |
59 | @Override
60 | public List selectList(String statement, Object parameter, RowBounds rowBounds) {
61 | return this.sqlSessionProxy.selectList(statement, parameter, rowBounds);
62 | }
63 |
64 | @Override
65 | public Map selectMap(String statement, String mapKey) {
66 | return this.sqlSessionProxy.selectMap(statement, mapKey);
67 | }
68 |
69 | @Override
70 | public Map selectMap(String statement, Object parameter, String mapKey) {
71 | return this.sqlSessionProxy.selectMap(statement, parameter, mapKey);
72 | }
73 |
74 | @Override
75 | public Map selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
76 | return this.sqlSessionProxy.selectMap(statement, parameter, mapKey, rowBounds);
77 | }
78 |
79 | @Override
80 | public Cursor selectCursor(String statement) {
81 | return this.sqlSessionProxy.selectCursor(statement);
82 | }
83 |
84 | @Override
85 | public Cursor selectCursor(String statement, Object parameter) {
86 | return this.sqlSessionProxy.selectCursor(statement, parameter);
87 | }
88 |
89 | @Override
90 | public Cursor selectCursor(String statement, Object parameter, RowBounds rowBounds) {
91 | return this.sqlSessionProxy.selectCursor(statement, parameter, rowBounds);
92 | }
93 |
94 | @Override
95 | public void select(String statement, Object parameter, ResultHandler handler) {
96 | this.sqlSessionProxy.select(statement, parameter, handler);
97 | }
98 |
99 | @Override
100 | public void select(String statement, ResultHandler handler) {
101 | this.sqlSessionProxy.select(statement, handler);
102 | }
103 |
104 | @Override
105 | public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
106 | this.sqlSessionProxy.select(statement, parameter, rowBounds, handler);
107 | }
108 |
109 | @Override
110 | public int insert(String statement) {
111 | return this.sqlSessionProxy.insert(statement);
112 | }
113 |
114 | @Override
115 | public int insert(String statement, Object parameter) {
116 | return this.sqlSessionProxy.insert(statement, parameter);
117 | }
118 |
119 | @Override
120 | public int update(String statement) {
121 | return this.sqlSessionProxy.update(statement);
122 | }
123 |
124 | @Override
125 | public int update(String statement, Object parameter) {
126 | return this.sqlSessionProxy.update(statement, parameter);
127 | }
128 |
129 | @Override
130 | public int delete(String statement) {
131 | return this.sqlSessionProxy.delete(statement);
132 | }
133 |
134 | @Override
135 | public int delete(String statement, Object parameter) {
136 | return this.sqlSessionProxy.delete(statement, parameter);
137 | }
138 |
139 | @Override
140 | public void commit() {
141 | throw new UnsupportedOperationException("Manual close is not allowed over a Transactional SqlSession");
142 | }
143 |
144 | @Override
145 | public void commit(boolean force) {
146 | throw new UnsupportedOperationException("Manual close is not allowed over a Transactional SqlSession");
147 | }
148 |
149 | @Override
150 | public void rollback() {
151 | throw new UnsupportedOperationException("Manual close is not allowed over a Transactional SqlSession");
152 | }
153 |
154 | @Override
155 | public void rollback(boolean force) {
156 | throw new UnsupportedOperationException("Manual close is not allowed over a Transactional SqlSession");
157 | }
158 |
159 | @Override
160 | public List flushStatements() {
161 | return this.sqlSessionProxy.flushStatements();
162 | }
163 |
164 | @Override
165 | public void close() {
166 | throw new UnsupportedOperationException("Manual close is not allowed over a Transactional SqlSession");
167 | }
168 |
169 | @Override
170 | public void clearCache() {
171 | this.sqlSessionProxy.clearCache();
172 | }
173 |
174 | @Override
175 | public Configuration getConfiguration() {
176 | return this.sqlSessionFactory.getConfiguration();
177 | }
178 |
179 | @Override
180 | public T getMapper(Class type) {
181 | return getConfiguration().getMapper(type, this);
182 | }
183 |
184 | @Override
185 | public Connection getConnection() {
186 | return this.sqlSessionProxy.getConnection();
187 | }
188 |
189 | private class TransactionalSqlSessionInterceptor implements InvocationHandler {
190 | private final Map sqlSessionMap = new ConcurrentHashMap<>();
191 |
192 | @Override
193 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
194 | SqlSession sqlSession = null;
195 | try {
196 | sqlSession = getSqlSession();
197 | Object result = method.invoke(sqlSession, args);
198 | sqlSession.commit();
199 | return result;
200 | } catch (Throwable t) {
201 | sqlSession.rollback();
202 | throw ExceptionUtil.unwrapThrowable(t);
203 | } finally {
204 | if (!isTransactionActive() && sqlSession != null) {
205 | sqlSession.close();
206 | }
207 | }
208 | }
209 |
210 | private SqlSession getSqlSession() throws Exception {
211 | if (isTransactionActive()) {
212 | SqlSession sqlSession = sqlSessionMap.computeIfAbsent(transactionManager.getTransaction(),
213 | (transaction) -> {
214 | SqlSession session = sqlSessionFactory.openSession();
215 | try {
216 | transaction.registerSynchronization(new Synchronization() {
217 | @Override
218 | public void beforeCompletion() {
219 | session.close();
220 | sqlSessionMap.remove(transaction);
221 | }
222 |
223 | @Override
224 | public void afterCompletion(int status) {
225 | }
226 | });
227 | } catch (Exception e) {
228 | throw new RuntimeException(
229 | "Session " + session + " can not register synchronization in transaction ", e);
230 | }
231 | return session;
232 | });
233 | return sqlSession;
234 | } else {
235 | return sqlSessionFactory.openSession();
236 | }
237 | }
238 |
239 | private boolean isTransactionActive() {
240 | try {
241 | if (transactionManager == null) {
242 | return false;
243 | }
244 | Transaction tx = transactionManager.getTransaction();
245 | return tx != null
246 | && (tx.getStatus() == Status.STATUS_ACTIVE || tx.getStatus() == Status.STATUS_MARKED_ROLLBACK);
247 | } catch (Exception e) {
248 | return false;
249 | }
250 | }
251 | }
252 | }
253 |
--------------------------------------------------------------------------------
/mybatis/runtime/src/main/java/io/quarkiverse/mybatis/runtime/XMLConfigDelegateBuilder.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.runtime;
2 |
3 | import org.apache.ibatis.session.Configuration;
4 |
5 | import io.quarkiverse.mybatis.runtime.config.MyBatisRuntimeConfig;
6 |
7 | public interface XMLConfigDelegateBuilder {
8 | void setConfig(MyBatisRuntimeConfig config);
9 |
10 | Configuration getConfiguration() throws Exception;
11 |
12 | Configuration parse() throws Exception;
13 | }
14 |
--------------------------------------------------------------------------------
/mybatis/runtime/src/main/java/io/quarkiverse/mybatis/runtime/config/MyBatisDataSourceRuntimeConfig.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.runtime.config;
2 |
3 | import java.util.Optional;
4 | import java.util.Set;
5 |
6 | import org.apache.ibatis.mapping.ResultSetType;
7 | import org.apache.ibatis.session.AutoMappingBehavior;
8 | import org.apache.ibatis.session.AutoMappingUnknownColumnBehavior;
9 | import org.apache.ibatis.session.ExecutorType;
10 | import org.apache.ibatis.session.LocalCacheScope;
11 | import org.apache.ibatis.type.JdbcType;
12 |
13 | import io.quarkus.runtime.annotations.ConfigGroup;
14 | import io.smallrye.config.WithName;
15 |
16 | @ConfigGroup
17 | public interface MyBatisDataSourceRuntimeConfig {
18 | /**
19 | * MyBatis environment id
20 | */
21 | Optional environment();
22 |
23 | /**
24 | * MyBatis transaction factory
25 | */
26 | Optional transactionFactory();
27 |
28 | /**
29 | * MyBatis databaseId
30 | */
31 | Optional databaseId();
32 |
33 | /**
34 | * MyBatis initial sql
35 | */
36 | @WithName("initial-sql")
37 | Optional initialSql();
38 |
39 | /**
40 | * MyBatis cacheEnabled
41 | */
42 | Optional cacheEnabled();
43 |
44 | /**
45 | * MyBatis lazyLoadingEnabled
46 | */
47 | Optional lazyLoadingEnabled();
48 |
49 | /**
50 | * MyBatis aggressiveLazyLoading
51 | */
52 | Optional aggressiveLazyLoading();
53 |
54 | /**
55 | * MyBatis useColumnLabel
56 | */
57 | Optional useColumnLabel();
58 |
59 | /**
60 | * MyBatis useGeneratedKeys
61 | */
62 | Optional useGeneratedKeys();
63 |
64 | /**
65 | * MyBatis autoMappingBehavior
66 | */
67 | Optional autoMappingBehavior();
68 |
69 | /**
70 | * MyBatis autoMappingUnknownColumnBehavior
71 | */
72 | Optional autoMappingUnknownColumnBehavior();
73 |
74 | /**
75 | * MyBatis defaultExecutorType
76 | */
77 | Optional defaultExecutorType();
78 |
79 | /**
80 | * MyBatis defaultStatementTimeout
81 | */
82 | Optional defaultStatementTimeout();
83 |
84 | /**
85 | * MyBatis defaultFetchSize
86 | */
87 | Optional defaultFetchSize();
88 |
89 | /**
90 | * MyBatis defaultResultSetType
91 | */
92 | Optional defaultResultSetType();
93 |
94 | /**
95 | * MyBatis safeRowBoundsEnabled
96 | */
97 | Optional safeRowBoundsEnabled();
98 |
99 | /**
100 | * MyBatis safeResultHandlerEnabled
101 | */
102 | Optional safeResultHandlerEnabled();
103 |
104 | /**
105 | * MyBatis mapUnderscoreToCamelCase
106 | */
107 | Optional mapUnderscoreToCamelCase();
108 |
109 | /**
110 | * MyBatis multipleResultSetsEnabled
111 | */
112 | Optional multipleResultSetsEnabled();
113 |
114 | /**
115 | * MyBatis localCacheScope
116 | */
117 | Optional localCacheScope();
118 |
119 | /**
120 | * MyBatis jdbcTypeForNull
121 | */
122 | Optional jdbcTypeForNull();
123 |
124 | /**
125 | * MyBatis lazyLoadTriggerMethods
126 | */
127 | Optional> lazyLoadTriggerMethods();
128 |
129 | /**
130 | * MyBatis defaultScriptingLanguage
131 | */
132 | Optional defaultScriptingLanguage();
133 |
134 | /**
135 | * MyBatis defaultEnumTypeHandler
136 | */
137 | Optional defaultEnumTypeHandler();
138 |
139 | /**
140 | * MyBatis callSettersOnNulls
141 | */
142 | Optional callSettersOnNulls();
143 |
144 | /**
145 | * MyBatis returnInstanceForEmptyRow
146 | */
147 | Optional returnInstanceForEmptyRow();
148 |
149 | /**
150 | * MyBatis logPrefix
151 | */
152 | Optional logPrefix();
153 |
154 | /**
155 | * MyBatis logImpl
156 | */
157 | Optional logImpl();
158 |
159 | /**
160 | * MyBatis proxyFactory
161 | */
162 | Optional proxyFactory();
163 |
164 | /**
165 | * MyBatis vfsImpl
166 | */
167 | Optional vfsImpl();
168 |
169 | /**
170 | * MyBatis useActualParamName
171 | */
172 | Optional useActualParamName();
173 |
174 | /**
175 | * MyBatis configurationFactory
176 | */
177 | Optional configurationFactory();
178 |
179 | /**
180 | * MyBatis shrinkWhitespacesInSql
181 | */
182 | Optional shrinkWhitespacesInSql();
183 |
184 | /**
185 | * MyBatis defaultSqlProviderType
186 | */
187 | Optional defaultSqlProviderType();
188 | }
189 |
--------------------------------------------------------------------------------
/mybatis/runtime/src/main/java/io/quarkiverse/mybatis/runtime/config/MyBatisRuntimeConfig.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.runtime.config;
2 |
3 | import java.util.List;
4 | import java.util.Map;
5 | import java.util.Optional;
6 | import java.util.Set;
7 |
8 | import org.apache.ibatis.mapping.ResultSetType;
9 | import org.apache.ibatis.session.AutoMappingBehavior;
10 | import org.apache.ibatis.session.AutoMappingUnknownColumnBehavior;
11 | import org.apache.ibatis.session.ExecutorType;
12 | import org.apache.ibatis.session.LocalCacheScope;
13 | import org.apache.ibatis.type.JdbcType;
14 |
15 | import io.quarkus.runtime.annotations.ConfigDocMapKey;
16 | import io.quarkus.runtime.annotations.ConfigDocSection;
17 | import io.quarkus.runtime.annotations.ConfigGroup;
18 | import io.quarkus.runtime.annotations.ConfigPhase;
19 | import io.quarkus.runtime.annotations.ConfigRoot;
20 | import io.smallrye.config.ConfigMapping;
21 | import io.smallrye.config.WithDefault;
22 | import io.smallrye.config.WithName;
23 | import io.smallrye.config.WithParentName;
24 |
25 | @ConfigRoot(phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED)
26 | @ConfigMapping(prefix = "quarkus.mybatis")
27 | public interface MyBatisRuntimeConfig {
28 | /**
29 | * Data sources config
30 | */
31 | @ConfigDocSection
32 | @ConfigDocMapKey("data-source-name")
33 | @WithParentName
34 | Map dataSources();
35 |
36 | /**
37 | * Support XML Configuration
38 | */
39 | XmlConfig xmlconfig();
40 |
41 | @ConfigGroup
42 | public interface XmlConfig {
43 | /**
44 | * enable mybatis xml configuration
45 | */
46 | @WithDefault("false")
47 | boolean enable();
48 |
49 | /**
50 | * xml configuration file
51 | */
52 | @WithDefault("mybatis-config.xml")
53 | String path();
54 | }
55 |
56 | /**
57 | * MyBatis environment id
58 | */
59 | @WithDefault("quarkus")
60 | String environment();
61 |
62 | /**
63 | * MyBatis transaction factory
64 | */
65 | @WithDefault("MANAGED")
66 | String transactionFactory();
67 |
68 | /**
69 | * MyBatis data source
70 | */
71 | @WithName("datasource")
72 | Optional dataSource();
73 |
74 | /**
75 | * MyBatis DatabaseId
76 | */
77 | Optional databaseId();
78 |
79 | /**
80 | * MyBatis initial sql
81 | */
82 | @WithName("initial-sql")
83 | Optional initialSql();
84 |
85 | /**
86 | * MyBatis cacheEnabled
87 | */
88 | @WithDefault("true")
89 | boolean cacheEnabled();
90 |
91 | /**
92 | * MyBatis lazyLoadingEnabled
93 | */
94 | @WithDefault("false")
95 | boolean lazyLoadingEnabled();
96 |
97 | /**
98 | * MyBatis aggressiveLazyLoading
99 | */
100 | @WithDefault("false")
101 | boolean aggressiveLazyLoading();
102 |
103 | /**
104 | * MyBatis useColumnLabel
105 | */
106 | @WithDefault("true")
107 | boolean useColumnLabel();
108 |
109 | /**
110 | * MyBatis useGeneratedKeys
111 | */
112 | @WithDefault("false")
113 | boolean useGeneratedKeys();
114 |
115 | /**
116 | * MyBatis autoMappingBehavior
117 | */
118 | @WithDefault("PARTIAL")
119 | AutoMappingBehavior autoMappingBehavior();
120 |
121 | /**
122 | * MyBatis autoMappingUnknownColumnBehavior
123 | */
124 | @WithDefault("NONE")
125 | AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior();
126 |
127 | /**
128 | * MyBatis defaultExecutorType
129 | */
130 | @WithDefault("SIMPLE")
131 | ExecutorType defaultExecutorType();
132 |
133 | /**
134 | * MyBatis defaultStatementTimeout
135 | */
136 | Optional defaultStatementTimeout();
137 |
138 | /**
139 | * MyBatis defaultFetchSize
140 | */
141 | Optional defaultFetchSize();
142 |
143 | /**
144 | * MyBatis defaultResultSetType
145 | */
146 | Optional defaultResultSetType();
147 |
148 | /**
149 | * MyBatis safeRowBoundsEnabled
150 | */
151 | @WithDefault("false")
152 | boolean safeRowBoundsEnabled();
153 |
154 | /**
155 | * MyBatis safeResultHandlerEnabled
156 | */
157 | @WithDefault("true")
158 | boolean safeResultHandlerEnabled();
159 |
160 | /**
161 | * MyBatis mapUnderscoreToCamelCase
162 | */
163 | @WithDefault("false")
164 | boolean mapUnderscoreToCamelCase();
165 |
166 | /**
167 | * MyBatis multipleResultSetsEnabled
168 | */
169 | @WithDefault("true")
170 | boolean multipleResultSetsEnabled();
171 |
172 | /**
173 | * MyBatis localCacheScope
174 | */
175 | @WithDefault("SESSION")
176 | LocalCacheScope localCacheScope();
177 |
178 | /**
179 | * MyBatis jdbcTypeForNull
180 | */
181 | @WithDefault("OTHER")
182 | JdbcType jdbcTypeForNull();
183 |
184 | /**
185 | * MyBatis lazyLoadTriggerMethods
186 | */
187 | @WithDefault("equals,clone,hashCode,toString")
188 | Set lazyLoadTriggerMethods();
189 |
190 | /**
191 | * MyBatis defaultScriptingLanguage
192 | */
193 | @WithDefault("org.apache.ibatis.scripting.xmltags.XMLLanguageDriver")
194 | String defaultScriptingLanguage();
195 |
196 | /**
197 | * MyBatis defaultEnumTypeHandler
198 | */
199 | @WithDefault("org.apache.ibatis.type.EnumTypeHandler")
200 | String defaultEnumTypeHandler();
201 |
202 | /**
203 | * MyBatis callSettersOnNulls
204 | */
205 | @WithDefault("false")
206 | boolean callSettersOnNulls();
207 |
208 | /**
209 | * MyBatis returnInstanceForEmptyRow
210 | */
211 | @WithDefault("false")
212 | boolean returnInstanceForEmptyRow();
213 |
214 | /**
215 | * MyBatis logPrefix
216 | */
217 | Optional logPrefix();
218 |
219 | /**
220 | * MyBatis logImpl
221 | */
222 | Optional logImpl();
223 |
224 | /**
225 | * MyBatis proxyFactory
226 | */
227 | @WithDefault("JAVASSIST")
228 | String proxyFactory();
229 |
230 | /**
231 | * MyBatis vfsImpl
232 | */
233 | Optional vfsImpl();
234 |
235 | /**
236 | * MyBatis useActualParamName
237 | */
238 | @WithDefault("true")
239 | boolean useActualParamName();
240 |
241 | /**
242 | * MyBatis configurationFactory
243 | */
244 | Optional configurationFactory();
245 |
246 | /**
247 | * MyBatis shrinkWhitespacesInSql
248 | */
249 | @WithDefault("false")
250 | public boolean shrinkWhitespacesInSql();
251 |
252 | /**
253 | * MyBatis defaultSqlProviderType
254 | */
255 | Optional defaultSqlProviderType();
256 |
257 | /**
258 | * MyBatis mapperLocations
259 | */
260 | Optional> mapperLocations();
261 | }
262 |
--------------------------------------------------------------------------------
/mybatis/runtime/src/main/java/io/quarkiverse/mybatis/runtime/meta/MapperDataSource.java:
--------------------------------------------------------------------------------
1 | package io.quarkiverse.mybatis.runtime.meta;
2 |
3 | import java.lang.annotation.ElementType;
4 | import java.lang.annotation.Retention;
5 | import java.lang.annotation.RetentionPolicy;
6 | import java.lang.annotation.Target;
7 |
8 | @Retention(RetentionPolicy.RUNTIME)
9 | @Target(ElementType.TYPE)
10 | public @interface MapperDataSource {
11 | String value();
12 | }
13 |
--------------------------------------------------------------------------------
/mybatis/runtime/src/main/resources/META-INF/quarkus-extension.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | name: "MyBatis SQL Mapper"
3 | metadata:
4 | icon-url: "https://raw.githubusercontent.com/mybatis/logo/master/logo-bird-ninja.svg"
5 | keywords:
6 | - "mybatis"
7 | guide: "https://quarkiverse.github.io/quarkiverse-docs/quarkus-mybatis/dev/index.html"
8 | categories:
9 | - "data"
10 | status: "stable"
11 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | io.quarkiverse
6 | quarkiverse-parent
7 | 20
8 |
9 | io.quarkiverse.mybatis
10 | quarkus-parent
11 | Quarkus - Parent
12 | 999-SNAPSHOT
13 | pom
14 |
15 | UTF-8
16 | UTF-8
17 | 1.8
18 | 1.8
19 | 3.8.1
20 | 3.5.3
21 | 3.23.2
22 | 3.5.19
23 | 3.5.12
24 | 3.0.3
25 |
26 |
27 | :git:git@github.com:quarkiverse/quarkus-mybatis.git
28 | scm:git:git@github.com:quarkiverse/quarkus-mybatis.git
29 | https://github.com/quarkiverse/quarkus-mybatis
30 | HEAD
31 |
32 |
33 | mybatis
34 | mybatis-plus
35 |
36 |
37 |
38 |
39 | io.quarkus
40 | quarkus-bom
41 | ${quarkus.version}
42 | pom
43 | import
44 |
45 |
46 | org.mybatis
47 | mybatis
48 | ${mybatis.version}
49 |
50 |
51 | com.baomidou
52 | mybatis-plus
53 | ${mybatis-plus.version}
54 |
55 |
56 | com.baomidou
57 | mybatis-plus-jsqlparser
58 | ${mybatis-plus.version}
59 |
60 |
61 | ru.vyarus
62 | generics-resolver
63 | ${vyarus.version}
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | org.apache.maven.plugins
72 | maven-compiler-plugin
73 | ${compiler.plugin.version}
74 |
75 |
76 | io.quarkus
77 | quarkus-maven-plugin
78 | ${quarkus.version}
79 |
80 |
81 | org.apache.maven.plugins
82 | maven-surefire-plugin
83 | ${surefire.plugin.version}
84 |
85 |
86 | org.jboss.logmanager.LogManager
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------