├── .github
└── workflows
│ ├── ci.yml
│ └── close-inactive-issues.yml
├── .gitignore
├── .mvn
└── wrapper
│ ├── MavenWrapperDownloader.java
│ ├── maven-wrapper.jar
│ └── maven-wrapper.properties
├── README.md
├── doma-spring-boot-autoconfigure
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── org
│ │ │ └── seasar
│ │ │ └── doma
│ │ │ └── boot
│ │ │ └── autoconfigure
│ │ │ ├── DomaAutoConfiguration.java
│ │ │ ├── DomaConfig.java
│ │ │ ├── DomaConfigBuilder.java
│ │ │ ├── DomaProperties.java
│ │ │ └── package-info.java
│ └── resources
│ │ └── META-INF
│ │ ├── spring.factories
│ │ └── spring
│ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
│ └── test
│ └── java
│ └── org
│ └── seasar
│ └── doma
│ └── boot
│ └── autoconfigure
│ └── DomaAutoConfigurationTest.java
├── doma-spring-boot-core
├── pom.xml
└── src
│ ├── main
│ └── java
│ │ └── org
│ │ └── seasar
│ │ └── doma
│ │ └── boot
│ │ ├── ConfigAutowireable.java
│ │ ├── DomaPersistenceExceptionTranslator.java
│ │ ├── DomaSpringBootSqlBuilderSettings.java
│ │ ├── Pageables.java
│ │ ├── PropertyMetamodelResolver.java
│ │ ├── ResourceLoaderScriptFileLoader.java
│ │ ├── TryLookupEntityListenerProvider.java
│ │ ├── UnifiedCriteriaPageable.java
│ │ ├── event
│ │ ├── DomaApplicationListener.java
│ │ ├── DomaEvent.java
│ │ ├── DomaEventEntityListener.java
│ │ ├── DomaEventListenerFactory.java
│ │ ├── PostDeleteEvent.java
│ │ ├── PostInsertEvent.java
│ │ ├── PostUpdateEvent.java
│ │ ├── PreDeleteEvent.java
│ │ ├── PreInsertEvent.java
│ │ ├── PreUpdateEvent.java
│ │ ├── annotation
│ │ │ ├── HandleDomaEvent.java
│ │ │ ├── HandlePostDelete.java
│ │ │ ├── HandlePostInsert.java
│ │ │ ├── HandlePostUpdate.java
│ │ │ ├── HandlePreDelete.java
│ │ │ ├── HandlePreInsert.java
│ │ │ ├── HandlePreUpdate.java
│ │ │ └── package-info.java
│ │ └── package-info.java
│ │ └── package-info.java
│ └── test
│ └── java
│ └── org
│ └── seasar
│ └── doma
│ └── boot
│ ├── DomaPersistenceExceptionTranslatorTest.java
│ ├── PageablesTest.java
│ ├── ResourceLoaderScriptFileLoaderTest.java
│ ├── TryLookupEntityListenerProviderTest.java
│ ├── UnifiedCriteriaPageableTest.java
│ └── event
│ ├── DomaApplicationListenerTest.java
│ └── DomaEventEntityListenerTest.java
├── doma-spring-boot-jacoco-aggregate
└── pom.xml
├── doma-spring-boot-samples
├── doma-spring-boot-sample-docker-compose
│ ├── README.md
│ ├── compose.yaml
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── org
│ │ │ │ └── seasar
│ │ │ │ └── doma
│ │ │ │ └── boot
│ │ │ │ └── sample
│ │ │ │ ├── Application.java
│ │ │ │ ├── Message.java
│ │ │ │ ├── MessageController.java
│ │ │ │ └── MessageDao.java
│ │ └── resources
│ │ │ ├── META-INF
│ │ │ └── org
│ │ │ │ └── seasar
│ │ │ │ └── doma
│ │ │ │ └── boot
│ │ │ │ └── sample
│ │ │ │ └── MessageDao
│ │ │ │ └── selectAll.sql
│ │ │ ├── application.properties
│ │ │ └── schema.sql
│ │ └── test
│ │ └── java
│ │ └── org
│ │ └── seasar
│ │ └── doma
│ │ └── boot
│ │ └── sample
│ │ └── ApplicationTest.java
├── doma-spring-boot-sample-entity-listener
│ ├── .mvn
│ │ └── wrapper
│ │ │ ├── maven-wrapper.jar
│ │ │ └── maven-wrapper.properties
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── org
│ │ │ │ └── seasar
│ │ │ │ └── doma
│ │ │ │ └── boot
│ │ │ │ └── sample
│ │ │ │ ├── Application.java
│ │ │ │ ├── Message.java
│ │ │ │ ├── MessageController.java
│ │ │ │ ├── MessageDao.java
│ │ │ │ └── MessageListener.java
│ │ └── resources
│ │ │ ├── META-INF
│ │ │ └── org
│ │ │ │ └── seasar
│ │ │ │ └── doma
│ │ │ │ └── boot
│ │ │ │ └── sample
│ │ │ │ └── MessageDao
│ │ │ │ └── selectAll.sql
│ │ │ ├── application.properties
│ │ │ └── schema.sql
│ │ └── test
│ │ └── java
│ │ └── org
│ │ └── seasar
│ │ └── doma
│ │ └── boot
│ │ └── sample
│ │ └── ApplicationTest.java
├── doma-spring-boot-sample-event-handler
│ ├── .mvn
│ │ └── wrapper
│ │ │ ├── maven-wrapper.jar
│ │ │ └── maven-wrapper.properties
│ ├── mvnw
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── org
│ │ │ │ └── seasar
│ │ │ │ └── doma
│ │ │ │ └── boot
│ │ │ │ └── sample
│ │ │ │ ├── Application.java
│ │ │ │ ├── Message.java
│ │ │ │ ├── MessageController.java
│ │ │ │ ├── MessageDao.java
│ │ │ │ └── MessageHandler.java
│ │ └── resources
│ │ │ ├── META-INF
│ │ │ └── org
│ │ │ │ └── seasar
│ │ │ │ └── doma
│ │ │ │ └── boot
│ │ │ │ └── sample
│ │ │ │ └── MessageDao
│ │ │ │ └── selectAll.sql
│ │ │ ├── application.properties
│ │ │ └── schema.sql
│ │ └── test
│ │ └── java
│ │ └── org
│ │ └── seasar
│ │ └── doma
│ │ └── boot
│ │ └── sample
│ │ └── ApplicationTest.java
├── doma-spring-boot-sample-simple
│ ├── .mvn
│ │ └── wrapper
│ │ │ ├── maven-wrapper.jar
│ │ │ └── maven-wrapper.properties
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── org
│ │ │ │ └── seasar
│ │ │ │ └── doma
│ │ │ │ └── boot
│ │ │ │ └── sample
│ │ │ │ ├── Application.java
│ │ │ │ ├── Message.java
│ │ │ │ ├── MessageController.java
│ │ │ │ └── MessageDao.java
│ │ └── resources
│ │ │ ├── META-INF
│ │ │ └── org
│ │ │ │ └── seasar
│ │ │ │ └── doma
│ │ │ │ └── boot
│ │ │ │ └── sample
│ │ │ │ └── MessageDao
│ │ │ │ └── selectAll.sql
│ │ │ ├── application.properties
│ │ │ └── schema.sql
│ │ └── test
│ │ └── java
│ │ └── org
│ │ └── seasar
│ │ └── doma
│ │ └── boot
│ │ └── sample
│ │ └── ApplicationTest.java
├── doma-spring-boot-sample-testcontainers
│ ├── .mvn
│ │ └── wrapper
│ │ │ ├── MavenWrapperDownloader.java
│ │ │ ├── maven-wrapper.jar
│ │ │ └── maven-wrapper.properties
│ ├── README.md
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── org
│ │ │ │ └── seasar
│ │ │ │ └── doma
│ │ │ │ └── boot
│ │ │ │ └── sample
│ │ │ │ ├── Application.java
│ │ │ │ ├── Message.java
│ │ │ │ ├── MessageController.java
│ │ │ │ └── MessageDao.java
│ │ └── resources
│ │ │ ├── META-INF
│ │ │ └── org
│ │ │ │ └── seasar
│ │ │ │ └── doma
│ │ │ │ └── boot
│ │ │ │ └── sample
│ │ │ │ └── MessageDao
│ │ │ │ └── selectAll.sql
│ │ │ ├── application.properties
│ │ │ └── schema.sql
│ │ └── test
│ │ └── java
│ │ └── org
│ │ └── seasar
│ │ └── doma
│ │ └── boot
│ │ └── sample
│ │ ├── ApplicationTest.java
│ │ ├── TestApplication.java
│ │ └── TestcontainersConfiguration.java
├── doma-spring-boot-sample-two-datasource
│ ├── .mvn
│ │ └── wrapper
│ │ │ ├── maven-wrapper.jar
│ │ │ └── maven-wrapper.properties
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── org
│ │ │ │ └── seasar
│ │ │ │ └── doma
│ │ │ │ └── boot
│ │ │ │ └── sample
│ │ │ │ ├── Application.java
│ │ │ │ ├── annotation
│ │ │ │ ├── Secondary.java
│ │ │ │ └── SecondaryConfigAutowireable.java
│ │ │ │ ├── configuration
│ │ │ │ ├── DataSourceConfiguration.java
│ │ │ │ ├── DomaConfiguration.java
│ │ │ │ └── TransactionManagerConfiguration.java
│ │ │ │ ├── dao
│ │ │ │ ├── PrimaryDao.java
│ │ │ │ └── SecondaryDao.java
│ │ │ │ ├── entity
│ │ │ │ ├── PrimaryMessage.java
│ │ │ │ └── SecondaryMessage.java
│ │ │ │ └── service
│ │ │ │ └── SampleService.java
│ │ └── resources
│ │ │ ├── META-INF
│ │ │ └── org
│ │ │ │ └── seasar
│ │ │ │ └── doma
│ │ │ │ └── boot
│ │ │ │ └── sample
│ │ │ │ └── dao
│ │ │ │ ├── PrimaryDao
│ │ │ │ └── selectById.sql
│ │ │ │ └── SecondaryDao
│ │ │ │ └── selectById.sql
│ │ │ ├── application.properties
│ │ │ ├── data.sql
│ │ │ ├── schema.sql
│ │ │ ├── secondary-data.sql
│ │ │ └── secondary-schema.sql
│ │ └── test
│ │ └── java
│ │ └── org
│ │ └── seasar
│ │ └── doma
│ │ └── boot
│ │ └── sample
│ │ └── ApplicationTest.java
├── doma-spring-boot-sample-unified-criteria
│ ├── .mvn
│ │ └── wrapper
│ │ │ ├── maven-wrapper.jar
│ │ │ └── maven-wrapper.properties
│ ├── mvnw
│ ├── mvnw.cmd
│ ├── pom.xml
│ └── src
│ │ ├── main
│ │ ├── java
│ │ │ └── org
│ │ │ │ └── seasar
│ │ │ │ └── doma
│ │ │ │ └── boot
│ │ │ │ └── sample
│ │ │ │ ├── Application.java
│ │ │ │ ├── Message.java
│ │ │ │ └── MessageController.java
│ │ └── resources
│ │ │ ├── application.properties
│ │ │ └── schema.sql
│ │ └── test
│ │ └── java
│ │ └── org
│ │ └── seasar
│ │ └── doma
│ │ └── boot
│ │ └── sample
│ │ └── ApplicationTest.java
└── pom.xml
├── doma-spring-boot-starter
├── pom.xml
└── src
│ └── main
│ └── resources
│ └── META-INF
│ └── spring.provides
├── eclipse
└── eclipse-code-formatter.xml
├── how-to-release.md
├── mvnw
├── mvnw.cmd
├── pom.xml
└── renovate.json
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: Java CI with Maven
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | env:
10 | MAVEN_CLI_OPTS: --batch-mode --no-transfer-progress
11 |
12 | jobs:
13 | test:
14 | if: contains(github.event.head_commit.message, '[skip ci]') == false
15 | runs-on: ubuntu-latest
16 | timeout-minutes: 30
17 |
18 | steps:
19 | - uses: actions/checkout@v4
20 |
21 | - name: Set up JDK 17
22 | uses: actions/setup-java@v4
23 | with:
24 | distribution: liberica
25 | java-version: 17
26 | cache: maven
27 |
28 | - name: Grant execute permission for mvnw
29 | run: chmod +x mvnw
30 |
31 | - name: Test with Maven
32 | run: ./mvnw $MAVEN_CLI_OPTS formatter:validate test
33 |
34 | - name: Upload reports
35 | if: failure()
36 | uses: actions/upload-artifact@v4
37 | with:
38 | name: reports
39 | path: ./**/target/surefire-reports
40 |
41 | test-matrix:
42 | if: contains(github.event.head_commit.message, '[skip ci]') == false
43 | runs-on: ubuntu-latest
44 | timeout-minutes: 30
45 | needs: [ test ]
46 |
47 | strategy:
48 | matrix:
49 | # Latest LTS, latest release
50 | java: [ 21, 24 ]
51 | # OSS support versions
52 | # https://spring.io/projects/spring-boot#support
53 | # and milestone version of the next release
54 | spring-boot-version: [ 3.4.4, 3.5.0-M3 ]
55 |
56 | steps:
57 | - uses: actions/checkout@v4
58 |
59 | - name: Set up JDK ${{ matrix.java }}
60 | uses: actions/setup-java@v4
61 | with:
62 | distribution: liberica
63 | java-version: ${{ matrix.java }}
64 | cache: maven
65 |
66 | - name: Grant execute permission for mvnw
67 | run: chmod +x mvnw
68 |
69 | - name: Test with Maven
70 | run: ./mvnw $MAVEN_CLI_OPTS -pl :doma-spring-boot-core,:doma-spring-boot-autoconfigure,:doma-spring-boot-starter test -Dspring-boot.version=${{ matrix.spring-boot-version }}
71 |
72 | - name: Upload reports
73 | if: failure()
74 | uses: actions/upload-artifact@v4
75 | with:
76 | name: reports
77 | path: ./**/target/surefire-reports
78 |
79 | deploy:
80 | if: github.event_name == 'push' && contains(github.event.head_commit.message, '[skip ci]') == false
81 | runs-on: ubuntu-latest
82 | needs: [ test-matrix ]
83 |
84 | steps:
85 | - uses: actions/checkout@v4
86 |
87 | - name: Set up JDK 17
88 | uses: actions/setup-java@v4
89 | with:
90 | distribution: liberica
91 | java-version: 17
92 | cache: maven
93 |
94 | - name: Grant execute permission for mvnw
95 | run: chmod +x mvnw
96 |
97 | - name: Release Maven package
98 | uses: samuelmeuli/action-maven-publish@v1
99 | with:
100 | gpg_private_key: ${{ secrets.SIGNING_KEY }}
101 | gpg_passphrase: ${{ secrets.SIGNING_PASSWORD }}
102 | nexus_username: ${{ secrets.OSSRH_USERNAME }}
103 | nexus_password: ${{ secrets.OSSRH_PASSWORD }}
104 |
105 | - name: Upload reports
106 | if: failure()
107 | uses: actions/upload-artifact@v4
108 | with:
109 | name: reports
110 | path: ./**/target/surefire-reports
111 |
--------------------------------------------------------------------------------
/.github/workflows/close-inactive-issues.yml:
--------------------------------------------------------------------------------
1 | name: Close inactive issues
2 | on:
3 | schedule:
4 | - cron: "30 1 * * *"
5 |
6 | jobs:
7 | close-issues:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/stale@v9
11 | with:
12 | days-before-issue-stale: 60
13 | days-before-issue-close: 30
14 | stale-issue-label: "stale"
15 | stale-issue-message: "This issue is stale because it has been open for 60 days with no activity."
16 | close-issue-message: "This issue was closed because it has been inactive for 30 days since being marked as stale."
17 | days-before-pr-stale: 60
18 | days-before-pr-close: 30
19 | stale-pr-message: "This pull request is stale because it has been open for 60 days with no activity."
20 | close-pr-message: "This pull request was closed because it has been inactive for 30 days since being marked as stale."
21 | repo-token: ${{ secrets.GITHUB_TOKEN }}
22 |
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | target
3 | *.iml
4 | *~
5 | .*~
6 | *.versionsBackup
7 | .classpath
8 | .project
9 | .settings
10 | .factorypath
11 | .apt_generated
12 | .vscode/
13 | HELP.md
14 |
--------------------------------------------------------------------------------
/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2007-present the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | import java.net.*;
17 | import java.io.*;
18 | import java.nio.channels.*;
19 | import java.util.Properties;
20 |
21 | public class MavenWrapperDownloader {
22 |
23 | private static final String WRAPPER_VERSION = "0.5.6";
24 | /**
25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
26 | */
27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
29 |
30 | /**
31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
32 | * use instead of the default one.
33 | */
34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
35 | ".mvn/wrapper/maven-wrapper.properties";
36 |
37 | /**
38 | * Path where the maven-wrapper.jar will be saved to.
39 | */
40 | private static final String MAVEN_WRAPPER_JAR_PATH =
41 | ".mvn/wrapper/maven-wrapper.jar";
42 |
43 | /**
44 | * Name of the property which should be used to override the default download url for the wrapper.
45 | */
46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
47 |
48 | public static void main(String args[]) {
49 | System.out.println("- Downloader started");
50 | File baseDirectory = new File(args[0]);
51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
52 |
53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
54 | // wrapperUrl parameter.
55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
56 | String url = DEFAULT_DOWNLOAD_URL;
57 | if(mavenWrapperPropertyFile.exists()) {
58 | FileInputStream mavenWrapperPropertyFileInputStream = null;
59 | try {
60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
61 | Properties mavenWrapperProperties = new Properties();
62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
64 | } catch (IOException e) {
65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
66 | } finally {
67 | try {
68 | if(mavenWrapperPropertyFileInputStream != null) {
69 | mavenWrapperPropertyFileInputStream.close();
70 | }
71 | } catch (IOException e) {
72 | // Ignore ...
73 | }
74 | }
75 | }
76 | System.out.println("- Downloading from: " + url);
77 |
78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
79 | if(!outputFile.getParentFile().exists()) {
80 | if(!outputFile.getParentFile().mkdirs()) {
81 | System.out.println(
82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
83 | }
84 | }
85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
86 | try {
87 | downloadFileFromURL(url, outputFile);
88 | System.out.println("Done");
89 | System.exit(0);
90 | } catch (Throwable e) {
91 | System.out.println("- Error downloading");
92 | e.printStackTrace();
93 | System.exit(1);
94 | }
95 | }
96 |
97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
99 | String username = System.getenv("MVNW_USERNAME");
100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
101 | Authenticator.setDefault(new Authenticator() {
102 | @Override
103 | protected PasswordAuthentication getPasswordAuthentication() {
104 | return new PasswordAuthentication(username, password);
105 | }
106 | });
107 | }
108 | URL website = new URL(urlString);
109 | ReadableByteChannel rbc;
110 | rbc = Channels.newChannel(website.openStream());
111 | FileOutputStream fos = new FileOutputStream(destination);
112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
113 | fos.close();
114 | rbc.close();
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/domaframework/doma-spring-boot/3d75478c299a8b4b55579f23245b2c387b3631ce/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.10/apache-maven-3.9.10-bin.zip
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # doma-spring-boot
2 |
3 | Spring Boot Support for [Doma](https://github.com/domaframework/doma)
4 |
5 | [](https://github.com/domaframework/doma-spring-boot/actions?query=workflow%3A%22Java+CI+with+Maven%22)
6 |
7 | ## Document
8 |
9 | [GitHub Wiki](https://github.com/domaframework/doma-spring-boot/wiki)
10 |
11 | ## Issue Tracking
12 |
13 | [GitHub Issues](https://github.com/domaframework/doma-spring-boot/issues)
14 |
15 | ## Maven dependency
16 |
17 | ``` xml
18 |
19 | org.seasar.doma.boot
20 | doma-spring-boot-starter
21 | 2.4.0
22 |
23 |
24 | org.seasar.doma
25 | doma-processor
26 | 3.6.0
27 | true
28 |
29 | ```
30 |
31 | Add the following repository to use snapshots.
32 |
33 | ``` xml
34 |
35 | sonatype-snapshots
36 | Sonatype Snapshots
37 | https://oss.sonatype.org/content/repositories/snapshots
38 |
39 | true
40 |
41 |
42 | ```
43 |
44 | ## License
45 |
46 | Licensed under the Apache License, Version 2.0.
47 |
--------------------------------------------------------------------------------
/doma-spring-boot-autoconfigure/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | doma-spring-boot-autoconfigure
7 | jar
8 |
9 | doma-spring-boot-autoconfigure
10 | Spring Boot AutoConfigure project for Doma
11 |
12 |
13 | org.seasar.doma.boot
14 | doma-spring-boot
15 | 2.5.0-SNAPSHOT
16 | ../pom.xml
17 |
18 |
19 |
20 |
21 | org.seasar.doma.boot
22 | doma-spring-boot-core
23 | ${project.version}
24 |
25 |
26 | org.seasar.doma
27 | doma-slf4j
28 | ${doma.version}
29 |
30 |
31 | org.springframework
32 | spring-jdbc
33 |
34 |
35 | org.springframework.boot
36 | spring-boot-autoconfigure
37 |
38 |
39 | org.springframework.boot
40 | spring-boot-configuration-processor
41 | true
42 |
43 |
44 | org.springframework.boot
45 | spring-boot-starter-test
46 | test
47 |
48 |
49 | org.junit.jupiter
50 | junit-jupiter
51 | test
52 |
53 |
54 | com.h2database
55 | h2
56 | test
57 |
58 |
59 | org.postgresql
60 | postgresql
61 | test
62 |
63 |
64 | com.zaxxer
65 | HikariCP
66 | test
67 |
68 |
69 |
70 |
71 |
72 |
73 | org.apache.maven.plugins
74 | maven-jar-plugin
75 |
76 |
77 |
78 | doma.spring.boot.autoconfigure
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/doma-spring-boot-autoconfigure/src/main/java/org/seasar/doma/boot/autoconfigure/DomaConfig.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot.autoconfigure;
2 |
3 | import javax.sql.DataSource;
4 |
5 | import org.seasar.doma.jdbc.*;
6 | import org.seasar.doma.jdbc.dialect.Dialect;
7 | import org.seasar.doma.jdbc.statistic.StatisticManager;
8 |
9 | /**
10 | * {@link Config} implementation used in doma-spring-boot.
11 | *
12 | * @author Toshiaki Maki
13 | */
14 | public class DomaConfig implements Config {
15 |
16 | private final DataSource dataSource;
17 | private final Dialect dialect;
18 | private final JdbcLogger jdbcLogger;
19 | private final SqlFileRepository sqlFileRepository;
20 | private final RequiresNewController requiresNewController;
21 | private final ClassHelper classHelper;
22 | private final CommandImplementors commandImplementors;
23 | private final QueryImplementors queryImplementors;
24 | private final UnknownColumnHandler unknownColumnHandler;
25 | private final Naming naming;
26 | private final MapKeyNaming mapKeyNaming;
27 | private final Commenter commenter;
28 | private final EntityListenerProvider entityListenerProvider;
29 | private final DomaProperties domaProperties;
30 | private final DuplicateColumnHandler duplicateColumnHandler;
31 | private final ScriptFileLoader scriptFileLoader;
32 | private final SqlBuilderSettings sqlBuilderSettings;
33 | private final StatisticManager statisticManager;
34 |
35 | public DomaConfig(DomaConfigBuilder builder, DomaProperties domaProperties) {
36 | this.dataSource = builder.dataSource();
37 | this.dialect = builder.dialect();
38 | this.jdbcLogger = builder.jdbcLogger();
39 | this.sqlFileRepository = builder.sqlFileRepository();
40 | this.requiresNewController = builder.requiresNewController();
41 | this.classHelper = builder.classHelper();
42 | this.commandImplementors = builder.commandImplementors();
43 | this.queryImplementors = builder.queryImplementors();
44 | this.unknownColumnHandler = builder.unknownColumnHandler();
45 | this.naming = builder.naming();
46 | this.mapKeyNaming = builder.mapKeyNaming();
47 | this.commenter = builder.commenter();
48 | this.entityListenerProvider = builder.entityListenerProvider();
49 | this.duplicateColumnHandler = builder.duplicateColumnHandler();
50 | this.scriptFileLoader = builder.scriptFileLoader();
51 | this.sqlBuilderSettings = builder.sqlBuilderSettings();
52 | this.statisticManager = builder.statisticManager();
53 | this.domaProperties = domaProperties;
54 | }
55 |
56 | @Override
57 | public DataSource getDataSource() {
58 | return this.dataSource;
59 | }
60 |
61 | @Override
62 | public Dialect getDialect() {
63 | return this.dialect;
64 | }
65 |
66 | @Override
67 | public String getDataSourceName() {
68 | return this.domaProperties.getDataSourceName();
69 | }
70 |
71 | @Override
72 | public SqlFileRepository getSqlFileRepository() {
73 | return this.sqlFileRepository;
74 | }
75 |
76 | @Override
77 | public JdbcLogger getJdbcLogger() {
78 | return this.jdbcLogger;
79 | }
80 |
81 | @Override
82 | public RequiresNewController getRequiresNewController() {
83 | return this.requiresNewController;
84 | }
85 |
86 | @Override
87 | public ClassHelper getClassHelper() {
88 | return this.classHelper;
89 | }
90 |
91 | @Override
92 | public CommandImplementors getCommandImplementors() {
93 | return this.commandImplementors;
94 | }
95 |
96 | @Override
97 | public QueryImplementors getQueryImplementors() {
98 | return this.queryImplementors;
99 | }
100 |
101 | @Override
102 | public SqlLogType getExceptionSqlLogType() {
103 | return this.domaProperties.getExceptionSqlLogType();
104 | }
105 |
106 | @Override
107 | public UnknownColumnHandler getUnknownColumnHandler() {
108 | return this.unknownColumnHandler;
109 | }
110 |
111 | @Override
112 | public Naming getNaming() {
113 | return this.naming;
114 | }
115 |
116 | @Override
117 | public MapKeyNaming getMapKeyNaming() {
118 | return this.mapKeyNaming;
119 | }
120 |
121 | @Override
122 | public Commenter getCommenter() {
123 | return this.commenter;
124 | }
125 |
126 | @Override
127 | public int getMaxRows() {
128 | return this.domaProperties.getMaxRows();
129 | }
130 |
131 | @Override
132 | public int getFetchSize() {
133 | return this.domaProperties.getFetchSize();
134 | }
135 |
136 | @Override
137 | public int getQueryTimeout() {
138 | return this.domaProperties.getQueryTimeout();
139 | }
140 |
141 | @Override
142 | public int getBatchSize() {
143 | return this.domaProperties.getBatchSize();
144 | }
145 |
146 | @Override
147 | public EntityListenerProvider getEntityListenerProvider() {
148 | return this.entityListenerProvider;
149 | }
150 |
151 | @Override
152 | public DuplicateColumnHandler getDuplicateColumnHandler() {
153 | return this.duplicateColumnHandler;
154 | }
155 |
156 | @Override
157 | public ScriptFileLoader getScriptFileLoader() {
158 | return this.scriptFileLoader;
159 | }
160 |
161 | @Override
162 | public SqlBuilderSettings getSqlBuilderSettings() {
163 | return this.sqlBuilderSettings;
164 | }
165 |
166 | @Override
167 | public StatisticManager getStatisticManager() {
168 | return this.statisticManager;
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/doma-spring-boot-autoconfigure/src/main/java/org/seasar/doma/boot/autoconfigure/DomaConfigBuilder.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot.autoconfigure;
2 |
3 | import java.util.Objects;
4 |
5 | import javax.sql.DataSource;
6 |
7 | import org.seasar.doma.jdbc.*;
8 | import org.seasar.doma.jdbc.dialect.Dialect;
9 | import org.seasar.doma.jdbc.statistic.StatisticManager;
10 | import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;
11 |
12 | /**
13 | * Builder to create {@link DomaConfig}.
14 | *
15 | * @author Toshiaki Maki
16 | */
17 | public class DomaConfigBuilder {
18 | private DomaProperties domaProperties;
19 | private DataSource dataSource;
20 | /**
21 | * Default value is set in {@link DomaProperties}
22 | */
23 | private Dialect dialect;
24 | /**
25 | * Default value is set in {@link DomaProperties}
26 | */
27 | private JdbcLogger jdbcLogger;
28 | /**
29 | * Default value is set in {@link DomaProperties}
30 | */
31 | private SqlFileRepository sqlFileRepository;
32 | private RequiresNewController requiresNewController = ConfigSupport.defaultRequiresNewController;
33 | private ClassHelper classHelper = ConfigSupport.defaultClassHelper;
34 | private CommandImplementors commandImplementors = ConfigSupport.defaultCommandImplementors;
35 | private QueryImplementors queryImplementors = ConfigSupport.defaultQueryImplementors;
36 | private UnknownColumnHandler unknownColumnHandler = ConfigSupport.defaultUnknownColumnHandler;
37 | /**
38 | * Default value is set in {@link DomaProperties}
39 | */
40 | private Naming naming;
41 | private MapKeyNaming mapKeyNaming = ConfigSupport.defaultMapKeyNaming;
42 | private Commenter commenter = ConfigSupport.defaultCommenter;
43 | private EntityListenerProvider entityListenerProvider;
44 | private DuplicateColumnHandler duplicateColumnHandler;
45 | private ScriptFileLoader scriptFileLoader;
46 | private SqlBuilderSettings sqlBuilderSettings;
47 | private StatisticManager statisticManager;
48 |
49 | public DomaConfigBuilder(DomaProperties domaProperties) {
50 | this.domaProperties = Objects.requireNonNull(domaProperties);
51 | }
52 |
53 | public DataSource dataSource() {
54 | return dataSource;
55 | }
56 |
57 | /**
58 | * Set dataSource
59 | *
60 | * Note that the given dataSource is wrapped by
61 | * {@link TransactionAwareDataSourceProxy}.
62 | *
63 | * @param dataSource dataSource to use
64 | * @return chained builder
65 | */
66 | public DomaConfigBuilder dataSource(DataSource dataSource) {
67 | this.dataSource = new TransactionAwareDataSourceProxy(dataSource);
68 | return this;
69 | }
70 |
71 | public Dialect dialect() {
72 | return dialect;
73 | }
74 |
75 | public DomaConfigBuilder dialect(Dialect dialect) {
76 | this.dialect = dialect;
77 | return this;
78 | }
79 |
80 | public JdbcLogger jdbcLogger() {
81 | return jdbcLogger;
82 | }
83 |
84 | public DomaConfigBuilder jdbcLogger(JdbcLogger jdbcLogger) {
85 | this.jdbcLogger = jdbcLogger;
86 | return this;
87 | }
88 |
89 | public SqlFileRepository sqlFileRepository() {
90 | return sqlFileRepository;
91 | }
92 |
93 | public DomaConfigBuilder sqlFileRepository(SqlFileRepository sqlFileRepository) {
94 | this.sqlFileRepository = sqlFileRepository;
95 | return this;
96 | }
97 |
98 | public RequiresNewController requiresNewController() {
99 | return requiresNewController;
100 | }
101 |
102 | public DomaConfigBuilder requiresNewController(
103 | RequiresNewController requiresNewController) {
104 | this.requiresNewController = requiresNewController;
105 | return this;
106 | }
107 |
108 | public ClassHelper classHelper() {
109 | return classHelper;
110 | }
111 |
112 | public DomaConfigBuilder classHelper(ClassHelper classHelper) {
113 | this.classHelper = classHelper;
114 | return this;
115 | }
116 |
117 | public CommandImplementors commandImplementors() {
118 | return commandImplementors;
119 | }
120 |
121 | public DomaConfigBuilder commandImplementors(CommandImplementors commandImplementors) {
122 | this.commandImplementors = commandImplementors;
123 | return this;
124 | }
125 |
126 | public QueryImplementors queryImplementors() {
127 | return queryImplementors;
128 | }
129 |
130 | public DomaConfigBuilder queryImplementors(QueryImplementors queryImplementors) {
131 | this.queryImplementors = queryImplementors;
132 | return this;
133 | }
134 |
135 | public UnknownColumnHandler unknownColumnHandler() {
136 | return unknownColumnHandler;
137 | }
138 |
139 | public DomaConfigBuilder unknownColumnHandler(
140 | UnknownColumnHandler unknownColumnHandler) {
141 | this.unknownColumnHandler = unknownColumnHandler;
142 | return this;
143 | }
144 |
145 | public Naming naming() {
146 | return naming;
147 | }
148 |
149 | public DomaConfigBuilder naming(Naming naming) {
150 | this.naming = naming;
151 | return this;
152 | }
153 |
154 | public MapKeyNaming mapKeyNaming() {
155 | return mapKeyNaming;
156 | }
157 |
158 | public DomaConfigBuilder mapKeyNaming(MapKeyNaming mapKeyNaming) {
159 | this.mapKeyNaming = mapKeyNaming;
160 | return this;
161 | }
162 |
163 | public Commenter commenter() {
164 | return commenter;
165 | }
166 |
167 | public DomaConfigBuilder commenter(Commenter commenter) {
168 | this.commenter = commenter;
169 | return this;
170 | }
171 |
172 | public EntityListenerProvider entityListenerProvider() {
173 | return entityListenerProvider;
174 | }
175 |
176 | public DomaConfigBuilder entityListenerProvider(
177 | EntityListenerProvider entityListenerProvider) {
178 | this.entityListenerProvider = entityListenerProvider;
179 | return this;
180 | }
181 |
182 | public DuplicateColumnHandler duplicateColumnHandler() {
183 | return duplicateColumnHandler;
184 | }
185 |
186 | public DomaConfigBuilder duplicateColumnHandler(DuplicateColumnHandler duplicateColumnHandler) {
187 | this.duplicateColumnHandler = duplicateColumnHandler;
188 | return this;
189 | }
190 |
191 | public ScriptFileLoader scriptFileLoader() {
192 | return scriptFileLoader;
193 | }
194 |
195 | public DomaConfigBuilder scriptFileLoader(ScriptFileLoader scriptFileLoader) {
196 | this.scriptFileLoader = scriptFileLoader;
197 | return this;
198 | }
199 |
200 | public SqlBuilderSettings sqlBuilderSettings() {
201 | return sqlBuilderSettings;
202 | }
203 |
204 | public DomaConfigBuilder sqlBuilderSettings(SqlBuilderSettings sqlBuilderSettings) {
205 | this.sqlBuilderSettings = sqlBuilderSettings;
206 | return this;
207 | }
208 |
209 | public StatisticManager statisticManager() {
210 | return statisticManager;
211 | }
212 |
213 | public DomaConfigBuilder statisticManager(StatisticManager statisticManager) {
214 | this.statisticManager = statisticManager;
215 | return this;
216 | }
217 |
218 | public DomaConfig build() {
219 | return new DomaConfig(this, domaProperties);
220 | }
221 | }
222 |
--------------------------------------------------------------------------------
/doma-spring-boot-autoconfigure/src/main/java/org/seasar/doma/boot/autoconfigure/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Auto-configuration for Doma.
3 | */
4 | package org.seasar.doma.boot.autoconfigure;
5 |
--------------------------------------------------------------------------------
/doma-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories:
--------------------------------------------------------------------------------
1 | # Auto Configure
2 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
3 | org.seasar.doma.boot.autoconfigure.DomaAutoConfiguration
--------------------------------------------------------------------------------
/doma-spring-boot-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports:
--------------------------------------------------------------------------------
1 | org.seasar.doma.boot.autoconfigure.DomaAutoConfiguration
2 |
3 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | doma-spring-boot-core
7 | jar
8 |
9 | doma-spring-boot-core
10 | Spring Boot Core project for Doma
11 |
12 |
13 | org.seasar.doma.boot
14 | doma-spring-boot
15 | 2.5.0-SNAPSHOT
16 | ../pom.xml
17 |
18 |
19 |
20 |
21 | org.seasar.doma
22 | doma-core
23 | ${doma.version}
24 |
25 |
26 | org.springframework
27 | spring-context
28 |
29 |
30 | org.springframework
31 | spring-jdbc
32 |
33 |
34 | org.springframework.data
35 | spring-data-commons
36 |
37 |
38 | org.junit.jupiter
39 | junit-jupiter
40 | test
41 |
42 |
43 | org.assertj
44 | assertj-core
45 | test
46 |
47 |
48 | org.mockito
49 | mockito-core
50 | test
51 |
52 |
53 | com.h2database
54 | h2
55 | test
56 |
57 |
58 |
59 |
60 |
61 |
62 | org.apache.maven.plugins
63 | maven-jar-plugin
64 |
65 |
66 |
67 | doma.spring.boot.core
68 |
69 |
70 |
71 |
72 |
73 | org.apache.maven.plugins
74 | maven-compiler-plugin
75 |
76 |
77 |
78 | org.seasar.doma
79 | doma-processor
80 | ${doma.version}
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/ConfigAutowireable.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot;
2 |
3 | import org.seasar.doma.AnnotateWith;
4 | import org.seasar.doma.Annotation;
5 | import org.seasar.doma.AnnotationTarget;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.stereotype.Repository;
8 |
9 | /**
10 | * Annotate {@link Repository} on the generated Dao class and {@link Autowired} on the
11 | * constructor.
12 | * @author Toshiaki Maki
13 | */
14 | @AnnotateWith(annotations = {
15 | @Annotation(target = AnnotationTarget.CLASS, type = Repository.class),
16 | @Annotation(target = AnnotationTarget.CONSTRUCTOR, type = Autowired.class) })
17 | public @interface ConfigAutowireable {
18 | }
19 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/DomaPersistenceExceptionTranslator.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot;
2 |
3 | import java.sql.SQLException;
4 |
5 | import org.seasar.doma.jdbc.JdbcException;
6 | import org.seasar.doma.jdbc.NoResultException;
7 | import org.seasar.doma.jdbc.NonSingleColumnException;
8 | import org.seasar.doma.jdbc.NonUniqueResultException;
9 | import org.seasar.doma.jdbc.OptimisticLockException;
10 | import org.seasar.doma.jdbc.ResultMappingException;
11 | import org.seasar.doma.jdbc.SqlExecutionException;
12 | import org.seasar.doma.jdbc.UniqueConstraintException;
13 | import org.seasar.doma.jdbc.UnknownColumnException;
14 | import org.springframework.dao.DataAccessException;
15 | import org.springframework.dao.DuplicateKeyException;
16 | import org.springframework.dao.EmptyResultDataAccessException;
17 | import org.springframework.dao.IncorrectResultSizeDataAccessException;
18 | import org.springframework.dao.OptimisticLockingFailureException;
19 | import org.springframework.dao.TypeMismatchDataAccessException;
20 | import org.springframework.dao.UncategorizedDataAccessException;
21 | import org.springframework.dao.support.PersistenceExceptionTranslator;
22 | import org.springframework.jdbc.UncategorizedSQLException;
23 | import org.springframework.jdbc.support.SQLExceptionTranslator;
24 |
25 | /**
26 | * Converts Doma's {@link JdbcException} into Spring's {@link DataAccessException}.
27 | * @author Toshiaki Maki
28 | * @author Kazuki Shimizu
29 | */
30 | public class DomaPersistenceExceptionTranslator implements PersistenceExceptionTranslator {
31 |
32 | private final SQLExceptionTranslator translator;
33 |
34 | public DomaPersistenceExceptionTranslator(
35 | SQLExceptionTranslator sqlExceptionTranslator) {
36 | this.translator = sqlExceptionTranslator;
37 | }
38 |
39 | @Override
40 | public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
41 | if (!(ex instanceof JdbcException)) {
42 | // Fallback to other translators if not JdbcException
43 | return null;
44 | }
45 |
46 | if (ex instanceof OptimisticLockException) {
47 | return new OptimisticLockingFailureException(ex.getMessage(), ex);
48 | } else if (ex instanceof UniqueConstraintException) {
49 | return new DuplicateKeyException(ex.getMessage(), ex);
50 | } else if (ex instanceof NonUniqueResultException
51 | || ex instanceof NonSingleColumnException) {
52 | return new IncorrectResultSizeDataAccessException(ex.getMessage(), 1, ex);
53 | } else if (ex instanceof NoResultException) {
54 | return new EmptyResultDataAccessException(ex.getMessage(), 1, ex);
55 | } else if (ex instanceof UnknownColumnException
56 | || ex instanceof ResultMappingException) {
57 | return new TypeMismatchDataAccessException(ex.getMessage(), ex);
58 | }
59 |
60 | if (ex.getCause() instanceof SQLException) {
61 | SQLException e = (SQLException) ex.getCause();
62 | String sql = null;
63 | if (ex instanceof SqlExecutionException) {
64 | sql = ((SqlExecutionException) ex).getRawSql();
65 | }
66 | DataAccessException dae = translator.translate(ex.getMessage(), sql, e);
67 | return (dae != null ? dae : new UncategorizedSQLException(ex.getMessage(), sql, e));
68 | }
69 |
70 | return new UncategorizedDataAccessException(ex.getMessage(), ex) {
71 | };
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/DomaSpringBootSqlBuilderSettings.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot;
2 |
3 | import java.util.function.Predicate;
4 |
5 | import org.seasar.doma.jdbc.SqlBuilderSettings;
6 |
7 | public class DomaSpringBootSqlBuilderSettings implements SqlBuilderSettings {
8 |
9 | private final Predicate shouldRemoveBlockComment;
10 | private final Predicate shouldRemoveLineComment;
11 | private final boolean shouldRemoveBlankLines;
12 | private final boolean shouldRequireInListPadding;
13 |
14 | public DomaSpringBootSqlBuilderSettings(Predicate shouldRemoveBlockComment,
15 | Predicate shouldRemoveLineComment, boolean shouldRemoveBlankLines,
16 | boolean shouldRequireInListPadding) {
17 | this.shouldRemoveBlockComment = shouldRemoveBlockComment;
18 | this.shouldRemoveLineComment = shouldRemoveLineComment;
19 | this.shouldRemoveBlankLines = shouldRemoveBlankLines;
20 | this.shouldRequireInListPadding = shouldRequireInListPadding;
21 | }
22 |
23 | @Override
24 | public boolean shouldRemoveBlockComment(String comment) {
25 | return shouldRemoveBlockComment.test(comment);
26 | }
27 |
28 | @Override
29 | public boolean shouldRemoveLineComment(String comment) {
30 | return shouldRemoveLineComment.test(comment);
31 | }
32 |
33 | @Override
34 | public boolean shouldRemoveBlankLines() {
35 | return shouldRemoveBlankLines;
36 | }
37 |
38 | @Override
39 | public boolean shouldRequireInListPadding() {
40 | return shouldRequireInListPadding;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/Pageables.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot;
2 |
3 | import org.seasar.doma.jdbc.SelectOptions;
4 | import org.springframework.data.domain.Pageable;
5 |
6 | /**
7 | * Converts Utilities for {@link Pageable} to be used with Doma.
8 | *
9 | * @author Toshiaki Maki
10 | */
11 | public final class Pageables {
12 | /**
13 | * Converts {@link Pageable} to {@link SelectOptions}
14 | *
15 | * @param pageable {@link Pageable} object to convert
16 | * @return {@link SelectOptions} object corresponds to the given {@link Pageable}
17 | * object.
18 | */
19 | public static SelectOptions toSelectOptions(Pageable pageable) {
20 | final int offset = pageable.getPageNumber() * pageable.getPageSize();
21 | final int limit = pageable.getPageSize();
22 | return SelectOptions.get().offset(offset).limit(limit);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/PropertyMetamodelResolver.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot;
2 |
3 | import java.util.Optional;
4 |
5 | import org.seasar.doma.jdbc.criteria.metamodel.PropertyMetamodel;
6 |
7 | /**
8 | * A resolver that maps property names to {@link PropertyMetamodel}
9 | */
10 | @FunctionalInterface
11 | public interface PropertyMetamodelResolver {
12 | /**
13 | * Resolves the specified property name into a {@link PropertyMetamodel}.
14 | *
15 | * @param propertyName the name of the property to resolve
16 | * @return an {@link Optional} containing the resolved {@link PropertyMetamodel}
17 | * if found,
18 | * or an empty {@link Optional} if the property name cannot be resolved
19 | */
20 | Optional> resolve(String propertyName);
21 | }
22 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/ResourceLoaderScriptFileLoader.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot;
2 |
3 | import java.io.IOException;
4 | import java.io.UncheckedIOException;
5 | import java.net.URL;
6 |
7 | import org.seasar.doma.jdbc.ScriptFileLoader;
8 | import org.springframework.core.io.ResourceLoader;
9 |
10 | public class ResourceLoaderScriptFileLoader implements ScriptFileLoader {
11 |
12 | private final ResourceLoader resourceLoader;
13 |
14 | public ResourceLoaderScriptFileLoader(ResourceLoader resourceLoader) {
15 | this.resourceLoader = resourceLoader;
16 | }
17 |
18 | @Override
19 | public URL loadAsURL(String path) {
20 | try {
21 | var resource = resourceLoader.getResource(ResourceLoader.CLASSPATH_URL_PREFIX + path);
22 | if (resource.exists()) {
23 | return resource.getURL();
24 | }
25 | resource = resourceLoader.getResource(ResourceLoader.CLASSPATH_URL_PREFIX + "/" + path);
26 | if (resource.exists()) {
27 | return resource.getURL();
28 | }
29 | return null;
30 | } catch (IOException e) {
31 | throw new UncheckedIOException(e);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/TryLookupEntityListenerProvider.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot;
2 |
3 | import java.util.Map;
4 | import java.util.function.Supplier;
5 |
6 | import org.seasar.doma.jdbc.EntityListenerProvider;
7 | import org.seasar.doma.jdbc.entity.EntityListener;
8 | import org.springframework.beans.BeansException;
9 | import org.springframework.context.ApplicationContext;
10 | import org.springframework.context.ApplicationContextAware;
11 |
12 | /**
13 | * {@link EntityListenerProvider} implementation that {@link EntityListener} managed by
14 | * Spring Framework, or else created by Doma.
15 | *
16 | * @author backpaper0
17 | *
18 | */
19 | public class TryLookupEntityListenerProvider implements EntityListenerProvider,
20 | ApplicationContextAware {
21 |
22 | private ApplicationContext context;
23 |
24 | @Override
25 | public > LISTENER get(
26 | Class listenerClass, Supplier listenerSupplier) {
27 | Map beans = context.getBeansOfType(listenerClass);
28 | if (beans.size() > 1) {
29 | throw new IllegalStateException("Bean type of " + listenerClass
30 | + " bean must be unique!");
31 | }
32 | return beans.values().stream().findAny().orElseGet(listenerSupplier);
33 | }
34 |
35 | @Override
36 | public void setApplicationContext(ApplicationContext applicationContext)
37 | throws BeansException {
38 | this.context = applicationContext;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/event/DomaApplicationListener.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot.event;
2 |
3 | import java.lang.annotation.Annotation;
4 | import java.lang.reflect.Method;
5 | import java.lang.reflect.ParameterizedType;
6 | import java.lang.reflect.Type;
7 | import java.util.Collections;
8 | import java.util.IdentityHashMap;
9 | import java.util.Objects;
10 | import java.util.Set;
11 |
12 | import org.seasar.doma.Entity;
13 | import org.seasar.doma.boot.event.annotation.HandleDomaEvent;
14 | import org.springframework.beans.factory.BeanFactory;
15 | import org.springframework.context.ApplicationListener;
16 | import org.springframework.core.annotation.AnnotationUtils;
17 | import org.springframework.core.annotation.MergedAnnotation;
18 | import org.springframework.core.annotation.MergedAnnotations;
19 | import org.springframework.util.ReflectionUtils;
20 |
21 | public class DomaApplicationListener implements ApplicationListener> {
22 |
23 | private final Set> contextClasses;
24 | private final String beanName;
25 | private final Method method;
26 | private final BeanFactory beanFactory;
27 |
28 | public DomaApplicationListener(String beanName, Method method, BeanFactory beanFactory) {
29 |
30 | int parameterCount = method.getParameterCount();
31 | if (parameterCount < 1) {
32 | throw new IllegalArgumentException("Must receive an entity");
33 | } else if (parameterCount > 2) {
34 | throw new IllegalArgumentException("Too many parameters");
35 | }
36 |
37 | Class> entityClass = method.getParameterTypes()[0];
38 | if (entityClass.isAnnotationPresent(Entity.class) == false) {
39 | throw new IllegalArgumentException("First parameter must be entity class");
40 | }
41 |
42 | Set> contextClasses = Collections.newSetFromMap(new IdentityHashMap<>());
43 | MergedAnnotations annotations = MergedAnnotations.from(method);
44 | for (MergedAnnotation annotation : annotations) {
45 | HandleDomaEvent handleDomaEvent = AnnotationUtils.findAnnotation(
46 | annotation.getType(), HandleDomaEvent.class);
47 | if (handleDomaEvent != null) {
48 | contextClasses.add(handleDomaEvent.contextClass());
49 | }
50 | }
51 |
52 | if (parameterCount == 2) {
53 | if (contextClasses.size() > 1) {
54 | throw new IllegalArgumentException(
55 | "To annotate with multi annotations must be only entity parameter");
56 | }
57 |
58 | Class> contextClass = method.getParameterTypes()[1];
59 | if (contextClass != contextClasses.iterator().next()) {
60 | throw new IllegalArgumentException(
61 | "Mismatch between annotation and event context");
62 | }
63 | Type t = method.getGenericParameterTypes()[1];
64 | if (t instanceof ParameterizedType) {
65 | Type typeArg = ((ParameterizedType) t).getActualTypeArguments()[0];
66 | if (typeArg != entityClass) {
67 | throw new IllegalArgumentException(
68 | "Mismatch between entity class and variable bound to event context");
69 | }
70 | }
71 | }
72 |
73 | ReflectionUtils.makeAccessible(method);
74 |
75 | this.contextClasses = Objects.requireNonNull(contextClasses);
76 | this.beanName = Objects.requireNonNull(beanName);
77 | this.method = Objects.requireNonNull(method);
78 | this.beanFactory = Objects.requireNonNull(beanFactory);
79 | }
80 |
81 | @Override
82 | public void onApplicationEvent(DomaEvent, ?> event) {
83 | Object entity = event.getSource();
84 | Object context = event.getContext();
85 | if (shouldHandle(context.getClass())
86 | && method.getParameterTypes()[0].isAssignableFrom(entity.getClass())) {
87 | Object[] args;
88 | if (method.getParameterCount() == 1) {
89 | args = new Object[] { entity };
90 | } else {
91 | args = new Object[] { entity, context };
92 | }
93 | Object target = beanFactory.getBean(beanName);
94 | ReflectionUtils.invokeMethod(method, target, args);
95 | }
96 | }
97 |
98 | private boolean shouldHandle(Class> clazz) {
99 | for (Class> contextClasse : contextClasses) {
100 | if (contextClasse.isAssignableFrom(clazz)) {
101 | return true;
102 | }
103 | }
104 | return false;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/event/DomaEvent.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot.event;
2 |
3 | import org.springframework.context.ApplicationEvent;
4 |
5 | /**
6 | * Abstract base class for events emitted by Doma.
7 | */
8 | public abstract class DomaEvent extends ApplicationEvent {
9 | private final S context;
10 |
11 | protected DomaEvent(T source, S context) {
12 | super(source);
13 | this.context = context;
14 | }
15 |
16 | @Override
17 | @SuppressWarnings("unchecked")
18 | public T getSource() {
19 | return (T) this.source;
20 | }
21 |
22 | public S getContext() {
23 | return this.context;
24 | }
25 | }
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/event/DomaEventEntityListener.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot.event;
2 |
3 | import org.seasar.doma.jdbc.entity.*;
4 | import org.springframework.context.ApplicationEventPublisher;
5 | import org.springframework.context.ApplicationEventPublisherAware;
6 |
7 | /**
8 | * {@link EntityListener} implementation that publishes {@link DomaEvent}.
9 | *
10 | * This class extends {@link NullEntityListener} so that {@link org.seasar.doma.Entity} is
11 | * available with default parameters.
12 | *
13 | * @param Entity class
14 | * @author Toshiaki Maki
15 | */
16 | public class DomaEventEntityListener extends NullEntityListener implements
17 | ApplicationEventPublisherAware {
18 |
19 | private ApplicationEventPublisher eventPublisher;
20 |
21 | @Override
22 | public void preInsert(T t, PreInsertContext context) {
23 | this.eventPublisher.publishEvent(new PreInsertEvent<>(t, context));
24 | }
25 |
26 | @Override
27 | public void preUpdate(T t, PreUpdateContext context) {
28 | this.eventPublisher.publishEvent(new PreUpdateEvent<>(t, context));
29 | }
30 |
31 | @Override
32 | public void preDelete(T t, PreDeleteContext context) {
33 | this.eventPublisher.publishEvent(new PreDeleteEvent<>(t, context));
34 | }
35 |
36 | @Override
37 | public void postInsert(T t, PostInsertContext context) {
38 | this.eventPublisher.publishEvent(new PostInsertEvent<>(t, context));
39 | }
40 |
41 | @Override
42 | public void postUpdate(T t, PostUpdateContext context) {
43 | this.eventPublisher.publishEvent(new PostUpdateEvent<>(t, context));
44 | }
45 |
46 | @Override
47 | public void postDelete(T t, PostDeleteContext context) {
48 | this.eventPublisher.publishEvent(new PostDeleteEvent<>(t, context));
49 | }
50 |
51 | @Override
52 | public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) {
53 | this.eventPublisher = eventPublisher;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/event/DomaEventListenerFactory.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot.event;
2 |
3 | import java.lang.reflect.Method;
4 | import org.seasar.doma.boot.event.annotation.HandleDomaEvent;
5 | import org.springframework.beans.BeansException;
6 | import org.springframework.beans.factory.BeanFactory;
7 | import org.springframework.beans.factory.BeanFactoryAware;
8 | import org.springframework.context.ApplicationListener;
9 | import org.springframework.context.event.EventListenerFactory;
10 | import org.springframework.core.Ordered;
11 | import org.springframework.core.annotation.AnnotationUtils;
12 |
13 | public class DomaEventListenerFactory implements EventListenerFactory, Ordered,
14 | BeanFactoryAware {
15 |
16 | private int order = Ordered.HIGHEST_PRECEDENCE;
17 | private BeanFactory beanFactory;
18 |
19 | @Override
20 | public boolean supportsMethod(Method method) {
21 | return AnnotationUtils.findAnnotation(method, HandleDomaEvent.class) != null;
22 | }
23 |
24 | @Override
25 | public ApplicationListener> createApplicationListener(String beanName,
26 | Class> type, Method method) {
27 | return new DomaApplicationListener(beanName, method, beanFactory);
28 | }
29 |
30 | @Override
31 | public int getOrder() {
32 | return order;
33 | }
34 |
35 | public void setOrder(int order) {
36 | this.order = order;
37 | }
38 |
39 | @Override
40 | public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
41 | this.beanFactory = beanFactory;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/event/PostDeleteEvent.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot.event;
2 |
3 | import org.seasar.doma.jdbc.entity.PostDeleteContext;
4 |
5 | public class PostDeleteEvent extends DomaEvent> {
6 |
7 | public PostDeleteEvent(T source, PostDeleteContext context) {
8 | super(source, context);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/event/PostInsertEvent.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot.event;
2 |
3 | import org.seasar.doma.jdbc.entity.PostInsertContext;
4 |
5 | public class PostInsertEvent extends DomaEvent> {
6 |
7 | public PostInsertEvent(T source, PostInsertContext context) {
8 | super(source, context);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/event/PostUpdateEvent.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot.event;
2 |
3 | import org.seasar.doma.jdbc.entity.PostUpdateContext;
4 |
5 | public class PostUpdateEvent extends DomaEvent> {
6 |
7 | public PostUpdateEvent(T source, PostUpdateContext context) {
8 | super(source, context);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/event/PreDeleteEvent.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot.event;
2 |
3 | import org.seasar.doma.jdbc.entity.PreDeleteContext;
4 |
5 | public class PreDeleteEvent extends DomaEvent> {
6 |
7 | public PreDeleteEvent(T source, PreDeleteContext context) {
8 | super(source, context);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/event/PreInsertEvent.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot.event;
2 |
3 | import org.seasar.doma.jdbc.entity.PreInsertContext;
4 |
5 | public class PreInsertEvent extends DomaEvent> {
6 |
7 | public PreInsertEvent(T source, PreInsertContext context) {
8 | super(source, context);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/event/PreUpdateEvent.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot.event;
2 |
3 | import org.seasar.doma.jdbc.entity.PreUpdateContext;
4 |
5 | public class PreUpdateEvent extends DomaEvent> {
6 |
7 | public PreUpdateEvent(T source, PreUpdateContext context) {
8 | super(source, context);
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/event/annotation/HandleDomaEvent.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot.event.annotation;
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 | import org.springframework.context.event.EventListener;
8 |
9 | @EventListener
10 | @Target({ ElementType.ANNOTATION_TYPE })
11 | @Retention(RetentionPolicy.RUNTIME)
12 | public @interface HandleDomaEvent {
13 | Class> contextClass();
14 | }
15 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/event/annotation/HandlePostDelete.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot.event.annotation;
2 |
3 | import java.lang.annotation.*;
4 | import org.seasar.doma.jdbc.entity.PostDeleteContext;
5 |
6 | @HandleDomaEvent(contextClass = PostDeleteContext.class)
7 | @Target({ ElementType.TYPE, ElementType.METHOD })
8 | @Retention(RetentionPolicy.RUNTIME)
9 | @Inherited
10 | public @interface HandlePostDelete {
11 | }
12 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/event/annotation/HandlePostInsert.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot.event.annotation;
2 |
3 | import java.lang.annotation.*;
4 | import org.seasar.doma.jdbc.entity.PostInsertContext;
5 |
6 | @HandleDomaEvent(contextClass = PostInsertContext.class)
7 | @Target({ ElementType.TYPE, ElementType.METHOD })
8 | @Retention(RetentionPolicy.RUNTIME)
9 | @Inherited
10 | public @interface HandlePostInsert {
11 | }
12 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/event/annotation/HandlePostUpdate.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot.event.annotation;
2 |
3 | import java.lang.annotation.*;
4 | import org.seasar.doma.jdbc.entity.PostUpdateContext;
5 |
6 | @HandleDomaEvent(contextClass = PostUpdateContext.class)
7 | @Target({ ElementType.TYPE, ElementType.METHOD })
8 | @Retention(RetentionPolicy.RUNTIME)
9 | @Inherited
10 | public @interface HandlePostUpdate {
11 | }
12 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/event/annotation/HandlePreDelete.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot.event.annotation;
2 |
3 | import java.lang.annotation.*;
4 | import org.seasar.doma.jdbc.entity.PreDeleteContext;
5 |
6 | @HandleDomaEvent(contextClass = PreDeleteContext.class)
7 | @Target({ ElementType.TYPE, ElementType.METHOD })
8 | @Retention(RetentionPolicy.RUNTIME)
9 | @Inherited
10 | public @interface HandlePreDelete {
11 | }
12 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/event/annotation/HandlePreInsert.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot.event.annotation;
2 |
3 | import java.lang.annotation.*;
4 | import org.seasar.doma.jdbc.entity.PreInsertContext;
5 |
6 | @HandleDomaEvent(contextClass = PreInsertContext.class)
7 | @Target({ ElementType.TYPE, ElementType.METHOD })
8 | @Retention(RetentionPolicy.RUNTIME)
9 | @Inherited
10 | public @interface HandlePreInsert {
11 | }
12 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/event/annotation/HandlePreUpdate.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot.event.annotation;
2 |
3 | import java.lang.annotation.*;
4 | import org.seasar.doma.jdbc.entity.PreUpdateContext;
5 |
6 | @HandleDomaEvent(contextClass = PreUpdateContext.class)
7 | @Target({ ElementType.TYPE, ElementType.METHOD })
8 | @Retention(RetentionPolicy.RUNTIME)
9 | @Inherited
10 | public @interface HandlePreUpdate {
11 | }
12 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/event/annotation/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Annotations for {@link org.seasar.doma.boot.event.DomaEvent}.
3 | */
4 | package org.seasar.doma.boot.event.annotation;
5 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/event/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Doma Event Handler.
3 | */
4 | package org.seasar.doma.boot.event;
5 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/main/java/org/seasar/doma/boot/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Spring Boot integration with Doma.
3 | */
4 | package org.seasar.doma.boot;
5 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/test/java/org/seasar/doma/boot/DomaPersistenceExceptionTranslatorTest.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot;
2 |
3 | import static org.junit.jupiter.api.Assertions.*;
4 | import static org.junit.jupiter.api.Assertions.assertInstanceOf;
5 |
6 | import java.sql.SQLException;
7 | import java.util.Collections;
8 |
9 | import org.junit.jupiter.api.Test;
10 | import org.seasar.doma.DomaException;
11 | import org.seasar.doma.jdbc.ConfigException;
12 | import org.seasar.doma.jdbc.NoResultException;
13 | import org.seasar.doma.jdbc.NonSingleColumnException;
14 | import org.seasar.doma.jdbc.NonUniqueResultException;
15 | import org.seasar.doma.jdbc.OptimisticLockException;
16 | import org.seasar.doma.jdbc.ResultMappingException;
17 | import org.seasar.doma.jdbc.SqlExecutionException;
18 | import org.seasar.doma.jdbc.SqlKind;
19 | import org.seasar.doma.jdbc.SqlLogType;
20 | import org.seasar.doma.jdbc.UniqueConstraintException;
21 | import org.seasar.doma.jdbc.UnknownColumnException;
22 | import org.seasar.doma.message.Message;
23 | import org.springframework.dao.DataAccessException;
24 | import org.springframework.dao.DuplicateKeyException;
25 | import org.springframework.dao.EmptyResultDataAccessException;
26 | import org.springframework.dao.IncorrectResultSizeDataAccessException;
27 | import org.springframework.dao.OptimisticLockingFailureException;
28 | import org.springframework.dao.TypeMismatchDataAccessException;
29 | import org.springframework.dao.UncategorizedDataAccessException;
30 | import org.springframework.jdbc.UncategorizedSQLException;
31 | import org.springframework.jdbc.support.SQLExceptionSubclassTranslator;
32 |
33 | class DomaPersistenceExceptionTranslatorTest {
34 |
35 | private final DomaPersistenceExceptionTranslator translator = new DomaPersistenceExceptionTranslator(
36 | new SQLExceptionSubclassTranslator());
37 |
38 | @Test
39 | void testOccurNotJdbcException() {
40 | DataAccessException dataAccessException = translator
41 | .translateExceptionIfPossible(new DomaException(Message.DOMA2008));
42 | assertNull(dataAccessException);
43 | }
44 |
45 | @Test
46 | void testOccurSqlExecutionException() {
47 | DataAccessException dataAccessException = translator
48 | .translateExceptionIfPossible(new SqlExecutionException(
49 | SqlLogType.FORMATTED, SqlKind.SELECT,
50 | "select * from todo where todo_id = ?",
51 | "select * from todo where todo_id = '000000001'",
52 | "TodoDao/findOne.sql", new SQLException(), null));
53 | assertInstanceOf(UncategorizedSQLException.class, dataAccessException);
54 | assertEquals("select * from todo where todo_id = ?",
55 | ((UncategorizedSQLException) dataAccessException).getSql());
56 | }
57 |
58 | @Test
59 | void testThrowOptimisticLockingFailureException() {
60 | DataAccessException dataAccessException = translator
61 | .translateExceptionIfPossible(new OptimisticLockException(
62 | SqlLogType.FORMATTED,
63 | SqlKind.SELECT,
64 | "update todo set title = ? where todo_id = ? and version = ?",
65 | "update todo set title = 'Modified Title' where todo_id = '000000001' and version = 1",
66 | "TodoDao/update.sql"));
67 | assertInstanceOf(OptimisticLockingFailureException.class, dataAccessException);
68 | }
69 |
70 | @Test
71 | void testThrowDuplicateKeyException() {
72 | DataAccessException dataAccessException = translator
73 | .translateExceptionIfPossible(new UniqueConstraintException(
74 | SqlLogType.FORMATTED,
75 | SqlKind.INSERT,
76 | "insert into todo (todo_id, title) values (?, ?)",
77 | "insert into todo (todo_id, title) values ('000000001', 'Title')",
78 | "TodoDao/insert.sql", new SQLException()));
79 | assertInstanceOf(DuplicateKeyException.class, dataAccessException);
80 | }
81 |
82 | @Test
83 | void testThrowIncorrectResultSizeDataAccessException() {
84 | {
85 | DataAccessException dataAccessException = translator
86 | .translateExceptionIfPossible(new NonUniqueResultException(
87 | SqlLogType.FORMATTED, SqlKind.SELECT,
88 | "select * from todo where created_at = ?",
89 | "select * from todo where created_at = '2016-03-06'",
90 | "TodoDao/findBy.sql"));
91 | assertInstanceOf(IncorrectResultSizeDataAccessException.class, dataAccessException);
92 | }
93 | {
94 | DataAccessException dataAccessException = translator
95 | .translateExceptionIfPossible(new NonSingleColumnException(
96 | SqlLogType.FORMATTED,
97 | SqlKind.SELECT,
98 | "select todo_id, title from todo where created_at = ?",
99 | "select todo_id, title from todo where created_at = '2016-03-06'",
100 | "TodoDao/findBy.sql"));
101 | assertInstanceOf(IncorrectResultSizeDataAccessException.class, dataAccessException);
102 | }
103 | }
104 |
105 | @Test
106 | void testThrowEmptyResultDataAccessException() {
107 | DataAccessException dataAccessException = translator
108 | .translateExceptionIfPossible(new NoResultException(SqlLogType.FORMATTED,
109 | SqlKind.SELECT, "select * from todo where todo_id = ?",
110 | "select * from todo where todo_id = '000000001'",
111 | "TodoDao/findOne.sql"));
112 | assertInstanceOf(EmptyResultDataAccessException.class, dataAccessException);
113 | }
114 |
115 | @Test
116 | void testThrowTypeMismatchDataAccessException() {
117 | {
118 | DataAccessException dataAccessException = translator
119 | .translateExceptionIfPossible(new UnknownColumnException(
120 | SqlLogType.FORMATTED, "todo_id", "todoId", "model.Todo",
121 | SqlKind.SELECT, "select * from todo where created_at = ?",
122 | "select * from todo where created_at = '2016-03-06'",
123 | "TodoDao/findBy.sql"));
124 | assertInstanceOf(TypeMismatchDataAccessException.class, dataAccessException);
125 | }
126 | {
127 | DataAccessException dataAccessException = translator
128 | .translateExceptionIfPossible(new ResultMappingException(
129 | SqlLogType.FORMATTED,
130 | "Todo",
131 | Collections.singletonList("finished"),
132 | Collections.singletonList("modified_at"),
133 | SqlKind.SELECT,
134 | "select todo_id, title from todo where created_at = ?",
135 | "select todo_id, title from todo where created_at = '2016-03-06'",
136 | "TodoDao/findBy.sql"));
137 | assertInstanceOf(TypeMismatchDataAccessException.class, dataAccessException);
138 | }
139 | }
140 |
141 | @Test
142 | void testThrowUncategorizedDataAccessException() {
143 | DataAccessException dataAccessException = translator
144 | .translateExceptionIfPossible(new ConfigException("DomaConfig",
145 | "configure"));
146 | assertInstanceOf(UncategorizedDataAccessException.class, dataAccessException);
147 | }
148 |
149 | }
150 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/test/java/org/seasar/doma/boot/PageablesTest.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot;
2 |
3 | import static org.junit.jupiter.api.Assertions.*;
4 |
5 | import org.junit.jupiter.api.Test;
6 | import org.seasar.doma.jdbc.SelectOptions;
7 | import org.seasar.doma.jdbc.SelectOptionsAccessor;
8 | import org.springframework.data.domain.PageRequest;
9 |
10 | class PageablesTest {
11 |
12 | @Test
13 | void testToSelectOptions() throws Exception {
14 | SelectOptions options = Pageables.toSelectOptions(pageRequest(0, 10));
15 | assertEquals(0L, SelectOptionsAccessor.getOffset(options));
16 | assertEquals(10L, SelectOptionsAccessor.getLimit(options));
17 | }
18 |
19 | @Test
20 | void testToSelectOptions2() throws Exception {
21 | SelectOptions options = Pageables.toSelectOptions(pageRequest(2, 10));
22 | assertEquals(20L, SelectOptionsAccessor.getOffset(options));
23 | assertEquals(10L, SelectOptionsAccessor.getLimit(options));
24 | }
25 |
26 | @Test
27 | void testToSelectOptions3() throws Exception {
28 | SelectOptions options = Pageables.toSelectOptions(pageRequest(2, 5));
29 | assertEquals(10L, SelectOptionsAccessor.getOffset(options));
30 | assertEquals(5L, SelectOptionsAccessor.getLimit(options));
31 | }
32 |
33 | private static PageRequest pageRequest(int page, int size) throws Exception {
34 | try {
35 | // Try PageRequest.of(int, int) added since Spring Data Commons 2.0
36 | return (PageRequest) PageRequest.class.getMethod("of", int.class, int.class)
37 | .invoke(null, page, size);
38 | } catch (@SuppressWarnings("unused") NoSuchMethodException e) {
39 | // If 'of' method is missing (In other words, Spring Data Commons version is
40 | // less than 2.0),
41 | // then it use constructor with two int arguments.
42 | return PageRequest.class.getConstructor(int.class, int.class).newInstance(
43 | page, size);
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/test/java/org/seasar/doma/boot/ResourceLoaderScriptFileLoaderTest.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot;
2 |
3 | import static org.junit.jupiter.api.Assertions.assertNull;
4 | import static org.junit.jupiter.api.Assertions.assertEquals;
5 | import static org.mockito.Mockito.mock;
6 | import static org.mockito.Mockito.when;
7 |
8 | import java.net.URL;
9 |
10 | import org.junit.jupiter.api.Test;
11 | import org.springframework.core.io.Resource;
12 | import org.springframework.core.io.ResourceLoader;
13 |
14 | class ResourceLoaderScriptFileLoaderTest {
15 |
16 | @Test
17 | void testLoadAsURL() throws Exception {
18 | var location = "META-INF/com/example/dao/TestDao/test.script";
19 | var expectedURL = new URL("file:///" + location);
20 | var resourceLoader = mock(ResourceLoader.class);
21 | var resource = mock(Resource.class);
22 |
23 | when(resourceLoader.getResource(ResourceLoader.CLASSPATH_URL_PREFIX + location))
24 | .thenReturn(resource);
25 | when(resource.exists()).thenReturn(true);
26 | when(resource.getURL()).thenReturn(expectedURL);
27 |
28 | var sut = new ResourceLoaderScriptFileLoader(resourceLoader);
29 | var actualURL = sut.loadAsURL(location);
30 | assertEquals(expectedURL, actualURL);
31 | }
32 |
33 | @Test
34 | void testLoadAsURLFallback() throws Exception {
35 | var location = "META-INF/com/example/dao/TestDao/test.script";
36 | var expectedURL = new URL("file:///" + location);
37 | var resourceLoader = mock(ResourceLoader.class);
38 | var resource = mock(Resource.class);
39 | var notExistsResource = mock(Resource.class);
40 |
41 | when(resourceLoader.getResource(ResourceLoader.CLASSPATH_URL_PREFIX + location))
42 | .thenReturn(notExistsResource);
43 | when(resourceLoader.getResource(ResourceLoader.CLASSPATH_URL_PREFIX + "/" + location))
44 | .thenReturn(resource);
45 | when(notExistsResource.exists()).thenReturn(false);
46 | when(resource.exists()).thenReturn(true);
47 | when(resource.getURL()).thenReturn(expectedURL);
48 |
49 | var sut = new ResourceLoaderScriptFileLoader(resourceLoader);
50 | var actualURL = sut.loadAsURL(location);
51 | assertEquals(expectedURL, actualURL);
52 | }
53 |
54 | @Test
55 | void testLoadAsURLScriptNotFound() {
56 | var location = "META-INF/com/example/dao/TestDao/test.script";
57 | var resourceLoader = mock(ResourceLoader.class);
58 | var notExistsResource = mock(Resource.class);
59 |
60 | when(resourceLoader.getResource(ResourceLoader.CLASSPATH_URL_PREFIX + location))
61 | .thenReturn(notExistsResource);
62 | when(resourceLoader.getResource(ResourceLoader.CLASSPATH_URL_PREFIX + "/" + location))
63 | .thenReturn(notExistsResource);
64 | when(notExistsResource.exists()).thenReturn(false);
65 |
66 | var sut = new ResourceLoaderScriptFileLoader(resourceLoader);
67 | var actualURL = sut.loadAsURL(location);
68 | assertNull(actualURL);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/doma-spring-boot-core/src/test/java/org/seasar/doma/boot/TryLookupEntityListenerProviderTest.java:
--------------------------------------------------------------------------------
1 | package org.seasar.doma.boot;
2 |
3 | import static org.junit.jupiter.api.Assertions.*;
4 | import static org.junit.jupiter.api.Assertions.assertThrows;
5 |
6 | import org.junit.jupiter.api.Test;
7 | import org.seasar.doma.jdbc.entity.EntityListener;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.context.ApplicationContext;
10 | import org.springframework.context.annotation.AnnotationConfigApplicationContext;
11 | import org.springframework.context.annotation.Bean;
12 | import org.springframework.stereotype.Component;
13 |
14 | class TryLookupEntityListenerProviderTest {
15 |
16 | @Test
17 | void testManaged() throws Exception {
18 | try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
19 | context.register(FooListener.class);
20 | context.refresh();
21 | TryLookupEntityListenerProvider provider = new TryLookupEntityListenerProvider();
22 | provider.setApplicationContext(context);
23 | FooListener listener = provider.get(FooListener.class, FooListener::new);
24 | assertTrue(listener.managed);
25 | }
26 | }
27 |
28 | @Test
29 | void testManaged_notUnique() throws Exception {
30 | try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
31 | FooConfig.class)) {
32 | TryLookupEntityListenerProvider provider = new TryLookupEntityListenerProvider();
33 | provider.setApplicationContext(context);
34 | assertThrows(IllegalStateException.class, () -> {
35 | provider.get(FooListener.class, FooListener::new);
36 | });
37 | }
38 | }
39 |
40 | @Test
41 | void testNotManaged() throws Exception {
42 | try (AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext()) {
43 | context.refresh();
44 | TryLookupEntityListenerProvider provider = new TryLookupEntityListenerProvider();
45 | provider.setApplicationContext(context);
46 | FooListener listener = provider.get(FooListener.class, FooListener::new);
47 | assertFalse(listener.managed);
48 | }
49 | }
50 |
51 | @Component
52 | static class FooListener implements EntityListener