mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
78
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ccaa824e0 | ||
|
|
d6e46b15a3 | ||
|
|
bab9be0228 | ||
|
|
9331050a43 | ||
|
|
9bcd189730 | ||
|
|
428365ceb9 | ||
|
|
76c889c6d9 | ||
|
|
9e4007d25a | ||
|
|
9d7754b92d | ||
|
|
3c80032063 | ||
|
|
7dae937491 | ||
|
|
6ce5e865ca | ||
|
|
b0d8fa0286 | ||
|
|
83c85adbde | ||
|
|
a1b51fd8ef | ||
|
|
bcc4034371 | ||
|
|
3dde07fc9f | ||
|
|
87ada9e999 | ||
|
|
ea55f25d44 | ||
|
|
2231f723f8 | ||
|
|
7c16694d4b | ||
|
|
ea60ff47cf | ||
|
|
1f7912dab6 | ||
|
|
ec0c00eb72 | ||
|
|
dd99e32cc6 | ||
|
|
1decbe0152 | ||
|
|
d58e3d023f | ||
|
|
1598b40c36 | ||
|
|
66ef667a0a | ||
|
|
e821d66268 | ||
|
|
b8e164e04c | ||
|
|
9097466a7b | ||
|
|
99604d8ec3 | ||
|
|
95d37fc3dc | ||
|
|
76d85adc98 | ||
|
|
2f233db465 | ||
|
|
1ca73ca6aa | ||
|
|
d5e4c13fa8 | ||
|
|
b5ac31838c | ||
|
|
e3e9412eea | ||
|
|
d3427876b7 | ||
|
|
4b2976e31b | ||
|
|
5720ee65b3 | ||
|
|
7f441ce72e | ||
|
|
83e87b0c67 | ||
|
|
578feac87f | ||
|
|
42a64e715d | ||
|
|
12a3a180f4 | ||
|
|
8acd5bcb39 | ||
|
|
eb71756c65 | ||
|
|
8c8cadd471 | ||
|
|
222c49c59b | ||
|
|
1e860112e6 | ||
|
|
ffc21daaba | ||
|
|
f9adcb2c5a | ||
|
|
d051bba71f | ||
|
|
f414f04033 | ||
|
|
ac466ecd79 | ||
|
|
262a7f9bab | ||
|
|
bb02d74005 | ||
|
|
e9b2b8d266 | ||
|
|
fc16bde227 | ||
|
|
d1775dfcc4 | ||
|
|
3d5937f6da | ||
|
|
adca8cd8fa | ||
|
|
6d30e6310b | ||
|
|
79ed0a5f8e | ||
|
|
94b3a020d5 | ||
|
|
3e241907e6 | ||
|
|
c4af1d9b23 | ||
|
|
7702169762 | ||
|
|
8209d9e229 | ||
|
|
664120f369 | ||
|
|
e952b555e0 | ||
|
|
d99c50da75 | ||
|
|
d4bec166f7 | ||
|
|
63a23904ac | ||
|
|
1807fc201e |
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-clickhouse</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -41,13 +41,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-clickhouse</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-cockroach</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -41,13 +41,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-db2</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -41,13 +41,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-db2</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-h2</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -41,13 +41,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-hana</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -41,13 +41,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-hana</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-mariadb</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -41,13 +41,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-mariadb</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-mysql</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -41,13 +41,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-mysql</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-nuodb</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -41,13 +41,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-nuodb</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-oracle</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -41,13 +41,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-oracle</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-postgres</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -41,13 +41,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-sqlite</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -41,13 +41,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlite</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-sqlserver</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -41,13 +41,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlserver</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-yugabyte</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -41,13 +41,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean (all platforms)</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -40,7 +40,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-mapper</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -59,13 +59,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-all</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>composites</artifactId>
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean api</name>
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.service.SpiInTuples;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Default implementation of SpiInTuples.
|
||||
*/
|
||||
final class DInTuples implements SpiInTuples {
|
||||
|
||||
private final String[] properties;
|
||||
private final int propertyCount;
|
||||
private final List<Object[]> entries = new ArrayList<>();
|
||||
|
||||
|
||||
DInTuples(String[] properties) {
|
||||
this.properties = properties;
|
||||
this.propertyCount = properties.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InTuples add(Object... values) {
|
||||
if (values.length != propertyCount) {
|
||||
throw new IllegalArgumentException("Require " + propertyCount + " values but got " + values.length);
|
||||
}
|
||||
entries.add(values);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first property name.
|
||||
*/
|
||||
@Override
|
||||
public String[] properties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the value pairs.
|
||||
*/
|
||||
@Override
|
||||
public List<Object[]> entries() {
|
||||
return Collections.unmodifiableList(entries);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -38,12 +38,15 @@ final class DbContext {
|
||||
}
|
||||
}
|
||||
} catch (BeanNotEnhancedException e) {
|
||||
String msg = "Bean is not enhanced? See https://ebean.io/docs/trouble-shooting#not-enhanced";
|
||||
log.log(ERROR, msg, e);
|
||||
throw e;
|
||||
|
||||
} catch (DataSourceConfigurationException e) {
|
||||
String msg = "Configuration error creating DataSource for the default Database." +
|
||||
" This typically means a missing application-test.yaml or missing ebean-test dependency." +
|
||||
" See https://ebean.io/docs/trouble-shooting#datasource";
|
||||
log.log(ERROR, msg, e);
|
||||
throw new DataSourceConfigurationException(msg, e);
|
||||
|
||||
} catch (Throwable e) {
|
||||
|
||||
@@ -205,4 +205,16 @@ public interface DtoQuery<T> extends CancelableQuery {
|
||||
* Use the explicit transaction to execute the query.
|
||||
*/
|
||||
DtoQuery<T> usingTransaction(Transaction transaction);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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
|
||||
* against the master data source.
|
||||
*/
|
||||
DtoQuery<T> usingMaster();
|
||||
}
|
||||
|
||||
@@ -369,6 +369,11 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
Expression inPairs(Pairs pairs);
|
||||
|
||||
/**
|
||||
* In expression using multiple columns.
|
||||
*/
|
||||
Expression inTuples(InTuples pairs);
|
||||
|
||||
/**
|
||||
* In - property has a value in the array of values.
|
||||
*/
|
||||
|
||||
@@ -1131,6 +1131,11 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> inPairs(Pairs pairs);
|
||||
|
||||
/**
|
||||
* In expression using multiple columns.
|
||||
*/
|
||||
ExpressionList<T> inTuples(InTuples pairs);
|
||||
|
||||
/**
|
||||
* EXISTS a raw SQL SubQuery.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package io.ebean;
|
||||
|
||||
/**
|
||||
* IN expression using multiple columns.
|
||||
* <p>
|
||||
* Currently this is not supported with SQLServer or DB2.
|
||||
* <p>
|
||||
* Produces SQL expression in the form of (A,B,C) IN ((a0,b0,c0), (a1,b1,c1), ... )
|
||||
* where A,B,C are the properties in the tuples.
|
||||
*/
|
||||
public interface InTuples {
|
||||
|
||||
/**
|
||||
* Create given the properties in the tuples.
|
||||
*/
|
||||
static InTuples of(String... properties) {
|
||||
return new DInTuples(properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create given the properties in the tuples.
|
||||
*/
|
||||
static InTuples of(Query.Property<?>... properties) {
|
||||
String[] props = new String[properties.length];
|
||||
for (int i = 0; i < properties.length; i++) {
|
||||
props[i] = properties[i].toString();
|
||||
}
|
||||
return new DInTuples(props);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a tuple entry. All values must be non-null.
|
||||
*/
|
||||
InTuples add(Object... values);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package io.ebean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Helper methods for Lists.
|
||||
*/
|
||||
public final class Lists {
|
||||
|
||||
private Lists() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Partition the source List into sub-lists with a maximum size.
|
||||
* <p>
|
||||
* The sub-lists will all be the max size except for the last sub-list
|
||||
* which can potentially be smaller.
|
||||
*
|
||||
* @param source The source list
|
||||
* @param max The max size of each partition
|
||||
* @param <T> The list element type
|
||||
* @return List of sub-list partitions
|
||||
*/
|
||||
public static <T> List<List<T>> partition(List<T> source, int max) {
|
||||
final int totalCount = source.size();
|
||||
if (totalCount <= max) {
|
||||
return List.of(source);
|
||||
}
|
||||
final int numOfPartitions = (totalCount + max - 1) / max; // round up
|
||||
final var dest = new ArrayList<List<T>>(numOfPartitions);
|
||||
for (int i = 0; i < numOfPartitions; i++) {
|
||||
final int from = i * max;
|
||||
final int to = Math.min(from + max, totalCount);
|
||||
dest.add(source.subList(from, to));
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,14 @@ import io.avaje.lang.NonNullApi;
|
||||
import io.avaje.lang.Nullable;
|
||||
|
||||
import javax.persistence.NonUniqueResultException;
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
@@ -670,6 +672,16 @@ public interface Query<T> extends CancelableQuery {
|
||||
*/
|
||||
Query<T> apply(FetchPath fetchPath);
|
||||
|
||||
/**
|
||||
* Apply changes to the query conditional on the supplied predicate.
|
||||
* <p>
|
||||
* Typically, the changes are extra predicates etc.
|
||||
*
|
||||
* @param predicate The predicate which when true the changes are applied
|
||||
* @param apply The changes to apply to the query
|
||||
*/
|
||||
Query<T> alsoIf(BooleanSupplier predicate, Consumer<Query<T>> apply);
|
||||
|
||||
/**
|
||||
* Execute the query using the given transaction.
|
||||
*/
|
||||
@@ -685,6 +697,18 @@ public interface Query<T> extends CancelableQuery {
|
||||
*/
|
||||
Query<T> usingDatabase(Database database);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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
|
||||
* against the master data source.
|
||||
*/
|
||||
Query<T> usingMaster();
|
||||
|
||||
/**
|
||||
* Execute the query returning the list of Id's.
|
||||
* <p>
|
||||
|
||||
@@ -45,6 +45,18 @@ public interface SqlQuery extends Serializable, CancelableQuery {
|
||||
*/
|
||||
SqlQuery usingTransaction(Transaction transaction);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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
|
||||
* against the master data source.
|
||||
*/
|
||||
SqlQuery usingMaster();
|
||||
|
||||
/**
|
||||
* Execute the query returning a list.
|
||||
*/
|
||||
|
||||
@@ -135,7 +135,7 @@ public class DbConstraintNaming {
|
||||
*/
|
||||
protected String joinColumnNames(String[] columns) {
|
||||
if (columns.length == 1) {
|
||||
return normaliseColumn(columns[0]);
|
||||
return normaliseColumn(columns[0]).replace(" ", "_");
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package io.ebean.service;
|
||||
|
||||
import io.ebean.InTuples;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Internal extension to InTuples.
|
||||
*/
|
||||
public interface SpiInTuples extends InTuples {
|
||||
|
||||
/**
|
||||
* Return the properties of the tuples.
|
||||
*/
|
||||
String[] properties();
|
||||
|
||||
/**
|
||||
* Return all the tuple entries.
|
||||
*/
|
||||
List<Object[]> entries();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package io.ebean;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class ListsTest {
|
||||
|
||||
@Test
|
||||
void partition_empty() {
|
||||
List<List<Integer>> partitions = Lists.partition(List.of(), 5);
|
||||
assertThat(partitions).hasSize(1);
|
||||
assertThat(partitions.get(0)).hasSize(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void partition_lt() {
|
||||
List<List<Integer>> partitions = Lists.partition(List.of(1, 2, 3, 4), 5);
|
||||
assertThat(partitions).hasSize(1);
|
||||
assertThat(partitions.get(0)).hasSize(4);
|
||||
}
|
||||
|
||||
@Test
|
||||
void partition_eq() {
|
||||
List<List<Integer>> partitions = Lists.partition(List.of(1, 2, 3, 4, 5), 5);
|
||||
assertThat(partitions).hasSize(1);
|
||||
assertThat(partitions.get(0)).hasSize(5);
|
||||
}
|
||||
|
||||
@Test
|
||||
void partition_gt() {
|
||||
List<List<Integer>> partitions = Lists.partition(List.of(1, 2, 3, 4, 5, 6), 5);
|
||||
assertThat(partitions).hasSize(2);
|
||||
assertThat(partitions.get(0)).hasSize(5);
|
||||
assertThat(partitions.get(1)).hasSize(1);
|
||||
assertThat(partitions.get(0)).containsExactly(1, 2, 3, 4, 5);
|
||||
assertThat(partitions.get(1)).containsExactly(6);
|
||||
}
|
||||
|
||||
@Test
|
||||
void partition_gt1_letters() {
|
||||
var partitions = Lists.partition(List.of("a", "b", "c", "d"), 3);
|
||||
assertThat(partitions).hasSize(2);
|
||||
assertThat(partitions.get(0)).hasSize(3);
|
||||
assertThat(partitions.get(1)).hasSize(1);
|
||||
assertThat(partitions.get(0)).containsExactly("a", "b", "c");
|
||||
assertThat(partitions.get(1)).containsExactly("d");
|
||||
}
|
||||
|
||||
@Test
|
||||
void partition_gt1a_letters() {
|
||||
var partitions = Lists.partition(List.of("a", "b", "c", "d", "e"), 3);
|
||||
assertThat(partitions).hasSize(2);
|
||||
assertThat(partitions.get(0)).hasSize(3);
|
||||
assertThat(partitions.get(1)).hasSize(2);
|
||||
assertThat(partitions.get(0)).containsExactly("a", "b", "c");
|
||||
assertThat(partitions.get(1)).containsExactly("d", "e");
|
||||
}
|
||||
|
||||
@Test
|
||||
void partition_eq2_letters() {
|
||||
var partitions = Lists.partition(List.of("a", "b", "c", "d", "e", "f"), 3);
|
||||
assertThat(partitions).hasSize(2);
|
||||
assertThat(partitions.get(0)).hasSize(3);
|
||||
assertThat(partitions.get(1)).hasSize(3);
|
||||
assertThat(partitions.get(0)).containsExactly("a", "b", "c");
|
||||
assertThat(partitions.get(1)).containsExactly("d", "e", "f");
|
||||
}
|
||||
|
||||
@Test
|
||||
void partition_gt2_letters() {
|
||||
var partitions = Lists.partition(List.of("a", "b", "c", "d", "e", "f", "g"), 3);
|
||||
assertThat(partitions).hasSize(3);
|
||||
assertThat(partitions.get(0)).hasSize(3);
|
||||
assertThat(partitions.get(1)).hasSize(3);
|
||||
assertThat(partitions.get(2)).hasSize(1);
|
||||
assertThat(partitions.get(0)).containsExactly("a", "b", "c");
|
||||
assertThat(partitions.get(1)).containsExactly("d", "e", "f");
|
||||
assertThat(partitions.get(2)).containsExactly("g");
|
||||
}
|
||||
}
|
||||
+25
-25
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean bom</name>
|
||||
@@ -89,25 +89,25 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -125,13 +125,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-mapper</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -155,46 +155,46 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>kotlin-querybean-generator</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-redis</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-spring-txn</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- platforms -->
|
||||
@@ -202,67 +202,67 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-clickhouse</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-db2</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-h2</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-hana</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-mariadb</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-mysql</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-nuodb</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-oracle</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgres</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-sqlite</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-sqlserver</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
@@ -16,7 +16,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
+6
-6
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core</artifactId>
|
||||
@@ -22,7 +22,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -46,7 +46,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -159,21 +159,21 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlserver</artifactId>
|
||||
<version>13.20.1-SNAPSHOT</version>
|
||||
<version>13.21.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -5,6 +5,11 @@ package io.ebeaninternal.api;
|
||||
*/
|
||||
public interface CQueryPlanKey {
|
||||
|
||||
/**
|
||||
* Return true if the query plan should be cached.
|
||||
*/
|
||||
boolean useCache();
|
||||
|
||||
/**
|
||||
* Used by read audit such that we can log read audit entries without the full sql
|
||||
* (which would make the read audit logs verbose).
|
||||
|
||||
@@ -135,8 +135,9 @@ public interface SpiEbeanServer extends SpiServer, ExtendedServer, BeanCollectio
|
||||
* Create a ServerTransaction for query purposes.
|
||||
*
|
||||
* @param tenantId For multi-tenant lazy loading provide the tenantId to use.
|
||||
* @param useMaster Set to true when the query should use the master data source.
|
||||
*/
|
||||
SpiTransaction createReadOnlyTransaction(Object tenantId);
|
||||
SpiTransaction createReadOnlyTransaction(Object tenantId, boolean useMaster);
|
||||
|
||||
/**
|
||||
* An event from another server in the cluster used to notify local
|
||||
|
||||
@@ -31,6 +31,11 @@ public interface SpiExpressionRequest {
|
||||
*/
|
||||
SpiOrmQueryRequest<?> queryRequest();
|
||||
|
||||
/**
|
||||
* Return the underling buffer.
|
||||
*/
|
||||
StringBuilder buffer();
|
||||
|
||||
/**
|
||||
* Append to the expression sql without any parsing.
|
||||
*/
|
||||
|
||||
@@ -235,6 +235,11 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
|
||||
*/
|
||||
String planLabel();
|
||||
|
||||
/**
|
||||
* Return true if this query should not use the read only data source.
|
||||
*/
|
||||
boolean isUseMaster();
|
||||
|
||||
/**
|
||||
* Return true if this is a "find by id" query. This includes a check for a single "equal to" expression for the Id.
|
||||
*/
|
||||
|
||||
@@ -5,6 +5,11 @@ package io.ebeaninternal.api;
|
||||
*/
|
||||
public interface SpiSqlBinding extends SpiCancelableQuery {
|
||||
|
||||
/**
|
||||
* Return true if this query should not use the read only data source.
|
||||
*/
|
||||
boolean isUseMaster();
|
||||
|
||||
/**
|
||||
* Return the named or positioned parameters.
|
||||
*/
|
||||
|
||||
@@ -48,7 +48,7 @@ public abstract class AbstractSqlQueryRequest implements CancelableQuery {
|
||||
transaction = server.currentServerTransaction();
|
||||
if (transaction == null || !transaction.isActive()) {
|
||||
// create a local readOnly transaction
|
||||
transaction = server.createReadOnlyTransaction(null);
|
||||
transaction = server.createReadOnlyTransaction(null, query.isUseMaster());
|
||||
createdTransaction = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ final class DefaultBeanLoader {
|
||||
query.setLoadDescription("+lazy", null);
|
||||
}
|
||||
|
||||
query.select(parentDesc.idBinder().getIdProperty());
|
||||
query.select(parentDesc.idBinder().idSelect());
|
||||
if (onlyIds) {
|
||||
query.fetch(many.name(), many.targetIdProperty());
|
||||
} else {
|
||||
@@ -137,7 +137,7 @@ final class DefaultBeanLoader {
|
||||
private List<?> executeQuery(LoadRequest loadRequest, SpiQuery<?> query) {
|
||||
if (onIterateUseExtraTxn && loadRequest.isParentFindIterate()) {
|
||||
// MySql - we need a different transaction to execute the secondary query
|
||||
SpiTransaction extraTxn = server.createReadOnlyTransaction(query.tenantId());
|
||||
SpiTransaction extraTxn = server.createReadOnlyTransaction(query.tenantId(), query.isUseMaster());
|
||||
try {
|
||||
return server.findList(query, extraTxn);
|
||||
} finally {
|
||||
|
||||
@@ -2123,8 +2123,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiTransaction createReadOnlyTransaction(Object tenantId) {
|
||||
return transactionManager.createReadOnlyTransaction(tenantId);
|
||||
public SpiTransaction createReadOnlyTransaction(Object tenantId, boolean useMaster) {
|
||||
return transactionManager.createReadOnlyTransaction(tenantId, useMaster);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+4
-2
@@ -56,7 +56,10 @@ final class MultiTenantDbCatalogSupplier implements DataSourceSupplier {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection readOnlyConnection(Object tenantId) throws SQLException {
|
||||
public Connection readOnlyConnection(Object tenantId, boolean useMaster) throws SQLException {
|
||||
if (readOnly == null || useMaster) {
|
||||
return catalogDataSource.getConnectionForTenant(tenantId);
|
||||
}
|
||||
return readOnly.getConnectionForTenant(tenantId);
|
||||
}
|
||||
|
||||
@@ -103,7 +106,6 @@ final class MultiTenantDbCatalogSupplier implements DataSourceSupplier {
|
||||
*/
|
||||
@Override
|
||||
public Connection getConnection() throws SQLException {
|
||||
|
||||
Connection connection = dataSource.getConnection();
|
||||
connection.setCatalog(tenantCatalog());
|
||||
return connection;
|
||||
|
||||
+6
-3
@@ -56,8 +56,12 @@ final class MultiTenantDbSchemaSupplier implements DataSourceSupplier {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection readOnlyConnection(Object tenantId) throws SQLException {
|
||||
return readOnly.getConnectionForTenant(tenantId);
|
||||
public Connection readOnlyConnection(Object tenantId, boolean useMaster) throws SQLException {
|
||||
if (readOnly == null || useMaster) {
|
||||
return schemaDataSource.getConnectionForTenant(tenantId);
|
||||
} else {
|
||||
return readOnly.getConnectionForTenant(tenantId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -106,7 +110,6 @@ final class MultiTenantDbSchemaSupplier implements DataSourceSupplier {
|
||||
*/
|
||||
@Override
|
||||
public Connection getConnection() throws SQLException {
|
||||
|
||||
Connection connection = dataSource.getConnection();
|
||||
connection.setSchema(tenantSchema());
|
||||
return connection;
|
||||
|
||||
@@ -43,8 +43,8 @@ final class MultiTenantDbSupplier implements DataSourceSupplier {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection readOnlyConnection(Object tenantId) throws SQLException {
|
||||
throw new SQLException("Not currently supported");
|
||||
public Connection readOnlyConnection(Object tenantId, boolean useMaster) throws SQLException {
|
||||
return dataSourceProvider.dataSource(tenantId).getConnection();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -220,7 +220,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
} else {
|
||||
// create an implicit transaction to execute this query
|
||||
// potentially using read-only DataSource with autoCommit
|
||||
transaction = server.createReadOnlyTransaction(query.tenantId());
|
||||
transaction = server.createReadOnlyTransaction(query.tenantId(), query.isUseMaster());
|
||||
}
|
||||
createdTransaction = true;
|
||||
}
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ public final class PersistDeferredRelationship {
|
||||
return; // could not bind: TODO: should we log/throw an error?
|
||||
}
|
||||
// bind the where clause for the bean
|
||||
Object[] idValues = beanDescriptor.idBinder().getIdValues(bean);
|
||||
Object[] idValues = beanDescriptor.idBinder().values(bean);
|
||||
for (int j = 0; j < idValues.length; j++) {
|
||||
sqlUpdate.setParameter(pos + j, idValues[j]);
|
||||
}
|
||||
|
||||
@@ -41,8 +41,12 @@ final class SimpleDataSourceProvider implements DataSourceSupplier {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection readOnlyConnection(Object tenantId) throws SQLException {
|
||||
return readOnlyDataSource.getConnection();
|
||||
public Connection readOnlyConnection(Object tenantId, boolean useMaster) throws SQLException {
|
||||
if (readOnlyDataSource == null || useMaster) {
|
||||
return dataSource.getConnection();
|
||||
} else {
|
||||
return readOnlyDataSource.getConnection();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -212,7 +212,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
private final EntityBean prototypeEntityBean;
|
||||
|
||||
private final IdBinder idBinder;
|
||||
private final String idSelect;
|
||||
private String idBinderInLHSSql;
|
||||
private String idBinderIdSql;
|
||||
private String deleteByIdSql;
|
||||
@@ -355,23 +354,11 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
propertiesIndex[i] = propMap.get(ebi.property(i));
|
||||
}
|
||||
}
|
||||
idSelect = initIdSelect();
|
||||
}
|
||||
|
||||
String initIdSelect() {
|
||||
if (idProperty != null && !idProperty.name().equals("_idClass")) {
|
||||
return idProperty.name();
|
||||
} else if (entityType == EntityType.EMBEDDED) {
|
||||
return null;
|
||||
} else {
|
||||
StringJoiner sj = new StringJoiner(",");
|
||||
for (BeanProperty prop : propertiesNonMany) {
|
||||
if (prop.isImportedPrimaryKey()) {
|
||||
sj.add(prop.name());
|
||||
}
|
||||
}
|
||||
return sj.toString().intern();
|
||||
}
|
||||
public String idSelect() {
|
||||
if (idBinder == null) throw new UnsupportedOperationException();
|
||||
return idBinder.idSelect();
|
||||
}
|
||||
|
||||
public boolean isJacksonCorePresent() {
|
||||
@@ -543,10 +530,10 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
unidirectional.initialise(initContext);
|
||||
}
|
||||
idBinder.initialise();
|
||||
idBinderInLHSSql = idBinder.getBindIdInSql(baseTableAlias);
|
||||
idBinderIdSql = idBinder.getBindIdSql(baseTableAlias);
|
||||
String idBinderInLHSSqlNoAlias = idBinder.getBindIdInSql(null);
|
||||
String idEqualsSql = idBinder.getBindIdSql(null);
|
||||
idBinderInLHSSql = idBinder.bindInSql(baseTableAlias);
|
||||
idBinderIdSql = idBinder.bindEqSql(baseTableAlias);
|
||||
String idBinderInLHSSqlNoAlias = idBinder.bindInSql(null);
|
||||
String idEqualsSql = idBinder.bindEqSql(null);
|
||||
deleteByIdSql = "delete from " + baseTable + " where " + idEqualsSql;
|
||||
whereIdInSql = " where " + idBinderInLHSSqlNoAlias + " ";
|
||||
deleteByIdInSql = "delete from " + baseTable + whereIdInSql;
|
||||
@@ -868,10 +855,10 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
private SqlUpdate deleteByIdList(List<Object> idList, DeleteMode mode) {
|
||||
String baseSql = mode.isHard() ? deleteByIdInSql : softDeleteByIdInSql;
|
||||
StringBuilder sb = new StringBuilder(baseSql);
|
||||
String inClause = idBinder.getIdInValueExprDelete(idList.size());
|
||||
String inClause = idBinder.idInValueExprDelete(idList.size());
|
||||
sb.append(inClause);
|
||||
DefaultSqlUpdate delete = new DefaultSqlUpdate(sb.toString());
|
||||
idBinder.addIdInBindValues(delete, idList);
|
||||
idBinder.addBindValues(delete, idList);
|
||||
return delete;
|
||||
}
|
||||
|
||||
@@ -882,7 +869,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
private SqlUpdate deleteById(Object id, DeleteMode mode) {
|
||||
String baseSql = mode.isHard() ? deleteByIdSql : softDeleteByIdSql;
|
||||
DefaultSqlUpdate sqlDelete = new DefaultSqlUpdate(baseSql);
|
||||
Object[] bindValues = idBinder.getBindValues(id);
|
||||
Object[] bindValues = idBinder.bindValues(id);
|
||||
for (Object bindValue : bindValues) {
|
||||
sqlDelete.setParameter(bindValue);
|
||||
}
|
||||
@@ -1516,7 +1503,9 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
}
|
||||
|
||||
public void queryPlan(CQueryPlanKey key, CQueryPlan plan) {
|
||||
queryPlanCache.put(key, plan);
|
||||
if (key.useCache()) {
|
||||
queryPlanCache.put(key, plan);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1537,7 +1526,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
* Return a Sql update statement to set the importedId value (deferred execution).
|
||||
*/
|
||||
public String updateImportedIdSql(ImportedId prop) {
|
||||
return "update " + baseTable + " set " + prop.importedIdClause() + " where " + idBinder.getBindIdSql(null);
|
||||
return "update " + baseTable + " set " + prop.importedIdClause() + " where " + idBinder.bindEqSql(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1631,7 +1620,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
* Return a raw expression for 'where parent id in ...' clause.
|
||||
*/
|
||||
String parentIdInExpr(int parentIdSize, String rawWhere) {
|
||||
String inClause = idBinder.getIdInValueExpr(false, parentIdSize);
|
||||
String inClause = idBinder.idInValueExpr(false, parentIdSize);
|
||||
return idBinder.isIdInExpandedForm() ? inClause : rawWhere + inClause;
|
||||
}
|
||||
|
||||
@@ -1684,7 +1673,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
if (alias == null) {
|
||||
return idBinderIdSql;
|
||||
} else {
|
||||
return idBinder.getBindIdSql(alias);
|
||||
return idBinder.bindEqSql(alias);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1710,7 +1699,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
* This 'flattens' any EmbeddedId or multiple Id property cases.
|
||||
*/
|
||||
public Object[] bindIdValues(Object idValue) {
|
||||
return idBinder.getBindValues(idValue);
|
||||
return idBinder.bindValues(idValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2118,7 +2107,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
* The usage is to provide simple id types for JSON processing (for embeddedId's).
|
||||
*/
|
||||
public Object idForJson(Object bean) {
|
||||
return idBinder.getIdForJson((EntityBean) bean);
|
||||
return idBinder.convertForJson((EntityBean) bean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2127,7 +2116,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
* The usage is to provide simple id types for JSON processing (for embeddedId's).
|
||||
*/
|
||||
Object convertIdFromJson(Object idValue) {
|
||||
return idBinder.convertIdFromJson(idValue);
|
||||
return idBinder.convertFromJson(idValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2135,7 +2124,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
* included in the query.
|
||||
*/
|
||||
public String defaultOrderBy() {
|
||||
return idBinder.getDefaultOrderBy();
|
||||
return idBinder.orderBy();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2450,9 +2439,13 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
|
||||
BeanProperty _findBeanProperty(String propName) {
|
||||
BeanProperty prop = propMap.get(propName);
|
||||
if (prop == null && inheritInfo != null) {
|
||||
// search in sub types...
|
||||
return inheritInfo.findSubTypeProperty(propName);
|
||||
if (prop == null) {
|
||||
if ("_$IdClass$".equals(propName)) {
|
||||
return idProperty;
|
||||
} else if (inheritInfo != null) {
|
||||
// search in sub types...
|
||||
return inheritInfo.findSubTypeProperty(propName);
|
||||
}
|
||||
}
|
||||
return prop;
|
||||
}
|
||||
@@ -3057,10 +3050,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
return idProperty;
|
||||
}
|
||||
|
||||
public String idSelect() {
|
||||
return idSelect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this bean should be inserted rather than updated.
|
||||
*
|
||||
|
||||
@@ -23,11 +23,6 @@ abstract class BeanDescriptorElement<T> extends BeanDescriptor<T> {
|
||||
this.elementHelp = elementHelp;
|
||||
}
|
||||
|
||||
@Override
|
||||
String initIdSelect() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private String shortName(String name) {
|
||||
int pos = name.lastIndexOf('.');
|
||||
if (pos > 1) {
|
||||
|
||||
@@ -518,7 +518,7 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
|
||||
IdBinder idBinder = d.idBinder();
|
||||
if (idBinder instanceof IdBinderEmbedded) {
|
||||
IdBinderEmbedded embId = (IdBinderEmbedded) idBinder;
|
||||
BeanDescriptor<?> idBeanDescriptor = embId.getIdBeanDescriptor();
|
||||
BeanDescriptor<?> idBeanDescriptor = embId.descriptor();
|
||||
Class<?> idType = idBeanDescriptor.type();
|
||||
try {
|
||||
idType.getDeclaredMethod("hashCode");
|
||||
|
||||
@@ -456,7 +456,8 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
@Override
|
||||
public void appendFrom(DbSqlContext ctx, SqlJoinType joinType, String manyWhere) {
|
||||
if (formula && sqlFormulaJoin != null) {
|
||||
ctx.appendFormulaJoin(sqlFormulaJoin, joinType, manyWhere);
|
||||
String alias = ctx.tableAliasManyWhere(manyWhere);
|
||||
ctx.appendFormulaJoin(sqlFormulaJoin, joinType, alias);
|
||||
} else if (secondaryTableJoin != null) {
|
||||
String relativePrefix = ctx.relativePrefix(secondaryTableJoinPrefix);
|
||||
secondaryTableJoin.addJoin(joinType, relativePrefix, ctx);
|
||||
|
||||
@@ -122,7 +122,7 @@ public abstract class BeanPropertyAssoc<T> extends BeanProperty implements STree
|
||||
targetInheritInfo = targetDescriptor.inheritInfo();
|
||||
saveRecurseSkippable = targetDescriptor.isSaveRecurseSkippable();
|
||||
if (!targetIdBinder.isComplexId()) {
|
||||
targetIdProperty = targetIdBinder.getIdProperty();
|
||||
targetIdProperty = targetIdBinder.idSelect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,7 +458,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
*/
|
||||
@Override
|
||||
public Object[] assocIdValues(EntityBean bean) {
|
||||
return targetDescriptor.idBinder().getIdValues(bean);
|
||||
return targetDescriptor.idBinder().values(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -466,7 +466,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
*/
|
||||
@Override
|
||||
public String assocIdExpression(String prefix, String operator) {
|
||||
return targetDescriptor.idBinder().getAssocOneIdExpr(prefix, operator);
|
||||
return targetDescriptor.idBinder().assocExpr(prefix, operator);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -474,7 +474,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
*/
|
||||
@Override
|
||||
public String assocIdInValueExpr(boolean not, int size) {
|
||||
return targetDescriptor.idBinder().getIdInValueExpr(not, size);
|
||||
return targetDescriptor.idBinder().idInValueExpr(not, size);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -482,7 +482,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
*/
|
||||
@Override
|
||||
public String assocIdInExpr(String prefix) {
|
||||
return targetDescriptor.idBinder().getAssocIdInExpr(prefix);
|
||||
return targetDescriptor.idBinder().assocInExpr(prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+99
-67
@@ -21,13 +21,15 @@ class BeanPropertyAssocManySqlHelp<T> {
|
||||
private final String deleteByParentIdSql;
|
||||
private final String deleteByParentIdInSql;
|
||||
private final String elementCollectionInsertSql;
|
||||
private final boolean idInExpandedForm;
|
||||
|
||||
BeanPropertyAssocManySqlHelp(BeanPropertyAssocMany<T> many, ExportedProperty[] exportedProperties) {
|
||||
this.many = many;
|
||||
this.exportedProperties = exportedProperties;
|
||||
this.hasJoinTable = many.hasJoinTable();
|
||||
this.descriptor = many.descriptor();
|
||||
this.exportedPropertyBindProto = deriveExportedPropertyBindProto();
|
||||
this.exportedPropertyBindProto = initExportedBindProto();
|
||||
this.idInExpandedForm = descriptor.idBinder().isIdInExpandedForm();
|
||||
|
||||
String delStmt;
|
||||
if (hasJoinTable) {
|
||||
@@ -35,8 +37,8 @@ class BeanPropertyAssocManySqlHelp<T> {
|
||||
} else {
|
||||
delStmt = "delete from " + many.targetTable() + " where ";
|
||||
}
|
||||
deleteByParentIdSql = delStmt + deriveWhereParentIdSql(false, "");
|
||||
deleteByParentIdInSql = delStmt + deriveWhereParentIdSql(true, "");
|
||||
deleteByParentIdSql = delStmt + rawParentIdEQ("");
|
||||
deleteByParentIdInSql = delStmt;
|
||||
if (many.isElementCollection()) {
|
||||
elementCollectionInsertSql = elementCollectionInsert();
|
||||
} else {
|
||||
@@ -45,7 +47,7 @@ class BeanPropertyAssocManySqlHelp<T> {
|
||||
}
|
||||
|
||||
private String elementCollectionInsert() {
|
||||
StringBuilder sb = new StringBuilder(200);
|
||||
final StringBuilder sb = new StringBuilder(200);
|
||||
sb.append("insert into ").append(many.targetTable()).append(" (");
|
||||
append(sb);
|
||||
|
||||
@@ -54,7 +56,7 @@ class BeanPropertyAssocManySqlHelp<T> {
|
||||
sb.append(") values (");
|
||||
appendBind(sb, exportedProperties.length, true);
|
||||
appendBind(sb, cols.colCount, false);
|
||||
sb.append(")");
|
||||
sb.append(')');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@@ -73,7 +75,7 @@ class BeanPropertyAssocManySqlHelp<T> {
|
||||
|
||||
@Override
|
||||
public void visitEmbeddedScalar(BeanProperty p, BeanPropertyAssocOne<?> embedded) {
|
||||
sb.append(",").append(p.dbColumn());
|
||||
sb.append(',').append(p.dbColumn());
|
||||
colCount++;
|
||||
}
|
||||
|
||||
@@ -96,14 +98,14 @@ class BeanPropertyAssocManySqlHelp<T> {
|
||||
|
||||
String lazyFetchOrderBy(String fetchOrderBy) {
|
||||
// derive lazyFetchOrderBy
|
||||
StringBuilder sb = new StringBuilder(50);
|
||||
final String fkTableAlias = hasJoinTable ? "int_" : "t0";
|
||||
final var sb = new StringBuilder(50);
|
||||
for (int i = 0; i < exportedProperties.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(", ");
|
||||
}
|
||||
// these fk columns are either on the intersection (int_) or base table (t0)
|
||||
String fkTableAlias = hasJoinTable ? "int_" : "t0";
|
||||
sb.append(fkTableAlias).append(".").append(exportedProperties[i].getForeignDbColumn());
|
||||
sb.append(fkTableAlias).append('.').append(exportedProperties[i].getForeignDbColumn());
|
||||
}
|
||||
sb.append(", ").append(fetchOrderBy);
|
||||
return sb.toString().trim();
|
||||
@@ -113,56 +115,50 @@ class BeanPropertyAssocManySqlHelp<T> {
|
||||
* Add a where clause to the query for a given list of parent Id's.
|
||||
*/
|
||||
void addWhereParentIdIn(SpiQuery<?> query, List<Object> parentIds) {
|
||||
String tableAlias = hasJoinTable ? "int_." : "t0.";
|
||||
final String tableAlias = hasJoinTable ? "int_." : "t0.";
|
||||
if (hasJoinTable) {
|
||||
query.setM2MIncludeJoin(many.inverseJoin);
|
||||
}
|
||||
String rawWhere = deriveWhereParentIdSql(true, tableAlias);
|
||||
String expr = descriptor.parentIdInExpr(parentIds.size(), rawWhere);
|
||||
many.bindParentIdsIn(expr, parentIds, query);
|
||||
final String rawWhere = rawParentIdIN(tableAlias, parentIds.size());
|
||||
many.bindParentIdsIn(rawWhere, parentIds, query);
|
||||
}
|
||||
|
||||
List<Object> findIdsByParentId(Object parentId, Transaction t, List<Object> excludeDetailIds, boolean hard) {
|
||||
String rawWhere = deriveWhereParentIdSql(false, "");
|
||||
SpiEbeanServer server = descriptor.ebeanServer();
|
||||
SpiQuery<?> q = many.newQuery(server);
|
||||
many.bindParentIdEq(rawWhere, parentId, q);
|
||||
final SpiEbeanServer server = descriptor.ebeanServer();
|
||||
final SpiQuery<?> query = many.newQuery(server);
|
||||
many.bindParentIdEq(rawParentIdEQ(""), parentId, query);
|
||||
if (hard) {
|
||||
q.setIncludeSoftDeletes();
|
||||
query.setIncludeSoftDeletes();
|
||||
}
|
||||
if (excludeDetailIds != null && !excludeDetailIds.isEmpty()) {
|
||||
q.where().not(q.getExpressionFactory().idIn(excludeDetailIds));
|
||||
query.where().not(query.getExpressionFactory().idIn(excludeDetailIds));
|
||||
}
|
||||
return server.findIds(q, t);
|
||||
return server.findIds(query, t);
|
||||
}
|
||||
|
||||
List<Object> findIdsByParentIdList(List<Object> parentIds, Transaction t, List<Object> excludeDetailIds, boolean hard) {
|
||||
String rawWhere = deriveWhereParentIdSql(true, "");
|
||||
String inClause = buildInClauseBinding(parentIds.size(), exportedPropertyBindProto);
|
||||
String expr = rawWhere + inClause;
|
||||
|
||||
SpiEbeanServer server = descriptor.ebeanServer();
|
||||
SpiQuery<?> q = many.newQuery(server);
|
||||
//Query<?> q = server.find(propertyType);
|
||||
many.bindParentIdsIn(expr, parentIds, q);
|
||||
final SpiEbeanServer server = descriptor.ebeanServer();
|
||||
final SpiQuery<?> query = many.newQuery(server);
|
||||
many.bindParentIdsIn(rawParentIdIN("", parentIds.size()), parentIds, query);
|
||||
if (hard) {
|
||||
q.setIncludeSoftDeletes();
|
||||
query.setIncludeSoftDeletes();
|
||||
}
|
||||
if (excludeDetailIds != null && !excludeDetailIds.isEmpty()) {
|
||||
q.where().not(q.getExpressionFactory().idIn(excludeDetailIds));
|
||||
query.where().not(query.getExpressionFactory().idIn(excludeDetailIds));
|
||||
}
|
||||
return server.findIds(q, t);
|
||||
return server.findIds(query, t);
|
||||
}
|
||||
|
||||
SpiSqlUpdate deleteByParentId(Object parentId) {
|
||||
DefaultSqlUpdate sqlDelete = new DefaultSqlUpdate(deleteByParentIdSql);
|
||||
final var sqlDelete = new DefaultSqlUpdate(deleteByParentIdSql);
|
||||
many.bindParentId(sqlDelete, parentId);
|
||||
return sqlDelete;
|
||||
}
|
||||
|
||||
SpiSqlUpdate deleteByParentIdList(List<Object> parentIds) {
|
||||
String sql = Str.add(deleteByParentIdInSql, buildInClauseBinding(parentIds.size(), exportedPropertyBindProto));
|
||||
DefaultSqlUpdate delete = new DefaultSqlUpdate(sql);
|
||||
final String rawWhere = rawParentIdIN("", parentIds.size());
|
||||
final String sql = Str.add(deleteByParentIdInSql, rawWhere);
|
||||
final var delete = new DefaultSqlUpdate(sql);
|
||||
many.bindParentIds(delete, parentIds);
|
||||
return delete;
|
||||
}
|
||||
@@ -172,71 +168,107 @@ class BeanPropertyAssocManySqlHelp<T> {
|
||||
if (!skipComma || i > 0) {
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append("?");
|
||||
sb.append('?');
|
||||
}
|
||||
}
|
||||
|
||||
private void append(StringBuilder sb) {
|
||||
for (int i = 0; i < exportedProperties.length; i++) {
|
||||
String fkColumn = exportedProperties[i].getForeignDbColumn();
|
||||
if (i > 0) {
|
||||
sb.append(",");
|
||||
sb.append(',');
|
||||
}
|
||||
sb.append(fkColumn);
|
||||
sb.append(exportedProperties[i].getForeignDbColumn());
|
||||
}
|
||||
}
|
||||
|
||||
private String deriveWhereParentIdSql(boolean inClause, String tableAlias) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (inClause) {
|
||||
sb.append("(");
|
||||
private String rawParentIdIN(String tableAlias, int size) {
|
||||
if (idInExpandedForm) {
|
||||
return rawParentIdExpanded(tableAlias, size);
|
||||
} else {
|
||||
return rawParentIdStandard(tableAlias, size);
|
||||
}
|
||||
}
|
||||
|
||||
private String rawParentIdStandard(String tableAlias, int size) {
|
||||
if (descriptor.isSimpleId()) {
|
||||
return rawParentIdMultiBinder(tableAlias, size);
|
||||
}
|
||||
final var sb = new StringBuilder(100 + size * exportedPropertyBindProto.length());
|
||||
sb.append('(');
|
||||
for (int i = 0; i < exportedProperties.length; i++) {
|
||||
String fkColumn = exportedProperties[i].getForeignDbColumn();
|
||||
if (i > 0) {
|
||||
sb.append(inClause ? "," : " and ");
|
||||
sb.append(',');
|
||||
}
|
||||
sb.append(tableAlias).append(fkColumn);
|
||||
if (!inClause) {
|
||||
sb.append("=? ");
|
||||
}
|
||||
}
|
||||
if (inClause) {
|
||||
sb.append(")");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String buildInClauseBinding(int size, String bindProto) {
|
||||
if (descriptor.isSimpleId()) {
|
||||
return descriptor.idBinder().getIdInValueExpr(false, size);
|
||||
}
|
||||
StringBuilder sb = new StringBuilder(10 + (size * (bindProto.length() + 1)));
|
||||
sb.append(" in");
|
||||
sb.append(" (");
|
||||
sb.append(") in (");
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(",");
|
||||
sb.append(',');
|
||||
}
|
||||
sb.append(bindProto);
|
||||
sb.append(exportedPropertyBindProto);
|
||||
}
|
||||
sb.append(") ");
|
||||
sb.append(')');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String deriveExportedPropertyBindProto() {
|
||||
/**
|
||||
* Potentially a MultiValue binder like Postgres ANY Array binding.
|
||||
*/
|
||||
private String rawParentIdMultiBinder(String tableAlias, int size) {
|
||||
final String property = '(' + tableAlias + exportedProperties[0].getForeignDbColumn() + ')';
|
||||
final String inValueExpr = descriptor.idBinder().idInValueExpr(false, size);
|
||||
return property + inValueExpr;
|
||||
}
|
||||
|
||||
private String rawParentIdExpanded(String tableAlias, int size) {
|
||||
final String proto = parentIdExpandedProto(tableAlias);
|
||||
final var result = new StringBuilder(size * (proto.length() + 2) + 10).append('(');
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (i > 0) {
|
||||
result.append(" or ");
|
||||
}
|
||||
result.append(proto);
|
||||
}
|
||||
return result.append(')').toString();
|
||||
}
|
||||
|
||||
private String parentIdExpandedProto(String tableAlias) {
|
||||
final var sb = new StringBuilder(60).append('(');
|
||||
for (int i = 0; i < exportedProperties.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(" and ");
|
||||
}
|
||||
sb.append(tableAlias).append(exportedProperties[i].getForeignDbColumn()).append("=?");
|
||||
}
|
||||
return sb.append(')').toString();
|
||||
}
|
||||
|
||||
private String rawParentIdEQ(String tableAlias) {
|
||||
final var sb = new StringBuilder(80);
|
||||
for (int i = 0; i < exportedProperties.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(" and ");
|
||||
}
|
||||
sb.append(tableAlias).append(exportedProperties[i].getForeignDbColumn()).append("=?");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String initExportedBindProto() {
|
||||
if (exportedProperties.length == 1) {
|
||||
return "?";
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
final var sb = new StringBuilder(exportedProperties.length * 2 + 2);
|
||||
sb.append("(");
|
||||
for (int i = 0; i < exportedProperties.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(",");
|
||||
sb.append(',');
|
||||
}
|
||||
sb.append("?");
|
||||
sb.append('?');
|
||||
}
|
||||
sb.append(")");
|
||||
sb.append(')');
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
@@ -246,7 +246,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
}
|
||||
|
||||
private SqlUpdate deleteByParentIdList(List<Object> parentIds) {
|
||||
String sql = deleteByParentIdInSql + targetIdBinder.getIdInValueExpr(false, parentIds.size());
|
||||
String sql = deleteByParentIdInSql + targetIdBinder.idInValueExpr(false, parentIds.size());
|
||||
DefaultSqlUpdate delete = new DefaultSqlUpdate(sql);
|
||||
bindParentIds(delete, parentIds);
|
||||
return delete;
|
||||
@@ -276,7 +276,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
|
||||
private List<Object> findIdsByParentIdList(List<Object> parentIds, Transaction t) {
|
||||
String rawWhere = deriveWhereParentIdSql(true);
|
||||
String inClause = idBinder().getIdInValueExpr(false, parentIds.size());
|
||||
String inClause = idBinder().idInValueExpr(false, parentIds.size());
|
||||
String expr = rawWhere + inClause;
|
||||
SpiEbeanServer server = server();
|
||||
Query<?> q = server.find(type());
|
||||
@@ -487,7 +487,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
*/
|
||||
@Override
|
||||
public Object[] assocIdValues(EntityBean bean) {
|
||||
return targetDescriptor.idBinder().getIdValues(bean);
|
||||
return targetDescriptor.idBinder().values(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -495,7 +495,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
*/
|
||||
@Override
|
||||
public String assocIdExpression(String prefix, String operator) {
|
||||
return targetDescriptor.idBinder().getAssocOneIdExpr(prefix, operator);
|
||||
return targetDescriptor.idBinder().assocExpr(prefix, operator);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -503,7 +503,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
*/
|
||||
@Override
|
||||
public String assocIdInValueExpr(boolean not, int size) {
|
||||
return targetDescriptor.idBinder().getIdInValueExpr(not, size);
|
||||
return targetDescriptor.idBinder().idInValueExpr(not, size);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -511,7 +511,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
*/
|
||||
@Override
|
||||
public String assocIdInExpr(String prefix) {
|
||||
return targetDescriptor.idBinder().getAssocIdInExpr(prefix);
|
||||
return targetDescriptor.idBinder().assocInExpr(prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -613,12 +613,24 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add table join with explicit table alias.
|
||||
*/
|
||||
@Override
|
||||
public SqlJoinType addJoin(SqlJoinType joinType, String a1, String a2, DbSqlContext ctx) {
|
||||
if (sqlFormulaJoin != null) {
|
||||
ctx.appendFormulaJoin(sqlFormulaJoin, joinType, a1);
|
||||
}
|
||||
return super.addJoin(joinType, a1, a2, ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendFrom(DbSqlContext ctx, SqlJoinType joinType, String manyWhere) {
|
||||
if (!isTransient && !primaryKeyExport) {
|
||||
localHelp.appendFrom(ctx, joinType);
|
||||
if (sqlFormulaJoin != null) {
|
||||
ctx.appendFormulaJoin(sqlFormulaJoin, joinType, manyWhere);
|
||||
String alias = ctx.tableAliasManyWhere(manyWhere);
|
||||
ctx.appendFormulaJoin(sqlFormulaJoin, joinType, alias);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ public interface DbSqlContext {
|
||||
* Append a Sql Formula join. This converts the "${ta}" keyword to the current
|
||||
* table alias.
|
||||
*/
|
||||
void appendFormulaJoin(String sqlFormulaJoin, SqlJoinType joinType, String manyWhere);
|
||||
void appendFormulaJoin(String sqlFormulaJoin, SqlJoinType joinType, String tableAlias);
|
||||
|
||||
/**
|
||||
* Return the current content length.
|
||||
|
||||
@@ -26,6 +26,8 @@ public interface IdBinder {
|
||||
*/
|
||||
void initialise();
|
||||
|
||||
String idSelect();
|
||||
|
||||
/**
|
||||
* Return true if this is a compound key and must use expanded and or form.
|
||||
*/
|
||||
@@ -41,19 +43,10 @@ public interface IdBinder {
|
||||
*/
|
||||
Object readData(DataInput dataInput) throws IOException;
|
||||
|
||||
/**
|
||||
* Return the name(s) of the Id property(s). Comma delimited if there is more
|
||||
* than one.
|
||||
* <p>
|
||||
* This can be used to include in a query.
|
||||
* </p>
|
||||
*/
|
||||
String getIdProperty();
|
||||
|
||||
/**
|
||||
* Return the Id BeanProperty.
|
||||
*/
|
||||
STreeProperty getBeanProperty();
|
||||
STreeProperty beanProperty();
|
||||
|
||||
/**
|
||||
* Find a BeanProperty that is mapped to the database column.
|
||||
@@ -70,9 +63,14 @@ public interface IdBinder {
|
||||
* Return the default order by that may need to be used if the query includes
|
||||
* a many property.
|
||||
*/
|
||||
String getDefaultOrderBy();
|
||||
String orderBy();
|
||||
|
||||
String getOrderBy(String pathPrefix, boolean ascending);
|
||||
String orderBy(String pathPrefix, boolean ascending);
|
||||
|
||||
/**
|
||||
* Return the id values for a given bean.
|
||||
*/
|
||||
Object[] values(EntityBean bean);
|
||||
|
||||
/**
|
||||
* Return the values as an array of scalar bindable values.
|
||||
@@ -84,8 +82,7 @@ public interface IdBinder {
|
||||
* Added primarily for Query.addWhere().add(Expr.idEq()) support.
|
||||
* </p>
|
||||
*/
|
||||
Object[] getBindValues(Object idValue);
|
||||
|
||||
Object[] bindValues(Object idValue);
|
||||
|
||||
/**
|
||||
* For EmbeddedId convert the idValue into a simple map.
|
||||
@@ -94,7 +91,7 @@ public interface IdBinder {
|
||||
* This is used to provide a simple JSON serializable version of the id value.
|
||||
* </p>
|
||||
*/
|
||||
Object getIdForJson(EntityBean idValue);
|
||||
Object convertForJson(EntityBean idValue);
|
||||
|
||||
/**
|
||||
* For EmbeddedId the value is assumed to be a Map and this is
|
||||
@@ -106,12 +103,7 @@ public interface IdBinder {
|
||||
* This is used to provide a simple JSON serializable version of the id value.
|
||||
* </p>
|
||||
*/
|
||||
Object convertIdFromJson(Object value);
|
||||
|
||||
/**
|
||||
* Return the id values for a given bean.
|
||||
*/
|
||||
Object[] getIdValues(EntityBean bean);
|
||||
Object convertFromJson(Object value);
|
||||
|
||||
/**
|
||||
* Build a string of the logical expressions.
|
||||
@@ -119,12 +111,12 @@ public interface IdBinder {
|
||||
* Typically used to build a id = ? string.
|
||||
* </p>
|
||||
*/
|
||||
String getAssocOneIdExpr(String prefix, String operator);
|
||||
String assocExpr(String prefix, String operator);
|
||||
|
||||
/**
|
||||
* Return the logical id in expression taking into account embedded id's.
|
||||
*/
|
||||
String getAssocIdInExpr(String prefix);
|
||||
String assocInExpr(String prefix);
|
||||
|
||||
/**
|
||||
* Binds an id value to a prepared statement.
|
||||
@@ -139,27 +131,27 @@ public interface IdBinder {
|
||||
/**
|
||||
* Binds multiple id value to an update.
|
||||
*/
|
||||
void addIdInBindValues(DefaultSqlUpdate sqlUpdate, Collection<?> ids);
|
||||
void addBindValues(DefaultSqlUpdate sqlUpdate, Collection<?> ids);
|
||||
|
||||
/**
|
||||
* Binds multiple id value to a request.
|
||||
*/
|
||||
void addIdInBindValues(SpiExpressionRequest request, Collection<?> ids);
|
||||
void addBindValues(SpiExpressionRequest request, Collection<?> ids);
|
||||
|
||||
/**
|
||||
* Return the sql for binding the id using an IN clause.
|
||||
*/
|
||||
String getBindIdInSql(String baseTableAlias);
|
||||
String bindInSql(String baseTableAlias);
|
||||
|
||||
/**
|
||||
* Return the binding expression (like "?" or "(?,?)")for the Id.
|
||||
*/
|
||||
String getIdInValueExpr(boolean not, int size);
|
||||
String idInValueExpr(boolean not, int size);
|
||||
|
||||
/**
|
||||
* Same as getIdInValueExpr but for delete by id.
|
||||
*/
|
||||
String getIdInValueExprDelete(int size);
|
||||
String idInValueExprDelete(int size);
|
||||
|
||||
void buildRawSqlSelectChain(String prefix, List<String> selectChain);
|
||||
|
||||
@@ -188,7 +180,7 @@ public interface IdBinder {
|
||||
* Return the sql for binding the id to. This includes table alias and columns
|
||||
* that make up the id.
|
||||
*/
|
||||
String getBindIdSql(String baseTableAlias);
|
||||
String bindEqSql(String baseTableAlias);
|
||||
|
||||
/**
|
||||
* Cast or convert the Id value if necessary and optionally set it.
|
||||
|
||||
@@ -35,7 +35,7 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
public IdBinderEmbedded(boolean idInExpandedForm, BeanPropertyAssocOne<?> embIdProperty) {
|
||||
this.idInExpandedForm = idInExpandedForm;
|
||||
this.embIdProperty = embIdProperty;
|
||||
this.idClass = "_idClass".equals(embIdProperty.name());
|
||||
this.idClass = "_$IdClass$".equals(embIdProperty.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -45,13 +45,18 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
this.idInValueSql = idInExpandedForm ? idInExpanded() : idInCompressed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String idSelect() {
|
||||
return embIdProperty.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdInExpandedForm() {
|
||||
return idInExpandedForm;
|
||||
}
|
||||
|
||||
private String idInExpanded() {
|
||||
StringBuilder sb = new StringBuilder(30);
|
||||
final StringBuilder sb = new StringBuilder(30);
|
||||
sb.append("(");
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
if (i > 0) {
|
||||
@@ -64,7 +69,7 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
}
|
||||
|
||||
private String idInCompressed() {
|
||||
StringBuilder sb = new StringBuilder(20).append("(");
|
||||
final StringBuilder sb = new StringBuilder(props.length * 2 + 2).append("(");
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(",");
|
||||
@@ -76,40 +81,14 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanProperty getBeanProperty() {
|
||||
public BeanProperty beanProperty() {
|
||||
return embIdProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOrderBy(String pathPrefix, boolean ascending) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(", ");
|
||||
}
|
||||
if (pathPrefix != null) {
|
||||
sb.append(pathPrefix).append(".");
|
||||
}
|
||||
if (!idClass) {
|
||||
sb.append(embIdProperty.name()).append(".");
|
||||
}
|
||||
sb.append(props[i].name());
|
||||
if (!ascending) {
|
||||
sb.append(" desc");
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public BeanDescriptor<?> getIdBeanDescriptor() {
|
||||
public BeanDescriptor<?> descriptor() {
|
||||
return idDesc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdProperty() {
|
||||
return embIdProperty.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildRawSqlSelectChain(String prefix, List<String> selectChain) {
|
||||
if (!idClass) {
|
||||
@@ -136,33 +115,44 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultOrderBy() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
public String orderBy() {
|
||||
return orderBy(null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String orderBy(String pathPrefix, boolean ascending) {
|
||||
final StringBuilder sb = new StringBuilder(100);
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(", ");
|
||||
}
|
||||
if (pathPrefix != null) {
|
||||
sb.append(pathPrefix).append(".");
|
||||
}
|
||||
if (!idClass) {
|
||||
sb.append(embIdProperty.name()).append(".");
|
||||
}
|
||||
sb.append(props[i].name());
|
||||
if (!ascending) {
|
||||
sb.append(" desc");
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public BeanProperty[] getProperties() {
|
||||
public BeanProperty[] properties() {
|
||||
return props;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdInValueExprDelete(int size) {
|
||||
public String idInValueExprDelete(int size) {
|
||||
if (size <= 0) {
|
||||
throw new IndexOutOfBoundsException("The size must be at least 1");
|
||||
}
|
||||
if (!idInExpandedForm) {
|
||||
return getIdInValueExpr(false, size);
|
||||
return idInValueExpr(false, size);
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
final StringBuilder sb = new StringBuilder(80);
|
||||
sb.append("(");
|
||||
for (int j = 0; j < size; j++) {
|
||||
if (j > 0) {
|
||||
@@ -182,11 +172,11 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdInValueExpr(boolean not, int size) {
|
||||
public String idInValueExpr(boolean not, int size) {
|
||||
if (size <= 0) {
|
||||
throw new IndexOutOfBoundsException("The size must be at least 1");
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
final StringBuilder sb = new StringBuilder(80);
|
||||
if (not) {
|
||||
sb.append(" not");
|
||||
}
|
||||
@@ -209,20 +199,16 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getIdValues(EntityBean bean) {
|
||||
Object val = embIdProperty.getValue(bean);
|
||||
Object[] bindValues = new Object[props.length];
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
bindValues[i] = props[i].getValue((EntityBean) val);
|
||||
}
|
||||
return bindValues;
|
||||
public Object[] values(EntityBean bean) {
|
||||
return bindValues(embIdProperty.getValue(bean));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getBindValues(Object value) {
|
||||
Object[] bindValues = new Object[props.length];
|
||||
public Object[] bindValues(Object value) {
|
||||
final EntityBean bean = (EntityBean) value;
|
||||
final Object[] bindValues = new Object[props.length];
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
bindValues[i] = props[i].getValue((EntityBean) value);
|
||||
bindValues[i] = props[i].getValue(bean);
|
||||
}
|
||||
return bindValues;
|
||||
}
|
||||
@@ -231,9 +217,9 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
* Convert from embedded bean to Map.
|
||||
*/
|
||||
@Override
|
||||
public Object getIdForJson(EntityBean bean) {
|
||||
EntityBean ebValue = (EntityBean) embIdProperty.getValue(bean);
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
public Object convertForJson(EntityBean bean) {
|
||||
final EntityBean ebValue = (EntityBean) embIdProperty.getValue(bean);
|
||||
final Map<String, Object> map = new LinkedHashMap<>();
|
||||
for (BeanProperty prop : props) {
|
||||
map.put(prop.name(), prop.getValue(ebValue));
|
||||
}
|
||||
@@ -245,9 +231,9 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object convertIdFromJson(Object value) {
|
||||
Map<String, Object> map = (Map<String, Object>) value;
|
||||
EntityBean idValue = idDesc.createEntityBean();
|
||||
public Object convertFromJson(Object value) {
|
||||
final Map<String, Object> map = (Map<String, Object>) value;
|
||||
final EntityBean idValue = idDesc.createEntityBean();
|
||||
for (BeanProperty prop : props) {
|
||||
prop.setValue(idValue, map.get(prop.name()));
|
||||
}
|
||||
@@ -256,42 +242,43 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
|
||||
@Override
|
||||
public void bindId(DefaultSqlUpdate sqlUpdate, Object value) {
|
||||
final EntityBean bean = (EntityBean) value;
|
||||
for (BeanProperty prop : props) {
|
||||
Object embFieldValue = prop.getValue((EntityBean) value);
|
||||
sqlUpdate.setParameter(embFieldValue);
|
||||
sqlUpdate.setParameter(prop.getValue(bean));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindId(DataBind dataBind, Object value) throws SQLException {
|
||||
final EntityBean bean = (EntityBean) value;
|
||||
for (BeanProperty prop : props) {
|
||||
Object embFieldValue = prop.getValue((EntityBean) value);
|
||||
prop.bind(dataBind, embFieldValue);
|
||||
prop.bind(dataBind, prop.getValue(bean));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addIdInBindValues(DefaultSqlUpdate sqlUpdate, Collection<?> values) {
|
||||
public void addBindValues(DefaultSqlUpdate sqlUpdate, Collection<?> values) {
|
||||
for (Object value : values) {
|
||||
bindId(sqlUpdate, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addIdInBindValues(SpiExpressionRequest request, Collection<?> values) {
|
||||
public void addBindValues(SpiExpressionRequest request, Collection<?> values) {
|
||||
for (Object value : values) {
|
||||
final EntityBean bean = (EntityBean) value;
|
||||
for (BeanProperty prop : props) {
|
||||
request.addBindValue(prop.getValue((EntityBean) value));
|
||||
request.addBindValue(prop.getValue(bean));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object readData(DataInput dataInput) throws IOException {
|
||||
EntityBean embId = idDesc.createEntityBean();
|
||||
final EntityBean embId = idDesc.createEntityBean();
|
||||
boolean notNull = true;
|
||||
for (BeanProperty prop : props) {
|
||||
Object value = prop.readData(dataInput);
|
||||
final Object value = prop.readData(dataInput);
|
||||
prop.setValue(embId, value);
|
||||
if (value == null) {
|
||||
notNull = false;
|
||||
@@ -302,9 +289,9 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
|
||||
@Override
|
||||
public void writeData(DataOutput dataOutput, Object idValue) throws IOException {
|
||||
final EntityBean bean = (EntityBean) idValue;
|
||||
for (BeanProperty prop : props) {
|
||||
Object embFieldValue = prop.getValue((EntityBean) idValue);
|
||||
prop.writeData(dataOutput, embFieldValue);
|
||||
prop.writeData(dataOutput, prop.getValue(bean));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,10 +304,10 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
|
||||
@Override
|
||||
public Object read(DbReadContext ctx) throws SQLException {
|
||||
EntityBean embId = idDesc.createEntityBean();
|
||||
final EntityBean embId = idDesc.createEntityBean();
|
||||
boolean nullValue = true;
|
||||
for (BeanProperty prop : props) {
|
||||
Object value = prop.read(ctx);
|
||||
final Object value = prop.read(ctx);
|
||||
if (value != null) {
|
||||
prop.setValue(embId, value);
|
||||
nullValue = false;
|
||||
@@ -348,8 +335,8 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAssocIdInExpr(String prefix) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
public String assocInExpr(String prefix) {
|
||||
final StringBuilder sb = new StringBuilder(80);
|
||||
sb.append("(");
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
if (i > 0) {
|
||||
@@ -365,8 +352,8 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAssocOneIdExpr(String prefix, String operator) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
public String assocExpr(String prefix, String operator) {
|
||||
final StringBuilder sb = new StringBuilder(100);
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(" and ");
|
||||
@@ -383,8 +370,8 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBindIdSql(String baseTableAlias) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
public String bindEqSql(String baseTableAlias) {
|
||||
final StringBuilder sb = new StringBuilder(80);
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(" and ");
|
||||
@@ -398,11 +385,11 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBindIdInSql(String baseTableAlias) {
|
||||
public String bindInSql(String baseTableAlias) {
|
||||
if (idInExpandedForm) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
final StringBuilder sb = new StringBuilder(80);
|
||||
sb.append("(");
|
||||
for (int i = 0; i < props.length; i++) {
|
||||
if (i > 0) {
|
||||
@@ -442,8 +429,8 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
|
||||
@Override
|
||||
public String cacheKey(Object value) {
|
||||
EntityBean bean = (EntityBean)value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
final EntityBean bean = (EntityBean)value;
|
||||
final StringBuilder sb = new StringBuilder(80);
|
||||
for (BeanProperty prop : props) {
|
||||
Object val = prop.getValue(bean);
|
||||
if (val != null) {
|
||||
|
||||
@@ -2,11 +2,11 @@ package io.ebeaninternal.server.deploy.id;
|
||||
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.bind.DataBind;
|
||||
import io.ebeaninternal.server.core.DefaultSqlUpdate;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
import io.ebeaninternal.server.deploy.DbReadContext;
|
||||
import io.ebeaninternal.server.deploy.DbSqlContext;
|
||||
import io.ebeaninternal.server.bind.DataBind;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
@@ -27,13 +27,18 @@ final class IdBinderEmpty implements IdBinder {
|
||||
public void initialise() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String idSelect() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdInExpandedForm() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOrderBy(String pathPrefix, boolean ascending) {
|
||||
public String orderBy(String pathPrefix, boolean ascending) {
|
||||
return pathPrefix;
|
||||
}
|
||||
|
||||
@@ -42,12 +47,7 @@ final class IdBinderEmpty implements IdBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanProperty getBeanProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdProperty() {
|
||||
public BeanProperty beanProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -62,58 +62,58 @@ final class IdBinderEmpty implements IdBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultOrderBy() {
|
||||
public String orderBy() {
|
||||
// this should never happen?
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBindIdSql(String baseTableAlias) {
|
||||
public String bindEqSql(String baseTableAlias) {
|
||||
return bindIdSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAssocOneIdExpr(String prefix, String operator) {
|
||||
public String assocExpr(String prefix, String operator) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAssocIdInExpr(String prefix) {
|
||||
public String assocInExpr(String prefix) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdInValueExprDelete(int size) {
|
||||
return getIdInValueExpr(false, size);
|
||||
public String idInValueExprDelete(int size) {
|
||||
return idInValueExpr(false, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdInValueExpr(boolean not, int size) {
|
||||
public String idInValueExpr(boolean not, int size) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBindIdInSql(String baseTableAlias) {
|
||||
public String bindInSql(String baseTableAlias) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getIdValues(EntityBean bean) {
|
||||
public Object[] values(EntityBean bean) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getBindValues(Object idValue) {
|
||||
public Object[] bindValues(Object idValue) {
|
||||
return new Object[]{idValue};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdForJson(EntityBean bean) {
|
||||
public Object convertForJson(EntityBean bean) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convertIdFromJson(Object value) {
|
||||
public Object convertFromJson(Object value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -126,11 +126,11 @@ final class IdBinderEmpty implements IdBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addIdInBindValues(DefaultSqlUpdate sqlUpdate, Collection<?> ids) {
|
||||
public void addBindValues(DefaultSqlUpdate sqlUpdate, Collection<?> ids) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addIdInBindValues(SpiExpressionRequest request, Collection<?> ids) {
|
||||
public void addBindValues(SpiExpressionRequest request, Collection<?> ids) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -45,13 +45,18 @@ public final class IdBinderSimple implements IdBinder {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public String idSelect() {
|
||||
return idProperty.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdInExpandedForm() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOrderBy(String pathPrefix, boolean ascending) {
|
||||
public String orderBy(String pathPrefix, boolean ascending) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (pathPrefix != null) {
|
||||
sb.append(pathPrefix).append(".");
|
||||
@@ -69,15 +74,10 @@ public final class IdBinderSimple implements IdBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanProperty getBeanProperty() {
|
||||
public BeanProperty beanProperty() {
|
||||
return idProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdProperty() {
|
||||
return idProperty.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanProperty findBeanProperty(String dbColumnName) {
|
||||
if (dbColumnName.equalsIgnoreCase(idProperty.dbColumn())) {
|
||||
@@ -92,12 +92,12 @@ public final class IdBinderSimple implements IdBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultOrderBy() {
|
||||
public String orderBy() {
|
||||
return idProperty.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBindIdInSql(String baseTableAlias) {
|
||||
public String bindInSql(String baseTableAlias) {
|
||||
if (baseTableAlias == null) {
|
||||
return idProperty.dbColumn();
|
||||
} else {
|
||||
@@ -106,7 +106,7 @@ public final class IdBinderSimple implements IdBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBindIdSql(String baseTableAlias) {
|
||||
public String bindEqSql(String baseTableAlias) {
|
||||
if (baseTableAlias == null) {
|
||||
return bindIdSql;
|
||||
} else {
|
||||
@@ -115,22 +115,22 @@ public final class IdBinderSimple implements IdBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getIdValues(EntityBean bean) {
|
||||
public Object[] values(EntityBean bean) {
|
||||
return new Object[]{idProperty.getValue(bean)};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getBindValues(Object idValue) {
|
||||
public Object[] bindValues(Object idValue) {
|
||||
return new Object[]{idValue};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdInValueExprDelete(int size) {
|
||||
return getIdInValueExpr(false, size);
|
||||
public String idInValueExprDelete(int size) {
|
||||
return idInValueExpr(false, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdInValueExpr(boolean not, int size) {
|
||||
public String idInValueExpr(boolean not, int size) {
|
||||
if (size <= 0) {
|
||||
throw new IndexOutOfBoundsException("The size must be at least 1");
|
||||
}
|
||||
@@ -138,24 +138,24 @@ public final class IdBinderSimple implements IdBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addIdInBindValues(DefaultSqlUpdate sqlUpdate, Collection<?> ids) {
|
||||
public void addBindValues(DefaultSqlUpdate sqlUpdate, Collection<?> ids) {
|
||||
sqlUpdate.setParameter(new MultiValueWrapper(ids));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addIdInBindValues(SpiExpressionRequest request, Collection<?> values) {
|
||||
public void addBindValues(SpiExpressionRequest request, Collection<?> values) {
|
||||
List<Object> copy = new ArrayList<>(values);
|
||||
copy.replaceAll(idValue -> convertSetId(idValue, null));
|
||||
request.addBindValue(new MultiValueWrapper(copy));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdForJson(EntityBean bean) {
|
||||
public Object convertForJson(EntityBean bean) {
|
||||
return idProperty.getValue(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convertIdFromJson(Object value) {
|
||||
public Object convertFromJson(Object value) {
|
||||
// handle simple type conversion if required
|
||||
return convertId(value);
|
||||
}
|
||||
@@ -208,11 +208,11 @@ public final class IdBinderSimple implements IdBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAssocOneIdExpr(String prefix, String operator) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
public String assocExpr(String prefix, String operator) {
|
||||
StringBuilder sb = new StringBuilder(25);
|
||||
if (prefix != null) {
|
||||
sb.append(prefix);
|
||||
sb.append(".");
|
||||
sb.append('.');
|
||||
}
|
||||
sb.append(idProperty.name());
|
||||
sb.append(operator);
|
||||
@@ -220,7 +220,7 @@ public final class IdBinderSimple implements IdBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAssocIdInExpr(String prefix) {
|
||||
public String assocInExpr(String prefix) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (prefix != null) {
|
||||
sb.append(prefix);
|
||||
|
||||
+1
-1
@@ -654,7 +654,7 @@ public class DeployBeanDescriptor<T> {
|
||||
public void postAnnotations() {
|
||||
if (idClass != null) {
|
||||
idClassProperty = new DeployBeanPropertyAssocOne<>(this, idClass);
|
||||
idClassProperty.setName("_idClass");
|
||||
idClassProperty.setName("_$IdClass$");
|
||||
idClassProperty.setEmbedded();
|
||||
idClassProperty.setNullable(false);
|
||||
}
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ public class VisitProperties {
|
||||
|
||||
protected void visitProperties(BeanDescriptor<?> desc, BeanPropertyVisitor propertyVisitor) {
|
||||
BeanProperty idProp = desc.idProperty();
|
||||
if (idProp != null) {
|
||||
if (idProp != null && !idProp.name().equals("_$IdClass$")) {
|
||||
visit(propertyVisitor, idProp);
|
||||
}
|
||||
BeanPropertyAssocOne<?> unidirectional = desc.unidirectional();
|
||||
|
||||
+5
@@ -471,6 +471,11 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
return new InPairsExpression(pairs, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression inTuples(InTuples pairs) {
|
||||
return new InTuplesExpression(pairs, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* In - property has a value in the array of values.
|
||||
*/
|
||||
|
||||
+6
-2
@@ -612,9 +612,9 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
}
|
||||
for (SpiExpression expr : list) {
|
||||
expr.queryPlanHash(builder);
|
||||
builder.append(",");
|
||||
builder.append(',');
|
||||
}
|
||||
builder.append("]");
|
||||
builder.append(']');
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -902,6 +902,10 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return add(expr.inPairs(pairs));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> inTuples(InTuples pairs) {
|
||||
return add(expr.inTuples(pairs));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> exists(String sqlSubQuery, Object... bindValues) {
|
||||
|
||||
+5
@@ -110,6 +110,11 @@ public final class DefaultExpressionRequest implements SpiExpressionRequest {
|
||||
return queryRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuilder buffer() {
|
||||
return sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append text the underlying sql expression.
|
||||
*/
|
||||
|
||||
@@ -66,7 +66,7 @@ public final class IdInExpression extends NonPrepareExpression implements IdInCo
|
||||
return;
|
||||
}
|
||||
// Bind the ID values including EmbeddedId and multiple ID
|
||||
request.descriptor().idBinder().addIdInBindValues(request, idCollection);
|
||||
request.descriptor().idBinder().addBindValues(request, idCollection);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,8 +77,8 @@ public final class IdInExpression extends NonPrepareExpression implements IdInCo
|
||||
request.append(SQL_FALSE); // append false for this stage
|
||||
} else {
|
||||
final BeanDescriptor<?> descriptor = request.descriptor();
|
||||
request.property(descriptor.idBinder().getBindIdInSql(null));
|
||||
request.append(descriptor.idBinder().getIdInValueExpr(false, idCollection.size()));
|
||||
request.property(descriptor.idBinder().bindInSql(null));
|
||||
request.append(descriptor.idBinder().idInValueExpr(false, idCollection.size()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,9 +91,9 @@ public final class IdInExpression extends NonPrepareExpression implements IdInCo
|
||||
final IdBinder idBinder = descriptor.idBinder();
|
||||
if (idBinder.isComplexId()) {
|
||||
request.parse(descriptor.idBinderInLHSSql());
|
||||
request.append(idBinder.getIdInValueExpr(false, idCollection.size()));
|
||||
request.append(idBinder.idInValueExpr(false, idCollection.size()));
|
||||
} else {
|
||||
request.property(idBinder.getBeanProperty().name());
|
||||
request.property(idBinder.beanProperty().name());
|
||||
request.appendInExpression(false, idCollection);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebean.annotation.Platform;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Adds values as literals to SQL string.
|
||||
*/
|
||||
interface InLiterals {
|
||||
|
||||
/**
|
||||
* Add the value as a SQL literal to the buffer.
|
||||
*/
|
||||
void append(StringBuilder buffer, Object value);
|
||||
|
||||
/**
|
||||
* Return the InLiterals for the type of the given value.
|
||||
*/
|
||||
static InLiterals of(Object val, Platform platform) {
|
||||
if (val instanceof Number) {
|
||||
return NumLiteral.INSTANCE;
|
||||
}
|
||||
if (val instanceof String || val instanceof UUID) {
|
||||
return StrLiteral.INSTANCE;
|
||||
}
|
||||
if (val instanceof LocalDate) {
|
||||
return platform.base() == Platform.MYSQL ? DateEscapeLiteral.INSTANCE : DateLiteral.INSTANCE;
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
final class NumLiteral implements InLiterals {
|
||||
|
||||
static NumLiteral INSTANCE = new NumLiteral();
|
||||
|
||||
@Override
|
||||
public void append(StringBuilder buffer, Object value) {
|
||||
buffer.append(value);
|
||||
}
|
||||
}
|
||||
|
||||
final class StrLiteral implements InLiterals {
|
||||
|
||||
static StrLiteral INSTANCE = new StrLiteral();
|
||||
|
||||
@Override
|
||||
public void append(StringBuilder buffer, Object value) {
|
||||
buffer.append('\'').append(value).append('\'');
|
||||
}
|
||||
}
|
||||
|
||||
final class DateLiteral implements InLiterals {
|
||||
|
||||
static DateLiteral INSTANCE = new DateLiteral();
|
||||
|
||||
@Override
|
||||
public void append(StringBuilder buffer, Object value) {
|
||||
buffer.append("date ").append('\'').append(value).append('\'');
|
||||
}
|
||||
}
|
||||
|
||||
final class DateEscapeLiteral implements InLiterals {
|
||||
|
||||
static DateEscapeLiteral INSTANCE = new DateEscapeLiteral();
|
||||
|
||||
@Override
|
||||
public void append(StringBuilder buffer, Object value) {
|
||||
buffer.append("{d '").append(value).append("'}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebean.InTuples;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.event.BeanQueryRequest;
|
||||
import io.ebean.service.SpiInTuples;
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.NaturalKeyQueryData;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
final class InTuplesExpression extends AbstractExpression {
|
||||
|
||||
private final boolean not;
|
||||
private final String[] properties;
|
||||
private final List<Object[]> entries;
|
||||
private InLiterals[] literals;
|
||||
private boolean literalMode;
|
||||
|
||||
InTuplesExpression(InTuples pairs, boolean not) {
|
||||
super("");
|
||||
SpiInTuples inTuples = (SpiInTuples) pairs;
|
||||
this.properties = inTuples.properties();
|
||||
// the entries might be modified on cache hit.
|
||||
this.entries = inTuples.entries();
|
||||
this.not = not;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareExpression(BeanQueryRequest<?> request) {
|
||||
if (entries.size() > 50) {
|
||||
// check if this should go into literal mode
|
||||
final int maxInBinding = request.database().pluginApi().databasePlatform().maxInBinding();
|
||||
final int threshold = literalThreshold(maxInBinding, properties.length);
|
||||
if (entries.size() > threshold) {
|
||||
literals = initLiterals(request.database().platform());
|
||||
literalMode = literals != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private InLiterals[] initLiterals(Platform platform) {
|
||||
try {
|
||||
Object[] firstData = entries.get(0);
|
||||
final InLiterals[] literals = new InLiterals[firstData.length];
|
||||
for (int i = 0; i < firstData.length; i++) {
|
||||
literals[i] = InLiterals.of(firstData[i], platform);
|
||||
}
|
||||
return literals;
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// one of the value types is not supported as a SQL literal
|
||||
// so stick to binding only
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the threshold in number of entries before literal mode is used.
|
||||
*/
|
||||
static int literalThreshold(int maxInBinding, int propertyCount) {
|
||||
if (maxInBinding == 0) {
|
||||
return 5000 / propertyCount;
|
||||
}
|
||||
return (maxInBinding / propertyCount) - 200;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean naturalKey(NaturalKeyQueryData<?> data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDocQuery(DocQueryContext context) {
|
||||
throw new RuntimeException("Not supported with document query");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
if (literalMode) {
|
||||
return;
|
||||
}
|
||||
for (Object[] entry : entries) {
|
||||
for (Object value : entry) {
|
||||
requireNonNull(value);
|
||||
request.addBindValue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
if (entries.isEmpty()) {
|
||||
request.append(not ? SQL_TRUE : SQL_FALSE);
|
||||
return;
|
||||
}
|
||||
request.append("(");
|
||||
for (int i = 0; i < properties.length; i++) {
|
||||
if (i > 0) {
|
||||
request.append(",");
|
||||
}
|
||||
request.property(properties[i]);
|
||||
}
|
||||
request.append(") in (");
|
||||
if (literalMode) {
|
||||
addSqlLiterals(request);
|
||||
} else {
|
||||
addSqlBinding(request);
|
||||
}
|
||||
request.append(")");
|
||||
}
|
||||
|
||||
private void addSqlLiterals(SpiExpressionRequest request) {
|
||||
final var buffer = request.buffer();
|
||||
for (int i = 0; i < entries.size(); i++) {
|
||||
if (i > 0) {
|
||||
buffer.append(',');
|
||||
}
|
||||
buffer.append('(');
|
||||
Object[] values = entries.get(i);
|
||||
for (int v = 0; v < values.length; v++) {
|
||||
if (v > 0) {
|
||||
buffer.append(',');
|
||||
}
|
||||
literals[v].append(buffer, values[v]);
|
||||
}
|
||||
buffer.append(')');
|
||||
}
|
||||
}
|
||||
|
||||
private void addSqlBinding(SpiExpressionRequest request) {
|
||||
final String eb = entryBinding();
|
||||
for (int i = 0; i < entries.size(); i++) {
|
||||
if (i > 0) {
|
||||
request.append(",");
|
||||
}
|
||||
request.append(eb);
|
||||
}
|
||||
}
|
||||
|
||||
private String entryBinding() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append('(');
|
||||
for (int i = 0; i < properties.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(',');
|
||||
}
|
||||
sb.append('?');
|
||||
}
|
||||
return sb.append(')').toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Based on the number of values in the in clause.
|
||||
*/
|
||||
@Override
|
||||
public void queryPlanHash(StringBuilder builder) {
|
||||
if (literalMode) {
|
||||
builder.delete(0, builder.length());
|
||||
builder.append("$NoCache/").append(UUID.randomUUID()).append('/');
|
||||
return;
|
||||
}
|
||||
if (not) {
|
||||
builder.append("Not");
|
||||
}
|
||||
builder.append("InTuple[");
|
||||
for (String property : properties) {
|
||||
builder.append(property).append("-");
|
||||
}
|
||||
builder.append(entries.size()).append(']');
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryBindKey(BindValuesKey key) {
|
||||
key.add(entries.size());
|
||||
for (Object[] entry : entries) {
|
||||
for (Object value : entry) {
|
||||
key.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
InTuplesExpression that = (InTuplesExpression) other;
|
||||
return this.entries.size() == that.entries.size() && entries.equals(that.entries);
|
||||
}
|
||||
}
|
||||
@@ -710,6 +710,11 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
|
||||
return exprList.inPairs(pairs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> inTuples(InTuples pairs) {
|
||||
return exprList.inTuples(pairs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> in(String propertyName, Collection<?> values) {
|
||||
return exprList.in(propertyName, values);
|
||||
|
||||
@@ -224,14 +224,21 @@ public final class BatchControl {
|
||||
* Execute all the requests contained in the list.
|
||||
*/
|
||||
void executeNow(ArrayList<PersistRequest> list) throws BatchedSqlException {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (i % batchSize == 0) {
|
||||
// hit the batch size so flush
|
||||
flushPstmtHolder();
|
||||
boolean old = transaction.isFlushOnQuery();
|
||||
transaction.setFlushOnQuery(false);
|
||||
// disable flush on query due transsaction callbacks
|
||||
try {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (i % batchSize == 0) {
|
||||
// hit the batch size so flush
|
||||
flushPstmtHolder();
|
||||
}
|
||||
list.get(i).executeNow();
|
||||
}
|
||||
list.get(i).executeNow();
|
||||
flushPstmtHolder();
|
||||
} finally {
|
||||
transaction.setFlushOnQuery(old);
|
||||
}
|
||||
flushPstmtHolder();
|
||||
}
|
||||
|
||||
public void flushOnCommit() throws BatchedSqlException {
|
||||
|
||||
@@ -44,13 +44,21 @@ public final class DefaultPersister implements Persister {
|
||||
private final PersistExecute persistExecute;
|
||||
private final SpiEbeanServer server;
|
||||
private final BeanDescriptorManager beanDescriptorManager;
|
||||
private final int maxInBinding;
|
||||
private final int maxDeleteBatch;
|
||||
|
||||
public DefaultPersister(SpiEbeanServer server, Binder binder, BeanDescriptorManager descMgr) {
|
||||
this.server = server;
|
||||
this.beanDescriptorManager = descMgr;
|
||||
this.persistExecute = new DefaultPersistExecute(binder, server.config().getPersistBatchSize());
|
||||
this.maxInBinding = server.databasePlatform().maxInBinding();
|
||||
this.maxDeleteBatch = initMaxDeleteBatch(server.databasePlatform().maxInBinding());
|
||||
}
|
||||
|
||||
/**
|
||||
* When delete batching is required limit the size.
|
||||
* e.g. SqlServer has a 2100 parameter limit, so delete max 2000 for it.
|
||||
*/
|
||||
private int initMaxDeleteBatch(int maxInBinding) {
|
||||
return maxInBinding == 0 ? 1000 : maxInBinding;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -647,16 +655,13 @@ public final class DefaultPersister implements Persister {
|
||||
* Delete by Id or a List of Id's.
|
||||
*/
|
||||
private int delete(BeanDescriptor<?> descriptor, Object id, List<Object> idList, Transaction transaction, DeleteMode deleteMode) {
|
||||
if (idList == null || idList.size() <= maxDeleteBatch) {
|
||||
return deleteBatch(descriptor, id, idList, transaction, deleteMode);
|
||||
}
|
||||
int rows = 0;
|
||||
if (maxInBinding > 0) {
|
||||
// SqlServer has a 2100 parameter limit, so delete max 2000 ids at once
|
||||
// this gives space up to 100 more query parameters.
|
||||
while (idList != null && idList.size() > maxInBinding) {
|
||||
rows += deleteBatch(descriptor, id, idList.subList(0, maxInBinding), transaction, deleteMode);
|
||||
idList = idList.subList(maxInBinding, idList.size());
|
||||
}
|
||||
for (List<Object> batchOfIds : Lists.partition(idList, maxDeleteBatch)) {
|
||||
rows += deleteBatch(descriptor, id, batchOfIds, transaction, deleteMode);
|
||||
}
|
||||
rows += deleteBatch(descriptor, id, idList, transaction, deleteMode);
|
||||
return rows;
|
||||
}
|
||||
|
||||
|
||||
+9
-4
@@ -64,7 +64,6 @@ final class BindableIdEmbedded implements BindableId {
|
||||
|
||||
@Override
|
||||
public void dmlBind(BindableRequest request, EntityBean bean) throws SQLException {
|
||||
|
||||
EntityBean idValue = (EntityBean) embId.getValue(bean);
|
||||
for (BeanProperty prop : props) {
|
||||
Object value = prop.getValue(idValue);
|
||||
@@ -75,14 +74,20 @@ final class BindableIdEmbedded implements BindableId {
|
||||
|
||||
@Override
|
||||
public void dmlAppend(GenerateDmlRequest request) {
|
||||
for (BeanProperty prop : props) {
|
||||
request.appendColumn(prop.dbColumn());
|
||||
if (matches != null) {
|
||||
// prefer the match dbColumns over the embedded property ones
|
||||
for (MatchedImportedProperty match : matches) {
|
||||
request.appendColumn(match.dbColumn());
|
||||
}
|
||||
} else {
|
||||
for (BeanProperty prop : props) {
|
||||
request.appendColumn(prop.dbColumn());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deriveConcatenatedId(PersistRequestBean<?> persist) {
|
||||
|
||||
if (matches == null) {
|
||||
String m = "No matches for " + embId.fullName() + " the concatenated key columns where not found?"
|
||||
+ " I expect that the concatenated key was null, and this bean does"
|
||||
|
||||
+4
@@ -30,4 +30,8 @@ final class MatchedImportedEmbedded implements MatchedImportedProperty {
|
||||
localProp.setValue(embeddedId, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dbColumn() {
|
||||
return localProp.dbColumn();
|
||||
}
|
||||
}
|
||||
|
||||
+6
@@ -39,6 +39,12 @@ final class MatchedImportedFactory {
|
||||
return new MatchedImportedScalar(prop, beanProperty);
|
||||
}
|
||||
}
|
||||
// match on property name
|
||||
for (BeanProperty beanProperty : desc.propertiesBaseScalar()) {
|
||||
if (prop.name().equals(beanProperty.name())) {
|
||||
return new MatchedImportedScalar(prop, beanProperty);
|
||||
}
|
||||
}
|
||||
// there was no matching assoc one property.
|
||||
// example UserRole bean missing assoc one to User?
|
||||
return null;
|
||||
|
||||
+5
@@ -8,4 +8,9 @@ interface MatchedImportedProperty {
|
||||
* Populate the embeddedId bean from the source entity.
|
||||
*/
|
||||
void populate(EntityBean sourceBean, EntityBean embeddedId);
|
||||
|
||||
/**
|
||||
* Return the DB column to use.
|
||||
*/
|
||||
String dbColumn();
|
||||
}
|
||||
|
||||
+5
@@ -22,4 +22,9 @@ final class MatchedImportedScalar implements MatchedImportedProperty {
|
||||
localProp.setValue(embeddedId, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dbColumn() {
|
||||
return foreignProp.dbColumn();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ final class CQueryOrderBy {
|
||||
if (beanProperty instanceof BeanPropertyAssoc<?>) {
|
||||
BeanPropertyAssoc<?> ap = (BeanPropertyAssoc<?>) beanProperty;
|
||||
IdBinder idBinder = ap.targetDescriptor().idBinder();
|
||||
return idBinder.getOrderBy(el.elName(), p.isAscending());
|
||||
return idBinder.orderBy(el.elName(), p.isAscending());
|
||||
}
|
||||
return p.toStringFormat();
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ final class DefaultDbSqlContext implements DbSqlContext {
|
||||
|
||||
@Override
|
||||
public String tableAliasManyWhere(String prefix) {
|
||||
return alias.tableAliasManyWhere(prefix);
|
||||
return prefix == null ? tableAliasStack.peek() : alias.tableAliasManyWhere(prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -225,9 +225,8 @@ final class DefaultDbSqlContext implements DbSqlContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendFormulaJoin(String sqlFormulaJoin, SqlJoinType joinType, String manyWhere) {
|
||||
public void appendFormulaJoin(String sqlFormulaJoin, SqlJoinType joinType, String tableAlias) {
|
||||
// replace ${ta} placeholder with the real table alias...
|
||||
String tableAlias = manyWhere == null ? tableAliasStack.peek() : tableAliasManyWhere(manyWhere);
|
||||
String converted = sqlFormulaJoin.replace(tableAliasPlaceHolder, tableAlias);
|
||||
if (formulaJoins == null) {
|
||||
formulaJoins = new HashSet<>();
|
||||
@@ -240,11 +239,17 @@ final class DefaultDbSqlContext implements DbSqlContext {
|
||||
formulaJoins.add(converted);
|
||||
sb.append(" ");
|
||||
if (joinType == SqlJoinType.OUTER) {
|
||||
if ("join".equalsIgnoreCase(sqlFormulaJoin.substring(0, 4))) {
|
||||
if ("join".equalsIgnoreCase(converted.substring(0, 4))) {
|
||||
// prepend left as we are in the 'many' part
|
||||
sb.append("left ");
|
||||
}
|
||||
}
|
||||
if (joinType == SqlJoinType.INNER) {
|
||||
if ("left join".equalsIgnoreCase(converted.substring(0, 9))) {
|
||||
// remove left as we do not need it
|
||||
converted = converted.substring(5);
|
||||
}
|
||||
}
|
||||
sb.append(converted);
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
@@ -219,6 +220,11 @@ final class DefaultFetchGroupQuery<T> implements SpiFetchGroupQuery<T>, SpiQuery
|
||||
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> alsoIf(BooleanSupplier predicate, Consumer<Query<T>> apply) {
|
||||
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> usingTransaction(Transaction transaction) {
|
||||
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
|
||||
@@ -234,6 +240,11 @@ final class DefaultFetchGroupQuery<T> implements SpiFetchGroupQuery<T>, SpiQuery
|
||||
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> usingMaster() {
|
||||
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <A> List<A> findIds() {
|
||||
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
|
||||
|
||||
@@ -18,6 +18,11 @@ public class NativeSqlQueryPlanKey implements CQueryPlanKey {
|
||||
return partialKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useCache() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CQueryPlanKey withDeleteByIds() {
|
||||
throw new IllegalStateException("Not allowed");
|
||||
|
||||
@@ -19,7 +19,7 @@ public final class QueryPlanLoggerPostgres extends QueryPlanLogger {
|
||||
|
||||
@Override
|
||||
public SpiDbQueryPlan collectPlan(Connection conn, SpiQueryPlan plan, BindCapture bind) {
|
||||
String explain = "explain analyze " + plan.sql();
|
||||
String explain = "explain (analyze, buffers) " + plan.sql();
|
||||
try (PreparedStatement explainStmt = conn.prepareStatement(explain)) {
|
||||
bind.prepare(explainStmt, conn);
|
||||
try (ResultSet rset = explainStmt.executeQuery()) {
|
||||
|
||||
@@ -24,6 +24,11 @@ final class RawSqlQueryPlanKey implements CQueryPlanKey {
|
||||
return partialKey() + ":r";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useCache() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CQueryPlanKey withDeleteByIds() {
|
||||
throw new IllegalStateException("Not allowed");
|
||||
|
||||
@@ -81,7 +81,7 @@ class SqlTreeLoadBean implements SqlTreeLoad {
|
||||
// if we have no property ask first children (in a distinct select with join)
|
||||
if (children.length == 0) {
|
||||
// expected to be a findIds query
|
||||
return desc.idBinder().getBeanProperty();
|
||||
return desc.idBinder().beanProperty();
|
||||
}
|
||||
return children[0].singleAttributeReader();
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
lazyLoadParent.addSelectExported(ctx, prefix);
|
||||
}
|
||||
if (readId) {
|
||||
appendSelectId(ctx, idBinder.getBeanProperty());
|
||||
appendSelectId(ctx, idBinder.beanProperty());
|
||||
}
|
||||
for (STreeProperty property : properties) {
|
||||
if (!property.isAggregation()) {
|
||||
@@ -201,7 +201,7 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
if (!subQuery && inheritInfo != null) {
|
||||
ctx.appendColumn(inheritInfo.getDiscriminatorColumn());
|
||||
}
|
||||
appendSelectId(ctx, idBinder.getBeanProperty());
|
||||
appendSelectId(ctx, idBinder.beanProperty());
|
||||
}
|
||||
appendSelect(ctx, subQuery, properties);
|
||||
for (SqlTreeNode child : children) {
|
||||
|
||||
@@ -30,7 +30,7 @@ final class SqlTreeNodeManyRoot extends SqlTreeNodeBean {
|
||||
@Override
|
||||
public void appendDistinctOn(DbSqlContext ctx, boolean subQuery) {
|
||||
ctx.pushTableAlias(prefix);
|
||||
appendSelectId(ctx, idBinder.getBeanProperty());
|
||||
appendSelectId(ctx, idBinder.beanProperty());
|
||||
ctx.popTableAlias();
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ final class SqlTreeNodeRoot extends SqlTreeNodeBean {
|
||||
public void appendDistinctOn(DbSqlContext ctx, boolean subQuery) {
|
||||
if (readId) {
|
||||
ctx.pushTableAlias(prefix);
|
||||
appendSelectId(ctx, idBinder.getBeanProperty());
|
||||
appendSelectId(ctx, idBinder.beanProperty());
|
||||
ctx.popTableAlias();
|
||||
super.appendDistinctOn(ctx, subQuery);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ public class AbstractQuery implements SpiCancelableQuery {
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
private boolean cancelled;
|
||||
private CancelableQuery cancelableQuery;
|
||||
protected boolean useMaster;
|
||||
|
||||
@Override
|
||||
public final void cancel() {
|
||||
|
||||
@@ -48,6 +48,7 @@ public final class DefaultDtoQuery<T> extends AbstractQuery implements SpiDtoQue
|
||||
this.server = server;
|
||||
this.descriptor = descriptor;
|
||||
this.ormQuery = ormQuery;
|
||||
this.useMaster = ormQuery.isUseMaster();
|
||||
this.label = ormQuery.label();
|
||||
this.profileLocation = ormQuery.profileLocation();
|
||||
}
|
||||
@@ -88,6 +89,17 @@ public final class DefaultDtoQuery<T> extends AbstractQuery implements SpiDtoQue
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DtoQuery<T> usingMaster() {
|
||||
this.useMaster = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUseMaster() {
|
||||
return useMaster;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void findEach(Consumer<T> consumer) {
|
||||
server.findDtoEach(this, consumer);
|
||||
|
||||
@@ -26,6 +26,7 @@ import javax.persistence.PersistenceException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.*;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
@@ -282,6 +283,14 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> alsoIf(BooleanSupplier predicate, Consumer<Query<T>> consumer) {
|
||||
if (predicate.getAsBoolean()) {
|
||||
consumer.accept(this);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void addSoftDeletePredicate(String softDeletePredicate) {
|
||||
if (softDeletePredicates == null) {
|
||||
@@ -715,6 +724,7 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
// forUpdate is NOT copied - see #2762
|
||||
DefaultOrmQuery<T> copy = new DefaultOrmQuery<>(beanDescriptor, server, expressionFactory);
|
||||
copy.transaction = transaction;
|
||||
copy.useMaster = useMaster;
|
||||
copy.m2mIncludeJoin = m2mIncludeJoin;
|
||||
copy.profilingListener = profilingListener;
|
||||
copy.profileLocation = profileLocation;
|
||||
@@ -1037,13 +1047,13 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
if (temporalMode != SpiQuery.TemporalMode.CURRENT) {
|
||||
sb.append("/tm").append(temporalMode.ordinal());
|
||||
if (versionsStart != null) {
|
||||
sb.append("v");
|
||||
sb.append('v');
|
||||
}
|
||||
}
|
||||
if (forUpdate != null) {
|
||||
sb.append("/fu").append(forUpdate.ordinal());
|
||||
if (lockType != null) {
|
||||
sb.append("t").append(lockType.ordinal());
|
||||
sb.append('t').append(lockType.ordinal());
|
||||
}
|
||||
}
|
||||
if (id != null) {
|
||||
@@ -1082,27 +1092,27 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
if (detail != null) {
|
||||
sb.append("/d[");
|
||||
detail.queryPlanHash(sb);
|
||||
sb.append("]");
|
||||
sb.append(']');
|
||||
}
|
||||
if (bindParams != null) {
|
||||
sb.append("/b[");
|
||||
bindParams.buildQueryPlanHash(sb);
|
||||
sb.append("]");
|
||||
sb.append(']');
|
||||
}
|
||||
if (whereExpressions != null) {
|
||||
sb.append("/w[");
|
||||
whereExpressions.queryPlanHash(sb);
|
||||
sb.append("]");
|
||||
sb.append(']');
|
||||
}
|
||||
if (havingExpressions != null) {
|
||||
sb.append("/h[");
|
||||
havingExpressions.queryPlanHash(sb);
|
||||
sb.append("]");
|
||||
sb.append(']');
|
||||
}
|
||||
if (updateProperties != null) {
|
||||
sb.append("/u[");
|
||||
updateProperties.buildQueryPlanHash(sb);
|
||||
sb.append("]");
|
||||
sb.append(']');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
@@ -1396,6 +1406,17 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> usingMaster() {
|
||||
this.useMaster = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUseMaster() {
|
||||
return useMaster;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int delete() {
|
||||
return server.delete(this, transaction);
|
||||
|
||||
+11
@@ -49,6 +49,17 @@ public final class DefaultRelationalQuery extends AbstractQuery implements SpiSq
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlQuery usingMaster() {
|
||||
this.useMaster = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUseMaster() {
|
||||
return useMaster;
|
||||
}
|
||||
|
||||
private void transaction(Transaction transaction) {
|
||||
this.transaction = transaction;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,11 @@ final class OrmQueryPlanKey implements CQueryPlanKey {
|
||||
return new OrmQueryPlanKey(description + "/deleteByIds", 0, 0, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useCache() {
|
||||
return !description.startsWith("$NoCache");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String partialKey() {
|
||||
return description;
|
||||
|
||||
+3
-2
@@ -43,10 +43,11 @@ public interface DataSourceSupplier {
|
||||
/**
|
||||
* Return a connection from the read only DataSource taking into account a tenantId for multi-tenant lazy loading.
|
||||
*
|
||||
* @param tenantId Most often null but well supplied indicates a multi-tenant lazy loading query
|
||||
* @param tenantId Most often null but well supplied indicates a multi-tenant lazy loading query
|
||||
* @param useMaster When true use the master data source
|
||||
* @return the connection to use
|
||||
*/
|
||||
Connection readOnlyConnection(Object tenantId) throws SQLException;
|
||||
Connection readOnlyConnection(Object tenantId, boolean useMaster) throws SQLException;
|
||||
|
||||
/**
|
||||
* Shutdown the datasource de-registering the JDBC driver if requested.
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ public final class DocStoreTransactionManager extends TransactionManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiTransaction createReadOnlyTransaction(Object tenantId) {
|
||||
public SpiTransaction createReadOnlyTransaction(Object tenantId, boolean useMaster) {
|
||||
return new DocStoreOnlyTransaction(false, this);
|
||||
}
|
||||
|
||||
|
||||
+34
-10
@@ -32,6 +32,10 @@ final class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEve
|
||||
private static final String illegalStateMessage = "Transaction is Inactive";
|
||||
private static final String notExpectedMessage = "Not expected on read only transaction";
|
||||
|
||||
/**
|
||||
* Set false when using autoCommit (as a performance optimisation for the read-only case).
|
||||
*/
|
||||
private final boolean useCommit;
|
||||
private final TransactionManager manager;
|
||||
private final SpiTxnLogger logger;
|
||||
private final boolean logSql;
|
||||
@@ -60,7 +64,7 @@ final class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEve
|
||||
/**
|
||||
* Create without a tenantId.
|
||||
*/
|
||||
ImplicitReadOnlyTransaction(TransactionManager manager, Connection connection) {
|
||||
ImplicitReadOnlyTransaction(boolean useCommit, TransactionManager manager, Connection connection) {
|
||||
this.manager = manager;
|
||||
this.logger = manager.loggerReadOnly();
|
||||
this.logSql = logger.isLogSql();
|
||||
@@ -69,13 +73,18 @@ final class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEve
|
||||
this.connection = connection;
|
||||
this.persistenceContext = new DefaultPersistenceContext();
|
||||
this.startNanos = System.nanoTime();
|
||||
try {
|
||||
this.useCommit = useCommit && !connection.getAutoCommit();
|
||||
} catch (SQLException e) {
|
||||
throw new PersistenceException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create with a tenantId.
|
||||
*/
|
||||
ImplicitReadOnlyTransaction(TransactionManager manager, Connection connection, Object tenantId) {
|
||||
this(manager, connection);
|
||||
this(true, manager, connection);
|
||||
this.tenantId = tenantId;
|
||||
}
|
||||
|
||||
@@ -505,16 +514,22 @@ final class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEve
|
||||
// do nothing, expect AutoCommit
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit the transaction.
|
||||
*/
|
||||
@Override
|
||||
public void commit() {
|
||||
if (!active) {
|
||||
throw new IllegalStateException(illegalStateMessage);
|
||||
}
|
||||
// expect AutoCommit so just deactivate / put back into pool
|
||||
deactivate();
|
||||
try {
|
||||
if (useCommit) {
|
||||
try {
|
||||
connection.commit();
|
||||
} catch (SQLException e) {
|
||||
throw new PersistenceException(e);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -556,8 +571,17 @@ final class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEve
|
||||
if (!active) {
|
||||
throw new IllegalStateException(illegalStateMessage);
|
||||
}
|
||||
// expect AutoCommit so it really has already committed
|
||||
deactivate();
|
||||
try {
|
||||
if (useCommit) {
|
||||
try {
|
||||
connection.rollback();
|
||||
} catch (SQLException e) {
|
||||
throw new PersistenceException(e);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -565,7 +589,7 @@ final class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEve
|
||||
*/
|
||||
@Override
|
||||
public void end() throws PersistenceException {
|
||||
if (isActive()) {
|
||||
if (active) {
|
||||
rollback();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +190,6 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public final void setAutoPersistUpdates(boolean autoPersistUpdates) {
|
||||
this.autoPersistUpdates = autoPersistUpdates;
|
||||
@@ -251,7 +250,7 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
|
||||
callbackList.add(callback);
|
||||
}
|
||||
|
||||
private void withEachCallback(Consumer<TransactionCallback> consumer) {
|
||||
private void withEachCallbackFailSilent(Consumer<TransactionCallback> consumer) {
|
||||
if (callbackList != null) {
|
||||
// using old style loop to cater for case when new callbacks are added recursively (as otherwise iterator fails fast)
|
||||
for (int i = 0; i < callbackList.size(); i++) {
|
||||
@@ -259,17 +258,27 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
|
||||
consumer.accept(callbackList.get(i));
|
||||
} catch (Exception e) {
|
||||
log.log(ERROR, "Error executing transaction callback", e);
|
||||
throw wrapIfNeeded(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void withEachCallback(Consumer<TransactionCallback> consumer) {
|
||||
if (callbackList != null) {
|
||||
// using old style loop to cater for case when new callbacks are added recursively (as otherwise iterator fails fast)
|
||||
for (int i = 0; i < callbackList.size(); i++) {
|
||||
consumer.accept(callbackList.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void firePreRollback() {
|
||||
withEachCallback(TransactionCallback::preRollback);
|
||||
withEachCallbackFailSilent(TransactionCallback::preRollback);
|
||||
}
|
||||
|
||||
private void firePostRollback() {
|
||||
withEachCallback(TransactionCallback::postRollback);
|
||||
withEachCallbackFailSilent(TransactionCallback::postRollback);
|
||||
if (changeLogHolder != null) {
|
||||
changeLogHolder.postRollback();
|
||||
}
|
||||
|
||||
+2
-1
@@ -78,8 +78,9 @@ public final class JtaTransactionManager implements ExternalTransactionManager {
|
||||
*/
|
||||
@Override
|
||||
public Object getCurrentTransaction() {
|
||||
TransactionSynchronizationRegistry syncRegistry = registry();
|
||||
TransactionSynchronizationRegistry syncRegistry;
|
||||
try {
|
||||
syncRegistry = registry();
|
||||
SpiTransaction t = (SpiTransaction) syncRegistry.getResource(EBEAN_TXN_RESOURCE);
|
||||
if (t != null) {
|
||||
// we have already seen this transaction
|
||||
|
||||
+3
-2
@@ -21,9 +21,10 @@ abstract class TransactionFactory {
|
||||
/**
|
||||
* Return a new query only transaction.
|
||||
*
|
||||
* @param tenantId The tenantId for lazy loading queries.
|
||||
* @param tenantId The tenantId for lazy loading queries.
|
||||
* @param useMaster Explicitly use the master data source rather than read only data source
|
||||
*/
|
||||
abstract SpiTransaction createReadOnlyTransaction(Object tenantId);
|
||||
abstract SpiTransaction createReadOnlyTransaction(Object tenantId, boolean useMaster);
|
||||
|
||||
/**
|
||||
* Return a new transaction.
|
||||
|
||||
+3
-4
@@ -13,7 +13,7 @@ import java.sql.SQLException;
|
||||
*/
|
||||
class TransactionFactoryBasic extends TransactionFactory {
|
||||
|
||||
private final DataSource dataSource;
|
||||
protected final DataSource dataSource;
|
||||
|
||||
TransactionFactoryBasic(TransactionManager manager, DataSourceSupplier dataSourceSupplier) {
|
||||
super(manager);
|
||||
@@ -21,12 +21,11 @@ class TransactionFactoryBasic extends TransactionFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiTransaction createReadOnlyTransaction(Object tenantId) {
|
||||
public SpiTransaction createReadOnlyTransaction(Object tenantId, boolean useMaster) {
|
||||
Connection connection = null;
|
||||
try {
|
||||
connection = dataSource.getConnection();
|
||||
return create(false, connection);
|
||||
|
||||
return new ImplicitReadOnlyTransaction(true, manager, connection);
|
||||
} catch (PersistenceException ex) {
|
||||
JdbcClose.close(connection);
|
||||
throw ex;
|
||||
|
||||
+3
-3
@@ -26,11 +26,11 @@ final class TransactionFactoryBasicWithRead extends TransactionFactoryBasic {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiTransaction createReadOnlyTransaction(Object tenantId) {
|
||||
public SpiTransaction createReadOnlyTransaction(Object tenantId, boolean useMaster) {
|
||||
Connection connection = null;
|
||||
try {
|
||||
connection = readOnlyDataSource.getConnection();
|
||||
return new ImplicitReadOnlyTransaction(manager, connection);
|
||||
connection = useMaster ? dataSource.getConnection() : readOnlyDataSource.getConnection();
|
||||
return new ImplicitReadOnlyTransaction(useMaster, manager, connection);
|
||||
} catch (PersistenceException ex) {
|
||||
JdbcClose.close(connection);
|
||||
throw ex;
|
||||
|
||||
-1
@@ -11,7 +11,6 @@ final class TransactionFactoryBuilder {
|
||||
* Build and return based on multi-tenancy and read only DataSource.
|
||||
*/
|
||||
static TransactionFactory build(TransactionManager manager, DataSourceSupplier dataSourceSupplier, CurrentTenantProvider tenantProvider) {
|
||||
|
||||
boolean hasReadOnlyDataSource = dataSourceSupplier.readOnlyDataSource() != null;
|
||||
if (tenantProvider == null) {
|
||||
if (hasReadOnlyDataSource) {
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ class TransactionFactoryTenant extends TransactionFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiTransaction createReadOnlyTransaction(Object tenantId) {
|
||||
public SpiTransaction createReadOnlyTransaction(Object tenantId, boolean useMaster) {
|
||||
return create(false, tenantId);
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -23,14 +23,14 @@ final class TransactionFactoryTenantWithRead extends TransactionFactoryTenant {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiTransaction createReadOnlyTransaction(Object tenantId) {
|
||||
public SpiTransaction createReadOnlyTransaction(Object tenantId, boolean useMaster) {
|
||||
Connection connection = null;
|
||||
try {
|
||||
if (tenantId == null) {
|
||||
// obtain the tenantId if the DataSource requires it
|
||||
tenantId = dataSourceSupplier.currentTenantId();
|
||||
}
|
||||
connection = dataSourceSupplier.readOnlyConnection(tenantId);
|
||||
connection = dataSourceSupplier.readOnlyConnection(tenantId, useMaster);
|
||||
return new ImplicitReadOnlyTransaction(manager, connection, tenantId);
|
||||
} catch (PersistenceException ex) {
|
||||
JdbcClose.close(connection);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user