Compare commits

..
Author SHA1 Message Date
Rob Bygrave f27958210c #3433 - Put test back from desc -> description as desc as a column name isn't widely supported by other databases 2024-07-08 21:52:36 +12:00
Rob Bygrave 70cfc77b5b #3433 - Entity property called desc used with query order by desc generates bad sql 2024-07-04 00:01:00 +12:00
Rob Bygrave 8913bead89 [ebean-migration] #3434 - Connection is closed error running migration with MySql and Hikari (#3437) 2024-07-02 23:47:14 +12:00
Rob Bygrave cdf1cd8487 [ebean-redis] Fix for #3432 empty value for natural keys (#3436) 2024-07-02 22:06:57 +12:00
Rob Bygrave 2582c4b653 Bump to ebean-agent 14.5.0/15.5.0 with ASM 9.7 for JDK 22 and 23 support (#3435) 2024-07-02 18:08:08 +12:00
Rob Bygrave a9e3e2ea43 Version 14.4.0 2024-06-26 22:33:04 +12:00
Rob Bygrave 834ce971b3 Bump ebean-agent, no functional change 2024-06-26 22:19:58 +12:00
Rob Bygrave 5c27f89677 Change includeLabelInSql to default to true (#3431)
To disable this use ebean.includeLabelInSql=false or set this via
`DatabaseBuilder.includeLabelInSql(false)``
2024-06-26 20:32:19 +12:00
Rob Bygrave bfbbb7e7a7 Bump ebean-datasource dependency to 9.0 with automatic Lambda mode detection (#3430)
* Bump ebean-datasource dependency to 9.0 with automatic Lambda mode detection

ebean-datasource 9.0 automatically detects when it is running in AWS Lambda
and will set validateOnHeartbeat to false. In Lambda we don't want to validate
connections in background threads that can suspend in Lambda.
2024-06-26 20:27:49 +12:00
Rob Bygrave a8947c7d2f Bump ebean-migration dependency to 14.1.0 with fastMode enabled by default (#3429)
ebean-migration 14.1.0 defaults fastMode to true. This means that it first
runs a fast check that all migrations have been run. If that does not succeed
for any reason it runs the normal migration process.
2024-06-26 20:15:21 +12:00
Rob Bygrave d5401efb08 #3423 JtaTransactionManager keeps reference to already closed scope (and Transaction/connection ThreadLocal) when JtaTxnListener#afterCompletion is called by a different thread (#3424)
Bugfix for "Long/slow transaction reaper" in Wildfire that can close/rollback a transaction in a different thread. Fix is to use active flag to inactivate the transaction and detect that case in JtaTransactionManager.getCurrentTransaction()
2024-06-21 07:57:31 +12:00
Rob Bygrave 925ceaf441 Update build actions/setup-java@v4 2024-06-14 21:47:43 +12:00
Rob Bygrave c5fea13ca5 Update build actions/setup-java@v4 2024-06-14 21:42:06 +12:00
Rob Bygrave 6fa3759786 Add 23 to build 2024-06-14 21:34:54 +12:00
Rob Bygrave 1c5288b6ec Version 14.3.1 2024-06-10 19:26:40 +12:00
Rob Bygrave b485fb7440 Bump ebean-agent to 14.3.1 2024-06-10 19:02:41 +12:00
Rob Bygrave b07f909dd3 Bump parent pom to 4.2 with EA changes to annotation processing (#3417)
* Bump parent pom to 4.2 with EA changes to annotation processing

Annotation processing needs to be explicitly on in JDK 24 EA builds

* Bump bytebuddy version in ebean-test and use experimental=true for EA builds

* Use parent pom 4.3 with bytebuddy.experimental=true by default for surefire
2024-06-10 18:36:40 +12:00
Rob Bygrave fa92e7a4b7 Merge pull request #3416 from ebean-orm/feature/querybean-gen-suppresswarnings
Change QueryBean to use protected constructors, suppress warning on generated query beans
2024-06-10 12:39:53 +12:00
Rob Bygrave 1823ef288a Change QueryBean to use protected constructors, suppress warning on generated query beans 2024-06-07 22:48:04 +12:00
Rob Bygrave 7b2128b02f Merge pull request #3415 from ebean-orm/feature/3412
#3412 Use existing/parent transaction with fetch query on ToMany paths
2024-06-07 22:31:24 +12:00
Rob Bygrave 3c84a902e8 Followup for #3412 - Refactor DefaultBeanLoader move query creation logic into LoadBeanRequest
Move the query creation, using transaction and configure into LoadBeanRequest. This code then looks more like that of LoadManyRequest.
2024-06-07 22:26:48 +12:00
Rob Bygrave 3ce95c34cb #3412 Use existing/parent transaction with fetch query on ToMany paths
Fix such that LoadManyRequest uses the parent requests transaction rather
than obtain a new read only transaction to perform the fetch query.
2024-06-07 22:16:02 +12:00
Rob Bygrave d817dcb549 Merge pull request #3413 from ebean-orm/feature/fix-logging-naturalKey
Fix logging message for naturalKey MPUT to include the natural key properties
2024-05-31 21:57:24 +12:00
Rob Bygrave 5f218e1fdb Merge pull request #3409 from kaiyaok2/fix_NIO
Fixed non-idempotent tests in `TestCacheSerialization`
2024-05-31 21:56:33 +12:00
Rob Bygrave 59daf5689a Fix logging message for naturalKey MPUT to include the natural key properties 2024-05-31 21:52:38 +12:00
kaiyaok2 44efed5cd9 fixed non-idempotent tests 2024-05-26 23:57:12 +08:00
Rob Bygrave be28314e31 Update test kotlin to use kotlin-querybean-generator 14.3.0
Fixes the test as we now use QueryBean etc rather than TQRootBean
2024-05-16 00:05:55 +12:00
Rob Bygrave 053d82b54a Version 14.3.0 2024-05-14 22:10:08 +12:00
Rob Bygrave 0141e2effa Merge pull request #3401 from ebean-orm/feature/agent-14.3.0
Bump to ebean-agent 14.3.0
2024-05-14 21:18:12 +12:00
Rob Bygrave a33bb4d4c8 Bump to ebean-agent 14.3.0 2024-05-14 21:15:13 +12:00
Rob Bygrave d0348210be Merge pull request #3398 from ebean-orm/feature/NoTimeZone
mysql: Support "NoTimeZone" to bypass MySQL JDBC use of Timezone Calendar
2024-05-01 20:30:56 +12:00
Rob Bygrave 753cf66cf0 Merge pull request #3397 from ebean-orm/feature/distinctOn
Postgres: Add support for DISTINCT ON query clause
2024-05-01 20:30:41 +12:00
Rob Bygrave 4a8b4dd5fb mysql: Support "NoTimeZone" to bypass MySQL JDBC use of Timezone Calendar
Refer #3393 #3394
2024-05-01 20:24:10 +12:00
robin.bygrave 2faf7008db #3397 DISTINCT ON subquery support 2024-05-01 20:07:16 +12:00
Rob Bygrave 76c25cbe83 Postgres: Add support for DISTINCT ON query clause - fix test ebean.properties 2024-05-01 01:04:33 +12:00
Rob Bygrave 5c36a725f4 Postgres: Add support for DISTINCT ON query clause 2024-05-01 00:50:37 +12:00
Rob Bygrave b99d4f5a51 Merge pull request #3396 from ebean-orm/feature/limitOffset-with-labelComment
Include inline sql hint and comment in limit/offset sql
2024-04-30 23:57:04 +12:00
Rob Bygrave 7d18942357 Include inline sql hint and comment in limit/offset sql 2024-04-30 23:46:36 +12:00
141 changed files with 1181 additions and 974 deletions
+3 -3
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'zulu'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+3 -3
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+3 -3
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'zulu'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+3 -3
View File
@@ -16,18 +16,18 @@ jobs:
strategy:
fail-fast: false
matrix:
java_version: [GA,EA]
java_version: [GA,EA,23]
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: oracle-actions/setup-java@v1
with:
website: jdk.java.net
release: ${{ matrix.java_version }}
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+3 -3
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+3 -3
View File
@@ -17,14 +17,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+3 -3
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'zulu'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+3 -3
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+3 -3
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'zulu'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+3 -3
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+3 -3
View File
@@ -17,14 +17,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+3 -3
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+3 -3
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-clickhouse</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-db2</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-hana</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mariadb</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mysql</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-nuodb</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-oracle</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
</dependencies>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -22,13 +22,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
@@ -47,19 +47,19 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgis-types</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlite</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlserver</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
</dependencies>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
@@ -41,7 +41,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jackson-mapper</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
@@ -60,13 +60,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-all</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
</dependencies>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
</parent>
<artifactId>composites</artifactId>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
</parent>
<name>ebean api</name>
+67 -29
View File
@@ -186,15 +186,15 @@ public class OrderBy<T> implements Serializable {
if (list.isEmpty()) {
return null;
}
StringBuilder sb = new StringBuilder();
var append = new StringAppend();
for (int i = 0; i < list.size(); i++) {
Property property = list.get(i);
if (i > 0) {
sb.append(", ");
append.append(", ");
}
sb.append(property.toStringFormat());
property.toStringFormat(append);
}
return sb.toString();
return append.toString();
}
@Override
@@ -231,6 +231,55 @@ public class OrderBy<T> implements Serializable {
return this;
}
/**
* Append the order by clause.
*/
public interface Append {
/**
* Append a property expression.
*/
Append property(String property);
/**
* Append a literal.
*/
Append append(String literal);
/**
* Parse and append an expression.
*/
Append parse(String expression);
}
private static final class StringAppend implements Append {
private final StringBuilder builder = new StringBuilder();
@Override
public String toString() {
return builder.toString();
}
@Override
public Append property(String property) {
builder.append(property);
return this;
}
@Override
public Append append(String literal) {
builder.append(literal);
return this;
}
@Override
public Append parse(String raw) {
builder.append(raw);
return this;
}
}
/**
* A property and its ascending descending order.
*/
@@ -309,36 +358,25 @@ public class OrderBy<T> implements Serializable {
@Override
public String toString() {
return toStringFormat();
return property;
}
public String toStringFormat() {
if (nulls == null && collation == null) {
if (ascending) {
return property;
public void toStringFormat(Append append) {
if (collation != null) {
if (collation.contains("${}")) {
// this is a complex collation, e.g. DB2 - we must replace the property
append.parse(collation.replace("${}", property));
} else {
return property + " desc";
append.property(property).append(" collate ").append(collation);
}
} else {
StringBuilder sb = new StringBuilder();
if (collation != null) {
if (collation.contains("${}")) {
// this is a complex collation, e.g. DB2 - we must replace the property
sb.append(collation.replace("${}", property));
} else {
sb.append(property);
sb.append(" collate ").append(collation);
}
} else {
sb.append(property);
}
if (!ascending) {
sb.append(' ').append("desc");
}
if (nulls != null) {
sb.append(' ').append(nulls).append(' ').append(highLow);
}
return sb.toString();
append.property(property);
}
if (!ascending) {
append.append(" desc");
}
if (nulls != null) {
append.append(" ").append(nulls).append(" ").append(highLow);
}
}
@@ -40,6 +40,13 @@ public interface QueryBuilderProjection<SELF, T> {
*/
SELF select(String fetchProperties);
/**
* Set DISTINCT ON clause. This is a Postgres only SQL feature.
*
* @param distinctOn The properties to include in the DISTINCT ON clause.
*/
SELF distinctOn(String distinctOn);
/**
* Apply the fetchGroup which defines what part of the object graph to load.
*/
@@ -129,7 +129,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
* When true then include a sql comment in generated SELECT queries with the query
* label or profile location label.
*/
private boolean includeLabelInSql;
private boolean includeLabelInSql = true;
/**
* Interesting classes such as entities, embedded, ScalarTypes,
@@ -4,22 +4,8 @@ public final class AnsiSqlRowsLimiter implements SqlLimiter {
@Override
public SqlLimitResponse limit(SqlLimitRequest request) {
String dbSql = request.getDbSql();
StringBuilder sb = new StringBuilder(50 + dbSql.length());
sb.append("select ");
if (request.isDistinct()) {
sb.append("distinct ");
}
sb.append(dbSql);
int firstRow = request.getFirstRow();
if (firstRow > 0) {
sb.append(" offset ").append(firstRow).append(" rows");
}
int maxRows = request.getMaxRows();
if (maxRows > 0) {
sb.append(" fetch next ").append(maxRows).append(" rows only");
}
String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
final var ansiSql = request.ansiOffsetRows();
final var sql = request.getDbPlatform().completeSql(ansiSql, request.getOrmQuery());
return new SqlLimitResponse(sql);
}
}
@@ -199,21 +199,12 @@ public class DatabasePlatform {
protected SqlExceptionTranslator exceptionTranslator = new SqlCodeTranslator();
protected InsertSqlSyntaxExtension insertSqlSyntaxExtension = new StandardInsertSqlSyntax();
/**
* Instantiates a new database platform.
*/
public DatabasePlatform() {
}
/**
* Return the Insert SQL syntax helper.
*/
public InsertSqlSyntaxExtension insertSqlSyntaxExtension() {
return insertSqlSyntaxExtension;
}
/**
* Translate the SQLException into a specific persistence exception if possible.
*/
@@ -1,32 +0,0 @@
package io.ebean.config.dbplatform;
/**
* Insert SQL syntax to allow support for ClickHouse type optimisation for inserts.
*/
public interface InsertSqlSyntaxExtension {
/**
* Start the columns.
*/
String startColumns();
/**
* End of the columns.
*/
String endColumns();
/**
* Return true for insert to use standard binding.
*/
boolean useBinding();
/**
* Start types for non-standard binding (e.g. ClickHouse).
*/
String startTypes();
/**
* End types for non-standard binding (e.g. ClickHouse).
*/
String endTypes();
}
@@ -7,23 +7,16 @@ public final class LimitOffsetSqlLimiter implements SqlLimiter {
@Override
public SqlLimitResponse limit(SqlLimitRequest request) {
String dbSql = request.getDbSql();
StringBuilder sb = new StringBuilder(50 + dbSql.length());
sb.append("select ");
if (request.isDistinct()) {
sb.append("distinct ");
}
sb.append(dbSql);
final var buffer = request.selectDistinctOnSql();
int maxRows = request.getMaxRows();
if (maxRows > 0) {
sb.append(" limit ").append(maxRows);
buffer.append(" limit ").append(maxRows);
}
int firstRow = request.getFirstRow();
if (firstRow > 0) {
sb.append(" offset ").append(firstRow);
buffer.append(" offset ").append(firstRow);
}
String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
return new SqlLimitResponse(sql);
return new SqlLimitResponse(request.getDbPlatform().completeSql(buffer.toString(), request.getOrmQuery()));
}
}
@@ -8,6 +8,21 @@ import io.ebean.Query;
*/
public interface SqlLimitRequest {
/**
* Return ANSI SQL Offset and next rows.
*/
String ansiOffsetRows();
/**
* Create and return buffer including the select distinct clause.
*/
StringBuilder selectDistinct();
/**
* Create and return buffer including the select distinct on clause.
*/
StringBuilder selectDistinctOnSql();
/**
* Return true if the query uses distinct.
*/
@@ -1,32 +0,0 @@
package io.ebean.config.dbplatform;
/**
* Standard Insert SQL syntax.
*/
public final class StandardInsertSqlSyntax implements InsertSqlSyntaxExtension {
@Override
public String startColumns() {
return " (";
}
@Override
public String endColumns() {
return ") values (";
}
@Override
public boolean useBinding() {
return true;
}
@Override
public String startTypes() {
throw new IllegalStateException();
}
@Override
public String endTypes() {
throw new IllegalStateException();
}
}
@@ -76,7 +76,7 @@ class DatabaseConfigTest {
props.setProperty("skipDataSourceCheck", "true");
props.setProperty("readOnlyDatabase", "true");
props.setProperty("lengthCheck", "ON");
props.setProperty("includeLabelInSql", "true");
props.setProperty("includeLabelInSql", "false");
props.setProperty("queryPlan.enable", "true");
props.setProperty("queryPlan.thresholdMicros", "10000");
@@ -97,7 +97,7 @@ class DatabaseConfigTest {
assertTrue(settings.isLoadModuleInfo());
assertTrue(settings.skipDataSourceCheck());
assertTrue(settings.readOnlyDatabase());
assertTrue(settings.isIncludeLabelInSql());
assertFalse(settings.isIncludeLabelInSql());
assertThat(settings.getLengthCheck()).isEqualTo(LengthCheck.ON);
assertTrue(settings.isIdGeneratorAutomatic());
@@ -183,7 +183,7 @@ class DatabaseConfigTest {
assertEquals(10000L, config.getQueryPlanCaptureMaxTimeMillis());
assertEquals(10, config.getQueryPlanCaptureMaxCount());
assertThat(config.getLengthCheck()).isEqualTo(LengthCheck.OFF);
assertFalse(config.isIncludeLabelInSql());
assertTrue(config.isIncludeLabelInSql());
config.setLoadModuleInfo(false);
assertFalse(config.isAutoLoadModuleInfo());
+26 -26
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
</parent>
<name>ebean bom</name>
@@ -89,25 +89,25 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
@@ -125,13 +125,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jackson-mapper</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-ddl-generator</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
@@ -155,37 +155,37 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>querybean-generator</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>kotlin-querybean-generator</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-redis</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-spring-txn</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<!-- platforms -->
@@ -193,79 +193,79 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-clickhouse</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-db2</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-h2</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-hana</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-mariadb</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-mysql</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-nuodb</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-oracle</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgres</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgis</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgis-types</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-sqlite</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-sqlserver</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
</dependencies>
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
</parent>
<artifactId>ebean-core-type</artifactId>
@@ -16,7 +16,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
+7 -6
View File
@@ -3,7 +3,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
</parent>
<artifactId>ebean-core</artifactId>
@@ -22,7 +22,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
@@ -46,7 +46,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<dependency>
@@ -159,21 +159,21 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlserver</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
<scope>test</scope>
</dependency>
@@ -211,6 +211,7 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Dnet.bytebuddy.experimental=true</argLine>
<useSystemClassLoader>false</useSystemClassLoader>
<trimStackTrace>false</trimStackTrace>
<failIfNoTests>false</failIfNoTests>
@@ -84,10 +84,17 @@ public final class LoadBeanRequest extends LoadRequest {
return idList;
}
public SpiQuery<?> createQuery(SpiEbeanServer server) {
final SpiQuery<?> query = server.createQuery(beanType());
query.usingTransaction(transaction);
configureQuery(query);
return query;
}
/**
* Configure the query for lazy loading execution.
*/
public void configureQuery(SpiQuery<?> query) {
private void configureQuery(SpiQuery<?> query) {
query.setMode(Mode.LAZYLOAD_BEAN);
query.setPersistenceContext(loadBuffer.persistenceContext());
query.setLoadDescription(mode(), description());
@@ -94,6 +94,7 @@ public final class LoadManyRequest extends LoadRequest {
public SpiQuery<?> createQuery(SpiEbeanServer server) {
BeanPropertyAssocMany<?> many = many();
SpiQuery<?> query = many.newQuery(server);
query.usingTransaction(transaction);
String orderBy = many.lazyFetchOrderBy();
if (orderBy != null) {
query.orderBy(orderBy);
@@ -439,6 +439,11 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
@Override
SpiQuery<T> copy();
/**
* Return the distinct on clause.
*/
String distinctOn();
/**
* Return a copy of the query attaching to a different EbeanServer.
*/
@@ -549,7 +554,6 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
* Return true if the query should include the Id property.
* <p>
* distinct and single attribute queries exclude the Id property.
* </p>
*/
boolean isWithId();
@@ -357,4 +357,8 @@ public interface SpiTransaction extends Transaction {
*/
void postRollback(Throwable cause);
/**
* Set the transaction to be inactive via external transaction manager.
*/
void deactivateExternal();
}
@@ -447,4 +447,9 @@ public abstract class SpiTransactionProxy implements SpiTransaction {
public void postRollback(Throwable cause) {
transaction.postRollback(cause);
}
@Override
public void deactivateExternal() {
transaction.deactivateExternal();
}
}
@@ -126,9 +126,7 @@ final class DefaultBeanLoader {
if (loadRequest.checkEmpty()) {
throw new RuntimeException("Nothing in batch?");
}
final SpiQuery<?> query = server.createQuery(loadRequest.beanType());
query.usingTransaction(loadRequest.transaction());
loadRequest.configureQuery(query);
final SpiQuery<?> query = loadRequest.createQuery(server);
loadRequest.postLoad(executeQuery(loadRequest, query));
}
@@ -449,6 +449,9 @@ public final class InternalConfiguration {
*/
private DataTimeZone initDataTimeZone() {
String tz = config.getDataTimeZone();
if ("NoTimeZone".equals(tz)) {
return new NoDataTimeZone();
}
if (tz == null) {
if (isMySql(getPlatform())) {
return new MySqlDataTimeZone();
@@ -514,7 +514,7 @@ final class BeanDescriptorCacheHelp<T> {
if (natKeys != null && !natKeys.isEmpty()) {
if (natLog.isLoggable(DEBUG)) {
natLog.log(DEBUG, " MPUT {0}({1}, {2})", cacheName, naturalKey, natKeys.keySet());
natLog.log(DEBUG, " MPUT {0}({1}, {2})", cacheName, Arrays.toString(naturalKey), natKeys.keySet());
}
naturalKeyCache.putAll(natKeys);
}
@@ -5,7 +5,6 @@ import io.ebean.DatabaseBuilder;
import io.ebean.Model;
import io.ebean.RawSqlBuilder;
import io.ebean.annotation.ConstraintMode;
import io.ebean.annotation.Platform;
import io.ebean.bean.BeanCollection;
import io.ebean.bean.EntityBean;
import io.ebean.config.*;
@@ -633,8 +632,6 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
}
private void registerDescriptor(DeployBeanInfo<?> info) {
platformUsesColumnDefinitions(info);
BeanDescriptor<?> desc = new BeanDescriptor<>(this, info.getDescriptor());
descMap.put(desc.type().getName(), desc);
if (desc.isDocStoreMapped()) {
@@ -647,23 +644,6 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
}
}
private void platformUsesColumnDefinitions(DeployBeanInfo<?> info) {
if (databasePlatform.isPlatform(Platform.CLICKHOUSE) && !DbOffline.isGenerateMigration()) {
// ClickHouse uses column definition to optimise JDBC bulk inserts
DbPlatformTypeMapping typeMapping = databasePlatform.dbTypeMap();
for (DeployBeanProperty property : info.getDescriptor().propertiesAll()) {
if (property.getDbColumnDefn() == null) {
DbPlatformType dbPlatformType = typeMapping.get(property.getDbType());
String columnDefn = dbPlatformType.renderType(property.getDbLength(), property.getDbScale());
if (property.isNullable()) {
columnDefn = "Nullable(" + columnDefn + ")";
}
property.setDbColumnDefn(columnDefn);
}
}
}
}
/**
* Read the initial deployment information for the entities.
* <p>
@@ -43,11 +43,6 @@ public interface ImportedId {
*/
void dmlAppend(GenerateDmlRequest request);
/**
* Append column and type for Insert (ClickHouse).
*/
void dmlType(GenerateDmlRequest request);
/**
* Bind the value from the bean.
*/
@@ -66,16 +66,6 @@ public final class ImportedIdEmbedded implements ImportedId {
}
}
@Override
public void dmlType(GenerateDmlRequest request) {
boolean update = request.isUpdate();
for (ImportedIdSimple anImported : imported) {
if (anImported.isInclude(update)) {
anImported.dmlType(request);
}
}
}
@Override
public String importedIdClause() {
StringBuilder sb = new StringBuilder();
@@ -37,7 +37,6 @@ public final class ImportedIdSimple implements ImportedId, Comparable<ImportedId
final BeanPropertyAssoc<?> owner;
final String localDbColumn;
private final String localColumnDefn;
private final String localSqlFormula;
final BeanProperty foreignProperty;
private final int position;
@@ -50,7 +49,6 @@ public final class ImportedIdSimple implements ImportedId, Comparable<ImportedId
this.localDbColumn = InternString.intern(localDbColumn);
this.localSqlFormula = InternString.intern(localSqlFormula);
this.foreignProperty = foreignProperty;
this.localColumnDefn = foreignProperty.dbColumnDefn();
this.position = position;
this.insertable = insertable;
this.updateable = updateable;
@@ -145,11 +143,6 @@ public final class ImportedIdSimple implements ImportedId, Comparable<ImportedId
request.appendColumn(localDbColumn);
}
@Override
public void dmlType(GenerateDmlRequest request) {
request.appendColumnDefn(localDbColumn, localColumnDefn);
}
@Override
public String importedIdClause() {
return localDbColumn + " = ?";
@@ -75,7 +75,7 @@ final class SubQueryExpression extends AbstractExpression implements Unsupported
@Override
public void addSql(SpiExpressionRequest request) {
request.property(propName).append(op.expression).append('(').parse(sql).append(')');
request.property(propName).append(op.expression).append('(').append(sql).append(')');
}
@Override
@@ -15,26 +15,14 @@ public final class GenerateDmlRequest {
private String prefix2;
private int insertMode;
private int bindColumnCount;
private boolean hasColumnDefn;
GenerateDmlRequest append(String s) {
sb.append(s);
return this;
}
/**
* Append column and type for Insert (ClickHouse).
*/
public void appendColumnDefn(String columnName, String columnDefn) {
if (hasColumnDefn) {
sb.append(", ");
} else {
hasColumnDefn = true;
}
sb.append(columnName).append(' ').append(columnDefn);
}
public void appendColumn(String column) {
//String bind = (insertMode > 0) ? "?" : "=?";
appendColumn(column, "?");
}
@@ -4,7 +4,6 @@ import io.ebean.InsertOptions;
import io.ebean.annotation.Platform;
import io.ebean.bean.EntityBean;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.config.dbplatform.InsertSqlSyntaxExtension;
import io.ebeaninternal.server.core.PersistRequestBean;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.InheritInfo;
@@ -38,13 +37,10 @@ final class InsertMeta {
private final Bindable shadowFKey;
private final String[] identityDbColumns;
private final Platform platform;
private final InsertSqlSyntaxExtension insertMetaSql;
private final InsertMetaOptions options;
InsertMeta(DatabasePlatform dbPlatform, BeanDescriptor<?> desc, Bindable shadowFKey, BindableId id, BindableList all) {
this.platform = dbPlatform.platform();
this.insertMetaSql = dbPlatform.insertSqlSyntaxExtension();
this.options = InsertMetaPlatform.create(platform, desc, this);
this.discriminator = discriminator(desc);
this.id = id;
@@ -178,7 +174,7 @@ final class InsertMeta {
request.append(defaultValues());
return;
}
request.append(insertMetaSql.startColumns());
request.append(" (");
if (!nullId) {
id.dmlAppend(request);
}
@@ -193,28 +189,9 @@ final class InsertMeta {
} else {
allExcludeDraftOnly.dmlAppend(request);
}
request.append(insertMetaSql.endColumns());
if (insertMetaSql.useBinding()) {
request.append(request.insertBindBuffer());
request.append(")");
} else {
request.append(insertMetaSql.startTypes());
if (!nullId) {
id.dmlType(request);
}
if (shadowFKey != null) {
shadowFKey.dmlType(request);
}
if (discriminator != null) {
discriminator.dmlType(request);
}
if (draftTable) {
all.dmlType(request);
} else {
allExcludeDraftOnly.dmlType(request);
}
request.append(insertMetaSql.endTypes());
}
request.append(") values (");
request.append(request.insertBindBuffer());
request.append(")");
}
private String defaultValues() {
@@ -33,11 +33,6 @@ public interface Bindable {
*/
void dmlAppend(GenerateDmlRequest request);
/**
* Append column and type for Insert (ClickHouse).
*/
void dmlType(GenerateDmlRequest request);
/**
* Bind given the request and bean. The bean could be the oldValues bean
* when binding a update or delete where clause with ALL concurrency mode.
@@ -40,11 +40,6 @@ class BindableAssocOne implements Bindable {
importedId.dmlAppend(request);
}
@Override
public void dmlType(GenerateDmlRequest request) {
importedId.dmlType(request);
}
@Override
public void dmlBind(BindableRequest request, EntityBean bean) throws SQLException {
EntityBean assocBean = (EntityBean) assocOne.getValue(bean);
@@ -39,11 +39,6 @@ public final class BindableDiscriminator implements Bindable {
request.appendColumn(columnName);
}
@Override
public void dmlType(GenerateDmlRequest request) {
throw new IllegalArgumentException("Not supported");
}
@Override
public void dmlBind(BindableRequest bindRequest, EntityBean bean) throws SQLException {
bindRequest.bind(discValue, sqlType);
@@ -35,13 +35,6 @@ final class BindableEmbedded implements Bindable {
}
}
@Override
public void dmlType(GenerateDmlRequest request) {
for (Bindable item : items) {
item.dmlType(request);
}
}
@Override
public void addToUpdate(PersistRequestBean<?> request, List<Bindable> list) {
if (request.isAddToUpdate(embProp)) {
@@ -41,11 +41,6 @@ final class BindableEncryptedProperty implements Bindable {
request.appendColumn(prop.dbColumn(), prop.dbBind());
}
@Override
public void dmlType(GenerateDmlRequest request) {
request.appendColumnDefn(prop.dbColumn(), prop.dbColumnDefn());
}
@Override
public void dmlBind(BindableRequest request, EntityBean bean) throws SQLException {
Object value = null;
@@ -81,13 +81,6 @@ final class BindableIdEmbedded implements BindableId {
}
}
@Override
public void dmlType(GenerateDmlRequest request) {
for (BeanProperty prop : props) {
request.appendColumn(prop.dbColumnDefn());
}
}
@Override
public boolean deriveConcatenatedId(PersistRequestBean<?> persist) {
if (matches == null) {
@@ -28,11 +28,6 @@ final class BindableIdEmpty implements BindableId {
// nothing
}
@Override
public void dmlType(GenerateDmlRequest request) {
// nothing
}
@Override
public void dmlBind(BindableRequest request, EntityBean bean) {
// nothing
@@ -58,18 +58,17 @@ final class BindableIdScalar implements BindableId {
@Override
public void dmlAppend(GenerateDmlRequest request) {
request.appendColumn(uidProp.dbColumn());
}
@Override
public void dmlType(GenerateDmlRequest request) {
request.appendColumnDefn(uidProp.dbColumn(), uidProp.dbColumnDefn());
}
@Override
public void dmlBind(BindableRequest request, EntityBean bean) throws SQLException {
Object value = uidProp.getValue(bean);
request.bind(value, uidProp);
// used for summary logging
request.setIdValue(value);
}
@@ -60,13 +60,6 @@ public final class BindableList implements Bindable {
}
}
@Override
public void dmlType(GenerateDmlRequest request) {
for (Bindable item : items) {
item.dmlType(request);
}
}
@Override
public void dmlBind(BindableRequest bindRequest, EntityBean bean) throws SQLException {
for (Bindable item : items) {
@@ -36,11 +36,6 @@ class BindableProperty implements Bindable {
request.appendColumn(prop.dbColumn());
}
@Override
public void dmlType(GenerateDmlRequest request) {
request.appendColumnDefn(prop.dbColumn(), prop.dbColumnDefn());
}
/**
* Normal binding of a property value from the bean.
*/
@@ -41,11 +41,6 @@ final class BindablePropertyVersion implements Bindable {
request.appendColumn(prop.dbColumn());
}
@Override
public void dmlType(GenerateDmlRequest request) {
request.appendColumnDefn(prop.dbColumn(), prop.dbColumnDefn());
}
/**
* Normal binding of a property value from the bean.
*/
@@ -45,11 +45,6 @@ public final class BindableUnidirectional implements Bindable {
importedId.dmlAppend(request);
}
@Override
public void dmlType(GenerateDmlRequest request) {
importedId.dmlType(request);
}
@Override
public void dmlBind(BindableRequest request, EntityBean bean) throws SQLException {
PersistRequestBean<?> persistRequest = request.persistRequest();
@@ -3,7 +3,6 @@ package io.ebeaninternal.server.query;
import io.ebean.*;
import io.ebean.annotation.Platform;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.config.dbplatform.SqlLimitRequest;
import io.ebean.config.dbplatform.SqlLimitResponse;
import io.ebean.config.dbplatform.SqlLimiter;
import io.ebean.event.readaudit.ReadAuditQueryPlan;
@@ -533,7 +532,7 @@ final class CQueryBuilder {
private final boolean distinct;
private final boolean countSingleAttribute;
private final String dbOrderBy;
private boolean useSqlLimiter;
private final boolean useSqlLimiter;
private boolean hasWhere;
private BuildReq(String selectClause, OrmQueryRequest<?> request, CQueryPredicates predicates, SqlTree select) {
@@ -550,13 +549,15 @@ final class CQueryBuilder {
this.distinct = query.isDistinct() || select.isSqlDistinct();
this.dbOrderBy = predicates.dbOrderBy();
this.countSingleAttribute = query.isCountDistinct() && query.isSingleAttribute();
this.useSqlLimiter = selectClause == null
&& query.hasMaxRowsOrFirstRow()
&& (select.distinctOn() != null || select.manyProperty() == null || query.isSingleAttribute());
}
private void appendSelect() {
if (selectClause != null) {
sb.append(selectClause);
} else {
useSqlLimiter = (query.hasMaxRowsOrFirstRow() && (select.manyProperty() == null || query.isSingleAttribute()));
if (!useSqlLimiter) {
appendSelectDistinct();
}
@@ -581,7 +582,7 @@ final class CQueryBuilder {
if (request.isInlineCountDistinct()) {
sb.append(')');
}
if (distinct && dbOrderBy != null) {
if (distinct && dbOrderBy != null && query.distinctOn() == null) {
// add the orderBy columns to the select clause (due to distinct)
String[] tokens = DbOrderByTrim.trim(dbOrderBy).split(",");
for (String token : tokens) {
@@ -733,7 +734,7 @@ final class CQueryBuilder {
}
if (useSqlLimiter) {
// use LIMIT/OFFSET, ROW_NUMBER() or rownum type SQL query limitation
SqlLimitRequest r = new OrmQueryLimitRequest(sb.toString(), dbOrderBy, query, dbPlatform, distinct);
var r = new OrmQueryLimitRequest(sb.toString(), dbOrderBy, query, dbPlatform, distinct, select.distinctOn(), hint(), inlineSqlComment());
return sqlLimiter.limit(r);
} else {
if (updateStatement) {
@@ -5,6 +5,7 @@ import io.ebean.OrderBy.Property;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.BeanProperty;
import io.ebeaninternal.server.deploy.BeanPropertyAssoc;
import io.ebeaninternal.server.deploy.DeployParser;
import io.ebeaninternal.server.deploy.id.IdBinder;
import io.ebeaninternal.server.el.ElPropertyValue;
@@ -17,50 +18,81 @@ final class CQueryOrderBy {
private final BeanDescriptor<?> desc;
private final OrderBy<?> orderBy;
private final DeployParser parser;
/**
* Create the logical order by clause.
*/
public static String parse(BeanDescriptor<?> desc, OrderBy<?> orderBy) {
return new CQueryOrderBy(desc, orderBy).parseInternal();
static String parse(DeployParser parser, BeanDescriptor<?> desc, OrderBy<?> orderBy) {
return new CQueryOrderBy(parser, desc, orderBy).parseInternal();
}
private CQueryOrderBy(BeanDescriptor<?> desc, OrderBy<?> orderBy) {
private CQueryOrderBy(DeployParser parser, BeanDescriptor<?> desc, OrderBy<?> orderBy) {
this.desc = desc;
this.parser = parser;
this.orderBy = orderBy;
}
private String parseInternal() {
StringBuilder sb = new StringBuilder();
List<Property> properties = orderBy.getProperties();
if (properties.isEmpty()) {
// order by clause removed by filterMany()
return null;
}
var append = new StringAppend(parser);
for (int i = 0; i < properties.size(); i++) {
if (i > 0) {
sb.append(", ");
append.append(", ");
}
Property p = properties.get(i);
String expression = parseProperty(p);
sb.append(expression);
parseProperty(properties.get(i), append);
}
return sb.toString();
return append.toString();
}
private String parseProperty(Property p) {
String propName = p.getProperty();
ElPropertyValue el = desc.elGetValue(propName);
if (el == null) {
return p.toStringFormat();
private void parseProperty(Property p, StringAppend append) {
ElPropertyValue el = desc.elGetValue(p.getProperty());
if (el != null) {
BeanProperty beanProperty = el.beanProperty();
if (beanProperty instanceof BeanPropertyAssoc<?>) {
BeanPropertyAssoc<?> ap = (BeanPropertyAssoc<?>) beanProperty;
IdBinder idBinder = ap.targetDescriptor().idBinder();
append.parse(idBinder.orderBy(el.elName(), p.isAscending()));
return;
}
}
p.toStringFormat(append);
}
private static class StringAppend implements OrderBy.Append {
private final StringBuilder builder = new StringBuilder();
private final DeployParser parser;
StringAppend(DeployParser parser) {
this.parser = parser;
}
BeanProperty beanProperty = el.beanProperty();
if (beanProperty instanceof BeanPropertyAssoc<?>) {
BeanPropertyAssoc<?> ap = (BeanPropertyAssoc<?>) beanProperty;
IdBinder idBinder = ap.targetDescriptor().idBinder();
return idBinder.orderBy(el.elName(), p.isAscending());
@Override
public String toString() {
return builder.toString();
}
@Override
public OrderBy.Append property(String property) {
builder.append(parser.property(property));
return this;
}
@Override
public OrderBy.Append append(String literal) {
builder.append(literal);
return this;
}
@Override
public OrderBy.Append parse(String raw) {
builder.append(parser.parse(raw));
return this;
}
return p.toStringFormat();
}
}
@@ -7,7 +7,6 @@ import io.ebeaninternal.api.SpiExpressionList;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.server.bind.DataBind;
import io.ebeaninternal.server.core.OrmQueryRequest;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
import io.ebeaninternal.server.deploy.DeployParser;
import io.ebeaninternal.server.expression.DefaultExpressionRequest;
@@ -62,6 +61,7 @@ public final class CQueryPredicates {
*/
private String dbFilterMany;
private String dbOrderBy;
private String dbDistinctOn;
private String dbUpdateClause;
/**
* Includes from where and order by clauses.
@@ -177,10 +177,7 @@ public final class CQueryPredicates {
BeanPropertyAssocMany<?> manyProperty = request.determineMany();
if (buildSql) {
String logicalOrderBy = deriveOrderByWithMany(request.manyPropertyForOrderBy());
if (logicalOrderBy != null) {
dbOrderBy = deployParser.parse(logicalOrderBy);
}
dbOrderBy = deriveOrderByWithMany(deployParser, request.manyPropertyForOrderBy());
// create a copy of the includes required to support the orderBy
orderByIncludes = new HashSet<>(deployParser.includes());
}
@@ -209,6 +206,10 @@ public final class CQueryPredicates {
}
}
if (buildSql) {
final String distinctOn = query.distinctOn();
if (distinctOn != null) {
dbDistinctOn = deployParser.parse(distinctOn);
}
predicateIncludes = deployParser.includes();
}
}
@@ -231,51 +232,52 @@ public final class CQueryPredicates {
if (dbOrderBy != null) {
dbOrderBy = alias.parse(dbOrderBy);
}
if (dbDistinctOn != null) {
dbDistinctOn = alias.parse(dbDistinctOn);
}
}
private String parseOrderBy() {
private String parseOrderBy(DeployParser parser) {
OrderBy<?> orderBy = query.getOrderBy();
if (orderBy == null) {
return null;
}
return CQueryOrderBy.parse(request.descriptor(), orderBy);
return CQueryOrderBy.parse(parser, request.descriptor(), orderBy);
}
/**
* There is a many property we need to make sure the ordering is appropriate.
*/
private String deriveOrderByWithMany(BeanPropertyAssocMany<?> manyProp) {
private String deriveOrderByWithMany(DeployParser parser, BeanPropertyAssocMany<?> manyProp) {
String orderBy = parseOrderBy(parser);
if (manyProp == null) {
return parseOrderBy();
return orderBy;
}
String orderBy = parseOrderBy();
BeanDescriptor<?> desc = request.descriptor();
String orderById = desc.defaultOrderBy();
String orderById = parser.parse(request.descriptor().defaultOrderBy());
if (orderBy == null) {
orderBy = orderById;
}
// check for default ordering on the many property...
String manyOrderBy = manyProp.fetchOrderBy();
if (manyOrderBy != null) {
orderBy = orderBy + ", " + CQueryBuilder.prefixOrderByFields(manyProp.name(), manyOrderBy);
orderBy = orderBy + ", " + parser.parse(CQueryBuilder.prefixOrderByFields(manyProp.name(), manyOrderBy));
}
if (request.isFindById()) {
// only one master bean so should be fine...
return orderBy;
}
if (orderBy.startsWith(orderById)) {
return orderBy;
}
// more than one top level row may be returned so
// we need to make sure their is an order by on the
// top level first (to ensure master/detail construction).
int manyPos = orderBy.indexOf(manyProp.name());
int idPos = orderBy.indexOf(" " + orderById);
int idPos = orderBy.indexOf(orderById);
if (idPos == 0) {
return orderBy;
}
int manyPos = orderBy.indexOf("${" + manyProp.name() + "}");
if (manyPos == -1) {
// no ordering of the many
if (idPos == -1) {
// append the orderById so that master level objects are ordered
// even if the orderBy is not unique for the master object
return orderBy + ", " + orderById;
}
// orderById is already in the order by clause
@@ -284,7 +286,7 @@ public final class CQueryPredicates {
if (idPos == -1 || idPos >= manyPos) {
if (idPos > manyPos) {
// there was an error with the order by...
String msg = "A Query on [" + desc + "] includes a join to a 'many' association [" + manyProp.name()
String msg = "A Query on [" + request.descriptor() + "] includes a join to a 'many' association [" + manyProp.name()
+ "] with an incorrect orderBy [" + orderBy + "]. The id property [" + orderById
+ "] must come before the many property [" + manyProp.name() + "] in the orderBy."
+ " Ebean has automatically modified the orderBy clause to do this.";
@@ -351,6 +353,13 @@ public final class CQueryPredicates {
return dbOrderBy;
}
/**
* Return the db distinct on clause.
*/
String dbDistinctOn() {
return dbDistinctOn;
}
/**
* Return the includes required for the where and order by clause.
*/
@@ -59,6 +59,11 @@ final class DefaultFetchGroupQuery<T> implements SpiFetchGroupQuery<T>, SpiQuery
return new DFetchGroup<>(detail);
}
@Override
public Query<T> distinctOn(String distinctOn) {
throw new UnsupportedOperationException();
}
@Override
public Query<T> select(String columns) {
detail.select(columns);
@@ -156,6 +156,10 @@ public final class SqlTreeBuilder {
}
private String buildDistinctOn() {
String distinctOn = predicates.dbDistinctOn();
if (distinctOn != null) {
return distinctOn;
}
if (rawSql || !distinctOnPlatform || !sqlDistinct || Type.COUNT == query.type()) {
return null;
}
@@ -72,6 +72,7 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
* Lazy loading batch size (can override server wide default).
*/
private int lazyLoadBatchSize;
private String distinctOn;
private OrderBy<T> orderBy;
private String loadMode;
private String loadDescription;
@@ -515,7 +516,10 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
* Limit the number of fetch joins to Many properties, mark as query joins as needed.
*/
private void markQueryJoins() {
detail.markQueryJoins(beanDescriptor, lazyLoadManyPath, isAllowOneManyFetch(), type.defaultSelect());
if (distinctOn == null) {
// no automatic join to query join conversion when distinctOn is used
detail.markQueryJoins(beanDescriptor, lazyLoadManyPath, isAllowOneManyFetch(), type.defaultSelect());
}
}
private boolean isAllowOneManyFetch() {
@@ -639,12 +643,11 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
return countDistinctOrder;
}
/**
* Return true if the Id should be included in the query.
*/
@Override
public final boolean isWithId() {
return !manualId && !distinct && !singleAttribute;
// distinctOn orm query will auto include the id property
// distinctOn dto query does NOT (via setting manualId to true)
return !manualId && !singleAttribute && (!distinct || distinctOn != null);
}
@Override
@@ -740,6 +743,7 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
copy.baseTable = baseTable;
copy.rootTableAlias = rootTableAlias;
copy.distinct = distinct;
copy.distinctOn = distinctOn;
copy.allowLoadErrors = allowLoadErrors;
copy.timeout = timeout;
copy.mapKey = mapKey;
@@ -799,6 +803,11 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
this.type = type;
}
@Override
public String distinctOn() {
return distinctOn;
}
@Override
public final String loadDescription() {
return loadDescription;
@@ -1087,6 +1096,9 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
}
if (distinct) {
sb.append("/dt");
if (distinctOn != null) {
sb.append("/o:").append(distinctOn);
}
}
if (allowLoadErrors) {
sb.append("/ae");
@@ -1340,6 +1352,13 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
detail.addNested(name, nestedDetail, config);
}
@Override
public final Query<T> distinctOn(String distinctOn) {
this.distinctOn = distinctOn;
this.distinct = true;
return this;
}
@Override
public final Query<T> select(String columns) {
detail.select(columns);
@@ -11,13 +11,67 @@ public final class OrmQueryLimitRequest implements SqlLimitRequest {
private final String sql;
private final String sqlOrderBy;
private final boolean distinct;
private final String distinctOn;
private final String hint;
private final String label;
public OrmQueryLimitRequest(String sql, String sqlOrderBy, SpiQuery<?> ormQuery, DatabasePlatform dbPlatform, boolean distinct) {
this(sql, sqlOrderBy, ormQuery, dbPlatform, distinct, null, "", "");
}
public OrmQueryLimitRequest(String sql, String sqlOrderBy, SpiQuery<?> ormQuery, DatabasePlatform dbPlatform,
boolean distinct, String distinctOn, String hint, String label) {
this.sql = sql;
this.sqlOrderBy = sqlOrderBy;
this.ormQuery = ormQuery;
this.dbPlatform = dbPlatform;
this.distinct = distinct;
this.distinctOn = distinctOn;
this.hint = hint;
this.label = label;
}
private StringBuilder newBuffer() {
return new StringBuilder(50 + sql.length());
}
@Override
public String ansiOffsetRows() {
final var buffer = selectDistinct();
buffer.append(sql);
int firstRow = getFirstRow();
if (firstRow > 0) {
buffer.append(" offset ").append(firstRow).append(" rows");
}
int maxRows = getMaxRows();
if (maxRows > 0) {
buffer.append(" fetch next ").append(maxRows).append(" rows only");
}
return buffer.toString();
}
@Override
public StringBuilder selectDistinct() {
final var buffer = newBuffer();
buffer.append("select ").append(hint).append(label);
if (distinct) {
buffer.append("distinct ");
}
return buffer;
}
@Override
public StringBuilder selectDistinctOnSql() {
var buffer = newBuffer();
buffer.append("select ").append(hint).append(label);
if (distinct) {
buffer.append("distinct ");
if (distinctOn != null) {
buffer.append("on (").append(distinctOn).append(") ");
}
}
buffer.append(sql);
return buffer;
}
@Override
@@ -609,6 +609,11 @@ final class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEve
// do nothing
}
@Override
public void deactivateExternal() {
this.active = false;
}
/**
* Return true if the transaction is active.
*/
@@ -1082,6 +1082,11 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
return active;
}
@Override
public void deactivateExternal() {
this.active = false;
}
@Override
public final boolean isPersistCascade() {
return persistCascade;
@@ -94,9 +94,14 @@ public final class JtaTransactionManager implements ExternalTransactionManager {
// check current Ebean transaction
SpiTransaction currentEbeanTransaction = scope.inScope();
if (currentEbeanTransaction != null) {
// NOT expecting this so log WARNING
log.log(WARNING, "JTA Transaction - no current txn BUT using current Ebean one {0}", currentEbeanTransaction.id());
return currentEbeanTransaction;
if (currentEbeanTransaction.isActive()) {
// NOT expecting this so log WARNING
log.log(WARNING, "JTA Transaction - no current txn BUT using current Ebean one {0}", currentEbeanTransaction.id());
return currentEbeanTransaction;
} else {
log.log(DEBUG, "JTA Transaction - clearing inActive Ebean transaction {0}", currentEbeanTransaction.id());
scope.clearExternal();
}
}
UserTransaction ut = userTransaction();
@@ -186,27 +191,27 @@ public final class JtaTransactionManager implements ExternalTransactionManager {
@Override
public void afterCompletion(int status) {
switch (status) {
case Status.STATUS_COMMITTED:
log.log(DEBUG, "Jta Txn [{0}] committed", transaction.id());
transaction.postCommit();
// Remove this transaction object as it is completed
transactionManager.scope().clearExternal();
break;
try {
switch (status) {
case Status.STATUS_COMMITTED:
log.log(DEBUG, "Jta Txn [{0}] committed", transaction.id());
transaction.postCommit();
break;
case Status.STATUS_ROLLEDBACK:
log.log(DEBUG, "Jta Txn [{0}] rollback", transaction.id());
transaction.postRollback(null);
// Remove this transaction object as it is completed
transactionManager.scope().clearExternal();
break;
case Status.STATUS_ROLLEDBACK:
log.log(DEBUG, "Jta Txn [{0}] rollback", transaction.id());
transaction.postRollback(null);
break;
default:
log.log(DEBUG, "Jta Txn [{0}] status:{1}", transaction.id(), status);
default:
log.log(DEBUG, "Jta Txn [{0}] status:{1}", transaction.id(), status);
}
} finally {
transaction.deactivateExternal();
transactionManager.scope().clearExternal();
// No matter the completion status of the transaction, we release the connection we got from the pool.
JdbcClose.close(transaction.internalConnection());
}
// No matter the completion status of the transaction, we release the connection we got from the pool.
JdbcClose.close(transaction.internalConnection());
}
}
@@ -117,6 +117,10 @@ final class NoTransaction implements SpiTransaction {
// do nothing
}
@Override
public void deactivateExternal() {
// do nothing
}
@Override
public boolean isLogSql() {
@@ -196,10 +196,6 @@ public class InitDataSourceTest {
public void dataSourceDown(DataSource dataSource, SQLException reason) {
}
@Override
public void dataSourceWarning(DataSource dataSource, String msg) {
}
}
@Test
@@ -3,6 +3,7 @@ package io.ebeaninternal.server.querydefn;
import io.ebean.*;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.server.core.OrmQueryRequest;
import io.ebeaninternal.server.core.OrmQueryRequestTestHelper;
import io.ebeaninternal.server.expression.BaseExpressionTest;
@@ -54,6 +55,32 @@ public class DefaultOrmQueryTest extends BaseExpressionTest {
assertThat(q1.getId()).isEqualTo(42);
}
@Test
void when_distinctOn_then_planChanges() {
DefaultOrmQuery<Order> q1 = (DefaultOrmQuery<Order>) DB.find(Order.class).distinctOn("name");
DefaultOrmQuery<Order> q2 = (DefaultOrmQuery<Order>) DB.find(Order.class);
prepare(q1, q2);
assertThat(q1.createQueryPlanKey()).isNotEqualTo(q2.createQueryPlanKey());
}
@Test
void when_distinctOn_match() {
DefaultOrmQuery<Order> q1 = (DefaultOrmQuery<Order>) DB.find(Order.class).distinctOn("name");
DefaultOrmQuery<Order> q2 = (DefaultOrmQuery<Order>) DB.find(Order.class).distinctOn("name");
prepare(q1, q2);
assertThat(q1.createQueryPlanKey()).isEqualTo(q2.createQueryPlanKey());
assertThat(bindKey(q1)).isEqualTo(bindKey(q2));
}
@Test
void when_distinctOn_copy() {
DefaultOrmQuery<Order> q1 = (DefaultOrmQuery<Order>) DB.find(Order.class).distinctOn("name");
SpiQuery<Order> copy = q1.copy();
assertThat(copy.distinctOn()).isEqualTo("name");
}
@Test
public void when_addWhere_then_planChanges() {
+4 -4
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
</parent>
<name>ebean ddl generation</name>
@@ -28,14 +28,14 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
<scope>provided</scope>
</dependency>
@@ -65,7 +65,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-all</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
<scope>test</scope>
</dependency>
@@ -5,7 +5,6 @@ import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer;
import io.ebeaninternal.dbmigration.ddlgeneration.DdlHandler;
import io.ebeaninternal.dbmigration.ddlgeneration.DdlOptions;
import io.ebeaninternal.dbmigration.migration.Column;
public class ClickHouseDdl extends PlatformDdl {
@@ -18,16 +17,6 @@ public class ClickHouseDdl extends PlatformDdl {
this.columnNotNull = null;
}
@Override
protected String columnDefn(Column column) {
String defn = super.columnDefn(column);
if (isTrue(column.isNotnull()) || isTrue(column.isPrimaryKey())) {
return defn;
} else {
return "Nullable(" + defn + ")";
}
}
@Override
public DdlHandler createDdlHandler(DatabaseBuilder.Settings config) {
return new ClickHouseDdlHandler(config, this);
@@ -230,13 +230,13 @@ public class PlatformDdl {
* Write the column definition to the create table statement.
*/
protected void writeColumnDefinition(DdlBuffer buffer, Column column, DdlIdentity identity) {
buffer.append(" ");
buffer.append(quote(column.getName()), 29);
String columnDefn = columnDefn(column);
String columnDefn = convert(column.getType());
if (identity.useIdentity() && isTrue(column.isPrimaryKey())) {
columnDefn = asIdentityColumn(columnDefn, identity);
}
buffer.append(" ");
buffer.append(quote(column.getName()), 29);
buffer.append(columnDefn);
if (!Boolean.TRUE.equals(column.isPrimaryKey())) {
String defaultValue = convertDefaultValue(column.getDefaultValue());
@@ -251,13 +251,6 @@ public class PlatformDdl {
// so that the database can potentially provide a nice SQL error
}
/**
* Return the plaform specific column type definition.
*/
protected String columnDefn(Column column) {
return convert(column.getType());
}
/**
* Returns the check constraint.
*/
@@ -1,28 +0,0 @@
package io.ebeaninternal.dbmigration;
import io.ebean.platform.clickhouse.ClickHousePlatform;
import io.ebeaninternal.dbmigration.ddlgeneration.PlatformDdlBuilder;
import io.ebeaninternal.dbmigration.ddlgeneration.platform.PlatformDdl;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class ClickHousePlatformTest {
@Test
void testTypeConversion() {
PlatformDdl ddl = PlatformDdlBuilder.create(new ClickHousePlatform());
assertThat(ddl.convert("clob")).isEqualTo("String");
assertThat(ddl.convert("varchar(20)")).isEqualTo("String");
assertThat(ddl.convert("json")).isEqualTo("JSON");
assertThat(ddl.convert("jsonb")).isEqualTo("JSON");
assertThat(ddl.convert("decimal(10)")).isEqualTo("Decimal(10)");
assertThat(ddl.convert("decimal(8,4)")).isEqualTo("Decimal(8,4)");
assertThat(ddl.convert("decimal")).isEqualTo("Decimal(16,3)");
assertThat(ddl.convert("boolean")).isEqualTo("Bool");
assertThat(ddl.convert("bit")).isEqualTo("bit");
}
}
@@ -1,56 +0,0 @@
package io.ebeaninternal.dbmigration.ddlgeneration.platform;
import io.ebean.platform.clickhouse.ClickHousePlatform;
import io.ebeaninternal.dbmigration.migration.Column;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class ClickHouseDdlTest {
private final ClickHouseDdl ddl = new ClickHouseDdl(new ClickHousePlatform());
@Test
void convert() {
assertThat(ddl.convert("boolean")).isEqualTo("Bool");
assertThat(ddl.convert("integer")).isEqualTo("UInt32");
assertThat(ddl.convert("bigint")).isEqualTo("UInt64");
assertThat(ddl.convert("decimal(20,3)")).isEqualTo("Decimal(20,3)");
assertThat(ddl.convert("varchar(20)")).isEqualTo("String");
assertThat(ddl.convert("hstore")).isEqualTo("Map(String,String)");
assertThat(ddl.convert("json")).isEqualTo("JSON");
assertThat(ddl.convert("varchar[]")).isEqualTo("Array(String)");
}
@Test
void columnDefnNullable() {
Column column = new Column();
column.setType("varchar(20)");
column.setNotnull(null);
assertThat(ddl.columnDefn(column)).isEqualTo("Nullable(String)");
}
@Test
void columnDefnNullable2() {
Column column = new Column();
column.setType("varchar(20)");
column.setNotnull(Boolean.FALSE);
assertThat(ddl.columnDefn(column)).isEqualTo("Nullable(String)");
}
@Test
void columnDefnNotNull() {
Column column = new Column();
column.setType("varchar(20)");
column.setNotnull(Boolean.TRUE);
assertThat(ddl.columnDefn(column)).isEqualTo("String");
}
@Test
void columnDefnNotNullPrimaryKey() {
Column column = new Column();
column.setType("varchar(20)");
column.setPrimaryKey(Boolean.TRUE);
assertThat(ddl.columnDefn(column)).isEqualTo("String");
}
}
+2 -2
View File
@@ -3,7 +3,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -14,7 +14,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
<scope>provided</scope>
</dependency>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
</parent>
<name>ebean postgis types</name>
@@ -19,14 +19,14 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
</dependency>
<!-- provided scope -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
<scope>provided</scope>
</dependency>
@@ -62,7 +62,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
<scope>test</scope>
</dependency>
@@ -86,7 +86,7 @@
<extensions>true</extensions>
<configuration>
<tiles>
<tile>io.ebean.tile:enhancement:14.2.0</tile>
<tile>io.ebean.tile:enhancement:14.3.0</tile>
</tiles>
</configuration>
</plugin>
@@ -35,6 +35,8 @@ public class TestCacheSerialization {
assertEquals(p1, r2.getPoint()); // and did fail https://github.com/ebean-orm/ebean/issues/3026
assertEquals(pol, r2.getPolygon());
DB.delete(tb);
}
@Test
@@ -76,5 +78,7 @@ public class TestCacheSerialization {
assertEquals(pol, r2.getPolygon()); // and did fail https://github.com/ebean-orm/ebean/issues/3026
assertNull(r1.getPoint());
DB.delete(tb);
}
}
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
</parent>
<name>ebean querybean</name>
@@ -17,7 +17,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
<scope>provided</scope>
</dependency>
@@ -63,14 +63,14 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-ddl-generator</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
<scope>test</scope>
</dependency>
@@ -84,7 +84,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>querybean-generator</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
<scope>provided</scope>
</dependency>
@@ -100,7 +100,7 @@
<extensions>true</extensions>
<configuration>
<tiles>
<tile>io.ebean.tile:enhancement:14.2.0</tile>
<tile>io.ebean.tile:enhancement:14.3.0</tile>
</tiles>
</configuration>
</plugin>
@@ -59,6 +59,13 @@ public interface IQueryBean<T, R> extends QueryBuilder<R, T> {
*/
FetchGroup<T> buildFetchGroup();
/**
* Set DISTINCT ON properties. This is a Postgres only SQL feature.
*
* @param properties The properties to include in the DISTINCT ON clause.
*/
R distinctOn(TQProperty<R, ?>... properties);
/**
* Specify the properties to be loaded on the 'main' root level entity bean.
* <p>
@@ -88,14 +88,14 @@ public abstract class QueryBean<T, R> implements IQueryBean<T, R> {
/**
* Construct using the type of bean to query on and the default database.
*/
public QueryBean(Class<T> beanType) {
protected QueryBean(Class<T> beanType) {
this(beanType, DB.getDefault());
}
/**
* Construct using the type of bean to query on and a given database.
*/
public QueryBean(Class<T> beanType, Database database) {
protected QueryBean(Class<T> beanType, Database database) {
this(database.find(beanType));
}
@@ -119,7 +119,7 @@ public abstract class QueryBean<T, R> implements IQueryBean<T, R> {
* Construct using a query.
*/
@SuppressWarnings("unchecked")
public QueryBean(Query<T> query) {
protected QueryBean(Query<T> query) {
this.query = query;
this.root = (R) this;
}
@@ -129,7 +129,7 @@ public abstract class QueryBean<T, R> implements IQueryBean<T, R> {
* values for select() and fetch().
*/
@SuppressWarnings("unchecked")
public QueryBean(boolean aliasDummy) {
protected QueryBean(boolean aliasDummy) {
this.query = null;
this.root = (R) this;
}
@@ -159,6 +159,12 @@ public abstract class QueryBean<T, R> implements IQueryBean<T, R> {
return query;
}
@Override
public R distinctOn(String distinctOn) {
query.distinctOn(distinctOn);
return root;
}
@Override
public R select(String properties) {
query.select(properties);
@@ -171,6 +177,17 @@ public abstract class QueryBean<T, R> implements IQueryBean<T, R> {
return root;
}
@Override
@SafeVarargs
public final R distinctOn(TQProperty<R, ?>... properties) {
final var joiner = new StringJoiner(", ");
for (Query.Property<?> property : properties) {
joiner.add(property.toString());
}
distinctOn(joiner.toString());
return root;
}
@Override
@SafeVarargs
public final R select(TQProperty<R, ?>... properties) {
@@ -4,6 +4,7 @@ import io.ebean.*;
import io.ebean.annotation.Transactional;
import io.ebean.test.LoggedSql;
import io.ebean.types.Inet;
import io.ebeaninternal.api.SpiQuery;
import org.example.domain.Address;
import org.example.domain.Country;
import org.example.domain.Customer;
@@ -226,6 +227,22 @@ public class QCustomerTest {
.findList();
}
@Test
public void distinctOn() {
var c = QContact.alias();
var q = new QContact()
.distinctOn(c.customer)
.select(c.lastName, c.whenCreated)
.orderBy()
.customer.id.asc()
.whenCreated.desc()
.query();
SpiQuery<?> spiQuery = (SpiQuery<?>) q;
assertThat(spiQuery.distinctOn()).isEqualTo("customer");
assertThat(spiQuery.isDistinct()).isTrue();
}
@Transactional
@Test
public void forUpdate() {
@@ -314,7 +331,7 @@ public class QCustomerTest {
.query();
q.findList();
assertThat(q.getGeneratedSql()).isEqualTo("select t0.id, t0.name from be_customer t0 limit 10");
assertThat(q.getGeneratedSql()).isEqualTo("select /* QCustomerTest.filterManySeparateQuery */ t0.id, t0.name from be_customer t0 limit 10");
}
@Test
+15 -15
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.1.0</version>
<version>14.4.0</version>
</parent>
<artifactId>ebean-redis</artifactId>
@@ -13,51 +13,51 @@
<dependencies>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.5.6</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.2.3</version>
<version>4.4.8</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test</artifactId>
<version>14.1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.avaje.composite</groupId>
<artifactId>logback</artifactId>
<version>1.1</version>
<version>14.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>querybean-generator</artifactId>
<version>14.1.0</version>
<version>14.4.0</version>
<scope>provided</scope>
</dependency>
@@ -72,7 +72,7 @@
<extensions>true</extensions>
<configuration>
<tiles>
<tile>io.ebean.tile:enhancement:14.2.0</tile>
<tile>io.ebean.tile:enhancement:14.3.0</tile>
</tiles>
</configuration>
</plugin>
@@ -11,11 +11,12 @@ public final class EncodeSerializable implements Encode {
@Override
public byte[] encode(Object value) {
try {
ObjectOutputStream oos = new ObjectOutputStream(new ByteArrayOutputStream());
final var baos = new ByteArrayOutputStream();
final var oos = new ObjectOutputStream(baos);
oos.writeObject(value);
oos.flush();
oos.close();
return new ByteArrayOutputStream().toByteArray();
return baos.toByteArray();
} catch (IOException e) {
throw new RuntimeException("Failed to decode cache data", e);
}
@@ -0,0 +1,17 @@
package io.ebean.redis.encode;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class EncodeSerializableTest {
@Test
void encode() {
EncodeSerializable encodeSerializable = new EncodeSerializable();
byte[] asBytes = encodeSerializable.encode("HelloWorld");
Object result = encodeSerializable.decode(asBytes);
assertThat(result).isEqualTo("HelloWorld");
}
}
@@ -0,0 +1,40 @@
package org.domain;
import io.ebean.annotation.Cache;
import jakarta.persistence.Entity;
/**
* Using Natural Key caching but no Near Caching so always hitting Redis.
*/
@SuppressWarnings("unused")
@Cache(naturalKey = {"one", "two"})
@Entity
public class OtherOne extends EBase {
private final String one;
private final String two;
private String notes;
public OtherOne(String one, String two, String notes) {
this.one = one;
this.two = two;
this.notes = notes;
}
public String one() {
return one;
}
public String two() {
return two;
}
public String notes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
}
@@ -3,10 +3,8 @@ package org.integration;
import io.ebean.DB;
import io.ebean.cache.ServerCache;
import io.ebean.cache.ServerCacheStatistics;
import org.domain.Person;
import org.domain.RCust;
import org.domain.UChild;
import org.domain.UParent;
import org.domain.*;
import org.domain.query.QOtherOne;
import org.domain.query.QPerson;
import org.domain.query.QRCust;
import org.junit.jupiter.api.Test;
@@ -148,6 +146,37 @@ class IntegrationTest {
assertThat(stats2.getHitCount()).isEqualTo(3);
}
@Test
void testOtherOne() {
DB.save(new OtherOne("A", "B", "ab"));
DB.save(new OtherOne("A", "C", "ac"));
DB.save(new OtherOne("B", "B", "bb"));
ServerCache nkeyCache = DB.cacheManager().naturalKeyCache(OtherOne.class);
nkeyCache.clear();
nkeyCache.statistics(true);
OtherOne ab0 = findOther("A", "B");
OtherOne ab1 = findOther("A", "B");
OtherOne ab2 = findOther("A", "B");
OtherOne bb = findOther("B", "B");
assertThat(ab0).isNotNull();
assertThat(ab1).isNotNull();
assertThat(ab2).isNotNull();
assertThat(bb).isNotNull();
ServerCacheStatistics statistics = nkeyCache.statistics(true);
assertThat(statistics.getHitCount()).isEqualTo(2);
}
private static OtherOne findOther(String a, String b) {
return new QOtherOne()
.one.eq(a)
.two.eq(b)
.findOne();
}
@Test
void test() throws InterruptedException {

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