mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
112
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab45ad34e0 | ||
|
|
24b514f851 | ||
|
|
582fec7ce4 | ||
|
|
0b11c541c8 | ||
|
|
540ceab96f | ||
|
|
8b858a073a | ||
|
|
02dafc9838 | ||
|
|
0816810d3b | ||
|
|
1f6e2ee844 | ||
|
|
dc00765a98 | ||
|
|
a48b2f4ebe | ||
|
|
837563544f | ||
|
|
fd199f406b | ||
|
|
a48e96c7e9 | ||
|
|
7ba6e5f67d | ||
|
|
6ce42b1ca3 | ||
|
|
89617cefbe | ||
|
|
dd377621a4 | ||
|
|
d844855462 | ||
|
|
f68c25d5f3 | ||
|
|
61cfc7a979 | ||
|
|
3c98ee7f1b | ||
|
|
0738316f15 | ||
|
|
ceb83befa3 | ||
|
|
a0b04cceda | ||
|
|
03edfb5454 | ||
|
|
62015451df | ||
|
|
ed9113efe6 | ||
|
|
334793667e | ||
|
|
351a1c4739 | ||
|
|
b2de333dcc | ||
|
|
6091f7b683 | ||
|
|
43fb84cbc0 | ||
|
|
52a4e9e19b | ||
|
|
a2cdea24ed | ||
|
|
cd780208e5 | ||
|
|
9ce0e923d7 | ||
|
|
9e461e4708 | ||
|
|
5fa09a6f90 | ||
|
|
6babb2e6f5 | ||
|
|
26abe27e42 | ||
|
|
9b18d46b78 | ||
|
|
eed487ad26 | ||
|
|
c10865dfaf | ||
|
|
2352df309c | ||
|
|
feb2bd1e15 | ||
|
|
11c9bdfc6f | ||
|
|
4a6fc98395 | ||
|
|
7322030e90 | ||
|
|
77634fc3eb | ||
|
|
ed8d4b5fc4 | ||
|
|
187cc0903d | ||
|
|
1d7a14c8f4 | ||
|
|
c58b7d3da3 | ||
|
|
6b2cdc14aa | ||
|
|
6d712a92a0 | ||
|
|
ea11b0c3b6 | ||
|
|
08e8402d05 | ||
|
|
006ad79379 | ||
|
|
0e063549cd | ||
|
|
4f0d2cabfb | ||
|
|
80b2d9f983 | ||
|
|
287d0c467d | ||
|
|
a8835379e7 | ||
|
|
e4df20b9dc | ||
|
|
261b13ef4b | ||
|
|
7639034d7c | ||
|
|
e6e53e0d93 | ||
|
|
c71971eb5c | ||
|
|
357af58db4 | ||
|
|
0abdb1550a | ||
|
|
c32fc814f6 | ||
|
|
8e035939dc | ||
|
|
edf98ee250 | ||
|
|
5f0a75a130 | ||
|
|
d2f16cbf6a | ||
|
|
04ba81d12f | ||
|
|
f63e7ed5af | ||
|
|
66940c0f14 | ||
|
|
1f48b3a6b3 | ||
|
|
7d368097e9 | ||
|
|
c849e29316 | ||
|
|
c78a3dd6c4 | ||
|
|
a4455ddbf2 | ||
|
|
9787af77e4 | ||
|
|
3786fb09a5 | ||
|
|
f34e7b6003 | ||
|
|
089dd8e364 | ||
|
|
44770382fb | ||
|
|
6645e5b9ec | ||
|
|
2a62d413cc | ||
|
|
0046d983cb | ||
|
|
006e33cb3e | ||
|
|
e80e8e027a | ||
|
|
2e1b52d7d4 | ||
|
|
09d5163396 | ||
|
|
a6a38b9a92 | ||
|
|
bd4521b240 | ||
|
|
8a7379879b | ||
|
|
b78dd6f79a | ||
|
|
4ebb5fd112 | ||
|
|
487368976f | ||
|
|
c6defceec9 | ||
|
|
3576aafffc | ||
|
|
66234249c6 | ||
|
|
8ed3b765ec | ||
|
|
fcbcc53e27 | ||
|
|
b377e1a618 | ||
|
|
a0f612ed71 | ||
|
|
6f64821584 | ||
|
|
47e97a77a8 | ||
|
|
e8d3f50bb4 |
@@ -1,7 +1,10 @@
|
||||
|
||||
name: Build
|
||||
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches: master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-clickhouse</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-db2</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-hana</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-mariadb</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-mysql</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-nuodb</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-oracle</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
<properties>
|
||||
<postgis.jdbc.version>2.5.1</postgis.jdbc.version>
|
||||
<postgres.jdbc.version>42.6.0</postgres.jdbc.version>
|
||||
<postgres.jdbc.version>42.7.2</postgres.jdbc.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -22,13 +22,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -47,19 +47,19 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis-types</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlite</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlserver</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,31 +17,31 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-joda-time</artifactId>
|
||||
<version>13.24.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-jsonnode</artifactId>
|
||||
<version>13.24.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-mapper</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -60,13 +60,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-all</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>composites</artifactId>
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean api</name>
|
||||
@@ -39,7 +39,7 @@
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>avaje-config</artifactId>
|
||||
<version>3.9</version>
|
||||
<version>3.12</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -266,55 +266,6 @@ public final class DB {
|
||||
getDefault().register(transactionCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated for removal migrate using try-with-resources and commit on the transaction itself.
|
||||
* <p>
|
||||
* Commit the current transaction.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public static void commitTransaction() {
|
||||
getDefault().commitTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated for removal migrate to using try-with-resources and rollback on the transaction itself.
|
||||
* <p>
|
||||
* Rollback the current transaction.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public static void rollbackTransaction() {
|
||||
getDefault().rollbackTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the current transaction has already been committed do nothing otherwise
|
||||
* rollback the transaction.
|
||||
* <p>
|
||||
* It is preferable to use <em>try with resources</em> rather than this.
|
||||
* <p>
|
||||
* Useful to put in a finally block to ensure the transaction is ended, rather
|
||||
* than a rollbackTransaction() in each catch block.
|
||||
* <p>
|
||||
* Code example:
|
||||
*
|
||||
* <pre>{@code
|
||||
* DB.beginTransaction();
|
||||
* try {
|
||||
* // do some fetching and or persisting
|
||||
*
|
||||
* // commit at the end
|
||||
* DB.commitTransaction();
|
||||
*
|
||||
* } finally {
|
||||
* // if commit didn't occur then rollback the transaction
|
||||
* DB.endTransaction();
|
||||
* }
|
||||
* }</pre>
|
||||
*/
|
||||
public static void endTransaction() {
|
||||
getDefault().endTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the current transaction as rollback only.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
package io.ebean;
|
||||
|
||||
final class DInsertOptionsBuilder implements InsertOptions.Builder {
|
||||
|
||||
private Boolean getGeneratedKeys;
|
||||
private boolean onConflictUpdate;
|
||||
private boolean onConflictNothing;
|
||||
private String constraint;
|
||||
private String uniqueColumns;
|
||||
private String updateSet;
|
||||
|
||||
@Override
|
||||
public InsertOptions.Builder onConflictNothing() {
|
||||
this.onConflictNothing = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertOptions.Builder onConflictUpdate() {
|
||||
this.onConflictUpdate = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertOptions.Builder constraint(String constraint) {
|
||||
this.constraint = constraint;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertOptions.Builder uniqueColumns(String uniqueColumns) {
|
||||
this.uniqueColumns = uniqueColumns;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertOptions.Builder updateSet(String updateSet) {
|
||||
this.updateSet = updateSet;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertOptions.Builder getGeneratedKeys(boolean getGeneratedKeys) {
|
||||
this.getGeneratedKeys = getGeneratedKeys;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InsertOptions build() {
|
||||
return new Options(constraint, uniqueColumns, updateSet, onConflictUpdate, onConflictNothing, getGeneratedKeys);
|
||||
}
|
||||
|
||||
static final class Options implements InsertOptions {
|
||||
|
||||
private static final String UPDATE = "U";
|
||||
private static final String NOTHING = "N";
|
||||
private static final String NORMAL = "_";
|
||||
private final String key;
|
||||
private final Boolean getGeneratedKeys;
|
||||
private final String constraint;
|
||||
private final String uniqueColumns;
|
||||
private final String updateSet;
|
||||
|
||||
Options(String constraint, String uniqueColumns, String updateSet, boolean onConflictUpdate, boolean onConflictNothing, Boolean getGeneratedKeys) {
|
||||
this.constraint = constraint;
|
||||
this.uniqueColumns = uniqueColumns;
|
||||
this.updateSet = updateSet;
|
||||
this.getGeneratedKeys = getGeneratedKeys;
|
||||
this.key = (onConflictUpdate ? UPDATE : onConflictNothing ? NOTHING : NORMAL)
|
||||
+ '+' + plus(constraint)
|
||||
+ '+' + plus(uniqueColumns)
|
||||
+ '+' + plus(updateSet);
|
||||
}
|
||||
|
||||
private String plus(String val) {
|
||||
return val == null ? "" : val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String key() {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String constraint() {
|
||||
return constraint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String uniqueColumns() {
|
||||
return uniqueColumns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String updateSet() {
|
||||
return updateSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getGetGeneratedKeys() {
|
||||
return getGeneratedKeys;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package io.ebean;
|
||||
import jakarta.persistence.PersistenceException;
|
||||
|
||||
/**
|
||||
* Thrown when a foreign key constraint is enforced.
|
||||
* Thrown when a foreign key constraint is enforced or a field is too large.
|
||||
*/
|
||||
public class DataIntegrityException extends PersistenceException {
|
||||
private static final long serialVersionUID = -6740171949170180970L;
|
||||
@@ -14,4 +14,11 @@ public class DataIntegrityException extends PersistenceException {
|
||||
public DataIntegrityException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create with message only.
|
||||
*/
|
||||
public DataIntegrityException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,16 +88,16 @@ public interface Database {
|
||||
|
||||
/**
|
||||
* Return a new database builder.
|
||||
* <pre>{@code
|
||||
*
|
||||
* // build the 'default' database using configuration
|
||||
* // from application.properties / application.yaml
|
||||
*
|
||||
* Database db = Database.builder()
|
||||
* .loadFromProperties()
|
||||
* .build();
|
||||
*
|
||||
* }</pre>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // build the 'default' database using configuration
|
||||
* // from application.properties / application.yaml
|
||||
*
|
||||
* Database db = Database.builder()
|
||||
* .loadFromProperties()
|
||||
* .build();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
static DatabaseBuilder builder() {
|
||||
return new DatabaseConfig();
|
||||
@@ -666,49 +666,6 @@ public interface Database {
|
||||
*/
|
||||
void flush();
|
||||
|
||||
/**
|
||||
* Deprecated for removal migrate using try-with-resources and commit on the transaction itself.
|
||||
* <p>
|
||||
* Commit the current transaction.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
void commitTransaction();
|
||||
|
||||
/**
|
||||
* Deprecated for removal migrate to using try-with-resources and rollback on the transaction itself.
|
||||
* <p>
|
||||
* Rollback the current transaction.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
void rollbackTransaction();
|
||||
|
||||
/**
|
||||
* If the current transaction has already been committed do nothing otherwise
|
||||
* rollback the transaction.
|
||||
* <p>
|
||||
* Useful to put in a finally block to ensure the transaction is ended, rather
|
||||
* than a rollbackTransaction() in each catch block.
|
||||
* <p>
|
||||
* Code example:
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* database.beginTransaction();
|
||||
* try {
|
||||
* // do some fetching and or persisting ...
|
||||
*
|
||||
* // commit at the end
|
||||
* database.commitTransaction();
|
||||
*
|
||||
* } finally {
|
||||
* // if commit didn't occur then rollback the transaction
|
||||
* database.endTransaction();
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
void endTransaction();
|
||||
|
||||
/**
|
||||
* Refresh the values of a bean.
|
||||
* <p>
|
||||
@@ -1227,22 +1184,53 @@ public interface Database {
|
||||
*/
|
||||
void insert(Object bean);
|
||||
|
||||
/**
|
||||
* Insert the bean with options (ON CONFLICT DO UPDATE | DO NOTHING).
|
||||
* <p>
|
||||
* Currently, this is limited to use with Postgres only,
|
||||
* <p>
|
||||
* When using this ebean will look to determine the unique columns by looking at
|
||||
* the mapping like {@code @Column(unique=true} and {@code @Index(unique=true}.
|
||||
*/
|
||||
void insert(Object bean, InsertOptions insertOptions);
|
||||
|
||||
/**
|
||||
* Insert the bean with a transaction.
|
||||
*/
|
||||
void insert(Object bean, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Insert the beans with options (ON CONFLICT DO UPDATE | DO NOTHING) and transaction.
|
||||
* <p>
|
||||
* Currently, this is limited to use with Postgres only,
|
||||
*/
|
||||
void insert(Object bean, InsertOptions insertOptions, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Insert a collection of beans. If there is no current transaction one is created and used to
|
||||
* insert all the beans in the collection.
|
||||
*/
|
||||
void insertAll(Collection<?> beans);
|
||||
|
||||
/**
|
||||
* Insert the beans with options - typically ON CONFLICT DO UPDATE | DO NOTHING.
|
||||
* <p>
|
||||
* Currently, this is limited to use with Postgres only,
|
||||
*/
|
||||
void insertAll(Collection<?> beans, InsertOptions options);
|
||||
|
||||
/**
|
||||
* Insert a collection of beans with an explicit transaction.
|
||||
*/
|
||||
void insertAll(Collection<?> beans, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Insert the beans with options (ON CONFLICT DO UPDATE | DO NOTHING) and transaction.
|
||||
* <p>
|
||||
* Currently, this is limited to use with Postgres only,
|
||||
*/
|
||||
void insertAll(Collection<?> beans, InsertOptions options, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute explicitly passing a transaction.
|
||||
*/
|
||||
|
||||
@@ -87,6 +87,7 @@ public interface DatabaseBuilder {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the Database.
|
||||
*/
|
||||
@@ -2208,6 +2209,15 @@ public interface DatabaseBuilder {
|
||||
@Deprecated
|
||||
DatabaseBuilder setLoadModuleInfo(boolean loadModuleInfo);
|
||||
|
||||
/**
|
||||
* Set if generated SQL SELECT should include the query label as an
|
||||
* inline SQL comment (to help reference back from the SQL to the code
|
||||
* that executed the query.
|
||||
*
|
||||
* @param includeLabelInSql When true include a SQL inline comment in generated SELECT queries.
|
||||
*/
|
||||
DatabaseConfig includeLabelInSql(boolean includeLabelInSql);
|
||||
|
||||
/**
|
||||
* Set the naming convention to apply to metrics names.
|
||||
*/
|
||||
@@ -2221,6 +2231,11 @@ public interface DatabaseBuilder {
|
||||
@Deprecated
|
||||
DatabaseBuilder setMetricNaming(Function<String, String> metricNaming);
|
||||
|
||||
/**
|
||||
* Sets the length check mode.
|
||||
*/
|
||||
DatabaseConfig lengthCheck(LengthCheck lengthCheck);
|
||||
|
||||
/**
|
||||
* Provides read access (getters) for the DatabaseBuilder configuration
|
||||
* that has been set.
|
||||
@@ -3098,10 +3113,20 @@ public interface DatabaseBuilder {
|
||||
*/
|
||||
boolean isLoadModuleInfo();
|
||||
|
||||
/**
|
||||
* Return true if generated sql select query should include an inline sql comment with the
|
||||
* query label or profile location label.
|
||||
*/
|
||||
boolean isIncludeLabelInSql();
|
||||
|
||||
/**
|
||||
* Return the naming convention to apply to metrics names.
|
||||
*/
|
||||
Function<String, String> getMetricNaming();
|
||||
|
||||
/**
|
||||
* Returns the length check mode.
|
||||
*/
|
||||
LengthCheck getLengthCheck();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package io.ebean;
|
||||
import io.avaje.lang.NonNullApi;
|
||||
import io.avaje.lang.Nullable;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -206,14 +208,19 @@ public interface DtoQuery<T> extends CancelableQuery {
|
||||
*/
|
||||
DtoQuery<T> usingTransaction(Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the query using the given connection.
|
||||
*/
|
||||
DtoQuery<T> usingConnection(Connection connection);
|
||||
|
||||
/**
|
||||
* Ensure that the master DataSource is used if there is a read only data source
|
||||
* being used (that is using a read replica database potentially with replication lag).
|
||||
* <p>
|
||||
* When the database is configured with a read-only DataSource via
|
||||
* say {@link io.ebean.config.DatabaseConfig#setReadOnlyDataSource(DataSource)} then
|
||||
* say {@link io.ebean.DatabaseBuilder#readOnlyDataSource(DataSource)} then
|
||||
* by default when a query is run without an active transaction, it uses the read-only data
|
||||
* source. We we use {@code usingMaster()} to instead ensure that the query is executed
|
||||
* source. We use {@code usingMaster()} to instead ensure that the query is executed
|
||||
* against the master data source.
|
||||
*/
|
||||
DtoQuery<T> usingMaster();
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.avaje.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Options to be used with insert such as ON CONFLICT DO UPDATE | NOTHING.
|
||||
*/
|
||||
public interface InsertOptions {
|
||||
|
||||
/**
|
||||
* Use ON CONFLICT UPDATE with automatic determination of the unique columns to conflict on.
|
||||
* <p>
|
||||
* Uses mapping to determine the unique columns - {@code @Column(unique=true)} and {@code @Index(unique=true)} .
|
||||
*/
|
||||
InsertOptions ON_CONFLICT_UPDATE = InsertOptions.builder()
|
||||
.onConflictUpdate()
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Use ON CONFLICT DO NOTHING with automatic determination of the unique columns to conflict on.
|
||||
* <p>
|
||||
* Uses mapping to determine the unique columns - {@code @Column(unique=true)} and {@code @Index(unique=true)} .
|
||||
*/
|
||||
InsertOptions ON_CONFLICT_NOTHING = InsertOptions.builder()
|
||||
.onConflictNothing()
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Return a builder for InsertOptions.
|
||||
*/
|
||||
static Builder builder() {
|
||||
return new DInsertOptionsBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the constraint name that is used for ON CONFLICT.
|
||||
*/
|
||||
@Nullable
|
||||
String constraint();
|
||||
|
||||
/**
|
||||
* Return the unique columns that is used for ON CONFLICT.
|
||||
* <p>
|
||||
* When not explicitly set will use mapping like {@code @Column(unique=true)} to determine the
|
||||
* non-unique columns.
|
||||
*/
|
||||
@Nullable
|
||||
String uniqueColumns();
|
||||
|
||||
/**
|
||||
* Return the ON CONFLICT UPDATE SET clause.
|
||||
* <p>
|
||||
* When not set will use the non-unique columns.
|
||||
*/
|
||||
@Nullable
|
||||
String updateSet();
|
||||
|
||||
/**
|
||||
* Return if GetGeneratedKeys should be used to fetch the generated keys after insert.
|
||||
*/
|
||||
@Nullable
|
||||
Boolean getGetGeneratedKeys();
|
||||
|
||||
/**
|
||||
* Return the key for these build options.
|
||||
*/
|
||||
String key();
|
||||
|
||||
/**
|
||||
* The builder for InsertOptions.
|
||||
*/
|
||||
interface Builder {
|
||||
|
||||
/**
|
||||
* Use a ON CONFLICT UPDATE automatically determining the unique columns.
|
||||
*/
|
||||
Builder onConflictUpdate();
|
||||
|
||||
/**
|
||||
* Use a ON CONFLICT DO NOTHING automatically determining the unique columns.
|
||||
*/
|
||||
Builder onConflictNothing();
|
||||
|
||||
/**
|
||||
* Specify an explicit conflict constraint name.
|
||||
* <p>
|
||||
* When this is used then unique columns will not be used.
|
||||
*/
|
||||
Builder constraint(String constraint);
|
||||
|
||||
/**
|
||||
* Specify the unique columns for the conflict target.
|
||||
* <p>
|
||||
* When not specified and constraint is also not specified then
|
||||
* it will automatically determine the unique columns
|
||||
* based on mapping like {@code @Column(unique=true)} and
|
||||
* {@code @Index(unique=true)} .
|
||||
*/
|
||||
Builder uniqueColumns(String uniqueColumns);
|
||||
|
||||
/**
|
||||
* Specify the ON CONFLICT DO UPDATE SET clause.
|
||||
* <p>
|
||||
* When not specified ebean will include all the non-unique columns.
|
||||
*/
|
||||
Builder updateSet(String updateSet);
|
||||
|
||||
/**
|
||||
* Specify if GetGeneratedKeys should be used to return generated keys.
|
||||
*/
|
||||
Builder getGeneratedKeys(boolean getGeneratedKeys);
|
||||
|
||||
/**
|
||||
* Build and return the insert options.
|
||||
*/
|
||||
InsertOptions build();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -702,9 +702,9 @@ public interface Query<T> extends CancelableQuery {
|
||||
* being used (that is using a read replica database potentially with replication lag).
|
||||
* <p>
|
||||
* When the database is configured with a read-only DataSource via
|
||||
* say {@link io.ebean.config.DatabaseConfig#setReadOnlyDataSource(DataSource)} then
|
||||
* say {@link io.ebean.DatabaseBuilder#readOnlyDataSource(DataSource)} then
|
||||
* by default when a query is run without an active transaction, it uses the read-only data
|
||||
* source. We we use {@code usingMaster()} to instead ensure that the query is executed
|
||||
* source. We use {@code usingMaster()} to instead ensure that the query is executed
|
||||
* against the master data source.
|
||||
*/
|
||||
Query<T> usingMaster();
|
||||
@@ -970,6 +970,25 @@ public interface Query<T> extends CancelableQuery {
|
||||
@Nullable
|
||||
<A> A findSingleAttribute();
|
||||
|
||||
/**
|
||||
* Execute the query returning a single optional attribute value.
|
||||
* <p>
|
||||
* <h3>Example</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* Optional<String> maybeName =
|
||||
* new QCustomer()
|
||||
* .select(name)
|
||||
* .id.eq(42)
|
||||
* .status.eq(NEW)
|
||||
* .findSingleAttributeOrEmpty();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @return an optional value for the selected property
|
||||
*/
|
||||
<A> Optional<A> findSingleAttributeOrEmpty();
|
||||
|
||||
/**
|
||||
* Return true if this is countDistinct query.
|
||||
*/
|
||||
@@ -1582,6 +1601,14 @@ public interface Query<T> extends CancelableQuery {
|
||||
*/
|
||||
Query<T> setLabel(String label);
|
||||
|
||||
/**
|
||||
* Set a SQL query hint.
|
||||
* <p>
|
||||
* This results in an inline comment that immediately follows
|
||||
* after the select keyword in the form: {@code /*+ hint *\/ }
|
||||
*/
|
||||
Query<T> setHint(String hint);
|
||||
|
||||
/**
|
||||
* Set to true if this query should execute against the doc store.
|
||||
* <p>
|
||||
|
||||
@@ -3,7 +3,9 @@ package io.ebean;
|
||||
import io.avaje.lang.NonNullApi;
|
||||
import io.avaje.lang.Nullable;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.io.Serializable;
|
||||
import java.sql.Connection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
@@ -45,14 +47,19 @@ public interface SqlQuery extends Serializable, CancelableQuery {
|
||||
*/
|
||||
SqlQuery usingTransaction(Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the query using the given connection.
|
||||
*/
|
||||
SqlQuery usingConnection(Connection connection);
|
||||
|
||||
/**
|
||||
* Ensure that the master DataSource is used if there is a read only data source
|
||||
* being used (that is using a read replica database potentially with replication lag).
|
||||
* <p>
|
||||
* When the database is configured with a read-only DataSource via
|
||||
* say {@link io.ebean.config.DatabaseConfig#setReadOnlyDataSource(DataSource)} then
|
||||
* say {@link io.ebean.DatabaseBuilder#readOnlyDataSource(DataSource)}then
|
||||
* by default when a query is run without an active transaction, it uses the read-only data
|
||||
* source. We we use {@code usingMaster()} to instead ensure that the query is executed
|
||||
* source. We use {@code usingMaster()} to instead ensure that the query is executed
|
||||
* against the master data source.
|
||||
*/
|
||||
SqlQuery usingMaster();
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package io.ebean.config;
|
||||
|
||||
import io.avaje.config.Config;
|
||||
import io.avaje.config.Configuration;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
@@ -19,16 +16,6 @@ public class ContainerConfig {
|
||||
private String podName;
|
||||
private int port;
|
||||
private Properties properties;
|
||||
private Configuration configuration;
|
||||
|
||||
public ContainerConfig() {
|
||||
this.configuration = Config.asConfiguration();
|
||||
this.active = configuration.getBool("ebean.cluster.active", active);
|
||||
this.serviceName = configuration.getNullable("ebean.cluster.serviceName", serviceName);
|
||||
this.namespace = configuration.getNullable("ebean.cluster.namespace", namespace);
|
||||
this.podName = configuration.getNullable("ebean.cluster.podName", podName);
|
||||
this.port = configuration.getInt("ebean.cluster.port", 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the service name.
|
||||
@@ -104,7 +91,7 @@ public class ContainerConfig {
|
||||
* Return the deployment properties.
|
||||
*/
|
||||
public Properties getProperties() {
|
||||
return properties != null ? properties : configuration.asProperties();
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,4 +101,25 @@ public class ContainerConfig {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the settings from properties.
|
||||
*/
|
||||
public void loadFromProperties(Properties properties) {
|
||||
this.properties = properties;
|
||||
this.active = getProperty(properties, "ebean.cluster.active", active);
|
||||
this.serviceName = properties.getProperty("ebean.cluster.serviceName", serviceName);
|
||||
this.namespace = properties.getProperty("ebean.cluster.namespace", namespace);
|
||||
this.podName = properties.getProperty("ebean.cluster.podName", podName);
|
||||
String portParam = properties.getProperty("ebean.cluster.port");
|
||||
if (portParam != null) {
|
||||
this.port = Integer.parseInt(portParam);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the boolean property setting.
|
||||
*/
|
||||
protected boolean getProperty(Properties properties, String key, boolean defaultValue) {
|
||||
return "true".equalsIgnoreCase(properties.getProperty(key, Boolean.toString(defaultValue)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,6 +125,12 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
*/
|
||||
private boolean loadModuleInfo = true;
|
||||
|
||||
/**
|
||||
* When true then include a sql comment in generated SELECT queries with the query
|
||||
* label or profile location label.
|
||||
*/
|
||||
private boolean includeLabelInSql;
|
||||
|
||||
/**
|
||||
* Interesting classes such as entities, embedded, ScalarTypes,
|
||||
* Listeners, Finders, Controllers, AttributeConverters etc.
|
||||
@@ -236,7 +242,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
*/
|
||||
private PersistBatch persistBatchOnCascade = PersistBatch.INHERIT;
|
||||
|
||||
private int persistBatchSize = 20;
|
||||
private int persistBatchSize = 100;
|
||||
|
||||
private EnumType defaultEnumType = EnumType.ORDINAL;
|
||||
|
||||
@@ -545,6 +551,8 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
|
||||
private String dumpMetricsOptions;
|
||||
|
||||
private LengthCheck lengthCheck = LengthCheck.OFF;
|
||||
|
||||
private Function<String, String> metricNaming = MetricNamingMatch.INSTANCE;
|
||||
|
||||
/**
|
||||
@@ -2131,6 +2139,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
readOnlyDatabase = p.getBoolean("readOnlyDatabase", readOnlyDatabase);
|
||||
autoPersistUpdates = p.getBoolean("autoPersistUpdates", autoPersistUpdates);
|
||||
loadModuleInfo = p.getBoolean("loadModuleInfo", loadModuleInfo);
|
||||
includeLabelInSql = p.getBoolean("includeLabelInSql", includeLabelInSql);
|
||||
maxCallStack = p.getInt("maxCallStack", maxCallStack);
|
||||
dumpMetricsOnShutdown = p.getBoolean("dumpMetricsOnShutdown", dumpMetricsOnShutdown);
|
||||
dumpMetricsOptions = p.get("dumpMetricsOptions", dumpMetricsOptions);
|
||||
@@ -2195,6 +2204,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
jdbcFetchSizeFindEach = p.getInt("jdbcFetchSizeFindEach", jdbcFetchSizeFindEach);
|
||||
jdbcFetchSizeFindList = p.getInt("jdbcFetchSizeFindList", jdbcFetchSizeFindList);
|
||||
databasePlatformName = p.get("databasePlatformName", databasePlatformName);
|
||||
lengthCheck = p.getEnum(LengthCheck.class, "lengthCheck", lengthCheck);
|
||||
|
||||
uuidVersion = p.getEnum(UuidVersion.class, "uuidVersion", uuidVersion);
|
||||
uuidStateFile = p.get("uuidStateFile", uuidStateFile);
|
||||
@@ -2544,6 +2554,11 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
return loadModuleInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludeLabelInSql() {
|
||||
return includeLabelInSql;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated - migrate to {@link #isLoadModuleInfo()}.
|
||||
*/
|
||||
@@ -2560,6 +2575,12 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseConfig includeLabelInSql(boolean includeLabelInSql) {
|
||||
this.includeLabelInSql = includeLabelInSql;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<String, String> getMetricNaming() {
|
||||
return metricNaming;
|
||||
@@ -2571,6 +2592,19 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length check mode.
|
||||
*/
|
||||
public LengthCheck getLengthCheck() {
|
||||
return lengthCheck;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseConfig lengthCheck(LengthCheck lengthCheck) {
|
||||
this.lengthCheck = lengthCheck;
|
||||
return this;
|
||||
}
|
||||
|
||||
public enum UuidVersion {
|
||||
VERSION4,
|
||||
VERSION1,
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package io.ebean.config;
|
||||
|
||||
/**
|
||||
* Defines the length-check mode.
|
||||
*
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*/
|
||||
public enum LengthCheck {
|
||||
/**
|
||||
* By default, length checking is off. This means, strings/jsons and files are passed to the DB and the DB might or might not check the length.
|
||||
* The DB has to check the data length. Note this is not possible for certain datatypes (e.g. clob without size)
|
||||
*/
|
||||
OFF,
|
||||
/**
|
||||
* When enabling length check, ebean validates strings/json strings and files before saving them to DB.
|
||||
*/
|
||||
ON,
|
||||
/**
|
||||
* Same as "ON", but take the UTF8-bytelength for validation. This may be useful, if you have an UTF8 based charset (default for DB2)
|
||||
*/
|
||||
UTF8
|
||||
}
|
||||
@@ -769,4 +769,15 @@ public class DatabasePlatform {
|
||||
public boolean supportsNativeJavaTime() {
|
||||
return supportsNativeJavaTime;
|
||||
}
|
||||
|
||||
public String inlineSqlComment(String label) {
|
||||
if (label == null) {
|
||||
return "";
|
||||
}
|
||||
return "/* " + label + " */ ";
|
||||
}
|
||||
|
||||
public String inlineSqlHint(String hint) {
|
||||
return "/*+ " + hint + " */ ";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import java.sql.Driver;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
@@ -23,7 +24,7 @@ public final class ShutdownManager {
|
||||
|
||||
private static final System.Logger log = EbeanVersion.log;
|
||||
private static final ReentrantLock lock = new ReentrantLock();
|
||||
private static final List<Database> databases = new ArrayList<>();
|
||||
private static final List<Database> databases = Collections.synchronizedList(new ArrayList<>());
|
||||
private static final ShutdownHook shutdownHook = new ShutdownHook();
|
||||
|
||||
private static boolean stopping;
|
||||
@@ -177,12 +178,7 @@ public final class ShutdownManager {
|
||||
* Register an ebeanServer to be shutdown when the JVM is shutdown.
|
||||
*/
|
||||
public static void registerDatabase(Database server) {
|
||||
lock.lock();
|
||||
try {
|
||||
databases.add(server);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
databases.add(server);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,12 +188,7 @@ public final class ShutdownManager {
|
||||
* </p>
|
||||
*/
|
||||
public static void unregisterDatabase(Database server) {
|
||||
lock.lock();
|
||||
try {
|
||||
databases.remove(server);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
databases.remove(server);
|
||||
}
|
||||
|
||||
private static class ShutdownHook extends Thread {
|
||||
|
||||
@@ -22,6 +22,8 @@ public class JsonWriteOptions {
|
||||
|
||||
protected JsonConfig.Include include;
|
||||
|
||||
protected boolean includeLoadedImplicit = true;
|
||||
|
||||
protected Map<String, JsonWriteBeanVisitor<?>> visitorMap;
|
||||
|
||||
/**
|
||||
@@ -73,6 +75,20 @@ public class JsonWriteOptions {
|
||||
this.include = include;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should loaded properties be included implicit, if no other fetch path is specified (default = true).
|
||||
*/
|
||||
public boolean isIncludeLoadedImplicit() {
|
||||
return includeLoadedImplicit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set include loaded properties implicit (default = true).
|
||||
*/
|
||||
public void setIncludeLoadedImplicit(boolean includeLoadedImplicit) {
|
||||
this.includeLoadedImplicit = includeLoadedImplicit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a JsonWriteBeanVisitor for the root level.
|
||||
*/
|
||||
|
||||
@@ -75,6 +75,8 @@ class DatabaseConfigTest {
|
||||
props.setProperty("defaultServer", "false");
|
||||
props.setProperty("skipDataSourceCheck", "true");
|
||||
props.setProperty("readOnlyDatabase", "true");
|
||||
props.setProperty("lengthCheck", "ON");
|
||||
props.setProperty("includeLabelInSql", "true");
|
||||
|
||||
props.setProperty("queryPlan.enable", "true");
|
||||
props.setProperty("queryPlan.thresholdMicros", "10000");
|
||||
@@ -95,6 +97,8 @@ class DatabaseConfigTest {
|
||||
assertTrue(settings.isLoadModuleInfo());
|
||||
assertTrue(settings.skipDataSourceCheck());
|
||||
assertTrue(settings.readOnlyDatabase());
|
||||
assertTrue(settings.isIncludeLabelInSql());
|
||||
assertThat(settings.getLengthCheck()).isEqualTo(LengthCheck.ON);
|
||||
|
||||
assertTrue(settings.isIdGeneratorAutomatic());
|
||||
assertFalse(settings.getPlatformConfig().isCaseSensitiveCollation());
|
||||
@@ -128,8 +132,11 @@ class DatabaseConfigTest {
|
||||
|
||||
assertThat(settings.getMappingLocations()).containsExactly("classpath:/foo","bar");
|
||||
|
||||
config.setPersistBatch(PersistBatch.NONE);
|
||||
config.setPersistBatchOnCascade(PersistBatch.NONE);
|
||||
config.persistBatch(PersistBatch.NONE)
|
||||
.persistBatchOnCascade(PersistBatch.NONE)
|
||||
.lengthCheck(LengthCheck.ON)
|
||||
.lengthCheck(LengthCheck.UTF8);
|
||||
|
||||
|
||||
Properties props1 = new Properties();
|
||||
props1.setProperty("ebean.persistBatch", "ALL");
|
||||
@@ -146,6 +153,7 @@ class DatabaseConfigTest {
|
||||
|
||||
assertEquals(PersistBatch.ALL, settings.getPersistBatch());
|
||||
assertEquals(PersistBatch.ALL, settings.getPersistBatchOnCascade());
|
||||
assertEquals(LengthCheck.UTF8, settings.getLengthCheck());
|
||||
|
||||
config.setEnabledL2Regions("r0,orgs");
|
||||
assertEquals("r0,orgs", settings.getEnabledL2Regions());
|
||||
@@ -174,6 +182,8 @@ class DatabaseConfigTest {
|
||||
assertEquals(600, config.getQueryPlanCapturePeriodSecs());
|
||||
assertEquals(10000L, config.getQueryPlanCaptureMaxTimeMillis());
|
||||
assertEquals(10, config.getQueryPlanCaptureMaxCount());
|
||||
assertThat(config.getLengthCheck()).isEqualTo(LengthCheck.OFF);
|
||||
assertFalse(config.isIncludeLabelInSql());
|
||||
|
||||
config.setLoadModuleInfo(false);
|
||||
assertFalse(config.isAutoLoadModuleInfo());
|
||||
|
||||
+31
-31
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean bom</name>
|
||||
@@ -89,103 +89,103 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-joda-time</artifactId>
|
||||
<version>13.24.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-jsonnode</artifactId>
|
||||
<version>13.24.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-mapper</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>13.18.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-xml</artifactId>
|
||||
<version>13.18.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-autotune</artifactId>
|
||||
<version>13.18.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>kotlin-querybean-generator</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-redis</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-spring-txn</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- platforms -->
|
||||
@@ -193,79 +193,79 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-clickhouse</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-db2</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-h2</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-hana</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-mariadb</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-mysql</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-nuodb</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-oracle</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgres</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis-types</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-sqlite</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-sqlserver</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
@@ -16,7 +16,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -30,7 +30,7 @@
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.6.0</version>
|
||||
<version>42.7.2</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -174,4 +174,9 @@ public interface DataBinder {
|
||||
*/
|
||||
String popJson();
|
||||
|
||||
/**
|
||||
* Returns the last bound object (e.g. for BindValidation). Note for InputStreams you'll get an InputStreamInfo.
|
||||
*/
|
||||
Object popLastObject();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package io.ebean.core.type;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Helper to transports length info of DataBind.setBinaryStream(stream, length) to BindValidation
|
||||
*
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*/
|
||||
public final class InputStreamInfo {
|
||||
|
||||
private final InputStream stream;
|
||||
private final long length;
|
||||
|
||||
public InputStreamInfo(InputStream stream, long length) {
|
||||
this.stream = stream;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
public InputStream stream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
public long length() {
|
||||
return length;
|
||||
}
|
||||
}
|
||||
+8
-8
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core</artifactId>
|
||||
@@ -22,7 +22,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -46,13 +46,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>13.18.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -151,7 +151,7 @@
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.6.0</version>
|
||||
<version>42.7.2</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
@@ -159,21 +159,21 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlserver</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ package io.ebeaninternal.api;
|
||||
import io.ebean.TxScope;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Used internally to handle the scoping of transactions for methods.
|
||||
@@ -47,6 +49,11 @@ public final class ScopeTrans {
|
||||
private boolean nestedCommit;
|
||||
private boolean nestedUseSavepoint;
|
||||
|
||||
/**
|
||||
* The UserObjects when using in nested transactions.
|
||||
*/
|
||||
private Map<String, Object> userObjects;
|
||||
|
||||
public ScopeTrans(boolean rollbackOnChecked, boolean created, SpiTransaction transaction, TxScope txScope) {
|
||||
this.rollbackOnChecked = rollbackOnChecked;
|
||||
this.created = created;
|
||||
@@ -218,4 +225,17 @@ public final class ScopeTrans {
|
||||
return e instanceof RuntimeException || rollbackOnChecked;
|
||||
}
|
||||
|
||||
public void putUserObject(String name, Object value) {
|
||||
if (userObjects == null) {
|
||||
userObjects = new HashMap<>();
|
||||
}
|
||||
userObjects.put(name, value);
|
||||
}
|
||||
|
||||
public Object getUserObject(String name) {
|
||||
if (userObjects == null) {
|
||||
return null;
|
||||
}
|
||||
return userObjects.get(name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package io.ebeaninternal.api;
|
||||
|
||||
import io.ebeaninternal.server.transaction.TransactionScopeManager;
|
||||
import io.ebeaninternal.server.util.ArrayStack;
|
||||
|
||||
import jakarta.persistence.PersistenceException;
|
||||
|
||||
/**
|
||||
@@ -173,4 +172,31 @@ public final class ScopedTransaction extends SpiTransactionProxy {
|
||||
return current.caughtThrowable(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* New user objects are always written to the current ScopeTrans.
|
||||
*/
|
||||
@Override
|
||||
public void putUserObject(String name, Object value) {
|
||||
current.putUserObject(name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the userObject in the stack, Herew we search
|
||||
* the stack and return the first found userObject
|
||||
*/
|
||||
@Override
|
||||
public Object getUserObject(String name) {
|
||||
Object obj = current.getUserObject(name);
|
||||
if (obj != null) {
|
||||
return obj;
|
||||
}
|
||||
for (ScopeTrans trans : stack) {
|
||||
obj = trans.getUserObject(name);
|
||||
if (obj != null) {
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
return transaction.getUserObject(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -86,6 +86,11 @@ public interface SpiEbeanServer extends SpiServer, ExtendedServer, BeanCollectio
|
||||
*/
|
||||
SpiTransactionManager transactionManager();
|
||||
|
||||
/**
|
||||
* End the current transaction if it is active.
|
||||
*/
|
||||
void endTransaction();
|
||||
|
||||
/**
|
||||
* Return all the descriptors.
|
||||
*/
|
||||
|
||||
@@ -3,13 +3,14 @@ package io.ebeaninternal.api;
|
||||
import io.ebeaninternal.server.core.SpiOrmQueryRequest;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.expression.platform.DbExpressionHandler;
|
||||
import io.ebeaninternal.server.expression.platform.DbExpressionRequest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Request object used for gathering expression sql and bind values.
|
||||
*/
|
||||
public interface SpiExpressionRequest {
|
||||
public interface SpiExpressionRequest extends DbExpressionRequest {
|
||||
|
||||
/**
|
||||
* Return the DB specific handler for JSON and ARRAY expressions.
|
||||
@@ -34,11 +35,13 @@ public interface SpiExpressionRequest {
|
||||
/**
|
||||
* Append to the expression sql without any parsing.
|
||||
*/
|
||||
@Override
|
||||
SpiExpressionRequest append(String expression);
|
||||
|
||||
/**
|
||||
* Append to the expression sql without any parsing.
|
||||
*/
|
||||
@Override
|
||||
SpiExpressionRequest append(char c);
|
||||
|
||||
/**
|
||||
@@ -47,6 +50,7 @@ public interface SpiExpressionRequest {
|
||||
* This is a fast path case when expression is a bean property path and falls back to using parse()
|
||||
* when that isn't the case.
|
||||
*/
|
||||
@Override
|
||||
SpiExpressionRequest property(String expression);
|
||||
|
||||
/**
|
||||
|
||||
@@ -226,6 +226,11 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
|
||||
*/
|
||||
ProfileLocation profileLocation();
|
||||
|
||||
/**
|
||||
* Return the SQL hint to include in the query.
|
||||
*/
|
||||
String hint();
|
||||
|
||||
/**
|
||||
* Return the label set on the query.
|
||||
*/
|
||||
@@ -654,6 +659,16 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
|
||||
*/
|
||||
ObjectGraphNode parentNode();
|
||||
|
||||
/**
|
||||
* Set that this is a future query that will execute in the background.
|
||||
*/
|
||||
void usingFuture();
|
||||
|
||||
/**
|
||||
* Return true if this is a future query.
|
||||
*/
|
||||
boolean isUsingFuture();
|
||||
|
||||
/**
|
||||
* Return false when this is a lazy load or refresh query for a bean.
|
||||
* <p>
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package io.ebeaninternal.server.bind;
|
||||
|
||||
import io.ebean.core.type.DataBinder;
|
||||
import io.ebean.core.type.InputStreamInfo;
|
||||
import io.ebeaninternal.api.CoreLog;
|
||||
import io.ebeaninternal.server.core.timezone.DataTimeZone;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.*;
|
||||
import java.util.ArrayList;
|
||||
@@ -23,6 +27,8 @@ public class DataBind implements DataBinder {
|
||||
protected int pos;
|
||||
private String json;
|
||||
|
||||
private Object lastObject = null;
|
||||
|
||||
public DataBind(DataTimeZone dataTimeZone, PreparedStatement pstmt, Connection connection) {
|
||||
this.dataTimeZone = dataTimeZone;
|
||||
this.pstmt = pstmt;
|
||||
@@ -65,16 +71,19 @@ public class DataBind implements DataBinder {
|
||||
@Override
|
||||
public void setObject(Object value) throws SQLException {
|
||||
pstmt.setObject(++pos, value);
|
||||
lastObject = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setObject(Object value, int sqlType) throws SQLException {
|
||||
pstmt.setObject(++pos, value, sqlType);
|
||||
lastObject = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNull(int jdbcType) throws SQLException {
|
||||
pstmt.setNull(++pos, jdbcType);
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,7 +105,7 @@ public class DataBind implements DataBinder {
|
||||
}
|
||||
}
|
||||
|
||||
private void closeInputStreams() {
|
||||
public void closeInputStreams() {
|
||||
if (inputStreams != null) {
|
||||
for (InputStream inputStream : inputStreams) {
|
||||
try {
|
||||
@@ -117,36 +126,43 @@ public class DataBind implements DataBinder {
|
||||
@Override
|
||||
public void setString(String value) throws SQLException {
|
||||
pstmt.setString(++pos, value);
|
||||
lastObject = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setInt(int value) throws SQLException {
|
||||
pstmt.setInt(++pos, value);
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setLong(long value) throws SQLException {
|
||||
pstmt.setLong(++pos, value);
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setShort(short value) throws SQLException {
|
||||
pstmt.setShort(++pos, value);
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setFloat(float value) throws SQLException {
|
||||
pstmt.setFloat(++pos, value);
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setDouble(double value) throws SQLException {
|
||||
pstmt.setDouble(++pos, value);
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setBigDecimal(BigDecimal value) throws SQLException {
|
||||
pstmt.setBigDecimal(++pos, value);
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -157,6 +173,7 @@ public class DataBind implements DataBinder {
|
||||
} else {
|
||||
pstmt.setDate(++pos, value);
|
||||
}
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -167,6 +184,7 @@ public class DataBind implements DataBinder {
|
||||
} else {
|
||||
pstmt.setTimestamp(++pos, value);
|
||||
}
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -177,26 +195,31 @@ public class DataBind implements DataBinder {
|
||||
} else {
|
||||
pstmt.setTime(++pos, value);
|
||||
}
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBoolean(boolean value) throws SQLException {
|
||||
pstmt.setBoolean(++pos, value);
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBytes(byte[] value) throws SQLException {
|
||||
pstmt.setBytes(++pos, value);
|
||||
lastObject = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setByte(byte value) throws SQLException {
|
||||
pstmt.setByte(++pos, value);
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChar(char value) throws SQLException {
|
||||
pstmt.setString(++pos, String.valueOf(value));
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -211,21 +234,31 @@ public class DataBind implements DataBinder {
|
||||
}
|
||||
inputStreams.add(inputStream);
|
||||
pstmt.setBinaryStream(++pos, inputStream, length);
|
||||
lastObject = new InputStreamInfo(inputStream, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlob(byte[] bytes) throws SQLException {
|
||||
pstmt.setBinaryStream(++pos, new ByteArrayInputStream(bytes), bytes.length);
|
||||
lastObject = bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClob(String content) throws SQLException {
|
||||
pstmt.setCharacterStream(++pos, new StringReader(content), content.length());
|
||||
lastObject = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setArray(String arrayType, Object[] elements) throws SQLException {
|
||||
pstmt.setArray(++pos, connection.createArrayOf(arrayType, elements));
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object popLastObject() {
|
||||
Object ret = lastObject;
|
||||
lastObject = null;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -756,16 +756,6 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
currentTransaction().flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commitTransaction() {
|
||||
currentTransaction().commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollbackTransaction() {
|
||||
currentTransaction().rollback();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endTransaction() {
|
||||
Transaction transaction = transactionManager.inScope();
|
||||
@@ -1273,6 +1263,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
@Override
|
||||
public <T> FutureRowCount<T> findFutureCount(SpiQuery<T> query) {
|
||||
SpiQuery<T> copy = query.copy();
|
||||
copy.usingFuture();
|
||||
boolean createdTransaction = false;
|
||||
SpiTransaction transaction = query.transaction();
|
||||
if (transaction == null) {
|
||||
@@ -1291,6 +1282,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
@Override
|
||||
public <T> FutureIds<T> findFutureIds(SpiQuery<T> query) {
|
||||
SpiQuery<T> copy = query.copy();
|
||||
copy.usingFuture();
|
||||
boolean createdTransaction = false;
|
||||
SpiTransaction transaction = query.transaction();
|
||||
if (transaction == null) {
|
||||
@@ -1309,6 +1301,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
@Override
|
||||
public <T> FutureList<T> findFutureList(SpiQuery<T> query) {
|
||||
SpiQuery<T> spiQuery = query.copy();
|
||||
spiQuery.usingFuture();
|
||||
// FutureList query always run in it's own persistence content
|
||||
spiQuery.setPersistenceContext(new DefaultPersistenceContext());
|
||||
if (!spiQuery.isDisableReadAudit()) {
|
||||
@@ -1651,41 +1644,50 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}, transaction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert the bean.
|
||||
*/
|
||||
@Override
|
||||
public void insert(Object bean) {
|
||||
insert(bean, null);
|
||||
persister.insert(checkEntityBean(bean), null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(Object bean, @Nullable InsertOptions insertOptions) {
|
||||
persister.insert(checkEntityBean(bean), insertOptions, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert the bean with a transaction.
|
||||
*/
|
||||
@Override
|
||||
public void insert(Object bean, @Nullable Transaction transaction) {
|
||||
persister.insert(checkEntityBean(bean), transaction);
|
||||
persister.insert(checkEntityBean(bean), null, transaction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(Object bean, InsertOptions insertOptions, Transaction transaction) {
|
||||
persister.insert(checkEntityBean(bean), insertOptions, transaction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert all beans in the collection.
|
||||
*/
|
||||
@Override
|
||||
public void insertAll(Collection<?> beans) {
|
||||
insertAll(beans, null);
|
||||
insertAll(beans, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertAll(Collection<?> beans, InsertOptions options) {
|
||||
insertAll(beans, options, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert all beans in the collection with a transaction.
|
||||
*/
|
||||
@Override
|
||||
public void insertAll(@Nullable Collection<?> beans, @Nullable Transaction transaction) {
|
||||
insertAll(beans, null, transaction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertAll(@Nullable Collection<?> beans, InsertOptions options, @Nullable Transaction transaction) {
|
||||
if (beans == null || beans.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
executeInTrans((txn) -> {
|
||||
txn.checkBatchEscalationOnCollection();
|
||||
for (Object bean : beans) {
|
||||
persister.insert(checkEntityBean(bean), txn);
|
||||
persister.insert(checkEntityBean(bean), options, txn);
|
||||
}
|
||||
return 0;
|
||||
}, transaction);
|
||||
|
||||
@@ -35,7 +35,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
private final OrmQueryEngine queryEngine;
|
||||
private final SpiQuery<T> query;
|
||||
private final BeanFindController finder;
|
||||
private final Boolean readOnly;
|
||||
private LoadContext loadContext;
|
||||
private PersistenceContext persistenceContext;
|
||||
private HashQuery cacheKey;
|
||||
@@ -52,7 +51,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
this.finder = beanDescriptor.beanFinder();
|
||||
this.queryEngine = queryEngine;
|
||||
this.query = query;
|
||||
this.readOnly = query.isReadOnly();
|
||||
this.persistenceContext = query.persistenceContext();
|
||||
}
|
||||
|
||||
@@ -135,13 +133,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
return loadContext.secondaryQueriesMinBatchSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Normal, sharedInstance, ReadOnly state of this query.
|
||||
*/
|
||||
public Boolean isReadOnly() {
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BeanDescriptor for the associated bean.
|
||||
*/
|
||||
@@ -782,4 +773,10 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
public int forwardOnlyFetchSize() {
|
||||
return queryEngine.forwardOnlyFetchSize();
|
||||
}
|
||||
|
||||
public void clearContext() {
|
||||
if (!transaction.isAutoPersistUpdates()) {
|
||||
beanDescriptor.contextClear(transaction.persistenceContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebean.InsertOptions;
|
||||
import io.ebean.ValuePair;
|
||||
import io.ebean.annotation.DocStoreMode;
|
||||
import io.ebean.bean.EntityBean;
|
||||
@@ -124,6 +125,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
* Many-to-many intersection table changes that are held for later batch processing.
|
||||
*/
|
||||
private List<SaveMany> saveMany;
|
||||
private InsertOptions insertOptions;
|
||||
|
||||
public PersistRequestBean(SpiEbeanServer server, T bean, Object parentBean, BeanManager<T> mgr, SpiTransaction t,
|
||||
PersistExecute persistExecute, PersistRequest.Type type, int flags) {
|
||||
@@ -380,6 +382,14 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
return intercept.dirtyPropertyNames();
|
||||
}
|
||||
|
||||
public boolean isChangedProperty(int propertyIndex) {
|
||||
if (dirtyProperties == null) {
|
||||
return intercept.isChangedProperty(propertyIndex);
|
||||
} else {
|
||||
return dirtyProperties[propertyIndex];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the dirty properties on this request.
|
||||
*/
|
||||
@@ -865,8 +875,8 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
}
|
||||
setNotifyCache();
|
||||
boolean isChangeLog = beanDescriptor.isChangeLog();
|
||||
if (type == Type.UPDATE && (isChangeLog || notifyCache || docStoreMode == DocStoreMode.UPDATE)) {
|
||||
// get the dirty properties for update notification to the doc store
|
||||
if (type == Type.UPDATE) {
|
||||
// get the dirty properties for notify cache & orphanRemoval of vanilla collection detection
|
||||
dirtyProperties = intercept.dirtyProperties();
|
||||
}
|
||||
if (isChangeLog) {
|
||||
@@ -909,21 +919,27 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
}
|
||||
|
||||
private void controllerPost() {
|
||||
switch (type) {
|
||||
case INSERT:
|
||||
controller.postInsert(this);
|
||||
break;
|
||||
case UPDATE:
|
||||
controller.postUpdate(this);
|
||||
break;
|
||||
case DELETE_SOFT:
|
||||
controller.postSoftDelete(this);
|
||||
break;
|
||||
case DELETE:
|
||||
controller.postDelete(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
boolean old = transaction.isFlushOnQuery();
|
||||
transaction.setFlushOnQuery(false);
|
||||
try {
|
||||
switch (type) {
|
||||
case INSERT:
|
||||
controller.postInsert(this);
|
||||
break;
|
||||
case UPDATE:
|
||||
controller.postUpdate(this);
|
||||
break;
|
||||
case DELETE_SOFT:
|
||||
controller.postSoftDelete(this);
|
||||
break;
|
||||
case DELETE:
|
||||
controller.postDelete(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} finally {
|
||||
transaction.setFlushOnQuery(old);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1408,4 +1424,12 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
private void setGeneratedId() {
|
||||
beanDescriptor.setGeneratedId(entityBean, transaction);
|
||||
}
|
||||
|
||||
public void setInsertOptions(InsertOptions insertOptions) {
|
||||
this.insertOptions = insertOptions;
|
||||
}
|
||||
|
||||
public InsertOptions insertOptions() {
|
||||
return insertOptions;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,10 +77,13 @@ public final class PersistRequestOrmUpdate extends PersistRequest {
|
||||
*/
|
||||
@Override
|
||||
public void postExecute() {
|
||||
OrmUpdateType ormUpdateType = ormUpdate.ormUpdateType();
|
||||
if (OrmUpdateType.INSERT != ormUpdateType && !transaction.isAutoPersistUpdates()) {
|
||||
beanDescriptor.contextClear(transaction.persistenceContext());
|
||||
}
|
||||
if (startNanos > 0) {
|
||||
persistExecute.collectOrmUpdate(label, startNanos);
|
||||
}
|
||||
OrmUpdateType ormUpdateType = ormUpdate.ormUpdateType();
|
||||
String tableName = ormUpdate.baseTable();
|
||||
if (transaction.isLogSummary()) {
|
||||
transaction.logSummary("{0} table[{1}] rows[{2}] bind[{3}]", ormUpdateType, tableName, rowCount, bindLog);
|
||||
|
||||
@@ -3,10 +3,13 @@ package io.ebeaninternal.server.core;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.api.SpiSqlUpdate;
|
||||
import io.ebeaninternal.api.SpiTransaction;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.persist.BatchControl;
|
||||
import io.ebeaninternal.server.persist.PersistExecute;
|
||||
import io.ebeaninternal.server.persist.TrimLogSql;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Persist request specifically for CallableSql.
|
||||
*/
|
||||
@@ -156,6 +159,14 @@ public final class PersistRequestUpdateSql extends PersistRequest {
|
||||
*/
|
||||
@Override
|
||||
public void postExecute() {
|
||||
if (sqlType != SqlType.SQL_INSERT && !transaction.isAutoPersistUpdates()) {
|
||||
List<BeanDescriptor<?>> descriptors = server.descriptors(tableName);
|
||||
if (descriptors != null) {
|
||||
for (BeanDescriptor<?> descriptor : descriptors) {
|
||||
descriptor.contextClear(transaction.persistenceContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (startNanos > 0) {
|
||||
persistExecute.collectSqlUpdate(label, startNanos);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebean.CallableSql;
|
||||
import io.ebean.MergeOptions;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.SqlUpdate;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.Update;
|
||||
import io.avaje.lang.Nullable;
|
||||
import io.ebean.*;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.meta.MetricVisitor;
|
||||
import io.ebeaninternal.api.SpiSqlUpdate;
|
||||
@@ -31,9 +27,9 @@ public interface Persister {
|
||||
void update(EntityBean entityBean, Transaction t);
|
||||
|
||||
/**
|
||||
* Force an Insert using the given bean.
|
||||
* Perform an Insert using the given bean.
|
||||
*/
|
||||
void insert(EntityBean entityBean, Transaction t);
|
||||
void insert(EntityBean entityBean, @Nullable InsertOptions insertOptions, @Nullable Transaction t);
|
||||
|
||||
/**
|
||||
* Insert or update the bean depending on its state.
|
||||
@@ -44,7 +40,6 @@ public interface Persister {
|
||||
* Delete a bean given it's type and id value.
|
||||
* <p>
|
||||
* This will also cascade delete one level of children.
|
||||
* </p>
|
||||
*/
|
||||
int delete(Class<?> beanType, Object id, Transaction transaction, boolean permanent);
|
||||
|
||||
|
||||
@@ -2056,6 +2056,13 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
pc.clear(rootBeanType, idValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear a bean from the persistence context.
|
||||
*/
|
||||
public void contextClear(PersistenceContext pc) {
|
||||
pc.clear(rootBeanType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a bean from the persistence context (such that we don't fetch it in the same transaction).
|
||||
*/
|
||||
|
||||
@@ -106,6 +106,7 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
|
||||
private final String asOfViewSuffix;
|
||||
private final boolean jacksonCorePresent;
|
||||
private final int queryPlanTTLSeconds;
|
||||
private final BindMaxLength bindMaxLength;
|
||||
private int entityBeanCount;
|
||||
private List<BeanDescriptor<?>> immutableDescriptorList;
|
||||
/**
|
||||
@@ -160,6 +161,19 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
|
||||
this.changeLogListener = config.changeLogListener(bootupClasses.getChangeLogListener());
|
||||
this.changeLogRegister = config.changeLogRegister(bootupClasses.getChangeLogRegister());
|
||||
this.jacksonCorePresent = config.isJacksonCorePresent();
|
||||
this.bindMaxLength = initMaxLength();
|
||||
}
|
||||
|
||||
BindMaxLength initMaxLength() {
|
||||
LengthCheck lengthCheck = this.config.getLengthCheck();
|
||||
switch (lengthCheck) {
|
||||
case OFF:
|
||||
return null;
|
||||
case UTF8:
|
||||
return BindMaxLength.ofUtf8();
|
||||
default:
|
||||
return BindMaxLength.ofStandard();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -399,7 +413,7 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
|
||||
* Return the BeanDescriptors mapped to the table.
|
||||
*/
|
||||
public List<BeanDescriptor<?>> descriptors(String tableName) {
|
||||
return tableToDescMap.get(tableName.toLowerCase());
|
||||
return tableName == null ? Collections.emptyList() : tableToDescMap.get(tableName.toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1501,6 +1515,10 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
|
||||
return list;
|
||||
}
|
||||
|
||||
public BindMaxLength bindMaxLength() {
|
||||
return bindMaxLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator to sort the BeanDescriptors by name.
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebeaninternal.server.deploy;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import io.ebean.DataIntegrityException;
|
||||
import io.ebean.ValuePair;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
@@ -40,8 +41,8 @@ import io.ebeanservice.docstore.api.mapping.DocMappingBuilder;
|
||||
import io.ebeanservice.docstore.api.mapping.DocPropertyMapping;
|
||||
import io.ebeanservice.docstore.api.mapping.DocPropertyOptions;
|
||||
import io.ebeanservice.docstore.api.support.DocStructure;
|
||||
|
||||
import jakarta.persistence.PersistenceException;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
@@ -166,6 +167,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
*/
|
||||
private final String dbComment;
|
||||
private final DbEncryptFunction dbEncryptFunction;
|
||||
private final BindMaxLength bindMaxLength;
|
||||
private int deployOrder;
|
||||
final boolean jsonSerialize;
|
||||
final boolean jsonDeserialize;
|
||||
@@ -258,6 +260,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
}
|
||||
this.jsonSerialize = deploy.isJsonSerialize();
|
||||
this.jsonDeserialize = deploy.isJsonDeserialize();
|
||||
this.bindMaxLength = deploy.bindMaxLength();
|
||||
}
|
||||
|
||||
private String tableAliasIntern(BeanDescriptor<?> descriptor, String s, boolean dbEncrypted, String dbColumn) {
|
||||
@@ -345,6 +348,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
this.elPlaceHolderEncrypted = override.replace(source.elPlaceHolderEncrypted, source.dbColumn);
|
||||
this.jsonSerialize = source.jsonSerialize;
|
||||
this.jsonDeserialize = source.jsonDeserialize;
|
||||
this.bindMaxLength = source.bindMaxLength;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -555,6 +559,18 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void bind(DataBind b, Object value) throws SQLException {
|
||||
scalarType.bind(b, value);
|
||||
if (bindMaxLength != null) {
|
||||
Object obj = b.popLastObject();
|
||||
long length = bindMaxLength.length(dbLength, obj);
|
||||
if (length > dbLength) {
|
||||
b.closeInputStreams();
|
||||
String s = String.valueOf(value); // take original bind value here.
|
||||
if (s.length() > 50) {
|
||||
s = s.substring(0, 47) + "...";
|
||||
}
|
||||
throw new DataIntegrityException("Cannot bind value '" + s + "' (effective length=" + length + ") to column '" + dbColumn + "' (length=" + dbLength + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings(value = "unchecked")
|
||||
@@ -1166,14 +1182,14 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
* Returns true if this <code>isLob()</code> or the type will effectively map to a lob.
|
||||
*/
|
||||
@Override
|
||||
public boolean isDbLob() {
|
||||
public boolean isLobForPlatform() {
|
||||
if (lob) {
|
||||
return true;
|
||||
}
|
||||
switch (dbType) {
|
||||
case DbPlatformType.JSON:
|
||||
case DbPlatformType.JSONB:
|
||||
return dbLength == 0; // must be analog to DbPlatformTypeMapping.lookup
|
||||
return dbLength == 0 || dbLength > 4000; // must be analog to DbPlatformTypeMapping.lookup
|
||||
case DbPlatformType.JSONBlob:
|
||||
case DbPlatformType.JSONClob:
|
||||
return true;
|
||||
|
||||
@@ -379,6 +379,9 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
for (ExportedProperty exportedProperty : exportedProperties) {
|
||||
row.addColumn(exportedProperty.getForeignDbColumn());
|
||||
}
|
||||
if (importedId == null) {
|
||||
throw new PersistenceException("Missing @Id property on bean related to ManyToMany " + fullName());
|
||||
}
|
||||
importedId.buildImport(row);
|
||||
return row.build();
|
||||
}
|
||||
@@ -585,10 +588,9 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the join properties from the parent bean to the child bean.
|
||||
* This is only valid for OneToMany and NOT valid for ManyToMany.
|
||||
* Set the parent bean to the child (update the relationship).
|
||||
*/
|
||||
public void setJoinValuesToChild(EntityBean parent, EntityBean child, Object mapKeyValue) {
|
||||
public void setParentToChild(EntityBean parent, EntityBean child, Object mapKeyValue) {
|
||||
if (mapKeyProperty != null) {
|
||||
mapKeyProperty.setValue(child, mapKeyValue);
|
||||
}
|
||||
@@ -599,6 +601,31 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the parent bean has been set to the child (updated the relationship).
|
||||
*/
|
||||
public boolean setParentToChild(EntityBean parent, EntityBean child, Object mapKeyValue, BeanDescriptor<?> parentDesc) {
|
||||
if (manyToMany
|
||||
|| childMasterProperty == null
|
||||
|| !child._ebean_getIntercept().isLoadedProperty(childMasterProperty.propertyIndex())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Object currentParent = childMasterProperty.getValue(child);
|
||||
if (currentParent != null) {
|
||||
Object newId = parentDesc.getId(parent);
|
||||
Object oldId = parentDesc.id(currentParent);
|
||||
if (Objects.equals(newId, oldId)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
childMasterProperty.setValueIntercept(child, parent);
|
||||
if (mapKeyProperty != null) {
|
||||
mapKeyProperty.setValue(child, mapKeyValue);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the order by clause used to order the fetching of the data for
|
||||
* this list, set or map.
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package io.ebeaninternal.server.deploy;
|
||||
|
||||
import io.ebean.core.type.InputStreamInfo;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* The max length check on bind values.
|
||||
*/
|
||||
public interface BindMaxLength {
|
||||
|
||||
/**
|
||||
* Return a UTF8 based implementation.
|
||||
*/
|
||||
static BindMaxLength ofUtf8() {
|
||||
return new UTF8();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a standard implementation.
|
||||
*/
|
||||
static BindMaxLength ofStandard() {
|
||||
return new Standard();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the length of the object.
|
||||
*/
|
||||
long length(int dbLength, Object obj);
|
||||
|
||||
/**
|
||||
* Length check based on UTF8 bytes.
|
||||
*/
|
||||
final class UTF8 implements BindMaxLength {
|
||||
|
||||
@Override
|
||||
public long length(int dbLength, Object obj) {
|
||||
if (obj == null) {
|
||||
return -1;
|
||||
} else if (obj instanceof String) {
|
||||
String s = (String) obj;
|
||||
return utf8String(dbLength, s);
|
||||
} else if (obj instanceof byte[]) {
|
||||
return ((byte[]) obj).length;
|
||||
} else if (obj instanceof InputStreamInfo) {
|
||||
return ((InputStreamInfo) obj).length();
|
||||
} else if ("org.postgresql.util.PGobject".equals(obj.getClass().getCanonicalName())) {
|
||||
String value = ((org.postgresql.util.PGobject) obj).getValue();
|
||||
return value == null ? -1 : utf8String(dbLength, value);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private static int utf8String(int dbLength, String s) {
|
||||
int stringLength = s.length();
|
||||
if (stringLength > dbLength) {
|
||||
return stringLength;
|
||||
} else if (stringLength * 4 <= dbLength) {
|
||||
return -1;
|
||||
} else {
|
||||
return s.getBytes(StandardCharsets.UTF_8).length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard string length implementation.
|
||||
*/
|
||||
final class Standard implements BindMaxLength {
|
||||
|
||||
@Override
|
||||
public long length(int dbLength, Object obj) {
|
||||
if (obj == null) {
|
||||
return -1;
|
||||
} else if (obj instanceof String) {
|
||||
return ((String) obj).length();
|
||||
} else if (obj instanceof byte[]) {
|
||||
return ((byte[]) obj).length;
|
||||
} else if (obj instanceof InputStreamInfo) {
|
||||
return ((InputStreamInfo) obj).length();
|
||||
} else if ("org.postgresql.util.PGobject".equals(obj.getClass().getCanonicalName())) {
|
||||
String value = ((org.postgresql.util.PGobject) obj).getValue();
|
||||
return value == null ? -1 : value.length();
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -63,7 +63,7 @@ class DynamicPropertyAggregationFormula extends DynamicPropertyBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDbLob() {
|
||||
public boolean isLobForPlatform() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -1,10 +1,10 @@
|
||||
package io.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import io.ebean.DatabaseBuilder;
|
||||
import io.ebean.annotation.Cache;
|
||||
import io.ebean.annotation.DocStore;
|
||||
import io.ebean.annotation.DocStoreMode;
|
||||
import io.ebean.annotation.Identity;
|
||||
import io.ebean.DatabaseBuilder;
|
||||
import io.ebean.config.TableName;
|
||||
import io.ebean.config.dbplatform.IdType;
|
||||
import io.ebean.config.dbplatform.PlatformIdGenerator;
|
||||
@@ -21,7 +21,6 @@ import io.ebeaninternal.server.idgen.UuidV1IdGenerator;
|
||||
import io.ebeaninternal.server.idgen.UuidV1RndIdGenerator;
|
||||
import io.ebeaninternal.server.idgen.UuidV4IdGenerator;
|
||||
import io.ebeaninternal.server.rawsql.SpiRawSql;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
|
||||
@@ -139,6 +138,10 @@ public class DeployBeanDescriptor<T> {
|
||||
this.beanType = beanType;
|
||||
}
|
||||
|
||||
public BindMaxLength bindMaxLength() {
|
||||
return manager.bindMaxLength();
|
||||
}
|
||||
|
||||
private String[] readPropertyNames() {
|
||||
try {
|
||||
Field field = beanType.getField("_ebean_props");
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
package io.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import io.avaje.lang.Nullable;
|
||||
import io.ebean.annotation.*;
|
||||
import io.ebean.config.ScalarTypeConverter;
|
||||
import io.ebean.config.dbplatform.DbDefaultValue;
|
||||
import io.ebean.config.dbplatform.DbEncrypt;
|
||||
import io.ebean.config.dbplatform.DbEncryptFunction;
|
||||
import io.ebean.config.dbplatform.ExtraDbTypes;
|
||||
import io.ebean.core.type.ScalarType;
|
||||
import io.ebean.util.AnnotationUtil;
|
||||
import io.ebeaninternal.server.core.InternString;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
import io.ebeaninternal.server.deploy.BindMaxLength;
|
||||
import io.ebeaninternal.server.deploy.DbMigrationInfo;
|
||||
import io.ebeaninternal.server.deploy.DeployDocPropertyOptions;
|
||||
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedProperty;
|
||||
@@ -1133,4 +1136,20 @@ public class DeployBeanProperty {
|
||||
boolean isJsonType() {
|
||||
return mutationDetection != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BindMaxLength bindMaxLength() {
|
||||
if (dbLength == 0) {
|
||||
return null;
|
||||
}
|
||||
switch (dbType) {
|
||||
case Types.VARCHAR:
|
||||
case Types.BLOB:
|
||||
case ExtraDbTypes.JSON:
|
||||
return desc.bindMaxLength();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.BitwiseOp;
|
||||
|
||||
/**
|
||||
@@ -9,7 +8,7 @@ import io.ebeaninternal.server.expression.BitwiseOp;
|
||||
abstract class BaseDbExpression implements DbExpressionHandler {
|
||||
|
||||
@Override
|
||||
public void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
|
||||
public void bitwise(DbExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
|
||||
final String bitOp = bitOp(operator);
|
||||
request.append('(').property(propName).append(' ').append(bitOp).append(" ? ").append(compare).append(" ?)");
|
||||
}
|
||||
@@ -28,7 +27,7 @@ abstract class BaseDbExpression implements DbExpressionHandler {
|
||||
/**
|
||||
* Common alternative where the bitwise operation is a function (specifically bitand is used - H2 and Oracle).
|
||||
*/
|
||||
protected void bitwiseFunction(SpiExpressionRequest request, String propName, BitwiseOp operator, String compare) {
|
||||
protected void bitwiseFunction(DbExpressionRequest request, String propName, BitwiseOp operator, String compare) {
|
||||
final String funcName = functionName(operator);
|
||||
request.append(funcName).append('(').property(propName).append(", ?) ").append(compare).append(" ?");
|
||||
}
|
||||
|
||||
+3
-4
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.Op;
|
||||
|
||||
/**
|
||||
@@ -9,17 +8,17 @@ import io.ebeaninternal.server.expression.Op;
|
||||
class BasicDbExpression extends BaseDbExpression {
|
||||
|
||||
@Override
|
||||
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
public void json(DbExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
throw new RuntimeException("JSON expressions only supported on Postgres and Oracle");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayContains(SpiExpressionRequest request, String propName, boolean contains, Object... values) {
|
||||
public void arrayContains(DbExpressionRequest request, String propName, boolean contains, Object... values) {
|
||||
throw new RuntimeException("ARRAY expressions only supported on Postgres");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty) {
|
||||
public void arrayIsEmpty(DbExpressionRequest request, String propName, boolean empty) {
|
||||
throw new RuntimeException("ARRAY expressions only supported on Postgres");
|
||||
}
|
||||
}
|
||||
|
||||
+4
-5
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.BitwiseOp;
|
||||
import io.ebeaninternal.server.expression.Op;
|
||||
|
||||
@@ -12,22 +11,22 @@ public interface DbExpressionHandler {
|
||||
/**
|
||||
* Write the db platform specific json expression.
|
||||
*/
|
||||
void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value);
|
||||
void json(DbExpressionRequest request, String propName, String path, Op operator, Object value);
|
||||
|
||||
/**
|
||||
* Add SQL for ARRAY CONTAINS expression.
|
||||
*/
|
||||
void arrayContains(SpiExpressionRequest request, String propName, boolean contains, Object... values);
|
||||
void arrayContains(DbExpressionRequest request, String propName, boolean contains, Object... values);
|
||||
|
||||
/**
|
||||
* Add SQL for ARRAY IS EMPTY expression.
|
||||
*/
|
||||
void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty);
|
||||
void arrayIsEmpty(DbExpressionRequest request, String propName, boolean empty);
|
||||
|
||||
/**
|
||||
* Add the bitwise expression.
|
||||
*/
|
||||
void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match);
|
||||
void bitwise(DbExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match);
|
||||
|
||||
/**
|
||||
* Performs a "CONCAT" operation for that platform.
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
/**
|
||||
* Request building the expression sql.
|
||||
*/
|
||||
public interface DbExpressionRequest {
|
||||
|
||||
/**
|
||||
* Append to the expression sql without any parsing.
|
||||
*/
|
||||
DbExpressionRequest append(String expression);
|
||||
|
||||
/**
|
||||
* Append to the expression sql without any parsing.
|
||||
*/
|
||||
DbExpressionRequest append(char c);
|
||||
|
||||
/**
|
||||
* Append to the expression sql with logical property parsing to db columns with logical path prefix.
|
||||
*/
|
||||
DbExpressionRequest property(String expression);
|
||||
}
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.BitwiseOp;
|
||||
|
||||
/**
|
||||
@@ -9,7 +8,7 @@ import io.ebeaninternal.server.expression.BitwiseOp;
|
||||
final class H2DbExpression extends BasicDbExpression {
|
||||
|
||||
@Override
|
||||
public void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
|
||||
public void bitwise(DbExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
|
||||
final String funcName = functionName(operator);
|
||||
request.append(funcName).append('(').property(propName).append(", cast(? as long)) ").append(compare).append(" cast(? as long)");
|
||||
}
|
||||
|
||||
+4
-5
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.BitwiseOp;
|
||||
import io.ebeaninternal.server.expression.Op;
|
||||
|
||||
@@ -10,17 +9,17 @@ import io.ebeaninternal.server.expression.Op;
|
||||
final class HanaDbExpression extends BaseDbExpression {
|
||||
|
||||
@Override
|
||||
public void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
|
||||
public void bitwise(DbExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
|
||||
bitwiseFunction(request, propName, operator, compare);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
public void json(DbExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
request.append("json_value(").property(propName).append(", '$.").append(path).append("')").append(operator.bind());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty) {
|
||||
public void arrayIsEmpty(DbExpressionRequest request, String propName, boolean empty) {
|
||||
request.append("cardinality(").property(propName).append(')');
|
||||
if (empty) {
|
||||
request.append(" = 0");
|
||||
@@ -41,7 +40,7 @@ final class HanaDbExpression extends BaseDbExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayContains(SpiExpressionRequest request, String propName, boolean contains, Object... values) {
|
||||
public void arrayContains(DbExpressionRequest request, String propName, boolean contains, Object... values) {
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (i > 0) {
|
||||
request.append(" and ");
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.Op;
|
||||
|
||||
/**
|
||||
@@ -9,7 +8,7 @@ import io.ebeaninternal.server.expression.Op;
|
||||
final class MariaDbExpression extends BasicDbExpression {
|
||||
|
||||
@Override
|
||||
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
public void json(DbExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
request.append('(').property(propName).append(" ->> '$.").append(path).append("')").append(operator.bind());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.Op;
|
||||
|
||||
/**
|
||||
@@ -9,7 +8,7 @@ import io.ebeaninternal.server.expression.Op;
|
||||
final class MySqlDbExpression extends BasicDbExpression {
|
||||
|
||||
@Override
|
||||
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
public void json(DbExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
request.append('(').property(propName).append(" ->> '$.").append(path).append("')").append(operator.bind());
|
||||
}
|
||||
|
||||
|
||||
+4
-5
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.BitwiseOp;
|
||||
import io.ebeaninternal.server.expression.Op;
|
||||
|
||||
@@ -15,7 +14,7 @@ final class OracleDbExpression extends BaseDbExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
public void json(DbExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
if (operator == Op.EXISTS) {
|
||||
request.append("json_exists(").property(propName).append(", '$.").append(path).append("')");
|
||||
} else if (operator == Op.NOT_EXISTS) {
|
||||
@@ -26,17 +25,17 @@ final class OracleDbExpression extends BaseDbExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
|
||||
public void bitwise(DbExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
|
||||
bitwiseFunction(request, propName, operator, compare);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayContains(SpiExpressionRequest request, String propName, boolean contains, Object... values) {
|
||||
public void arrayContains(DbExpressionRequest request, String propName, boolean contains, Object... values) {
|
||||
throw new IllegalStateException("ARRAY expressions not supported on Oracle");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty) {
|
||||
public void arrayIsEmpty(DbExpressionRequest request, String propName, boolean empty) {
|
||||
throw new IllegalStateException("ARRAY expressions not supported on Oracle");
|
||||
}
|
||||
}
|
||||
|
||||
+3
-4
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.Op;
|
||||
|
||||
/**
|
||||
@@ -14,7 +13,7 @@ final class PostgresDbExpression extends BaseDbExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
public void json(DbExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
String[] paths = path.split("\\.");
|
||||
if (paths.length == 1) {
|
||||
// (t0.content ->> 'title') = 'Some value'
|
||||
@@ -34,7 +33,7 @@ final class PostgresDbExpression extends BaseDbExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayContains(SpiExpressionRequest request, String propName, boolean contains, Object... values) {
|
||||
public void arrayContains(DbExpressionRequest request, String propName, boolean contains, Object... values) {
|
||||
if (!contains) {
|
||||
request.append("not (");
|
||||
}
|
||||
@@ -49,7 +48,7 @@ final class PostgresDbExpression extends BaseDbExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty) {
|
||||
public void arrayIsEmpty(DbExpressionRequest request, String propName, boolean empty) {
|
||||
request.append("coalesce(cardinality(").property(propName).append("),0)");
|
||||
if (empty) {
|
||||
request.append(" = 0");
|
||||
|
||||
+3
-4
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.Op;
|
||||
|
||||
/**
|
||||
@@ -9,19 +8,19 @@ import io.ebeaninternal.server.expression.Op;
|
||||
final class SqlServerDbExpression extends BaseDbExpression {
|
||||
|
||||
@Override
|
||||
public void json(final SpiExpressionRequest request, final String propName,
|
||||
public void json(final DbExpressionRequest request, final String propName,
|
||||
final String path, final Op operator, final Object value) {
|
||||
request.append("json_value(").property(propName).append(", '$.").append(path).append("')").append(operator.bind());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayContains(final SpiExpressionRequest request, final String propName,
|
||||
public void arrayContains(final DbExpressionRequest request, final String propName,
|
||||
final boolean contains, final Object... values) {
|
||||
throw new RuntimeException("ARRAY expressions not supported on Microsoft SQL Server");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayIsEmpty(final SpiExpressionRequest request, final String propName, final boolean empty) {
|
||||
public void arrayIsEmpty(final DbExpressionRequest request, final String propName, final boolean empty) {
|
||||
throw new RuntimeException("ARRAY expressions not supported on Microsoft SQL Server");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,7 +402,13 @@ public final class DJsonContext implements SpiJsonContext {
|
||||
private WriteJson createWriteJson(JsonGenerator gen, JsonWriteOptions options) {
|
||||
FetchPath pathProps = (options == null) ? null : options.getPathProperties();
|
||||
Map<String, JsonWriteBeanVisitor<?>> visitors = (options == null) ? null : options.getVisitorMap();
|
||||
return new WriteJson(server, gen, pathProps, visitors, determineObjectMapper(options), determineInclude(options));
|
||||
return new WriteJson(server,
|
||||
gen,
|
||||
pathProps,
|
||||
visitors,
|
||||
determineObjectMapper(options),
|
||||
determineInclude(options),
|
||||
options == null || options.isIncludeLoadedImplicit());
|
||||
}
|
||||
|
||||
private <T> void toJsonFromCollection(Collection<T> collection, String key, JsonGenerator gen, JsonWriteOptions options) throws IOException {
|
||||
@@ -490,4 +496,5 @@ public final class DJsonContext implements SpiJsonContext {
|
||||
JsonConfig.Include include = options.getInclude();
|
||||
return (include != null) ? include : defaultInclude;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,12 +31,15 @@ public final class WriteJson implements SpiJsonWriter {
|
||||
private final ArrayStack<Object> parentBeans;
|
||||
private final Object objectMapper;
|
||||
private final JsonConfig.Include include;
|
||||
private final boolean includeLoadedImplicit;
|
||||
|
||||
|
||||
/**
|
||||
* Construct for full bean use (normal).
|
||||
*/
|
||||
public WriteJson(SpiEbeanServer server, JsonGenerator generator, FetchPath fetchPath,
|
||||
Map<String, JsonWriteBeanVisitor<?>> visitors, Object objectMapper, JsonConfig.Include include) {
|
||||
Map<String, JsonWriteBeanVisitor<?>> visitors, Object objectMapper, JsonConfig.Include include,
|
||||
boolean includeLoadedImplicit) {
|
||||
|
||||
this.server = server;
|
||||
this.generator = generator;
|
||||
@@ -44,6 +47,7 @@ public final class WriteJson implements SpiJsonWriter {
|
||||
this.visitors = visitors;
|
||||
this.objectMapper = objectMapper;
|
||||
this.include = include;
|
||||
this.includeLoadedImplicit = includeLoadedImplicit;
|
||||
this.parentBeans = new ArrayStack<>();
|
||||
this.pathStack = new PathStack();
|
||||
}
|
||||
@@ -54,6 +58,7 @@ public final class WriteJson implements SpiJsonWriter {
|
||||
public WriteJson(JsonGenerator generator, JsonConfig.Include include) {
|
||||
this.generator = generator;
|
||||
this.include = include;
|
||||
this.includeLoadedImplicit = true;
|
||||
this.visitors = null;
|
||||
this.server = null;
|
||||
this.fetchPath = null;
|
||||
@@ -443,7 +448,7 @@ public final class WriteJson implements SpiJsonWriter {
|
||||
currentIncludeProps = null;
|
||||
}
|
||||
}
|
||||
return new WriteBean(desc, explicitAllProps, currentIncludeProps, bean, visitor);
|
||||
return new WriteBean(desc, explicitAllProps, includeLoadedImplicit, currentIncludeProps, bean, visitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -477,6 +482,7 @@ public final class WriteJson implements SpiJsonWriter {
|
||||
public static class WriteBean {
|
||||
|
||||
final boolean explicitAllProps;
|
||||
final boolean includeLoadedImplicit;
|
||||
final Set<String> currentIncludeProps;
|
||||
final BeanDescriptor<?> desc;
|
||||
final EntityBean currentBean;
|
||||
@@ -485,14 +491,15 @@ public final class WriteJson implements SpiJsonWriter {
|
||||
final JsonWriteBeanVisitor visitor;
|
||||
|
||||
WriteBean(BeanDescriptor<?> desc, EntityBean currentBean, JsonWriteBeanVisitor<?> visitor) {
|
||||
this(desc, false, null, currentBean, visitor);
|
||||
this(desc, false, true, null, currentBean, visitor);
|
||||
}
|
||||
|
||||
WriteBean(BeanDescriptor<?> desc, boolean explicitAllProps, Set<String> currentIncludeProps, EntityBean currentBean, JsonWriteBeanVisitor<?> visitor) {
|
||||
WriteBean(BeanDescriptor<?> desc, boolean explicitAllProps, boolean includeLoadedImplicit, Set<String> currentIncludeProps, EntityBean currentBean, JsonWriteBeanVisitor<?> visitor) {
|
||||
super();
|
||||
this.desc = desc;
|
||||
this.currentBean = currentBean;
|
||||
this.explicitAllProps = explicitAllProps;
|
||||
this.includeLoadedImplicit = includeLoadedImplicit;
|
||||
this.currentIncludeProps = currentIncludeProps;
|
||||
this.visitor = visitor;
|
||||
}
|
||||
@@ -507,9 +514,11 @@ public final class WriteJson implements SpiJsonWriter {
|
||||
if (currentIncludeProps != null) {
|
||||
// explicitly controlled by pathProperties
|
||||
return currentIncludeProps.contains(prop.name());
|
||||
} else {
|
||||
} else if (includeLoadedImplicit){
|
||||
// include only loaded properties
|
||||
return currentBean._ebean_getIntercept().isLoadedProperty(prop.propertyIndex());
|
||||
} else {
|
||||
return prop.isId();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -226,7 +226,7 @@ public final class BatchControl {
|
||||
void executeNow(ArrayList<PersistRequest> list) throws BatchedSqlException {
|
||||
boolean old = transaction.isFlushOnQuery();
|
||||
transaction.setFlushOnQuery(false);
|
||||
// disable flush on query due transsaction callbacks
|
||||
// disable flush on query due transaction callbacks
|
||||
try {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (i % batchSize == 0) {
|
||||
|
||||
@@ -411,7 +411,7 @@ public final class DefaultPersister implements Persister {
|
||||
if (bean._ebean_getIntercept().isUpdate()) {
|
||||
update(bean, t);
|
||||
} else {
|
||||
insert(bean, t);
|
||||
insert(bean, null, t);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -419,12 +419,15 @@ public final class DefaultPersister implements Persister {
|
||||
* Insert this bean.
|
||||
*/
|
||||
@Override
|
||||
public void insert(EntityBean bean, Transaction t) {
|
||||
public void insert(EntityBean bean, InsertOptions insertOptions, Transaction t) {
|
||||
PersistRequestBean<?> req = createRequest(bean, t, PersistRequest.Type.INSERT);
|
||||
if (req.isSkipReference()) {
|
||||
// skip insert on reference bean
|
||||
return;
|
||||
}
|
||||
if (insertOptions != null) {
|
||||
req.setInsertOptions(insertOptions);
|
||||
}
|
||||
try {
|
||||
req.initTransIfRequiredWithBatchCascade();
|
||||
insert(req);
|
||||
|
||||
@@ -172,7 +172,9 @@ final class SaveManyBeans extends SaveManyBase {
|
||||
} else if (ebi.isNewOrDirty()) {
|
||||
skipSavingThisBean = false;
|
||||
// set the parent bean to detailBean
|
||||
many.setJoinValuesToChild(parentBean, detail, mapKeyValue);
|
||||
many.setParentToChild(parentBean, detail, mapKeyValue);
|
||||
} else if (many.setParentToChild(parentBean, detail, mapKeyValue, request.descriptor())) {
|
||||
skipSavingThisBean = false;
|
||||
} else {
|
||||
skipSavingThisBean = saveRecurseSkippable;
|
||||
}
|
||||
@@ -328,7 +330,7 @@ final class SaveManyBeans extends SaveManyBase {
|
||||
}
|
||||
|
||||
private boolean isChangedProperty() {
|
||||
return parentBean._ebean_getIntercept().isChangedProperty(many.propertyIndex());
|
||||
return request.isChangedProperty(many.propertyIndex());
|
||||
}
|
||||
|
||||
private void removeAssocManyOrphans() {
|
||||
|
||||
+9
-1
@@ -1,11 +1,15 @@
|
||||
package io.ebeaninternal.server.persist.dml;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Helper to support the generation of DML statements.
|
||||
*/
|
||||
public final class GenerateDmlRequest {
|
||||
|
||||
private final StringBuilder sb = new StringBuilder(100);
|
||||
private final List<String> columns = new ArrayList<>();
|
||||
private StringBuilder insertBindBuffer;
|
||||
private String prefix;
|
||||
private String prefix2;
|
||||
@@ -26,7 +30,7 @@ public final class GenerateDmlRequest {
|
||||
++bindColumnCount;
|
||||
sb.append(prefix);
|
||||
sb.append(column);
|
||||
//sb.append(expr);
|
||||
columns.add(column);
|
||||
if (insertMode > 0) {
|
||||
if (insertMode++ > 1) {
|
||||
insertBindBuffer.append(',');
|
||||
@@ -75,4 +79,8 @@ public final class GenerateDmlRequest {
|
||||
public boolean isUpdate() {
|
||||
return insertMode == 0;
|
||||
}
|
||||
|
||||
public List<String> columns() {
|
||||
return columns;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ public final class InsertHandler extends DmlHandler {
|
||||
|
||||
SpiTransaction t = persistRequest.transaction();
|
||||
// get the appropriate sql
|
||||
sql = meta.getSql(withId, persistRequest.isPublish());
|
||||
sql = meta.sql(withId, persistRequest.isPublish(), persistRequest.insertOptions());
|
||||
PreparedStatement pstmt;
|
||||
if (persistRequest.isBatched()) {
|
||||
pstmt = pstmtBatch(t, sql, persistRequest, useGeneratedKeys);
|
||||
@@ -134,7 +134,8 @@ public final class InsertHandler extends DmlHandler {
|
||||
if (idValue != null) {
|
||||
persistRequest.setGeneratedKey(idValue);
|
||||
}
|
||||
} else {
|
||||
} else if (persistRequest.insertOptions() == null) {
|
||||
// insert on conflict do nothing can not return generated key
|
||||
throw new PersistenceException("Autoincrement getGeneratedKeys() returned no rows?");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.ebeaninternal.server.persist.dml;
|
||||
|
||||
import io.ebean.InsertOptions;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
@@ -36,9 +37,11 @@ final class InsertMeta {
|
||||
private final Bindable shadowFKey;
|
||||
private final String[] identityDbColumns;
|
||||
private final Platform platform;
|
||||
private final InsertMetaOptions options;
|
||||
|
||||
InsertMeta(DatabasePlatform dbPlatform, BeanDescriptor<?> desc, Bindable shadowFKey, BindableId id, BindableList all) {
|
||||
this.platform = dbPlatform.platform();
|
||||
this.options = InsertMetaPlatform.create(platform, desc, this);
|
||||
this.discriminator = discriminator(desc);
|
||||
this.id = id;
|
||||
this.all = all;
|
||||
@@ -47,8 +50,8 @@ final class InsertMeta {
|
||||
|
||||
String tableName = desc.baseTable();
|
||||
String draftTableName = desc.draftTable();
|
||||
this.sqlWithId = genSql(false, tableName, false);
|
||||
this.sqlDraftWithId = desc.isDraftable() ? genSql(false, draftTableName, true) : sqlWithId;
|
||||
this.sqlWithId = sql(false, tableName, false);
|
||||
this.sqlDraftWithId = desc.isDraftable() ? sql(false, draftTableName, true) : sqlWithId;
|
||||
|
||||
// only available for single Id property
|
||||
if (id.isConcatenated()) {
|
||||
@@ -72,8 +75,8 @@ final class InsertMeta {
|
||||
this.supportsGetGeneratedKeys = dbPlatform.dbIdentity().isSupportsGetGeneratedKeys();
|
||||
this.supportsSelectLastInsertedId = desc.supportsSelectLastInsertedId();
|
||||
}
|
||||
this.sqlNullId = genSql(true, tableName, false);
|
||||
this.sqlDraftNullId = desc.isDraftable() ? genSql(true, draftTableName, true) : sqlNullId;
|
||||
this.sqlNullId = sql(true, tableName, false);
|
||||
this.sqlDraftNullId = desc.isDraftable() ? sql(true, draftTableName, true) : sqlNullId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,9 +140,20 @@ final class InsertMeta {
|
||||
}
|
||||
|
||||
/**
|
||||
* get the sql based whether the id value(s) are null.
|
||||
* Return the sql for the given options.
|
||||
*/
|
||||
public String getSql(boolean withId, boolean publish) {
|
||||
public String sql(boolean withId, boolean publish, InsertOptions insertOptions) {
|
||||
if (insertOptions == null) {
|
||||
return sql(withId, publish);
|
||||
}
|
||||
return options.sql(withId, insertOptions);
|
||||
}
|
||||
|
||||
String sqlFor(boolean withId) {
|
||||
return withId ? sqlWithId : sqlNullId;
|
||||
}
|
||||
|
||||
private String sql(boolean withId, boolean publish) {
|
||||
if (withId) {
|
||||
return publish ? sqlWithId : sqlDraftWithId;
|
||||
} else {
|
||||
@@ -147,12 +161,18 @@ final class InsertMeta {
|
||||
}
|
||||
}
|
||||
|
||||
private String genSql(boolean nullId, String table, boolean draftTable) {
|
||||
private String sql(boolean nullId, String table, boolean draftTable) {
|
||||
GenerateDmlRequest request = new GenerateDmlRequest();
|
||||
sql(request, nullId, table, draftTable);
|
||||
return request.toString();
|
||||
}
|
||||
|
||||
void sql(GenerateDmlRequest request, boolean nullId, String table, boolean draftTable) {
|
||||
request.setInsertSetMode();
|
||||
request.append("insert into ").append(table);
|
||||
if (nullId && noColumnsForInsert(draftTable)) {
|
||||
return request.append(defaultValues()).toString();
|
||||
request.append(defaultValues());
|
||||
return;
|
||||
}
|
||||
request.append(" (");
|
||||
if (!nullId) {
|
||||
@@ -172,7 +192,6 @@ final class InsertMeta {
|
||||
request.append(") values (");
|
||||
request.append(request.insertBindBuffer());
|
||||
request.append(")");
|
||||
return request.toString();
|
||||
}
|
||||
|
||||
private String defaultValues() {
|
||||
@@ -196,5 +215,4 @@ final class InsertMeta {
|
||||
&& discriminator == null
|
||||
&& (draftTable ? all.isEmpty() : allExcludeDraftOnly.isEmpty());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package io.ebeaninternal.server.persist.dml;
|
||||
|
||||
import io.ebean.InsertOptions;
|
||||
|
||||
/**
|
||||
* Generator for insert SQL with options.
|
||||
*/
|
||||
interface InsertMetaOptions {
|
||||
|
||||
/**
|
||||
* Generate the SQL for the given insert options.
|
||||
*/
|
||||
String sql(boolean withId, InsertOptions insertOptions);
|
||||
}
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
package io.ebeaninternal.server.persist.dml;
|
||||
|
||||
import io.ebean.InsertOptions;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Postgres specific generation of insert on conflict.
|
||||
*/
|
||||
final class InsertMetaOptionsPostgres implements InsertMetaOptions {
|
||||
|
||||
private final InsertMeta meta;
|
||||
private final BeanDescriptor<?> desc;
|
||||
private final String baseTable;
|
||||
private final Map<String, String> sqlCache = new ConcurrentHashMap<>();
|
||||
|
||||
InsertMetaOptionsPostgres(InsertMeta meta, BeanDescriptor<?> desc) {
|
||||
this.meta = meta;
|
||||
this.desc = desc;
|
||||
this.baseTable = desc.baseTable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sql(boolean withId, InsertOptions options) {
|
||||
String key = withId + options.key();
|
||||
return sqlCache.computeIfAbsent(key, k -> generate(withId, options));
|
||||
}
|
||||
|
||||
private String generate(boolean withId, InsertOptions options) {
|
||||
char type = options.key().charAt(0);
|
||||
switch (type) {
|
||||
case 'U':
|
||||
return generate(withId, false, options);
|
||||
case 'N':
|
||||
return generate(withId, true, options);
|
||||
default:
|
||||
return meta.sqlFor(withId);
|
||||
}
|
||||
}
|
||||
|
||||
private String generate(boolean withId, boolean doNothing, InsertOptions options) {
|
||||
GenerateDmlRequest request = new GenerateDmlRequest();
|
||||
meta.sql(request, !withId, baseTable, false);
|
||||
request.append(" on conflict ");
|
||||
|
||||
List<String> uniqueColumns = desc.uniqueProps().stream()
|
||||
.flatMap(Arrays::stream)
|
||||
.map(BeanProperty::dbColumn)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
String constraintName = options.constraint();
|
||||
if (constraintName != null) {
|
||||
request.append("on constraint ").append(constraintName);
|
||||
} else {
|
||||
request.append("(");
|
||||
String cols = options.uniqueColumns();
|
||||
if (cols != null) {
|
||||
request.append(cols);
|
||||
} else {
|
||||
appendUniqueColumns(uniqueColumns, request);
|
||||
}
|
||||
request.append(")");
|
||||
}
|
||||
if (doNothing) {
|
||||
request.append(" do nothing");
|
||||
return request.toString();
|
||||
}
|
||||
request.append(" do update set ");
|
||||
String updateSet = options.updateSet();
|
||||
if (updateSet != null) {
|
||||
request.append(updateSet);
|
||||
} else {
|
||||
setColumns(withId, request, uniqueColumns);
|
||||
}
|
||||
return request.toString();
|
||||
}
|
||||
|
||||
private void setColumns(boolean withId, GenerateDmlRequest request, List<String> uniqueColumns) {
|
||||
List<String> columns = request.columns();
|
||||
columns.removeAll(uniqueColumns);
|
||||
if (withId) {
|
||||
BeanProperty idProperty = desc.idProperty();
|
||||
if (idProperty != null && !idProperty.isEmbedded()) {
|
||||
columns.remove(idProperty.dbColumn());
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < columns.size(); i++) {
|
||||
if (i > 0) {
|
||||
request.append(", ");
|
||||
}
|
||||
String col = columns.get(i);
|
||||
request.append(col).append("=excluded.").append(col);
|
||||
}
|
||||
}
|
||||
|
||||
private static void appendUniqueColumns(List<String> uniqueColumns, GenerateDmlRequest request) {
|
||||
if (uniqueColumns.isEmpty()) {
|
||||
throw new IllegalStateException("Unable to identify unique columns for INSERT ON CONFLICT - Add mapping like @Column(unique=true) or @Index(unique=true)");
|
||||
}
|
||||
for (int i = 0; i < uniqueColumns.size(); i++) {
|
||||
if (i > 0) {
|
||||
request.append(", ");
|
||||
}
|
||||
request.append(uniqueColumns.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package io.ebeaninternal.server.persist.dml;
|
||||
|
||||
import io.ebean.InsertOptions;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
|
||||
final class InsertMetaPlatform {
|
||||
|
||||
private static final NotSupported NOT_SUPPORTED = new NotSupported();
|
||||
|
||||
static InsertMetaOptions create(Platform platform, BeanDescriptor<?> desc, InsertMeta meta) {
|
||||
switch (platform.base()) {
|
||||
case POSTGRES:
|
||||
case YUGABYTE:
|
||||
case COCKROACH:
|
||||
return new InsertMetaOptionsPostgres(meta, desc);
|
||||
default:
|
||||
return NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
static final class NotSupported implements InsertMetaOptions {
|
||||
@Override
|
||||
public String sql(boolean withId, InsertOptions insertOptions) {
|
||||
throw new UnsupportedOperationException("InsertOptions not supported on this database platform");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -186,7 +186,7 @@ public final class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfi
|
||||
this.queryMode = query.mode();
|
||||
this.loadContextBean = queryMode.isLoadContextBean() || query.getForUpdateLockType() != null;
|
||||
this.lazyLoadManyProperty = query.lazyLoadMany();
|
||||
this.readOnly = request.isReadOnly();
|
||||
this.readOnly = query.isReadOnly();
|
||||
this.disableLazyLoading = query.isDisableLazyLoading();
|
||||
this.objectGraphNode = query.parentNode();
|
||||
this.profilingListener = query.profilingListener();
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package io.ebeaninternal.server.query;
|
||||
|
||||
import io.ebean.CountDistinctOrder;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.RawSql;
|
||||
import io.ebean.RawSqlBuilder;
|
||||
import io.ebean.*;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.config.dbplatform.SqlLimitRequest;
|
||||
@@ -52,11 +49,13 @@ final class CQueryBuilder {
|
||||
private final CQueryDraftSupport draftSupport;
|
||||
private final DatabasePlatform dbPlatform;
|
||||
private final boolean selectCountWithColumnAlias;
|
||||
private final boolean includeLabelInSql;
|
||||
|
||||
/**
|
||||
* Create the SqlGenSelect.
|
||||
*/
|
||||
CQueryBuilder(DatabasePlatform dbPlatform, Binder binder, CQueryHistorySupport historySupport, CQueryDraftSupport draftSupport) {
|
||||
CQueryBuilder(DatabaseBuilder.Settings config, DatabasePlatform dbPlatform, Binder binder, CQueryHistorySupport historySupport, CQueryDraftSupport draftSupport) {
|
||||
this.includeLabelInSql = config.isIncludeLabelInSql();
|
||||
this.dbPlatform = dbPlatform;
|
||||
this.binder = binder;
|
||||
this.draftSupport = draftSupport;
|
||||
@@ -596,7 +595,7 @@ final class CQueryBuilder {
|
||||
}
|
||||
|
||||
private void appendSelectDistinct() {
|
||||
sb.append("select ");
|
||||
sb.append("select ").append(hint()).append(inlineSqlComment());
|
||||
if (distinct && !countSingleAttribute) {
|
||||
if (request.isInlineCountDistinct()) {
|
||||
sb.append("count(");
|
||||
@@ -609,6 +608,30 @@ final class CQueryBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
private String hint() {
|
||||
String hint = query.hint();
|
||||
return hint == null ? "" : dbPlatform.inlineSqlHint(hint);
|
||||
}
|
||||
|
||||
private String inlineSqlComment() {
|
||||
if (!includeLabelInSql) {
|
||||
return "";
|
||||
}
|
||||
SpiQuery.Type type = query.type();
|
||||
if (type == SpiQuery.Type.SQ_EX || type == SpiQuery.Type.SQ_EXISTS) {
|
||||
return "";
|
||||
}
|
||||
final var label = query.label();
|
||||
if (label != null) {
|
||||
return dbPlatform.inlineSqlComment(label);
|
||||
}
|
||||
final var profileLocation = query.profileLocation();
|
||||
if (profileLocation != null) {
|
||||
return dbPlatform.inlineSqlComment(profileLocation.label());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private void appendFrom() {
|
||||
if (selectClause == null || !selectClause.startsWith("update")) {
|
||||
sb.append(" from ");
|
||||
|
||||
@@ -44,7 +44,7 @@ public final class CQueryEngine {
|
||||
this.defaultFetchSizeFindList = config.getJdbcFetchSizeFindList();
|
||||
this.forwardOnlyHintOnFindIterate = dbPlatform.forwardOnlyHintOnFindIterate();
|
||||
this.historySupport = new CQueryHistorySupport(dbPlatform.historySupport(), asOfTableMapping, config.getAsOfSysPeriod());
|
||||
this.queryBuilder = new CQueryBuilder(dbPlatform, binder, historySupport, new CQueryDraftSupport(draftTableMap));
|
||||
this.queryBuilder = new CQueryBuilder(config, dbPlatform, binder, historySupport, new CQueryDraftSupport(draftTableMap));
|
||||
}
|
||||
|
||||
public int forwardOnlyFetchSize() {
|
||||
@@ -74,6 +74,9 @@ public final class CQueryEngine {
|
||||
if (request.logSql()) {
|
||||
request.logSql("{0}; --bind({1}) --micros({2}) --rows({3})", query.generatedSql(), query.bindLog(), query.micros(), rows);
|
||||
}
|
||||
if (rows > 0) {
|
||||
request.clearContext();
|
||||
}
|
||||
return rows;
|
||||
} catch (SQLException e) {
|
||||
throw translate(request, query.bindLog(), query.generatedSql(), e);
|
||||
|
||||
@@ -61,6 +61,7 @@ final class CQueryUpdate implements SpiProfileTransactionEvent, CancelableQuery
|
||||
/**
|
||||
* Execute the update or delete statement returning the row count.
|
||||
*/
|
||||
@SuppressWarnings("resource")
|
||||
public int execute() throws SQLException {
|
||||
long startNano = System.nanoTime();
|
||||
try {
|
||||
@@ -109,6 +110,7 @@ final class CQueryUpdate implements SpiProfileTransactionEvent, CancelableQuery
|
||||
pstmt = null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("resource")
|
||||
@Override
|
||||
public void profile() {
|
||||
transaction()
|
||||
|
||||
@@ -133,6 +133,11 @@ final class DefaultFetchGroupQuery<T> implements SpiFetchGroupQuery<T>, SpiQuery
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> setHint(String hint) {
|
||||
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
|
||||
}
|
||||
|
||||
// Everything else deemed invalid
|
||||
|
||||
@Override
|
||||
@@ -305,6 +310,11 @@ final class DefaultFetchGroupQuery<T> implements SpiFetchGroupQuery<T>, SpiQuery
|
||||
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <A> Optional<A> findSingleAttributeOrEmpty() {
|
||||
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCountDistinct() {
|
||||
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
|
||||
|
||||
@@ -51,6 +51,10 @@ public final class DefaultOrmQueryEngine implements OrmQueryEngine {
|
||||
* Flushes the jdbc batch by default unless explicitly turned off on the transaction.
|
||||
*/
|
||||
private <T> void flushJdbcBatchOnQuery(OrmQueryRequest<T> request) {
|
||||
if (request.query().isUsingFuture()) {
|
||||
// future queries never invoke a flush
|
||||
return;
|
||||
}
|
||||
SpiTransaction t = request.transaction();
|
||||
if (t.isFlushOnQuery()) {
|
||||
// before we perform a query, we need to flush any
|
||||
|
||||
@@ -33,7 +33,7 @@ public interface STreeProperty extends ScalarDataReader<Object> {
|
||||
/**
|
||||
* Returns true, if this is a lob property from db-perspective.
|
||||
*/
|
||||
boolean isDbLob();
|
||||
boolean isLobForPlatform();
|
||||
|
||||
/**
|
||||
* Return true if the property is an embedded type.
|
||||
|
||||
@@ -48,7 +48,7 @@ public final class SqlTreeBuilder {
|
||||
private final SpiQuery.TemporalMode temporalMode;
|
||||
private SqlTreeNode rootNode;
|
||||
private boolean sqlDistinct;
|
||||
private final boolean distinctNoLobs;
|
||||
private final boolean platformDistinctNoLobs;
|
||||
private final SqlTreeCommon common;
|
||||
|
||||
/**
|
||||
@@ -63,7 +63,7 @@ public final class SqlTreeBuilder {
|
||||
this.query = null;
|
||||
this.subQuery = false;
|
||||
this.distinctOnPlatform = false;
|
||||
this.distinctNoLobs = false;
|
||||
this.platformDistinctNoLobs = false;
|
||||
this.queryDetail = queryDetail;
|
||||
this.predicates = predicates;
|
||||
this.temporalMode = SpiQuery.TemporalMode.CURRENT;
|
||||
@@ -98,7 +98,7 @@ public final class SqlTreeBuilder {
|
||||
this.predicates = predicates;
|
||||
this.alias = new SqlTreeAlias(request.baseTableAlias(), temporalMode);
|
||||
this.distinctOnPlatform = builder.isPlatformDistinctOn();
|
||||
this.distinctNoLobs = builder.isPlatformDistinctNoLobs();
|
||||
this.platformDistinctNoLobs = builder.isPlatformDistinctNoLobs();
|
||||
String fromForUpdate = builder.fromForUpdate(query);
|
||||
CQueryHistorySupport historySupport = builder.historySupport(query);
|
||||
CQueryDraftSupport draftSupport = builder.draftSupport(query);
|
||||
@@ -269,8 +269,8 @@ public final class SqlTreeBuilder {
|
||||
if (joinList != null) {
|
||||
joinList.add(selectNode);
|
||||
}
|
||||
if (sqlDistinct && distinctNoLobs) {
|
||||
selectNode.unselectLobs();
|
||||
if (sqlDistinct && platformDistinctNoLobs) {
|
||||
selectNode.unselectLobsForPlatform();
|
||||
}
|
||||
return selectNode;
|
||||
}
|
||||
|
||||
@@ -82,6 +82,6 @@ interface SqlTreeNode {
|
||||
/**
|
||||
* Unselect lobs (for distinct queries on DB2 and Oracle).
|
||||
*/
|
||||
default void unselectLobs() {
|
||||
default void unselectLobsForPlatform() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,16 +379,16 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
|
||||
|
||||
@Override
|
||||
public void unselectLobs() {
|
||||
public void unselectLobsForPlatform() {
|
||||
if (children != null) {
|
||||
for (SqlTreeNode child : children) {
|
||||
child.unselectLobs();
|
||||
child.unselectLobsForPlatform();
|
||||
}
|
||||
}
|
||||
if (hasLob()) {
|
||||
List<STreeProperty> lst = new ArrayList<>();
|
||||
for (STreeProperty prop : properties) {
|
||||
if (!prop.isDbLob()) {
|
||||
if (!prop.isLobForPlatform()) {
|
||||
lst.add(prop);
|
||||
}
|
||||
}
|
||||
@@ -399,7 +399,7 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
|
||||
private boolean hasLob() {
|
||||
for (STreeProperty prop : properties) {
|
||||
if (prop.isDbLob()) {
|
||||
if (prop.isLobForPlatform()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,10 @@ import io.ebeaninternal.api.*;
|
||||
import io.ebeaninternal.server.dto.DtoBeanDescriptor;
|
||||
import io.ebeaninternal.server.dto.DtoMappingRequest;
|
||||
import io.ebeaninternal.server.dto.DtoQueryPlan;
|
||||
import io.ebeaninternal.server.transaction.ExternalJdbcTransaction;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.sql.Connection;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@@ -86,6 +88,12 @@ public final class DefaultDtoQuery<T> extends AbstractQuery implements SpiDtoQue
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DtoQuery<T> usingConnection(Connection connection) {
|
||||
this.transaction = new ExternalJdbcTransaction(connection);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DtoQuery<T> usingMaster() {
|
||||
this.useMaster = true;
|
||||
@@ -242,6 +250,9 @@ public final class DefaultDtoQuery<T> extends AbstractQuery implements SpiDtoQue
|
||||
@Override
|
||||
public DtoQuery<T> setLabel(String label) {
|
||||
this.label = label;
|
||||
if (ormQuery != null) {
|
||||
ormQuery.setLabel(label);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,7 +57,9 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
private ProfilingListener profilingListener;
|
||||
private Type type;
|
||||
private String label;
|
||||
private String hint;
|
||||
private Mode mode = Mode.NORMAL;
|
||||
private boolean usingFuture;
|
||||
private Object tenantId;
|
||||
/**
|
||||
* Holds query in structured form.
|
||||
@@ -234,6 +236,11 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String hint() {
|
||||
return hint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String planLabel() {
|
||||
if (label != null) {
|
||||
@@ -257,6 +264,12 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Query<T> setHint(String hint) {
|
||||
this.hint = hint;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isAutoTunable() {
|
||||
return nativeSql == null && beanDescriptor.isAutoTunable();
|
||||
@@ -731,6 +744,7 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
copy.timeout = timeout;
|
||||
copy.mapKey = mapKey;
|
||||
copy.id = id;
|
||||
copy.hint = hint;
|
||||
copy.label = label;
|
||||
copy.nativeSql = nativeSql;
|
||||
copy.useBeanCache = useBeanCache;
|
||||
@@ -971,6 +985,16 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void usingFuture() {
|
||||
this.usingFuture = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isUsingFuture() {
|
||||
return usingFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isUsageProfiling() {
|
||||
return usageProfiling;
|
||||
@@ -1058,6 +1082,9 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
if (manualId) {
|
||||
sb.append("/md");
|
||||
}
|
||||
if (hint != null) {
|
||||
sb.append("/h:").append(hint);
|
||||
}
|
||||
if (distinct) {
|
||||
sb.append("/dt");
|
||||
}
|
||||
@@ -1161,7 +1188,7 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
// add the rawSql statement - if any
|
||||
if (orderByIsEmpty()) {
|
||||
if (rawSql != null && rawSql.getSql() != null) {
|
||||
order(rawSql.getSql().getOrderBy());
|
||||
orderBy(rawSql.getSql().getOrderBy());
|
||||
}
|
||||
}
|
||||
if (checkPagingOrderBy()) {
|
||||
@@ -1517,7 +1544,6 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public final <A> List<A> findSingleAttributeList() {
|
||||
return server.findSingleAttributeList(this);
|
||||
}
|
||||
@@ -1533,6 +1559,11 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
return !list.isEmpty() ? list.get(0) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <A> Optional<A> findSingleAttributeOrEmpty() {
|
||||
return Optional.ofNullable(findSingleAttribute());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final T findOne() {
|
||||
return server.findOne(this);
|
||||
|
||||
@@ -7,7 +7,9 @@ import io.ebeaninternal.api.BindParams;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.api.SpiSqlQuery;
|
||||
import io.ebeaninternal.api.SpiTransaction;
|
||||
import io.ebeaninternal.server.transaction.ExternalJdbcTransaction;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
@@ -50,6 +52,12 @@ public final class DefaultRelationalQuery extends AbstractQuery implements SpiSq
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlQuery usingConnection(Connection connection) {
|
||||
this.transaction = new ExternalJdbcTransaction(connection);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlQuery usingMaster() {
|
||||
this.useMaster = true;
|
||||
|
||||
@@ -2,12 +2,13 @@ package io.ebeaninternal.server.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EmptyStackException;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Stack based on ArrayList.
|
||||
*/
|
||||
public class ArrayStack<E> {
|
||||
public class ArrayStack<E> implements Iterable<E> {
|
||||
|
||||
private final List<E> list;
|
||||
|
||||
@@ -89,4 +90,9 @@ public class ArrayStack<E> {
|
||||
public boolean contains(E o) {
|
||||
return list.contains(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return list.iterator();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,27 @@ public class OrmQueryPlanKeyTest extends BaseTest {
|
||||
assertSame(query().createQueryPlanKey(), query().createQueryPlanKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_hintIsDifferent_expect_different() {
|
||||
DefaultOrmQuery<Customer> q1 = query();
|
||||
q1.setHint("a");
|
||||
assertDifferent(q1, query());
|
||||
|
||||
DefaultOrmQuery<Customer> q2 = query();
|
||||
q2.setHint("b");
|
||||
assertDifferent(q1, q2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_hintIsSame() {
|
||||
DefaultOrmQuery<Customer> q1 = query();
|
||||
q1.setHint("b");
|
||||
DefaultOrmQuery<Customer> q2 = query();
|
||||
q2.setHint("b");
|
||||
|
||||
assertSame(q1, q2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffTableJoinNull() {
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean ddl generation</name>
|
||||
@@ -28,14 +28,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-all</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean postgis types</name>
|
||||
<artifactId>ebean-postgis-types</artifactId>
|
||||
|
||||
<properties>
|
||||
<postgis.jdbc.version>2021.1.0</postgis.jdbc.version>
|
||||
<postgis.jdbc.version>2.5.1</postgis.jdbc.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -19,14 +19,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- provided scope -->
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.6.0</version>
|
||||
<version>42.7.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>13.25.1-jakarta</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@ package io.ebean.postgis;
|
||||
|
||||
import io.ebean.core.type.DataBinder;
|
||||
import io.ebeaninternal.server.type.GeoTypeBinder;
|
||||
import net.postgis.jdbc.PGgeometryLW;
|
||||
import net.postgis.jdbc.geometry.Geometry;
|
||||
import org.geolatte.geom.codec.Wkt;
|
||||
import org.postgis.Geometry;
|
||||
import org.postgis.PGgeometryLW;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
@@ -18,15 +18,15 @@ class PostgisGeoTypeBinder implements GeoTypeBinder {
|
||||
|
||||
@Override
|
||||
public void bind(DataBinder binder, int dataType, Object data) throws SQLException {
|
||||
if (data instanceof Geometry) {
|
||||
binder.setObject(new PGgeometryLW((Geometry) data));
|
||||
} else if (withGeolatte) {
|
||||
binder.setObject(new PGgeometryLW(toWktString(data)));
|
||||
}
|
||||
if (data instanceof Geometry) {
|
||||
binder.setObject(new PGgeometryLW((Geometry) data));
|
||||
} else if (withGeolatte) {
|
||||
binder.setObject(new PGgeometryLW(toWktString(data)));
|
||||
}
|
||||
}
|
||||
|
||||
private String toWktString(Object data) {
|
||||
org.geolatte.geom.Geometry<?> geoLatte = (org.geolatte.geom.Geometry<?>) data;
|
||||
org.geolatte.geom.Geometry<?> geoLatte = (org.geolatte.geom.Geometry<?>)data;
|
||||
return Wkt.newEncoder(Wkt.Dialect.POSTGIS_EWKT_1).encode(geoLatte);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user