mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
86
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7853bf0960 | ||
|
|
0128d64841 | ||
|
|
68b313f778 | ||
|
|
fad32c58d8 | ||
|
|
8f1ebdb89a | ||
|
|
f7703efde2 | ||
|
|
c5ffccb649 | ||
|
|
3e65705bf9 | ||
|
|
7469a38bbc | ||
|
|
7ea4311662 | ||
|
|
f556e04f58 | ||
|
|
d9c75a60a5 | ||
|
|
225bec7b28 | ||
|
|
da44f7e604 | ||
|
|
e0eda4f8be | ||
|
|
e4e780588c | ||
|
|
7c8f235550 | ||
|
|
9a77ec1567 | ||
|
|
ff426319f5 | ||
|
|
7f56aff9dd | ||
|
|
cdbdd98d36 | ||
|
|
7bf030f59c | ||
|
|
16dca28831 | ||
|
|
678b43693d | ||
|
|
7ab93a0cdf | ||
|
|
951f942c73 | ||
|
|
cf2ec4b81d | ||
|
|
7d1745ba53 | ||
|
|
7adbdbf532 | ||
|
|
40d9c88e34 | ||
|
|
15b3eb2bf3 | ||
|
|
ab45ad34e0 | ||
|
|
24b514f851 | ||
|
|
582fec7ce4 | ||
|
|
0b11c541c8 | ||
|
|
540ceab96f | ||
|
|
8b858a073a | ||
|
|
02dafc9838 | ||
|
|
0816810d3b | ||
|
|
1f6e2ee844 | ||
|
|
dc00765a98 | ||
|
|
a48b2f4ebe | ||
|
|
837563544f | ||
|
|
fd199f406b | ||
|
|
a48e96c7e9 | ||
|
|
7ba6e5f67d | ||
|
|
f53c56490c | ||
|
|
6ce42b1ca3 | ||
|
|
89617cefbe | ||
|
|
dd377621a4 | ||
|
|
d844855462 | ||
|
|
f68c25d5f3 | ||
|
|
61cfc7a979 | ||
|
|
3c98ee7f1b | ||
|
|
0738316f15 | ||
|
|
ceb83befa3 | ||
|
|
a0b04cceda | ||
|
|
03edfb5454 | ||
|
|
62015451df | ||
|
|
ed9113efe6 | ||
|
|
334793667e | ||
|
|
351a1c4739 | ||
|
|
b2de333dcc | ||
|
|
6091f7b683 | ||
|
|
43fb84cbc0 | ||
|
|
52a4e9e19b | ||
|
|
a2cdea24ed | ||
|
|
cd780208e5 | ||
|
|
9ce0e923d7 | ||
|
|
9e461e4708 | ||
|
|
5fa09a6f90 | ||
|
|
6babb2e6f5 | ||
|
|
26abe27e42 | ||
|
|
9b18d46b78 | ||
|
|
eed487ad26 | ||
|
|
c10865dfaf | ||
|
|
2352df309c | ||
|
|
feb2bd1e15 | ||
|
|
11c9bdfc6f | ||
|
|
559b39eedc | ||
|
|
0ebcba17f1 | ||
|
|
71edd33fa3 | ||
|
|
4a6fc98395 | ||
|
|
7322030e90 | ||
|
|
77634fc3eb | ||
|
|
ed8d4b5fc4 |
@@ -1,7 +1,10 @@
|
||||
|
||||
name: Build
|
||||
|
||||
on: [push, pull_request]
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches: master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-clickhouse</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-db2</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-hana</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-mariadb</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-mysql</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-nuodb</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-oracle</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
<properties>
|
||||
<postgis.jdbc.version>2.5.1</postgis.jdbc.version>
|
||||
<postgres.jdbc.version>42.6.0</postgres.jdbc.version>
|
||||
<postgres.jdbc.version>42.7.2</postgres.jdbc.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -22,13 +22,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -47,19 +47,19 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis-types</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlite</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlserver</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,31 +17,31 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-joda-time</artifactId>
|
||||
<version>13.24.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-jsonnode</artifactId>
|
||||
<version>13.24.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-mapper</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -60,13 +60,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-all</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>composites</artifactId>
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean api</name>
|
||||
@@ -39,7 +39,7 @@
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>avaje-config</artifactId>
|
||||
<version>3.10</version>
|
||||
<version>3.12</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -3,7 +3,7 @@ package io.ebean;
|
||||
import jakarta.persistence.PersistenceException;
|
||||
|
||||
/**
|
||||
* Thrown when a foreign key constraint is enforced.
|
||||
* Thrown when a foreign key constraint is enforced or a field is too large.
|
||||
*/
|
||||
public class DataIntegrityException extends PersistenceException {
|
||||
private static final long serialVersionUID = -6740171949170180970L;
|
||||
@@ -14,4 +14,11 @@ public class DataIntegrityException extends PersistenceException {
|
||||
public DataIntegrityException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create with message only.
|
||||
*/
|
||||
public DataIntegrityException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,16 +88,16 @@ public interface Database {
|
||||
|
||||
/**
|
||||
* Return a new database builder.
|
||||
* <pre>{@code
|
||||
*
|
||||
* // build the 'default' database using configuration
|
||||
* // from application.properties / application.yaml
|
||||
*
|
||||
* Database db = Database.builder()
|
||||
* .loadFromProperties()
|
||||
* .build();
|
||||
*
|
||||
* }</pre>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // build the 'default' database using configuration
|
||||
* // from application.properties / application.yaml
|
||||
*
|
||||
* Database db = Database.builder()
|
||||
* .loadFromProperties()
|
||||
* .build();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
static DatabaseBuilder builder() {
|
||||
return new DatabaseConfig();
|
||||
|
||||
@@ -85,6 +85,7 @@ public interface DatabaseBuilder {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the Database.
|
||||
*/
|
||||
@@ -2164,6 +2165,15 @@ public interface DatabaseBuilder {
|
||||
@Deprecated
|
||||
DatabaseBuilder setLoadModuleInfo(boolean loadModuleInfo);
|
||||
|
||||
/**
|
||||
* Set if generated SQL SELECT should include the query label as an
|
||||
* inline SQL comment (to help reference back from the SQL to the code
|
||||
* that executed the query.
|
||||
*
|
||||
* @param includeLabelInSql When true include a SQL inline comment in generated SELECT queries.
|
||||
*/
|
||||
DatabaseConfig includeLabelInSql(boolean includeLabelInSql);
|
||||
|
||||
/**
|
||||
* Set the naming convention to apply to metrics names.
|
||||
*/
|
||||
@@ -2177,6 +2187,11 @@ public interface DatabaseBuilder {
|
||||
@Deprecated
|
||||
DatabaseBuilder setMetricNaming(Function<String, String> metricNaming);
|
||||
|
||||
/**
|
||||
* Sets the length check mode.
|
||||
*/
|
||||
DatabaseConfig lengthCheck(LengthCheck lengthCheck);
|
||||
|
||||
/**
|
||||
* Provides read access (getters) for the DatabaseBuilder configuration
|
||||
* that has been set.
|
||||
@@ -3034,10 +3049,20 @@ public interface DatabaseBuilder {
|
||||
*/
|
||||
boolean isLoadModuleInfo();
|
||||
|
||||
/**
|
||||
* Return true if generated sql select query should include an inline sql comment with the
|
||||
* query label or profile location label.
|
||||
*/
|
||||
boolean isIncludeLabelInSql();
|
||||
|
||||
/**
|
||||
* Return the naming convention to apply to metrics names.
|
||||
*/
|
||||
Function<String, String> getMetricNaming();
|
||||
|
||||
/**
|
||||
* Returns the length check mode.
|
||||
*/
|
||||
LengthCheck getLengthCheck();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,6 +216,8 @@ public interface ExpressionList<T> {
|
||||
int delete();
|
||||
|
||||
/**
|
||||
* @deprecated migrate to {@link #usingTransaction(Transaction)} then delete().
|
||||
* <p>
|
||||
* Execute as a delete query deleting the 'root level' beans that match the predicates
|
||||
* in the query.
|
||||
* <p>
|
||||
@@ -225,6 +227,7 @@ public interface ExpressionList<T> {
|
||||
*
|
||||
* @return the number of rows that were deleted.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "13.1.0")
|
||||
int delete(Transaction transaction);
|
||||
|
||||
/**
|
||||
@@ -236,11 +239,14 @@ public interface ExpressionList<T> {
|
||||
int update();
|
||||
|
||||
/**
|
||||
* @deprecated migrate to {@link #usingTransaction(Transaction)} then update().
|
||||
* <p>
|
||||
* Execute as a update query with the given transaction.
|
||||
*
|
||||
* @return the number of rows that were updated.
|
||||
* @see UpdateQuery
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "13.1.0")
|
||||
int update(Transaction transaction);
|
||||
|
||||
/**
|
||||
@@ -412,6 +418,42 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
Optional<T> findOneOrEmpty();
|
||||
|
||||
/**
|
||||
* Execute find row count query in a background thread.
|
||||
* <p>
|
||||
* This returns a Future object which can be used to cancel, check the
|
||||
* execution status (isDone etc) and get the value (with or without a
|
||||
* timeout).
|
||||
* </p>
|
||||
*
|
||||
* @return a Future object for the row count query
|
||||
*/
|
||||
FutureRowCount<T> findFutureCount();
|
||||
|
||||
/**
|
||||
* Execute find Id's query in a background thread.
|
||||
* <p>
|
||||
* This returns a Future object which can be used to cancel, check the
|
||||
* execution status (isDone etc) and get the value (with or without a
|
||||
* timeout).
|
||||
* </p>
|
||||
*
|
||||
* @return a Future object for the list of Id's
|
||||
*/
|
||||
FutureIds<T> findFutureIds();
|
||||
|
||||
/**
|
||||
* Execute find list query in a background thread.
|
||||
* <p>
|
||||
* This returns a Future object which can be used to cancel, check the
|
||||
* execution status (isDone etc) and get the value (with or without a
|
||||
* timeout).
|
||||
* </p>
|
||||
*
|
||||
* @return a Future object for the list result of the query
|
||||
*/
|
||||
FutureList<T> findFutureList();
|
||||
|
||||
/**
|
||||
* Return a PagedList for this query using firstRow and maxRows.
|
||||
* <p>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package io.ebean;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* FutureIds represents the result of a background query execution for the Id's.
|
||||
* <p>
|
||||
* It extends the java.util.concurrent.Future with the ability to get the Id's
|
||||
* while the query is still executing in the background.
|
||||
* </p>
|
||||
*/
|
||||
public interface FutureIds<T> extends Future<List<Object>> {
|
||||
|
||||
/**
|
||||
* Returns the original query used to fetch the Id's.
|
||||
*/
|
||||
Query<T> getQuery();
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,903 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.avaje.lang.Nullable;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Build and execute an ORM query.
|
||||
*
|
||||
* @param <SELF> The type of the builder
|
||||
* @param <T> The entity bean type
|
||||
*/
|
||||
public interface QueryBuilder<SELF, T> extends QueryBuilderProjection<SELF, T> {
|
||||
|
||||
/**
|
||||
* Set root table alias.
|
||||
*/
|
||||
SELF alias(String alias);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
SELF alsoIf(BooleanSupplier predicate, Consumer<SELF> apply);
|
||||
|
||||
/**
|
||||
* Perform an 'As of' query using history tables to return the object graph
|
||||
* as of a time in the past.
|
||||
* <p>
|
||||
* To perform this query the DB must have underlying history tables.
|
||||
*
|
||||
* @param asOf the date time in the past at which you want to view the data
|
||||
*/
|
||||
SELF asOf(Timestamp asOf);
|
||||
|
||||
/**
|
||||
* Convert the query to a DTO bean query.
|
||||
* <p>
|
||||
* We effectively use the underlying ORM query to build the SQL and then execute
|
||||
* and map it into DTO beans.
|
||||
*/
|
||||
<D> DtoQuery<D> asDto(Class<D> dtoClass);
|
||||
|
||||
/**
|
||||
* Convert the query to a UpdateQuery.
|
||||
* <p>
|
||||
* Typically this is used with query beans to covert a query bean
|
||||
* query into an UpdateQuery like the examples below.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* int rowsUpdated = new QCustomer()
|
||||
* .name.startsWith("Rob")
|
||||
* .asUpdate()
|
||||
* .set("active", false)
|
||||
* .update();;
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* int rowsUpdated = new QContact()
|
||||
* .notes.note.startsWith("Make Inactive")
|
||||
* .email.endsWith("@foo.com")
|
||||
* .customer.id.equalTo(42)
|
||||
* .asUpdate()
|
||||
* .set("inactive", true)
|
||||
* .setRaw("email = lower(email)")
|
||||
* .update();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
UpdateQuery<T> asUpdate();
|
||||
|
||||
/**
|
||||
* Return a copy of the query.
|
||||
* <p>
|
||||
* This is so that you can use a Query as a "prototype" for creating other
|
||||
* query instances. You could create a Query with various where expressions
|
||||
* and use that as a "prototype" - using this copy() method to create a new
|
||||
* instance that you can then add other expressions then execute.
|
||||
* </p>
|
||||
*/
|
||||
SELF copy();
|
||||
|
||||
/**
|
||||
* Execute the query using the given transaction.
|
||||
*/
|
||||
SELF usingTransaction(Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the query using the given connection.
|
||||
*/
|
||||
SELF usingConnection(Connection connection);
|
||||
|
||||
/**
|
||||
* Execute the query using the given database.
|
||||
*/
|
||||
SELF 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.
|
||||
*/
|
||||
SELF usingMaster();
|
||||
|
||||
/**
|
||||
* Set the base table to use for this query.
|
||||
* <p>
|
||||
* Typically this is used when a table has partitioning and we wish to specify a specific
|
||||
* partition/table to query against.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* QOrder()
|
||||
* .setBaseTable("order_2019_05")
|
||||
* .status.equalTo(Status.NEW)
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
SELF setBaseTable(String baseTable);
|
||||
|
||||
/**
|
||||
* Specify the PersistenceContextScope to use for this query.
|
||||
* <p>
|
||||
* When this is not set the 'default' configured on {@link io.ebean.config.DatabaseConfig#setPersistenceContextScope(PersistenceContextScope)}
|
||||
* is used - this value defaults to {@link PersistenceContextScope#TRANSACTION}.
|
||||
* <p>
|
||||
* Note that the same persistence Context is used for subsequent lazy loading and query join queries.
|
||||
* <p>
|
||||
* Note that #findEach uses a 'per object graph' PersistenceContext so this scope is ignored for
|
||||
* queries executed as #findIterate, #findEach, #findEachWhile.
|
||||
*
|
||||
* @param scope The scope to use for this query and subsequent lazy loading.
|
||||
*/
|
||||
SELF setPersistenceContextScope(PersistenceContextScope scope);
|
||||
|
||||
/**
|
||||
* Explicitly specify whether to use AutoTune for this query.
|
||||
* <p>
|
||||
* If you do not call this method on a query the "Implicit AutoTune mode" is
|
||||
* used to determine if AutoTune should be used for a given query.
|
||||
* <p>
|
||||
* AutoTune can add additional fetch paths to the query and specify which
|
||||
* properties are included for each path. If you have explicitly defined some
|
||||
* fetch paths AutoTune will not remove them.
|
||||
*/
|
||||
SELF setAutoTune(boolean autoTune);
|
||||
|
||||
/**
|
||||
* Execute the query allowing properties with invalid JSON to be collected and not fail the query.
|
||||
* <pre>{@code
|
||||
*
|
||||
* // fetch a bean with JSON content
|
||||
* EBasicJsonList bean= DB.find(EBasicJsonList.class)
|
||||
* .setId(42)
|
||||
* .setAllowLoadErrors() // collect errors into bean state if we have invalid JSON
|
||||
* .findOne();
|
||||
*
|
||||
*
|
||||
* // get the invalid JSON errors from the bean state
|
||||
* Map<String, Exception> errors = server().getBeanState(bean).getLoadErrors();
|
||||
*
|
||||
* // If this map is not empty tell we have invalid JSON
|
||||
* // and should try and fix the JSON content or inform the user
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
SELF setAllowLoadErrors();
|
||||
|
||||
/**
|
||||
* Set the default lazy loading batch size to use.
|
||||
* <p>
|
||||
* When lazy loading is invoked on beans loaded by this query then this sets the
|
||||
* batch size used to load those beans.
|
||||
*
|
||||
* @param lazyLoadBatchSize the number of beans to lazy load in a single batch
|
||||
*/
|
||||
SELF setLazyLoadBatchSize(int lazyLoadBatchSize);
|
||||
|
||||
/**
|
||||
* Set a label on the query.
|
||||
* <p>
|
||||
* This label can be used to help identify query performance metrics but we can also use
|
||||
* profile location enhancement on Finders so for some that would be a better option.
|
||||
*/
|
||||
SELF setLabel(String label);
|
||||
|
||||
/**
|
||||
* Set a SQL query hint.
|
||||
* <p>
|
||||
* This results in an inline comment that immediately follows
|
||||
* after the select keyword in the form: {@code /*+ hint *\/ }
|
||||
*/
|
||||
SELF setHint(String hint);
|
||||
|
||||
/**
|
||||
* Execute the query including soft deleted rows.
|
||||
* <p>
|
||||
* This means that Ebean will not add any predicates to the query for filtering out
|
||||
* soft deleted rows. You can still add your own predicates for the deleted properties
|
||||
* and effectively you have full control over the query to include or exclude soft deleted
|
||||
* rows as needed for a given use case.
|
||||
*/
|
||||
SELF setIncludeSoftDeletes();
|
||||
|
||||
/**
|
||||
* Set true if you want to disable lazy loading.
|
||||
* <p>
|
||||
* That is, once the object graph is returned further lazy loading is disabled.
|
||||
*/
|
||||
SELF setDisableLazyLoading(boolean disableLazyLoading);
|
||||
|
||||
/**
|
||||
* Set whether this query uses DISTINCT.
|
||||
*/
|
||||
SELF setDistinct(boolean distinct);
|
||||
|
||||
/**
|
||||
* Set the first row to return for this query.
|
||||
*
|
||||
* @param firstRow the first row to include in the query result.
|
||||
*/
|
||||
SELF setFirstRow(int firstRow);
|
||||
|
||||
/**
|
||||
* Set the maximum number of rows to return in the query.
|
||||
*
|
||||
* @param maxRows the maximum number of rows to return in the query.
|
||||
*/
|
||||
SELF setMaxRows(int maxRows);
|
||||
|
||||
/**
|
||||
* Set RawSql to use for this query.
|
||||
*/
|
||||
SELF setRawSql(RawSql rawSql);
|
||||
|
||||
/**
|
||||
* Extended version for setDistinct in conjunction with "findSingleAttributeList";
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<CountedValue<Order.Status>> orderStatusCount =
|
||||
*
|
||||
* DB.find(Order.class)
|
||||
* .select("status")
|
||||
* .where()
|
||||
* .gt("orderDate", LocalDate.now().minusMonths(3))
|
||||
*
|
||||
* // fetch as single attribute with a COUNT
|
||||
* .setCountDistinct(CountDistinctOrder.COUNT_DESC_ATTR_ASC)
|
||||
* .findSingleAttributeList();
|
||||
*
|
||||
* for (CountedValue<Order.Status> entry : orderStatusCount) {
|
||||
* System.out.println(" count:" + entry.getCount()+" orderStatus:" + entry.getValue() );
|
||||
* }
|
||||
*
|
||||
* // produces
|
||||
*
|
||||
* count:3 orderStatus:NEW
|
||||
* count:1 orderStatus:SHIPPED
|
||||
* count:1 orderStatus:COMPLETE
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
SELF setCountDistinct(CountDistinctOrder orderBy);
|
||||
|
||||
/**
|
||||
* Set the property to use as keys for a map.
|
||||
* <p>
|
||||
* If no property is set then the id property is used.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // Assuming sku is unique for products...
|
||||
*
|
||||
* Map<String,Product> productMap = DB.find(Product.class)
|
||||
* .setMapKey("sku") // sku map keys...
|
||||
* .findMap();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param mapKey the property to use as keys for a map.
|
||||
*/
|
||||
SELF setMapKey(String mapKey);
|
||||
|
||||
/**
|
||||
* When set to true when you want the returned beans to be read only.
|
||||
*/
|
||||
SELF setReadOnly(boolean readOnly);
|
||||
|
||||
/**
|
||||
* Set a timeout on this query.
|
||||
* <p>
|
||||
* This will typically result in a call to setQueryTimeout() on a
|
||||
* preparedStatement. If the timeout occurs an exception will be thrown - this
|
||||
* will be a SQLException wrapped up in a PersistenceException.
|
||||
* </p>
|
||||
*
|
||||
* @param secs the query timeout limit in seconds. Zero means there is no limit.
|
||||
*/
|
||||
SELF setTimeout(int secs);
|
||||
|
||||
/**
|
||||
* A hint which for JDBC translates to the Statement.fetchSize().
|
||||
* <p>
|
||||
* Gives the JDBC driver a hint as to the number of rows that should be
|
||||
* fetched from the database when more rows are needed for ResultSet.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that internally findEach and findEachWhile will set the fetch size
|
||||
* if it has not already as these queries expect to process a lot of rows.
|
||||
* If we didn't then Postgres and MySql for example would eagerly pull back
|
||||
* all the row data and potentially consume a lot of memory in the process.
|
||||
* </p>
|
||||
* <p>
|
||||
* As findEach and findEachWhile automatically set the fetch size we don't have
|
||||
* to do so generally but we might still wish to for tuning a specific use case.
|
||||
* </p>
|
||||
*/
|
||||
SELF setBufferFetchSizeHint(int fetchSize);
|
||||
|
||||
/**
|
||||
* Set the mode to use the bean cache when executing this query.
|
||||
* <p>
|
||||
* By default, "find by id" and "find by natural key" will use the bean cache
|
||||
* when bean caching is enabled. Setting this to false means that the query
|
||||
* will not use the bean cache and instead hit the database.
|
||||
* <p>
|
||||
* By default, findList() with natural keys will not use the bean cache. In that
|
||||
* case we need to explicitly use the bean cache.
|
||||
*/
|
||||
SELF setBeanCacheMode(CacheMode beanCacheMode);
|
||||
|
||||
/**
|
||||
* Set the {@link CacheMode} to use the query for executing this query.
|
||||
*/
|
||||
SELF setUseQueryCache(CacheMode cacheMode);
|
||||
|
||||
/**
|
||||
* Set this to false to not use the bean cache.
|
||||
* <p>
|
||||
* This method is now superseded by {@link #setBeanCacheMode(CacheMode)}
|
||||
* which provides more explicit options controlled bean cache use.
|
||||
* <p>
|
||||
* This method is likely to be deprecated in the future with migration
|
||||
* over to setUseBeanCache().
|
||||
*/
|
||||
default SELF setUseCache(boolean useCache) {
|
||||
return setBeanCacheMode(useCache ? CacheMode.ON : CacheMode.OFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls {@link #setUseQueryCache(CacheMode)} with <code>ON</code> or <code>OFF</code>.
|
||||
*/
|
||||
default SELF setUseQueryCache(boolean enabled) {
|
||||
return setUseQueryCache(enabled ? CacheMode.ON : CacheMode.OFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the order by clause replacing the existing order by clause if there is
|
||||
* one.
|
||||
* <p>
|
||||
* This follows SQL syntax using commas between each property with the
|
||||
* optional asc and desc keywords representing ascending and descending order
|
||||
* respectively.
|
||||
*/
|
||||
SELF orderBy(String orderByClause);
|
||||
|
||||
/**
|
||||
* Set an OrderBy object to replace any existing OrderBy clause.
|
||||
*/
|
||||
SELF setOrderBy(OrderBy<T> orderBy);
|
||||
|
||||
/**
|
||||
* Controls, if paginated queries should always append an 'order by id' statement at the end to
|
||||
* guarantee a deterministic sort result. This may affect performance.
|
||||
* If this is not enabled, and an orderBy is set on the query, it's up to the programmer that
|
||||
* this query provides a deterministic result.
|
||||
*/
|
||||
SELF orderById(boolean orderById);
|
||||
|
||||
/**
|
||||
* Execute the query with the given lock type and WAIT.
|
||||
* <p>
|
||||
* Note that <code>forUpdate()</code> is the same as
|
||||
* <code>withLock(LockType.UPDATE)</code>.
|
||||
* <p>
|
||||
* Provides us with the ability to explicitly use Postgres
|
||||
* SHARE, KEY SHARE, NO KEY UPDATE and UPDATE row locks.
|
||||
*/
|
||||
SELF withLock(Query.LockType lockType);
|
||||
|
||||
/**
|
||||
* Execute the query with the given lock type and lock wait.
|
||||
* <p>
|
||||
* Note that <code>forUpdateNoWait()</code> is the same as
|
||||
* <code>withLock(LockType.UPDATE, LockWait.NOWAIT)</code>.
|
||||
* <p>
|
||||
* Provides us with the ability to explicitly use Postgres
|
||||
* SHARE, KEY SHARE, NO KEY UPDATE and UPDATE row locks.
|
||||
*/
|
||||
SELF withLock(Query.LockType lockType, Query.LockWait lockWait);
|
||||
|
||||
/**
|
||||
* Execute using "for update" clause which results in the DB locking the record.
|
||||
* <p>
|
||||
* The same as <code>withLock(LockType.UPDATE, LockWait.WAIT)</code>.
|
||||
*/
|
||||
SELF forUpdate();
|
||||
|
||||
/**
|
||||
* Execute using "for update" clause with "no wait" option.
|
||||
* <p>
|
||||
* This is typically a Postgres and Oracle only option at this stage.
|
||||
* <p>
|
||||
* The same as <code>withLock(LockType.UPDATE, LockWait.NOWAIT)</code>.
|
||||
*/
|
||||
SELF forUpdateNoWait();
|
||||
|
||||
/**
|
||||
* Execute using "for update" clause with "skip locked" option.
|
||||
* <p>
|
||||
* This is typically a Postgres and Oracle only option at this stage.
|
||||
* <p>
|
||||
* The same as <code>withLock(LockType.UPDATE, LockWait.SKIPLOCKED)</code>.
|
||||
*/
|
||||
SELF forUpdateSkipLocked();
|
||||
|
||||
/**
|
||||
* Returns the set of properties or paths that are unknown (do not map to known properties or paths).
|
||||
* <p>
|
||||
* Validate the query checking the where and orderBy expression paths to confirm if
|
||||
* they represent valid properties or paths for the given bean type.
|
||||
*/
|
||||
Set<String> validate();
|
||||
|
||||
/**
|
||||
* Return the sql that was generated for executing this query.
|
||||
* <p>
|
||||
* This is only available after the query has been executed and provided only
|
||||
* for informational purposes.
|
||||
*/
|
||||
String getGeneratedSql();
|
||||
|
||||
/**
|
||||
* Return the type of beans being queried.
|
||||
*/
|
||||
Class<T> getBeanType();
|
||||
|
||||
/**
|
||||
* Execute as a delete query deleting the 'root level' beans that match the predicates
|
||||
* in the query.
|
||||
* <p>
|
||||
* Note that if the query includes joins then the generated delete statement may not be
|
||||
* optimal depending on the database platform.
|
||||
*
|
||||
* @return the number of beans/rows that were deleted.
|
||||
*/
|
||||
int delete();
|
||||
|
||||
/**
|
||||
* Execute the query returning true if a row is found.
|
||||
* <p>
|
||||
* The query is executed using max rows of 1 and will only select the id property.
|
||||
* This method is really just a convenient way to optimise a query to perform a
|
||||
* 'does a row exist in the db' check.
|
||||
*
|
||||
* <h2>Example using a query bean:</h2>
|
||||
* <pre>{@code
|
||||
*
|
||||
* boolean userExists =
|
||||
* new QContact()
|
||||
* .email.equalTo("rob@foo.com")
|
||||
* .exists();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h2>Example:</h2>
|
||||
* <pre>{@code
|
||||
*
|
||||
* boolean userExists = query()
|
||||
* .where().eq("email", "rob@foo.com")
|
||||
* .exists();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @return True if the query finds a matching row in the database
|
||||
*/
|
||||
boolean exists();
|
||||
|
||||
/**
|
||||
* Execute the query returning either a single bean or null (if no matching
|
||||
* bean is found).
|
||||
* <p>
|
||||
* If more than 1 row is found for this query then a PersistenceException is
|
||||
* thrown.
|
||||
* <p>
|
||||
* This is useful when your predicates dictate that your query should only
|
||||
* return 0 or 1 results.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // assuming the sku of products is unique...
|
||||
* Product product =
|
||||
* new QProduct()
|
||||
* .sku.equalTo("aa113")
|
||||
* .findOne();
|
||||
* ...
|
||||
* }</pre>
|
||||
* <p>
|
||||
* It is also useful with finding objects by their id when you want to specify
|
||||
* further join information to optimise the query.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // Fetch order 42 and additionally fetch join its order details...
|
||||
* Order order =
|
||||
* new QOrder()
|
||||
* .fetch("details") // eagerly load the order details
|
||||
* .id.equalTo(42)
|
||||
* .findOne();
|
||||
*
|
||||
* // the order details were eagerly loaded
|
||||
* List<OrderDetail> details = order.getDetails();
|
||||
* ...
|
||||
* }</pre>
|
||||
*/
|
||||
@Nullable
|
||||
T findOne();
|
||||
|
||||
/**
|
||||
* Execute the query returning an optional bean.
|
||||
*/
|
||||
Optional<T> findOneOrEmpty();
|
||||
|
||||
/**
|
||||
* Execute the query returning the list of objects.
|
||||
* <p>
|
||||
* This query will execute against the EbeanServer that was used to create it.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<Customer> customers =
|
||||
* new QCustomer()
|
||||
* .name.ilike("rob%")
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @see Query#findList()
|
||||
*/
|
||||
List<T> findList();
|
||||
|
||||
/**
|
||||
* Execute the query returning the result as a Stream.
|
||||
* <p>
|
||||
* Note that this can support very large queries iterating
|
||||
* any number of results. To do so internally it can use
|
||||
* multiple persistence contexts.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // use try with resources to ensure Stream is closed
|
||||
*
|
||||
* try (Stream<Customer> stream = query.findStream()) {
|
||||
* stream
|
||||
* .map(...)
|
||||
* .collect(...);
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
Stream<T> findStream();
|
||||
|
||||
/**
|
||||
* Execute the query returning the set of objects.
|
||||
* <p>
|
||||
* This query will execute against the EbeanServer that was used to create it.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* Set<Customer> customers =
|
||||
* new QCustomer()
|
||||
* .name.ilike("rob%")
|
||||
* .findSet();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @see Query#findSet()
|
||||
*/
|
||||
Set<T> findSet();
|
||||
|
||||
/**
|
||||
* Execute the query returning the list of Id's.
|
||||
* <p>
|
||||
* This query will execute against the EbeanServer that was used to create it.
|
||||
*
|
||||
* @see Query#findIds()
|
||||
*/
|
||||
<A> List<A> findIds();
|
||||
|
||||
/**
|
||||
* Execute the query returning a map of the objects.
|
||||
* <p>
|
||||
* This query will execute against the EbeanServer that was used to create it.
|
||||
* <p>
|
||||
* You can use setMapKey() or asMapKey() to specify the property to be used as keys
|
||||
* on the map. If one is not specified then the id property is used.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* Map<String, Product> map =
|
||||
* new QProduct()
|
||||
* .sku.asMapKey()
|
||||
* .findMap();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @see Query#findMap()
|
||||
*/
|
||||
<K> Map<K, T> findMap();
|
||||
|
||||
/**
|
||||
* Execute the query iterating over the results.
|
||||
* <p>
|
||||
* Note that findIterate (and findEach and findEachWhile) uses a "per graph"
|
||||
* persistence context scope and adjusts jdbc fetch buffer size for large
|
||||
* queries. As such it is better to use findList for small queries.
|
||||
* <p>
|
||||
* Remember that with {@link QueryIterator} you must call {@link QueryIterator#close()}
|
||||
* when you have finished iterating the results (typically in a finally block).
|
||||
* <p>
|
||||
* findEach() and findEachWhile() are preferred to findIterate() as they ensure
|
||||
* the jdbc statement and resultSet are closed at the end of the iteration.
|
||||
* <p>
|
||||
* This query will execute against the EbeanServer that was used to create it.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* Query<Customer> query =
|
||||
* new QCustomer()
|
||||
* .status.equalTo(Customer.Status.NEW)
|
||||
* .orderBy()
|
||||
* id.asc()
|
||||
* .query();
|
||||
*
|
||||
* try (QueryIterator<Customer> it = query.findIterate()) {
|
||||
* while (it.hasNext()) {
|
||||
* Customer customer = it.next();
|
||||
* // do something with customer ...
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
QueryIterator<T> findIterate();
|
||||
|
||||
/**
|
||||
* Execute the query returning a list of values for a single property.
|
||||
* <p>
|
||||
* <h3>Example</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<String> names =
|
||||
* new QCustomer()
|
||||
* .setDistinct(true)
|
||||
* .select(name)
|
||||
* .findSingleAttributeList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @return the list of values for the selected property
|
||||
*/
|
||||
<A> List<A> findSingleAttributeList();
|
||||
|
||||
/**
|
||||
* Execute the query returning a single value or null for a single property.
|
||||
* <p>
|
||||
* <h3>Example</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* LocalDate maxDate =
|
||||
* new QCustomer()
|
||||
* .select("max(startDate)")
|
||||
* .findSingleAttribute();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @return a single value or null for the selected property
|
||||
*/
|
||||
@Nullable
|
||||
<A> A findSingleAttribute();
|
||||
|
||||
/**
|
||||
* Execute the query returning a single optional attribute value.
|
||||
* <p>
|
||||
* <h3>Example</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* Optional<String> maybeName =
|
||||
* new QCustomer()
|
||||
* .select(name)
|
||||
* .id.eq(42)
|
||||
* .status.eq(NEW)
|
||||
* .findSingleAttributeOrEmpty();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @return an optional value for the selected property
|
||||
*/
|
||||
<A> Optional<A> findSingleAttributeOrEmpty();
|
||||
|
||||
/**
|
||||
* Execute the query returning a hashset of values for a single property.
|
||||
*/
|
||||
<A> Set<A> findSingleAttributeSet();
|
||||
|
||||
/**
|
||||
* Execute the query processing the beans one at a time.
|
||||
* <p>
|
||||
* This method is appropriate to process very large query results as the
|
||||
* beans are consumed one at a time and do not need to be held in memory
|
||||
* (unlike #findList #findSet etc)
|
||||
* <p>
|
||||
* Note that internally Ebean can inform the JDBC driver that it is expecting larger
|
||||
* resultSet and specifically for MySQL this hint is required to stop it's JDBC driver
|
||||
* from buffering the entire resultSet. As such, for smaller resultSets findList() is
|
||||
* generally preferable.
|
||||
* <p>
|
||||
* Compared with #findEachWhile this will always process all the beans where as
|
||||
* #findEachWhile provides a way to stop processing the query result early before
|
||||
* all the beans have been read.
|
||||
* <p>
|
||||
* This method is functionally equivalent to findIterate() but instead of using an
|
||||
* iterator uses the Consumer interface which is better suited to use with closures.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* new QCustomer()
|
||||
* .status.equalTo(Status.NEW)
|
||||
* .orderBy().id.asc()
|
||||
* .findEach((Customer customer) -> {
|
||||
*
|
||||
* // do something with customer
|
||||
* System.out.println("-- visit " + customer);
|
||||
* });
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param consumer the consumer used to process the queried beans.
|
||||
*/
|
||||
void findEach(Consumer<T> consumer);
|
||||
|
||||
/**
|
||||
* Execute findEach streaming query batching the results for consuming.
|
||||
* <p>
|
||||
* This query execution will stream the results and is suited to consuming
|
||||
* large numbers of results from the database.
|
||||
* <p>
|
||||
* Typically, we use this batch consumer when we want to do further processing on
|
||||
* the beans and want to do that processing in batch form, for example - 100 at
|
||||
* a time.
|
||||
*
|
||||
* @param batch The number of beans processed in the batch
|
||||
* @param consumer Process the batch of beans
|
||||
*/
|
||||
void findEach(int batch, Consumer<List<T>> consumer);
|
||||
|
||||
/**
|
||||
* Execute the query using callbacks to a visitor to process the resulting
|
||||
* beans one at a time.
|
||||
* <p>
|
||||
* This method is functionally equivalent to findIterate() but instead of using an
|
||||
* iterator uses the Predicate interface which is better suited to use with closures.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* new QCustomer()
|
||||
* .status.equalTo(Status.NEW)
|
||||
* .orderBy().id.asc()
|
||||
* .findEachWhile((Customer customer) -> {
|
||||
*
|
||||
* // do something with customer
|
||||
* System.out.println("-- visit " + customer);
|
||||
*
|
||||
* // return true to continue processing or false to stop
|
||||
* return (customer.getId() < 40);
|
||||
* });
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param consumer the consumer used to process the queried beans.
|
||||
*/
|
||||
void findEachWhile(Predicate<T> consumer);
|
||||
|
||||
/**
|
||||
* Return versions of a @History entity bean.
|
||||
* <p>
|
||||
* Generally this query is expected to be a find by id or unique predicates query.
|
||||
* It will execute the query against the history returning the versions of the bean.
|
||||
*/
|
||||
List<Version<T>> findVersions();
|
||||
|
||||
/**
|
||||
* Return versions of a @History entity bean between a start and end timestamp.
|
||||
* <p>
|
||||
* Generally this query is expected to be a find by id or unique predicates query.
|
||||
* It will execute the query against the history returning the versions of the bean.
|
||||
*/
|
||||
List<Version<T>> findVersionsBetween(Timestamp start, Timestamp end);
|
||||
|
||||
/**
|
||||
* Return the count of entities this query should return.
|
||||
* <p>
|
||||
* This is the number of 'top level' or 'root level' entities.
|
||||
*/
|
||||
int findCount();
|
||||
|
||||
/**
|
||||
* Execute find row count query in a background thread.
|
||||
* <p>
|
||||
* This returns a Future object which can be used to cancel, check the
|
||||
* execution status (isDone etc) and get the value (with or without a
|
||||
* timeout).
|
||||
*
|
||||
* @return a Future object for the row count query
|
||||
*/
|
||||
FutureRowCount<T> findFutureCount();
|
||||
|
||||
/**
|
||||
* Execute find Id's query in a background thread.
|
||||
* <p>
|
||||
* This returns a Future object which can be used to cancel, check the
|
||||
* execution status (isDone etc) and get the value (with or without a
|
||||
* timeout).
|
||||
*
|
||||
* @return a Future object for the list of Id's
|
||||
*/
|
||||
FutureIds<T> findFutureIds();
|
||||
|
||||
/**
|
||||
* Execute find list query in a background thread.
|
||||
* <p>
|
||||
* This query will execute in it's own PersistenceContext and using its own transaction.
|
||||
* What that means is that it will not share any bean instances with other queries.
|
||||
*
|
||||
* @return a Future object for the list result of the query
|
||||
*/
|
||||
FutureList<T> findFutureList();
|
||||
|
||||
/**
|
||||
* Return a PagedList for this query using firstRow and maxRows.
|
||||
* <p>
|
||||
* The benefit of using this over findList() is that it provides functionality to get the
|
||||
* total row count etc.
|
||||
* <p>
|
||||
* If maxRows is not set on the query prior to calling findPagedList() then a
|
||||
* PersistenceException is thrown.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* PagedList<Order> pagedList =
|
||||
* new QOrder()
|
||||
* .setFirstRow(50)
|
||||
* .setMaxRows(20)
|
||||
* .findPagedList();
|
||||
*
|
||||
* // fetch the total row count in the background
|
||||
* pagedList.loadRowCount();
|
||||
*
|
||||
* List<Order> orders = pagedList.getList();
|
||||
* int totalRowCount = pagedList.getTotalRowCount();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @return The PagedList
|
||||
*/
|
||||
PagedList<T> findPagedList();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
package io.ebean;
|
||||
|
||||
/**
|
||||
* Builder for ORM Query projection (the select and fetch part).
|
||||
*
|
||||
* @param <SELF> The builder type
|
||||
* @param <T> The entity bean type
|
||||
*/
|
||||
public interface QueryBuilderProjection<SELF, T> {
|
||||
|
||||
/**
|
||||
* Apply the path properties replacing the select and fetch clauses.
|
||||
* <p>
|
||||
* This is typically used when the FetchPath is applied to both the query and the JSON output.
|
||||
*/
|
||||
SELF apply(FetchPath fetchPath);
|
||||
|
||||
/**
|
||||
* Specify the properties to fetch on the root level entity bean in comma delimited format.
|
||||
* <p>
|
||||
* The Id property is automatically included in the properties to fetch unless setDistinct(true)
|
||||
* is set on the query.
|
||||
* </p>
|
||||
* <p>
|
||||
* Use {@link #fetch(String, String)} to specify specific properties to fetch
|
||||
* on other non-root level paths of the object graph.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<Customer> customers = DB.find(Customer.class)
|
||||
* // Only fetch the customer id, name and status.
|
||||
* // This is described as a "Partial Object"
|
||||
* .select("name, status")
|
||||
* .where.ilike("name", "rob%")
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param fetchProperties the properties to fetch for this bean (* = all properties).
|
||||
*/
|
||||
SELF select(String fetchProperties);
|
||||
|
||||
/**
|
||||
* Apply the fetchGroup which defines what part of the object graph to load.
|
||||
*/
|
||||
SELF select(FetchGroup<T> fetchGroup);
|
||||
|
||||
/**
|
||||
* Specify a path to fetch eagerly including specific properties.
|
||||
* <p>
|
||||
* Ebean will endeavour to fetch this path using a SQL join. If Ebean determines that it can
|
||||
* not use a SQL join (due to maxRows or because it would result in a cartesian product) Ebean
|
||||
* will automatically convert this fetch query into a "query join" - i.e. use fetchQuery().
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // query orders...
|
||||
* List<Order> orders = DB.find(Order.class)
|
||||
* // fetch the customer...
|
||||
* // ... getting the customers name and phone number
|
||||
* .fetch("customer", "name, phoneNumber")
|
||||
*
|
||||
* // ... also fetch the customers billing address (* = all properties)
|
||||
* .fetch("customer.billingAddress", "*")
|
||||
* .findList();
|
||||
* }</pre>
|
||||
* <p>
|
||||
* If columns is null or "*" then all columns/properties for that path are fetched.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // fetch customers (their id, name and status)
|
||||
* List<Customer> customers = DB.find(Customer.class)
|
||||
* .select("name, status")
|
||||
* .fetch("contacts", "firstName,lastName,email")
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param path the property path we wish to fetch eagerly.
|
||||
* @param fetchProperties properties of the associated bean that you want to include in the
|
||||
* fetch (* means all properties, null also means all properties).
|
||||
*/
|
||||
SELF fetch(String path, String fetchProperties);
|
||||
|
||||
/**
|
||||
* Fetch the path and properties using a "query join" (separate SQL query).
|
||||
* <p>
|
||||
* This is the same as:
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* fetch(path, fetchProperties, FetchConfig.ofQuery())
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* This would be used instead of a fetch() when we use a separate SQL query to fetch this
|
||||
* part of the object graph rather than a SQL join.
|
||||
* <p>
|
||||
* We might typically get a performance benefit when the path to fetch is a OneToMany
|
||||
* or ManyToMany, the 'width' of the 'root bean' is wide and the cardinality of the many
|
||||
* is high.
|
||||
*
|
||||
* @param path the property path we wish to fetch eagerly.
|
||||
* @param fetchProperties properties of the associated bean that you want to include in the
|
||||
* fetch (* means all properties, null also means all properties).
|
||||
*/
|
||||
SELF fetchQuery(String path, String fetchProperties);
|
||||
|
||||
/**
|
||||
* Fetch the path and properties using L2 bean cache.
|
||||
*
|
||||
* @param path The path of the beans we are fetching from L2 cache.
|
||||
* @param fetchProperties The properties that should be loaded.
|
||||
*/
|
||||
SELF fetchCache(String path, String fetchProperties);
|
||||
|
||||
/**
|
||||
* Fetch the path and properties lazily (via batch lazy loading).
|
||||
* <p>
|
||||
* This is the same as:
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* fetch(path, fetchProperties, FetchConfig.ofLazy())
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* The reason for using fetchLazy() is to either:
|
||||
* <ul>
|
||||
* <li>Control/tune what is fetched as part of lazy loading</li>
|
||||
* <li>Make use of the L2 cache, build this part of the graph from L2 cache</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param path the property path we wish to fetch lazily.
|
||||
* @param fetchProperties properties of the associated bean that you want to include in the
|
||||
* fetch (* means all properties, null also means all properties).
|
||||
*/
|
||||
SELF fetchLazy(String path, String fetchProperties);
|
||||
|
||||
/**
|
||||
* Additionally specify a FetchConfig to use a separate query or lazy loading
|
||||
* to load this path.
|
||||
* <pre>{@code
|
||||
*
|
||||
* // fetch customers (their id, name and status)
|
||||
* List<Customer> customers = DB.find(Customer.class)
|
||||
* .select("name, status")
|
||||
* .fetch("contacts", "firstName,lastName,email", FetchConfig.ofLazy(10))
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param path the property path we wish to fetch eagerly.
|
||||
*/
|
||||
SELF fetch(String path, String fetchProperties, FetchConfig fetchConfig);
|
||||
|
||||
/**
|
||||
* Specify a path to fetch eagerly including all its properties.
|
||||
* <p>
|
||||
* Ebean will endeavour to fetch this path using a SQL join. If Ebean determines that it can
|
||||
* not use a SQL join (due to maxRows or because it would result in a cartesian product) Ebean
|
||||
* will automatically convert this fetch query into a "query join" - i.e. use fetchQuery().
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // fetch customers (their id, name and status)
|
||||
* List<Customer> customers = DB.find(Customer.class)
|
||||
* // eager fetch the contacts
|
||||
* .fetch("contacts")
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param path the property path we wish to fetch eagerly.
|
||||
*/
|
||||
SELF fetch(String path);
|
||||
|
||||
/**
|
||||
* Fetch the path eagerly using a "query join" (separate SQL query).
|
||||
* <p>
|
||||
* This is the same as:
|
||||
* <pre>{@code
|
||||
*
|
||||
* fetch(path, FetchConfig.ofQuery())
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* This would be used instead of a fetch() when we use a separate SQL query to fetch this
|
||||
* part of the object graph rather than a SQL join.
|
||||
* <p>
|
||||
* We might typically get a performance benefit when the path to fetch is a OneToMany
|
||||
* or ManyToMany, the 'width' of the 'root bean' is wide and the cardinality of the many
|
||||
* is high.
|
||||
*
|
||||
* @param path the property path we wish to fetch eagerly
|
||||
*/
|
||||
SELF fetchQuery(String path);
|
||||
|
||||
/**
|
||||
* Fetch the path eagerly using L2 cache.
|
||||
*/
|
||||
SELF fetchCache(String path);
|
||||
|
||||
/**
|
||||
* Fetch the path lazily (via batch lazy loading).
|
||||
* <p>
|
||||
* This is the same as:
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* fetch(path, FetchConfig.ofLazy())
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* The reason for using fetchLazy() is to either:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>Control/tune what is fetched as part of lazy loading</li>
|
||||
* <li>Make use of the L2 cache, build this part of the graph from L2 cache</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param path the property path we wish to fetch lazily.
|
||||
*/
|
||||
SELF fetchLazy(String path);
|
||||
|
||||
/**
|
||||
* Additionally specify a JoinConfig to specify a "query join" and or define
|
||||
* the lazy loading query.
|
||||
* <pre>{@code
|
||||
*
|
||||
* // fetch customers (their id, name and status)
|
||||
* List<Customer> customers = DB.find(Customer.class)
|
||||
* // lazy fetch contacts with a batch size of 100
|
||||
* .fetch("contacts", FetchConfig.ofLazy(100))
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
SELF fetch(String path, FetchConfig fetchConfig);
|
||||
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
package io.ebean.config;
|
||||
|
||||
import io.avaje.config.Config;
|
||||
import io.avaje.config.Configuration;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
@@ -19,16 +16,6 @@ public class ContainerConfig {
|
||||
private String podName;
|
||||
private int port;
|
||||
private Properties properties;
|
||||
private Configuration configuration;
|
||||
|
||||
public ContainerConfig() {
|
||||
this.configuration = Config.asConfiguration();
|
||||
this.active = configuration.getBool("ebean.cluster.active", active);
|
||||
this.serviceName = configuration.getNullable("ebean.cluster.serviceName", serviceName);
|
||||
this.namespace = configuration.getNullable("ebean.cluster.namespace", namespace);
|
||||
this.podName = configuration.getNullable("ebean.cluster.podName", podName);
|
||||
this.port = configuration.getInt("ebean.cluster.port", 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the service name.
|
||||
@@ -104,7 +91,7 @@ public class ContainerConfig {
|
||||
* Return the deployment properties.
|
||||
*/
|
||||
public Properties getProperties() {
|
||||
return properties != null ? properties : configuration.asProperties();
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,4 +101,25 @@ public class ContainerConfig {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the settings from properties.
|
||||
*/
|
||||
public void loadFromProperties(Properties properties) {
|
||||
this.properties = properties;
|
||||
this.active = getProperty(properties, "ebean.cluster.active", active);
|
||||
this.serviceName = properties.getProperty("ebean.cluster.serviceName", serviceName);
|
||||
this.namespace = properties.getProperty("ebean.cluster.namespace", namespace);
|
||||
this.podName = properties.getProperty("ebean.cluster.podName", podName);
|
||||
String portParam = properties.getProperty("ebean.cluster.port");
|
||||
if (portParam != null) {
|
||||
this.port = Integer.parseInt(portParam);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the boolean property setting.
|
||||
*/
|
||||
protected boolean getProperty(Properties properties, String key, boolean defaultValue) {
|
||||
return "true".equalsIgnoreCase(properties.getProperty(key, Boolean.toString(defaultValue)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,6 +123,12 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
*/
|
||||
private boolean loadModuleInfo = true;
|
||||
|
||||
/**
|
||||
* When true then include a sql comment in generated SELECT queries with the query
|
||||
* label or profile location label.
|
||||
*/
|
||||
private boolean includeLabelInSql;
|
||||
|
||||
/**
|
||||
* Interesting classes such as entities, embedded, ScalarTypes,
|
||||
* Listeners, Finders, Controllers, AttributeConverters etc.
|
||||
@@ -531,6 +537,8 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
|
||||
private String dumpMetricsOptions;
|
||||
|
||||
private LengthCheck lengthCheck = LengthCheck.OFF;
|
||||
|
||||
private Function<String, String> metricNaming = MetricNamingMatch.INSTANCE;
|
||||
|
||||
/**
|
||||
@@ -2061,6 +2069,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
readOnlyDatabase = p.getBoolean("readOnlyDatabase", readOnlyDatabase);
|
||||
autoPersistUpdates = p.getBoolean("autoPersistUpdates", autoPersistUpdates);
|
||||
loadModuleInfo = p.getBoolean("loadModuleInfo", loadModuleInfo);
|
||||
includeLabelInSql = p.getBoolean("includeLabelInSql", includeLabelInSql);
|
||||
maxCallStack = p.getInt("maxCallStack", maxCallStack);
|
||||
dumpMetricsOnShutdown = p.getBoolean("dumpMetricsOnShutdown", dumpMetricsOnShutdown);
|
||||
dumpMetricsOptions = p.get("dumpMetricsOptions", dumpMetricsOptions);
|
||||
@@ -2124,6 +2133,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
jdbcFetchSizeFindEach = p.getInt("jdbcFetchSizeFindEach", jdbcFetchSizeFindEach);
|
||||
jdbcFetchSizeFindList = p.getInt("jdbcFetchSizeFindList", jdbcFetchSizeFindList);
|
||||
databasePlatformName = p.get("databasePlatformName", databasePlatformName);
|
||||
lengthCheck = p.getEnum(LengthCheck.class, "lengthCheck", lengthCheck);
|
||||
|
||||
uuidVersion = p.getEnum(UuidVersion.class, "uuidVersion", uuidVersion);
|
||||
uuidStateFile = p.get("uuidStateFile", uuidStateFile);
|
||||
@@ -2473,6 +2483,11 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
return loadModuleInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludeLabelInSql() {
|
||||
return includeLabelInSql;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated - migrate to {@link #isLoadModuleInfo()}.
|
||||
*/
|
||||
@@ -2489,6 +2504,12 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseConfig includeLabelInSql(boolean includeLabelInSql) {
|
||||
this.includeLabelInSql = includeLabelInSql;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<String, String> getMetricNaming() {
|
||||
return metricNaming;
|
||||
@@ -2500,6 +2521,19 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length check mode.
|
||||
*/
|
||||
public LengthCheck getLengthCheck() {
|
||||
return lengthCheck;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseConfig lengthCheck(LengthCheck lengthCheck) {
|
||||
this.lengthCheck = lengthCheck;
|
||||
return this;
|
||||
}
|
||||
|
||||
public enum UuidVersion {
|
||||
VERSION4,
|
||||
VERSION1,
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package io.ebean.config;
|
||||
|
||||
/**
|
||||
* Defines the length-check mode.
|
||||
*
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*/
|
||||
public enum LengthCheck {
|
||||
/**
|
||||
* By default, length checking is off. This means, strings/jsons and files are passed to the DB and the DB might or might not check the length.
|
||||
* The DB has to check the data length. Note this is not possible for certain datatypes (e.g. clob without size)
|
||||
*/
|
||||
OFF,
|
||||
/**
|
||||
* When enabling length check, ebean validates strings/json strings and files before saving them to DB.
|
||||
*/
|
||||
ON,
|
||||
/**
|
||||
* Same as "ON", but take the UTF8-bytelength for validation. This may be useful, if you have an UTF8 based charset (default for DB2)
|
||||
*/
|
||||
UTF8
|
||||
}
|
||||
@@ -1,50 +1,29 @@
|
||||
package io.ebean.config;
|
||||
|
||||
import io.ebean.ProfileLocation;
|
||||
import io.ebean.bean.ObjectGraphNode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Slow query event.
|
||||
* The data for the slow query.
|
||||
*/
|
||||
public class SlowQueryEvent {
|
||||
|
||||
private final String sql;
|
||||
|
||||
private final long timeMillis;
|
||||
|
||||
private final int rowCount;
|
||||
|
||||
private final ObjectGraphNode originNode;
|
||||
|
||||
/**
|
||||
* Construct with the SQL and execution time in millis.
|
||||
*/
|
||||
public SlowQueryEvent(String sql, long timeMillis, int rowCount, ObjectGraphNode originNode) {
|
||||
this.sql = sql;
|
||||
this.timeMillis = timeMillis;
|
||||
this.rowCount = rowCount;
|
||||
this.originNode = originNode;
|
||||
}
|
||||
public interface SlowQueryEvent {
|
||||
|
||||
/**
|
||||
* Return the SQL for the slow query.
|
||||
*/
|
||||
public String getSql() {
|
||||
return sql;
|
||||
}
|
||||
String getSql();
|
||||
|
||||
/**
|
||||
* Return the execution time in millis.
|
||||
*/
|
||||
public long getTimeMillis() {
|
||||
return timeMillis;
|
||||
}
|
||||
long getTimeMillis();
|
||||
|
||||
/**
|
||||
* Return the total row count associated with the query.
|
||||
*/
|
||||
public int getRowCount() {
|
||||
return rowCount;
|
||||
}
|
||||
int getRowCount();
|
||||
|
||||
/**
|
||||
* Return the origin point for the root query.
|
||||
@@ -53,7 +32,20 @@ public class SlowQueryEvent {
|
||||
* shows the code that invoked the query.
|
||||
* </p>
|
||||
*/
|
||||
public ObjectGraphNode getOriginNode() {
|
||||
return originNode;
|
||||
}
|
||||
ObjectGraphNode getOriginNode();
|
||||
|
||||
/**
|
||||
* Return the bind parameters.
|
||||
*/
|
||||
List<Object> getBindParams();
|
||||
|
||||
/**
|
||||
* Return the label.
|
||||
*/
|
||||
String getLabel();
|
||||
|
||||
/**
|
||||
* Return the profile location.
|
||||
*/
|
||||
ProfileLocation getProfileLocation();
|
||||
}
|
||||
|
||||
@@ -769,4 +769,15 @@ public class DatabasePlatform {
|
||||
public boolean supportsNativeJavaTime() {
|
||||
return supportsNativeJavaTime;
|
||||
}
|
||||
|
||||
public String inlineSqlComment(String label) {
|
||||
if (label == null) {
|
||||
return "";
|
||||
}
|
||||
return "/* " + label + " */ ";
|
||||
}
|
||||
|
||||
public String inlineSqlHint(String hint) {
|
||||
return "/*+ " + hint + " */ ";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import java.sql.Driver;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
@@ -23,7 +24,7 @@ public final class ShutdownManager {
|
||||
|
||||
private static final System.Logger log = EbeanVersion.log;
|
||||
private static final ReentrantLock lock = new ReentrantLock();
|
||||
private static final List<Database> databases = new ArrayList<>();
|
||||
private static final List<Database> databases = Collections.synchronizedList(new ArrayList<>());
|
||||
private static final ShutdownHook shutdownHook = new ShutdownHook();
|
||||
|
||||
private static boolean stopping;
|
||||
@@ -177,12 +178,7 @@ public final class ShutdownManager {
|
||||
* Register an ebeanServer to be shutdown when the JVM is shutdown.
|
||||
*/
|
||||
public static void registerDatabase(Database server) {
|
||||
lock.lock();
|
||||
try {
|
||||
databases.add(server);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
databases.add(server);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,12 +188,7 @@ public final class ShutdownManager {
|
||||
* </p>
|
||||
*/
|
||||
public static void unregisterDatabase(Database server) {
|
||||
lock.lock();
|
||||
try {
|
||||
databases.remove(server);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
databases.remove(server);
|
||||
}
|
||||
|
||||
private static class ShutdownHook extends Thread {
|
||||
|
||||
@@ -22,6 +22,8 @@ public class JsonWriteOptions {
|
||||
|
||||
protected JsonConfig.Include include;
|
||||
|
||||
protected boolean includeLoadedImplicit = true;
|
||||
|
||||
protected Map<String, JsonWriteBeanVisitor<?>> visitorMap;
|
||||
|
||||
/**
|
||||
@@ -73,6 +75,20 @@ public class JsonWriteOptions {
|
||||
this.include = include;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should loaded properties be included implicit, if no other fetch path is specified (default = true).
|
||||
*/
|
||||
public boolean isIncludeLoadedImplicit() {
|
||||
return includeLoadedImplicit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set include loaded properties implicit (default = true).
|
||||
*/
|
||||
public void setIncludeLoadedImplicit(boolean includeLoadedImplicit) {
|
||||
this.includeLoadedImplicit = includeLoadedImplicit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a JsonWriteBeanVisitor for the root level.
|
||||
*/
|
||||
|
||||
@@ -75,6 +75,8 @@ class DatabaseConfigTest {
|
||||
props.setProperty("defaultServer", "false");
|
||||
props.setProperty("skipDataSourceCheck", "true");
|
||||
props.setProperty("readOnlyDatabase", "true");
|
||||
props.setProperty("lengthCheck", "ON");
|
||||
props.setProperty("includeLabelInSql", "true");
|
||||
|
||||
props.setProperty("queryPlan.enable", "true");
|
||||
props.setProperty("queryPlan.thresholdMicros", "10000");
|
||||
@@ -95,6 +97,8 @@ class DatabaseConfigTest {
|
||||
assertTrue(settings.isLoadModuleInfo());
|
||||
assertTrue(settings.skipDataSourceCheck());
|
||||
assertTrue(settings.readOnlyDatabase());
|
||||
assertTrue(settings.isIncludeLabelInSql());
|
||||
assertThat(settings.getLengthCheck()).isEqualTo(LengthCheck.ON);
|
||||
|
||||
assertTrue(settings.isIdGeneratorAutomatic());
|
||||
assertFalse(settings.getPlatformConfig().isCaseSensitiveCollation());
|
||||
@@ -128,8 +132,11 @@ class DatabaseConfigTest {
|
||||
|
||||
assertThat(settings.getMappingLocations()).containsExactly("classpath:/foo","bar");
|
||||
|
||||
config.setPersistBatch(PersistBatch.NONE);
|
||||
config.setPersistBatchOnCascade(PersistBatch.NONE);
|
||||
config.persistBatch(PersistBatch.NONE)
|
||||
.persistBatchOnCascade(PersistBatch.NONE)
|
||||
.lengthCheck(LengthCheck.ON)
|
||||
.lengthCheck(LengthCheck.UTF8);
|
||||
|
||||
|
||||
Properties props1 = new Properties();
|
||||
props1.setProperty("ebean.persistBatch", "ALL");
|
||||
@@ -146,6 +153,7 @@ class DatabaseConfigTest {
|
||||
|
||||
assertEquals(PersistBatch.ALL, settings.getPersistBatch());
|
||||
assertEquals(PersistBatch.ALL, settings.getPersistBatchOnCascade());
|
||||
assertEquals(LengthCheck.UTF8, settings.getLengthCheck());
|
||||
|
||||
config.setEnabledL2Regions("r0,orgs");
|
||||
assertEquals("r0,orgs", settings.getEnabledL2Regions());
|
||||
@@ -174,6 +182,8 @@ class DatabaseConfigTest {
|
||||
assertEquals(600, config.getQueryPlanCapturePeriodSecs());
|
||||
assertEquals(10000L, config.getQueryPlanCaptureMaxTimeMillis());
|
||||
assertEquals(10, config.getQueryPlanCaptureMaxCount());
|
||||
assertThat(config.getLengthCheck()).isEqualTo(LengthCheck.OFF);
|
||||
assertFalse(config.isIncludeLabelInSql());
|
||||
|
||||
config.setLoadModuleInfo(false);
|
||||
assertFalse(config.isAutoLoadModuleInfo());
|
||||
|
||||
+31
-31
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean bom</name>
|
||||
@@ -89,103 +89,103 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-joda-time</artifactId>
|
||||
<version>13.24.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-jsonnode</artifactId>
|
||||
<version>13.24.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-mapper</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>13.18.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-xml</artifactId>
|
||||
<version>13.18.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-autotune</artifactId>
|
||||
<version>13.18.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>kotlin-querybean-generator</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-redis</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-spring-txn</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- platforms -->
|
||||
@@ -193,79 +193,79 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-clickhouse</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-db2</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-h2</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-hana</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-mariadb</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-mysql</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-nuodb</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-oracle</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgres</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis-types</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-sqlite</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-sqlserver</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
@@ -16,7 +16,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -30,7 +30,7 @@
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.6.0</version>
|
||||
<version>42.7.2</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -174,4 +174,9 @@ public interface DataBinder {
|
||||
*/
|
||||
String popJson();
|
||||
|
||||
/**
|
||||
* Returns the last bound object (e.g. for BindValidation). Note for InputStreams you'll get an InputStreamInfo.
|
||||
*/
|
||||
Object popLastObject();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package io.ebean.core.type;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Helper to transports length info of DataBind.setBinaryStream(stream, length) to BindValidation
|
||||
*
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*/
|
||||
public final class InputStreamInfo {
|
||||
|
||||
private final InputStream stream;
|
||||
private final long length;
|
||||
|
||||
public InputStreamInfo(InputStream stream, long length) {
|
||||
this.stream = stream;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
public InputStream stream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
public long length() {
|
||||
return length;
|
||||
}
|
||||
}
|
||||
+7
-7
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core</artifactId>
|
||||
@@ -22,7 +22,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -46,7 +46,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
@@ -139,7 +139,7 @@
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.6.0</version>
|
||||
<version>42.7.2</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
@@ -147,21 +147,21 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlserver</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.1.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package io.ebeaninternal.api;
|
||||
import io.ebean.CacheMode;
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebeaninternal.server.core.BindPadding;
|
||||
import io.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
@@ -57,17 +58,22 @@ public final class LoadManyRequest extends LoadRequest {
|
||||
return loadContext.fullPath();
|
||||
}
|
||||
|
||||
private List<Object> parentIdList(SpiEbeanServer server) {
|
||||
List<Object> idList = new ArrayList<>();
|
||||
BeanPropertyAssocMany<?> many = many();
|
||||
private List<Object> parentIdList(SpiEbeanServer server, BeanPropertyAssocMany<?> many, PersistenceContext pc) {
|
||||
final var idList = new ArrayList<>(loadContext.size());
|
||||
final var descriptor = many.descriptor();
|
||||
for (int i = 0; i < loadContext.size(); i++) {
|
||||
BeanCollection<?> bc = loadContext.get(i);
|
||||
final BeanCollection<?> bc = loadContext.get(i);
|
||||
if (bc != null) {
|
||||
if (lazy && !originIncluded && bc == originCollection) {
|
||||
originIncluded = true;
|
||||
}
|
||||
idList.add(many.parentId(bc.owner()));
|
||||
final var parent = bc.owner();
|
||||
final var parentId = descriptor.getId(parent);
|
||||
idList.add(parentId);
|
||||
bc.setLoader(server); // don't use the load buffer again
|
||||
if (lazy) {
|
||||
descriptor.contextPutIfAbsent(pc, parentId, parent);
|
||||
if (!originIncluded && bc == originCollection) {
|
||||
originIncluded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (originCollection != null && !originIncluded) {
|
||||
@@ -75,7 +81,7 @@ public final class LoadManyRequest extends LoadRequest {
|
||||
idList.add(many.parentId(originCollection.owner()));
|
||||
originCollection.setLoader(server); // don't use the load buffer again
|
||||
}
|
||||
if (many.targetDescriptor().isPadInExpression()) {
|
||||
if (descriptor.isPadInExpression()) {
|
||||
BindPadding.padIds(idList);
|
||||
}
|
||||
return idList;
|
||||
@@ -99,8 +105,9 @@ public final class LoadManyRequest extends LoadRequest {
|
||||
query.where().raw(extraWhere.replace("${ta}", "t0").replace("${mta}", "int_"));
|
||||
}
|
||||
query.setLazyLoadForParents(many);
|
||||
many.addWhereParentIdIn(query, parentIdList(server));
|
||||
query.setPersistenceContext(loadContext.persistenceContext());
|
||||
final var pc = loadContext.persistenceContext();
|
||||
many.addWhereParentIdIn(query, parentIdList(server, many, pc));
|
||||
query.setPersistenceContext(pc);
|
||||
query.setLoadDescription(lazy ? "lazy" : "query", description());
|
||||
if (lazy) {
|
||||
query.setLazyLoadBatchSize(loadContext.batchSize());
|
||||
|
||||
@@ -336,6 +336,10 @@ public interface SpiEbeanServer extends SpiServer, ExtendedServer, BeanCollectio
|
||||
|
||||
<T> FutureRowCount<T> findFutureCount(SpiQuery<T> query);
|
||||
|
||||
<T> FutureIds<T> findFutureIds(SpiQuery<T> query);
|
||||
|
||||
<T> FutureList<T> findFutureList(SpiQuery<T> query);
|
||||
|
||||
<T> PagedList<T> findPagedList(SpiQuery<T> query);
|
||||
|
||||
<T> Set<T> findSet(SpiQuery<T> query);
|
||||
|
||||
@@ -71,7 +71,7 @@ public interface SpiExpression extends Expression {
|
||||
*
|
||||
* @param request the associated request.
|
||||
*/
|
||||
void addBindValues(SpiExpressionRequest request);
|
||||
void addBindValues(SpiExpressionBind request);
|
||||
|
||||
/**
|
||||
* Validate all the properties/paths associated with this expression.
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package io.ebeaninternal.api;
|
||||
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
|
||||
/**
|
||||
* Expression bind values capture.
|
||||
*/
|
||||
public interface SpiExpressionBind {
|
||||
|
||||
/**
|
||||
* Return the bean descriptor for the root type.
|
||||
*/
|
||||
BeanDescriptor<?> descriptor();
|
||||
|
||||
/**
|
||||
* Add an encryption key to bind to this request.
|
||||
*/
|
||||
void addBindEncryptKey(Object encryptKey);
|
||||
|
||||
/**
|
||||
* Add a bind value to this request.
|
||||
*/
|
||||
void addBindValue(Object bindValue);
|
||||
|
||||
/**
|
||||
* Escapes a string to use it as exact match in Like clause.
|
||||
*/
|
||||
String escapeLikeString(String value);
|
||||
}
|
||||
@@ -1,15 +1,15 @@
|
||||
package io.ebeaninternal.api;
|
||||
|
||||
import io.ebeaninternal.server.core.SpiOrmQueryRequest;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.expression.platform.DbExpressionHandler;
|
||||
import io.ebeaninternal.server.expression.platform.DbExpressionRequest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Request object used for gathering expression sql and bind values.
|
||||
*/
|
||||
public interface SpiExpressionRequest {
|
||||
public interface SpiExpressionRequest extends SpiExpressionBind, DbExpressionRequest {
|
||||
|
||||
/**
|
||||
* Return the DB specific handler for JSON and ARRAY expressions.
|
||||
@@ -21,11 +21,6 @@ public interface SpiExpressionRequest {
|
||||
*/
|
||||
String parseDeploy(String logicalProp);
|
||||
|
||||
/**
|
||||
* Return the bean descriptor for the root type.
|
||||
*/
|
||||
BeanDescriptor<?> descriptor();
|
||||
|
||||
/**
|
||||
* Return the associated QueryRequest.
|
||||
*/
|
||||
@@ -34,11 +29,13 @@ public interface SpiExpressionRequest {
|
||||
/**
|
||||
* Append to the expression sql without any parsing.
|
||||
*/
|
||||
@Override
|
||||
SpiExpressionRequest append(String expression);
|
||||
|
||||
/**
|
||||
* Append to the expression sql without any parsing.
|
||||
*/
|
||||
@Override
|
||||
SpiExpressionRequest append(char c);
|
||||
|
||||
/**
|
||||
@@ -47,6 +44,7 @@ public interface SpiExpressionRequest {
|
||||
* This is a fast path case when expression is a bean property path and falls back to using parse()
|
||||
* when that isn't the case.
|
||||
*/
|
||||
@Override
|
||||
SpiExpressionRequest property(String expression);
|
||||
|
||||
/**
|
||||
@@ -54,16 +52,6 @@ public interface SpiExpressionRequest {
|
||||
*/
|
||||
SpiExpressionRequest parse(String expression);
|
||||
|
||||
/**
|
||||
* Add an encryption key to bind to this request.
|
||||
*/
|
||||
void addBindEncryptKey(Object encryptKey);
|
||||
|
||||
/**
|
||||
* Add a bind value to this request.
|
||||
*/
|
||||
void addBindValue(Object bindValue);
|
||||
|
||||
/**
|
||||
* Return the accumulated expression sql for all expressions in this request.
|
||||
*/
|
||||
@@ -84,11 +72,6 @@ public interface SpiExpressionRequest {
|
||||
*/
|
||||
void appendLike(boolean rawLikeExpression);
|
||||
|
||||
/**
|
||||
* Escapes a string to use it as exact match in Like clause.
|
||||
*/
|
||||
String escapeLikeString(String value);
|
||||
|
||||
/**
|
||||
* Append IN expression taking into account platform and type support for Multi-value.
|
||||
*/
|
||||
|
||||
@@ -220,6 +220,11 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
|
||||
*/
|
||||
ProfileLocation profileLocation();
|
||||
|
||||
/**
|
||||
* Return the SQL hint to include in the query.
|
||||
*/
|
||||
String hint();
|
||||
|
||||
/**
|
||||
* Return the label set on the query.
|
||||
*/
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package io.ebeaninternal.server.bind;
|
||||
|
||||
import io.ebean.core.type.DataBinder;
|
||||
import io.ebean.core.type.InputStreamInfo;
|
||||
import io.ebeaninternal.api.CoreLog;
|
||||
import io.ebeaninternal.server.core.timezone.DataTimeZone;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.*;
|
||||
import java.util.ArrayList;
|
||||
@@ -23,6 +27,8 @@ public class DataBind implements DataBinder {
|
||||
protected int pos;
|
||||
private String json;
|
||||
|
||||
private Object lastObject = null;
|
||||
|
||||
public DataBind(DataTimeZone dataTimeZone, PreparedStatement pstmt, Connection connection) {
|
||||
this.dataTimeZone = dataTimeZone;
|
||||
this.pstmt = pstmt;
|
||||
@@ -65,16 +71,19 @@ public class DataBind implements DataBinder {
|
||||
@Override
|
||||
public void setObject(Object value) throws SQLException {
|
||||
pstmt.setObject(++pos, value);
|
||||
lastObject = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setObject(Object value, int sqlType) throws SQLException {
|
||||
pstmt.setObject(++pos, value, sqlType);
|
||||
lastObject = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNull(int jdbcType) throws SQLException {
|
||||
pstmt.setNull(++pos, jdbcType);
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,7 +105,7 @@ public class DataBind implements DataBinder {
|
||||
}
|
||||
}
|
||||
|
||||
private void closeInputStreams() {
|
||||
public void closeInputStreams() {
|
||||
if (inputStreams != null) {
|
||||
for (InputStream inputStream : inputStreams) {
|
||||
try {
|
||||
@@ -117,36 +126,43 @@ public class DataBind implements DataBinder {
|
||||
@Override
|
||||
public void setString(String value) throws SQLException {
|
||||
pstmt.setString(++pos, value);
|
||||
lastObject = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setInt(int value) throws SQLException {
|
||||
pstmt.setInt(++pos, value);
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setLong(long value) throws SQLException {
|
||||
pstmt.setLong(++pos, value);
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setShort(short value) throws SQLException {
|
||||
pstmt.setShort(++pos, value);
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setFloat(float value) throws SQLException {
|
||||
pstmt.setFloat(++pos, value);
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setDouble(double value) throws SQLException {
|
||||
pstmt.setDouble(++pos, value);
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setBigDecimal(BigDecimal value) throws SQLException {
|
||||
pstmt.setBigDecimal(++pos, value);
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -157,6 +173,7 @@ public class DataBind implements DataBinder {
|
||||
} else {
|
||||
pstmt.setDate(++pos, value);
|
||||
}
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -167,6 +184,7 @@ public class DataBind implements DataBinder {
|
||||
} else {
|
||||
pstmt.setTimestamp(++pos, value);
|
||||
}
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -177,26 +195,31 @@ public class DataBind implements DataBinder {
|
||||
} else {
|
||||
pstmt.setTime(++pos, value);
|
||||
}
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBoolean(boolean value) throws SQLException {
|
||||
pstmt.setBoolean(++pos, value);
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBytes(byte[] value) throws SQLException {
|
||||
pstmt.setBytes(++pos, value);
|
||||
lastObject = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setByte(byte value) throws SQLException {
|
||||
pstmt.setByte(++pos, value);
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChar(char value) throws SQLException {
|
||||
pstmt.setString(++pos, String.valueOf(value));
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -211,21 +234,31 @@ public class DataBind implements DataBinder {
|
||||
}
|
||||
inputStreams.add(inputStream);
|
||||
pstmt.setBinaryStream(++pos, inputStream, length);
|
||||
lastObject = new InputStreamInfo(inputStream, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlob(byte[] bytes) throws SQLException {
|
||||
pstmt.setBinaryStream(++pos, new ByteArrayInputStream(bytes), bytes.length);
|
||||
lastObject = bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClob(String content) throws SQLException {
|
||||
pstmt.setCharacterStream(++pos, new StringReader(content), content.length());
|
||||
lastObject = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setArray(String arrayType, Object[] elements) throws SQLException {
|
||||
pstmt.setArray(++pos, connection.createArrayOf(arrayType, elements));
|
||||
lastObject = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object popLastObject() {
|
||||
Object ret = lastObject;
|
||||
lastObject = null;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebean.ProfileLocation;
|
||||
import io.ebean.bean.ObjectGraphNode;
|
||||
import io.ebean.config.SlowQueryEvent;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Slow query event.
|
||||
*/
|
||||
final class DSlowQueryEvent implements SlowQueryEvent {
|
||||
|
||||
private final String sql;
|
||||
private final long timeMillis;
|
||||
private final int rowCount;
|
||||
private final ObjectGraphNode originNode;
|
||||
private final List<Object> bindParams;
|
||||
private final String label;
|
||||
private final ProfileLocation profileLocation;
|
||||
|
||||
/**
|
||||
* Construct with the SQL and execution time in millis.
|
||||
*/
|
||||
DSlowQueryEvent(String sql, long timeMillis, int rowCount, ObjectGraphNode originNode,
|
||||
List<Object> bindParams, String label, ProfileLocation profileLocation) {
|
||||
this.sql = sql;
|
||||
this.timeMillis = timeMillis;
|
||||
this.rowCount = rowCount;
|
||||
this.originNode = originNode;
|
||||
this.bindParams = bindParams;
|
||||
this.profileLocation = profileLocation;
|
||||
this.label = label != null ? label : profileLocation == null ? null : profileLocation.label();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSql() {
|
||||
return sql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTimeMillis() {
|
||||
return timeMillis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRowCount() {
|
||||
return rowCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectGraphNode getOriginNode() {
|
||||
return originNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> getBindParams() {
|
||||
return bindParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProfileLocation getProfileLocation() {
|
||||
return profileLocation;
|
||||
}
|
||||
}
|
||||
@@ -63,8 +63,8 @@ final class DefaultBeanLoader {
|
||||
Object parentId = parentDesc.getId(parentBean);
|
||||
if (pc == null) {
|
||||
pc = new DefaultPersistenceContext();
|
||||
parentDesc.contextPut(pc, parentId, parentBean);
|
||||
}
|
||||
parentDesc.contextPutIfAbsent(pc, parentId, parentBean);
|
||||
boolean useManyIdCache = beanCollection != null && parentDesc.isManyPropCaching() && many.isUseCache();
|
||||
if (useManyIdCache) {
|
||||
Boolean readOnly = null;
|
||||
|
||||
@@ -1200,6 +1200,47 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
return queryFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> FutureIds<T> findFutureIds(SpiQuery<T> query) {
|
||||
SpiQuery<T> copy = query.copy();
|
||||
copy.usingFuture();
|
||||
boolean createdTransaction = false;
|
||||
SpiTransaction transaction = query.transaction();
|
||||
if (transaction == null) {
|
||||
transaction = currentServerTransaction();
|
||||
if (transaction == null) {
|
||||
transaction = (SpiTransaction) createTransaction();
|
||||
createdTransaction = true;
|
||||
}
|
||||
copy.usingTransaction(transaction);
|
||||
}
|
||||
QueryFutureIds<T> queryFuture = new QueryFutureIds<>(new CallableQueryIds<>(this, copy, createdTransaction));
|
||||
backgroundExecutor.execute(queryFuture.futureTask());
|
||||
return queryFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> FutureList<T> findFutureList(SpiQuery<T> query) {
|
||||
SpiQuery<T> spiQuery = query.copy();
|
||||
spiQuery.usingFuture();
|
||||
// FutureList query always run in it's own persistence content
|
||||
spiQuery.setPersistenceContext(new DefaultPersistenceContext());
|
||||
// Create a new transaction solely to execute the findList() at some future time
|
||||
boolean createdTransaction = false;
|
||||
SpiTransaction transaction = query.transaction();
|
||||
if (transaction == null) {
|
||||
transaction = currentServerTransaction();
|
||||
if (transaction == null) {
|
||||
transaction = (SpiTransaction) createTransaction();
|
||||
createdTransaction = true;
|
||||
}
|
||||
spiQuery.usingTransaction(transaction);
|
||||
}
|
||||
QueryFutureList<T> queryFuture = new QueryFutureList<>(new CallableQueryList<>(this, spiQuery, createdTransaction));
|
||||
backgroundExecutor.execute(queryFuture.futureTask());
|
||||
return queryFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> PagedList<T> findPagedList(SpiQuery<T> query) {
|
||||
int maxRows = query.getMaxRows();
|
||||
@@ -1979,7 +2020,9 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
@Override
|
||||
public void slowQueryCheck(long timeMicros, int rowCount, SpiQuery<?> query) {
|
||||
if (timeMicros > slowQueryMicros && slowQueryListener != null) {
|
||||
slowQueryListener.process(new SlowQueryEvent(query.getGeneratedSql(), timeMicros / 1000L, rowCount, query.parentNode()));
|
||||
List<Object> bindParams = new SlowQueryBindCapture(query).capture();
|
||||
slowQueryListener.process(new DSlowQueryEvent(query.getGeneratedSql(), timeMicros / 1000L, rowCount,
|
||||
query.parentNode(), bindParams, query.label(), query.profileLocation()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import io.avaje.applog.AppLog;
|
||||
import io.ebean.bean.ObjectGraphNode;
|
||||
import io.ebean.ProfileLocation;
|
||||
import io.ebean.config.SlowQueryEvent;
|
||||
import io.ebean.config.SlowQueryListener;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static java.lang.System.Logger.Level.WARNING;
|
||||
|
||||
/**
|
||||
@@ -16,11 +18,10 @@ final class DefaultSlowQueryListener implements SlowQueryListener {
|
||||
|
||||
@Override
|
||||
public void process(SlowQueryEvent event) {
|
||||
String firstStack = "";
|
||||
ObjectGraphNode node = event.getOriginNode();
|
||||
if (node != null) {
|
||||
firstStack = node.origin().top();
|
||||
}
|
||||
log.log(WARNING, "Slow query warning - millis:{0} rows:{1} caller[{2}] sql[{3}]", event.getTimeMillis(), event.getRowCount(), firstStack, event.getSql());
|
||||
ProfileLocation profileLocation = event.getProfileLocation();
|
||||
String loc = profileLocation == null ? "" : profileLocation.fullLocation();
|
||||
List<Object> bindParams = event.getBindParams();
|
||||
log.log(WARNING, "Slow query warning - millis:{0} rows:{1} location:{2} sql[{3}] params{4}",
|
||||
event.getTimeMillis(), event.getRowCount(), loc, event.getSql(), bindParams);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -807,21 +807,27 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
}
|
||||
|
||||
private void controllerPost() {
|
||||
switch (type) {
|
||||
case INSERT:
|
||||
controller.postInsert(this);
|
||||
break;
|
||||
case UPDATE:
|
||||
controller.postUpdate(this);
|
||||
break;
|
||||
case DELETE_SOFT:
|
||||
controller.postSoftDelete(this);
|
||||
break;
|
||||
case DELETE:
|
||||
controller.postDelete(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
boolean old = transaction.isFlushOnQuery();
|
||||
transaction.setFlushOnQuery(false);
|
||||
try {
|
||||
switch (type) {
|
||||
case INSERT:
|
||||
controller.postInsert(this);
|
||||
break;
|
||||
case UPDATE:
|
||||
controller.postUpdate(this);
|
||||
break;
|
||||
case DELETE_SOFT:
|
||||
controller.postSoftDelete(this);
|
||||
break;
|
||||
case DELETE:
|
||||
controller.postDelete(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} finally {
|
||||
transaction.setFlushOnQuery(old);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebeaninternal.api.BindParams;
|
||||
import io.ebeaninternal.api.SpiExpressionBind;
|
||||
import io.ebeaninternal.api.SpiExpressionList;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.persist.MultiValueWrapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
final class SlowQueryBindCapture implements SpiExpressionBind {
|
||||
|
||||
private final SpiQuery<?> query;
|
||||
private final List<Object> bindParams = new ArrayList<>();
|
||||
|
||||
SlowQueryBindCapture(SpiQuery<?> query) {
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
List<Object> capture() {
|
||||
var params = query.bindParams();
|
||||
if (params != null) {
|
||||
var positionedParameters = params.positionedParameters();
|
||||
for (BindParams.Param param : positionedParameters) {
|
||||
if (param.isInParam()) {
|
||||
add(param.inValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
Object id = query.getId();
|
||||
if (id != null) {
|
||||
add(id);
|
||||
}
|
||||
SpiExpressionList<?> spiExpressionList = query.whereExpressions();
|
||||
if (spiExpressionList != null) {
|
||||
spiExpressionList.addBindValues(this);
|
||||
}
|
||||
return bindParams;
|
||||
}
|
||||
|
||||
private void add(Object value) {
|
||||
if (value instanceof MultiValueWrapper) {
|
||||
var mvw = (MultiValueWrapper) value;
|
||||
bindParams.add(mvw.getValues());
|
||||
} else {
|
||||
bindParams.add(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanDescriptor<?> descriptor() {
|
||||
return query.descriptor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValue(Object bindValue) {
|
||||
add(bindValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindEncryptKey(Object encryptKey) {
|
||||
bindParams.add("*");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String escapeLikeString(String value) {
|
||||
return query.descriptor().ebeanServer().databasePlatform().escapeLikeString(value);
|
||||
}
|
||||
}
|
||||
@@ -96,6 +96,7 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
|
||||
private final String asOfViewSuffix;
|
||||
private final boolean jacksonCorePresent;
|
||||
private final int queryPlanTTLSeconds;
|
||||
private final BindMaxLength bindMaxLength;
|
||||
private int entityBeanCount;
|
||||
private List<BeanDescriptor<?>> immutableDescriptorList;
|
||||
/**
|
||||
@@ -144,6 +145,19 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
|
||||
this.changeLogListener = config.changeLogListener(bootupClasses.getChangeLogListener());
|
||||
this.changeLogRegister = config.changeLogRegister(bootupClasses.getChangeLogRegister());
|
||||
this.jacksonCorePresent = config.isJacksonCorePresent();
|
||||
this.bindMaxLength = initMaxLength();
|
||||
}
|
||||
|
||||
BindMaxLength initMaxLength() {
|
||||
LengthCheck lengthCheck = this.config.getLengthCheck();
|
||||
switch (lengthCheck) {
|
||||
case OFF:
|
||||
return null;
|
||||
case UTF8:
|
||||
return BindMaxLength.ofUtf8();
|
||||
default:
|
||||
return BindMaxLength.ofStandard();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1346,6 +1360,10 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
|
||||
return list;
|
||||
}
|
||||
|
||||
public BindMaxLength bindMaxLength() {
|
||||
return bindMaxLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator to sort the BeanDescriptors by name.
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebeaninternal.server.deploy;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import io.ebean.DataIntegrityException;
|
||||
import io.ebean.ValuePair;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
@@ -10,7 +11,6 @@ import io.ebean.config.EncryptKey;
|
||||
import io.ebean.config.dbplatform.DbEncryptFunction;
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.core.type.DataReader;
|
||||
import io.ebean.core.type.DocPropertyType;
|
||||
import io.ebean.core.type.ScalarType;
|
||||
import io.ebean.plugin.Property;
|
||||
import io.ebean.text.StringParser;
|
||||
@@ -161,6 +161,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
*/
|
||||
private final String dbComment;
|
||||
private final DbEncryptFunction dbEncryptFunction;
|
||||
private final BindMaxLength bindMaxLength;
|
||||
private int deployOrder;
|
||||
final boolean jsonSerialize;
|
||||
final boolean jsonDeserialize;
|
||||
@@ -244,6 +245,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
}
|
||||
this.jsonSerialize = deploy.isJsonSerialize();
|
||||
this.jsonDeserialize = deploy.isJsonDeserialize();
|
||||
this.bindMaxLength = deploy.bindMaxLength();
|
||||
}
|
||||
|
||||
private String tableAliasIntern(BeanDescriptor<?> descriptor, String s, boolean dbEncrypted, String dbColumn) {
|
||||
@@ -326,6 +328,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
this.elPlaceHolderEncrypted = override.replace(source.elPlaceHolderEncrypted, source.dbColumn);
|
||||
this.jsonSerialize = source.jsonSerialize;
|
||||
this.jsonDeserialize = source.jsonDeserialize;
|
||||
this.bindMaxLength = source.bindMaxLength;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -536,6 +539,18 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void bind(DataBind b, Object value) throws SQLException {
|
||||
scalarType.bind(b, value);
|
||||
if (bindMaxLength != null) {
|
||||
Object obj = b.popLastObject();
|
||||
long length = bindMaxLength.length(dbLength, obj);
|
||||
if (length > dbLength) {
|
||||
b.closeInputStreams();
|
||||
String s = String.valueOf(value); // take original bind value here.
|
||||
if (s.length() > 50) {
|
||||
s = s.substring(0, 47) + "...";
|
||||
}
|
||||
throw new DataIntegrityException("Cannot bind value '" + s + "' (effective length=" + length + ") to column '" + dbColumn + "' (length=" + dbLength + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings(value = "unchecked")
|
||||
@@ -1128,14 +1143,14 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
* Returns true if this <code>isLob()</code> or the type will effectively map to a lob.
|
||||
*/
|
||||
@Override
|
||||
public boolean isDbLob() {
|
||||
public boolean isLobForPlatform() {
|
||||
if (lob) {
|
||||
return true;
|
||||
}
|
||||
switch (dbType) {
|
||||
case DbPlatformType.JSON:
|
||||
case DbPlatformType.JSONB:
|
||||
return dbLength == 0; // must be analog to DbPlatformTypeMapping.lookup
|
||||
return dbLength == 0 || dbLength > 4000; // must be analog to DbPlatformTypeMapping.lookup
|
||||
case DbPlatformType.JSONBlob:
|
||||
case DbPlatformType.JSONClob:
|
||||
return true;
|
||||
|
||||
@@ -360,6 +360,9 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
for (ExportedProperty exportedProperty : exportedProperties) {
|
||||
row.addColumn(exportedProperty.getForeignDbColumn());
|
||||
}
|
||||
if (importedId == null) {
|
||||
throw new PersistenceException("Missing @Id property on bean related to ManyToMany " + fullName());
|
||||
}
|
||||
importedId.buildImport(row);
|
||||
return row.build();
|
||||
}
|
||||
@@ -566,10 +569,9 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the join properties from the parent bean to the child bean.
|
||||
* This is only valid for OneToMany and NOT valid for ManyToMany.
|
||||
* Set the parent bean to the child (update the relationship).
|
||||
*/
|
||||
public void setJoinValuesToChild(EntityBean parent, EntityBean child, Object mapKeyValue) {
|
||||
public void setParentToChild(EntityBean parent, EntityBean child, Object mapKeyValue) {
|
||||
if (mapKeyProperty != null) {
|
||||
mapKeyProperty.setValue(child, mapKeyValue);
|
||||
}
|
||||
@@ -580,6 +582,31 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the parent bean has been set to the child (updated the relationship).
|
||||
*/
|
||||
public boolean setParentToChild(EntityBean parent, EntityBean child, Object mapKeyValue, BeanDescriptor<?> parentDesc) {
|
||||
if (manyToMany
|
||||
|| childMasterProperty == null
|
||||
|| !child._ebean_getIntercept().isLoadedProperty(childMasterProperty.propertyIndex())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Object currentParent = childMasterProperty.getValue(child);
|
||||
if (currentParent != null) {
|
||||
Object newId = parentDesc.getId(parent);
|
||||
Object oldId = parentDesc.id(currentParent);
|
||||
if (Objects.equals(newId, oldId)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
childMasterProperty.setValueIntercept(child, parent);
|
||||
if (mapKeyProperty != null) {
|
||||
mapKeyProperty.setValue(child, mapKeyValue);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the order by clause used to order the fetching of the data for
|
||||
* this list, set or map.
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package io.ebeaninternal.server.deploy;
|
||||
|
||||
import io.ebean.core.type.InputStreamInfo;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* The max length check on bind values.
|
||||
*/
|
||||
public interface BindMaxLength {
|
||||
|
||||
/**
|
||||
* Return a UTF8 based implementation.
|
||||
*/
|
||||
static BindMaxLength ofUtf8() {
|
||||
return new UTF8();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a standard implementation.
|
||||
*/
|
||||
static BindMaxLength ofStandard() {
|
||||
return new Standard();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the length of the object.
|
||||
*/
|
||||
long length(int dbLength, Object obj);
|
||||
|
||||
/**
|
||||
* Length check based on UTF8 bytes.
|
||||
*/
|
||||
final class UTF8 implements BindMaxLength {
|
||||
|
||||
@Override
|
||||
public long length(int dbLength, Object obj) {
|
||||
if (obj == null) {
|
||||
return -1;
|
||||
} else if (obj instanceof String) {
|
||||
String s = (String) obj;
|
||||
return utf8String(dbLength, s);
|
||||
} else if (obj instanceof byte[]) {
|
||||
return ((byte[]) obj).length;
|
||||
} else if (obj instanceof InputStreamInfo) {
|
||||
return ((InputStreamInfo) obj).length();
|
||||
} else if ("org.postgresql.util.PGobject".equals(obj.getClass().getCanonicalName())) {
|
||||
String value = ((org.postgresql.util.PGobject) obj).getValue();
|
||||
return value == null ? -1 : utf8String(dbLength, value);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private static int utf8String(int dbLength, String s) {
|
||||
int stringLength = s.length();
|
||||
if (stringLength > dbLength) {
|
||||
return stringLength;
|
||||
} else if (stringLength * 4 <= dbLength) {
|
||||
return -1;
|
||||
} else {
|
||||
return s.getBytes(StandardCharsets.UTF_8).length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard string length implementation.
|
||||
*/
|
||||
final class Standard implements BindMaxLength {
|
||||
|
||||
@Override
|
||||
public long length(int dbLength, Object obj) {
|
||||
if (obj == null) {
|
||||
return -1;
|
||||
} else if (obj instanceof String) {
|
||||
return ((String) obj).length();
|
||||
} else if (obj instanceof byte[]) {
|
||||
return ((byte[]) obj).length;
|
||||
} else if (obj instanceof InputStreamInfo) {
|
||||
return ((InputStreamInfo) obj).length();
|
||||
} else if ("org.postgresql.util.PGobject".equals(obj.getClass().getCanonicalName())) {
|
||||
String value = ((org.postgresql.util.PGobject) obj).getValue();
|
||||
return value == null ? -1 : value.length();
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -63,7 +63,7 @@ class DynamicPropertyAggregationFormula extends DynamicPropertyBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDbLob() {
|
||||
public boolean isLobForPlatform() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebeaninternal.server.deploy.id;
|
||||
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebeaninternal.api.SpiExpressionBind;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.core.DefaultSqlUpdate;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
@@ -143,7 +144,7 @@ public interface IdBinder {
|
||||
/**
|
||||
* Binds multiple id value to a request.
|
||||
*/
|
||||
void addBindValues(SpiExpressionRequest request, Collection<?> ids);
|
||||
void addBindValues(SpiExpressionBind request, Collection<?> ids);
|
||||
|
||||
/**
|
||||
* Return the sql for binding the id using an IN clause.
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.deploy.id;
|
||||
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.util.SplitName;
|
||||
import io.ebeaninternal.api.SpiExpressionBind;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.core.DefaultSqlUpdate;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
@@ -269,7 +270,7 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request, Collection<?> values) {
|
||||
public void addBindValues(SpiExpressionBind request, Collection<?> values) {
|
||||
for (Object value : values) {
|
||||
final EntityBean bean = (EntityBean) value;
|
||||
for (BeanProperty prop : props) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebeaninternal.server.deploy.id;
|
||||
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebeaninternal.api.SpiExpressionBind;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.bind.DataBind;
|
||||
import io.ebeaninternal.server.core.DefaultSqlUpdate;
|
||||
@@ -130,7 +131,7 @@ final class IdBinderEmpty implements IdBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request, Collection<?> ids) {
|
||||
public void addBindValues(SpiExpressionBind request, Collection<?> ids) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.deploy.id;
|
||||
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.core.type.ScalarType;
|
||||
import io.ebeaninternal.api.SpiExpressionBind;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.core.DefaultSqlUpdate;
|
||||
import io.ebeaninternal.server.core.InternString;
|
||||
@@ -143,7 +144,7 @@ public final class IdBinderSimple implements IdBinder {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request, Collection<?> values) {
|
||||
public void addBindValues(SpiExpressionBind request, Collection<?> values) {
|
||||
List<Object> copy = new ArrayList<>(values);
|
||||
copy.replaceAll(idValue -> convertSetId(idValue, null));
|
||||
request.addBindValue(new MultiValueWrapper(copy));
|
||||
|
||||
+5
-4
@@ -1,8 +1,8 @@
|
||||
package io.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import io.ebean.DatabaseBuilder;
|
||||
import io.ebean.annotation.Cache;
|
||||
import io.ebean.annotation.Identity;
|
||||
import io.ebean.DatabaseBuilder;
|
||||
import io.ebean.config.TableName;
|
||||
import io.ebean.config.dbplatform.IdType;
|
||||
import io.ebean.config.dbplatform.PlatformIdGenerator;
|
||||
@@ -18,9 +18,6 @@ import io.ebeaninternal.server.idgen.UuidV1IdGenerator;
|
||||
import io.ebeaninternal.server.idgen.UuidV1RndIdGenerator;
|
||||
import io.ebeaninternal.server.idgen.UuidV4IdGenerator;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
|
||||
@@ -110,6 +107,10 @@ public class DeployBeanDescriptor<T> {
|
||||
this.beanType = beanType;
|
||||
}
|
||||
|
||||
public BindMaxLength bindMaxLength() {
|
||||
return manager.bindMaxLength();
|
||||
}
|
||||
|
||||
private String[] readPropertyNames() {
|
||||
try {
|
||||
Field field = beanType.getField("_ebean_props");
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
package io.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import io.avaje.lang.Nullable;
|
||||
import io.ebean.annotation.*;
|
||||
import io.ebean.config.ScalarTypeConverter;
|
||||
import io.ebean.config.dbplatform.DbDefaultValue;
|
||||
import io.ebean.config.dbplatform.DbEncrypt;
|
||||
import io.ebean.config.dbplatform.DbEncryptFunction;
|
||||
import io.ebean.config.dbplatform.ExtraDbTypes;
|
||||
import io.ebean.core.type.ScalarType;
|
||||
import io.ebean.util.AnnotationUtil;
|
||||
import io.ebeaninternal.server.core.InternString;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
import io.ebeaninternal.server.deploy.BindMaxLength;
|
||||
import io.ebeaninternal.server.deploy.DbMigrationInfo;
|
||||
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedProperty;
|
||||
import io.ebeaninternal.server.el.ElPropertyValue;
|
||||
@@ -1075,4 +1078,20 @@ public class DeployBeanProperty {
|
||||
boolean isJsonType() {
|
||||
return mutationDetection != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BindMaxLength bindMaxLength() {
|
||||
if (dbLength == 0) {
|
||||
return null;
|
||||
}
|
||||
switch (dbType) {
|
||||
case Types.VARCHAR:
|
||||
case Types.BLOB:
|
||||
case ExtraDbTypes.JSON:
|
||||
return desc.bindMaxLength();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ abstract class AbstractExpression implements SpiExpression {
|
||||
validation.validate(propName);
|
||||
}
|
||||
|
||||
protected final ElPropertyValue getElProp(SpiExpressionRequest request) {
|
||||
protected final ElPropertyValue getElProp(SpiExpressionBind request) {
|
||||
return request.descriptor().elGetValue(propName);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionBind;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
|
||||
/**
|
||||
@@ -28,7 +29,7 @@ abstract class AbstractTextExpression extends AbstractExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
// do nothing, only execute against document store
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ final class AllEqualsExpression extends NonPrepareExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
if (propMap.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
+2
-1
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionBind;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -55,7 +56,7 @@ final class ArrayContainsExpression extends AbstractExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
for (Object value : values) {
|
||||
request.addBindValue(value);
|
||||
}
|
||||
|
||||
+2
-1
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionBind;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
|
||||
/**
|
||||
@@ -42,7 +43,7 @@ final class ArrayIsEmptyExpression extends AbstractExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
// nothing to bind
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionBind;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.el.ElPropertyValue;
|
||||
|
||||
@@ -27,7 +28,7 @@ final class BetweenExpression extends AbstractExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
ElPropertyValue prop = getElProp(request);
|
||||
if (prop != null && prop.isDbEncrypted()) {
|
||||
// bind the key as well as the value
|
||||
|
||||
+1
-1
@@ -54,7 +54,7 @@ final class BetweenPropertyExpression extends NonPrepareExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
request.addBindValue(val());
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionBind;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
|
||||
/**
|
||||
@@ -47,7 +48,7 @@ final class BitwiseExpression extends AbstractExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
request.addBindValue(flags);
|
||||
request.addBindValue(match);
|
||||
}
|
||||
|
||||
+2
-1
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionBind;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.el.ElPropertyValue;
|
||||
|
||||
@@ -22,7 +23,7 @@ final class CaseInsensitiveEqualExpression extends AbstractValueExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
ElPropertyValue prop = getElProp(request);
|
||||
if (prop != null && prop.isDbEncrypted()) {
|
||||
// bind the key as well as the value
|
||||
|
||||
+2
-8
@@ -5,12 +5,7 @@ import io.ebean.LikeType;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.event.BeanQueryRequest;
|
||||
import io.ebean.util.SplitName;
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.ManyWhereJoins;
|
||||
import io.ebeaninternal.api.NaturalKeyQueryData;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.api.SpiExpressionValidation;
|
||||
import io.ebeaninternal.api.*;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
@@ -177,8 +172,7 @@ final class DefaultExampleExpression implements SpiExpression, ExampleExpression
|
||||
* Adds bind values to the request.
|
||||
*/
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
for (SpiExpression item : list) {
|
||||
item.addBindValues(request);
|
||||
}
|
||||
|
||||
+16
-1
@@ -218,6 +218,21 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return query.update(transaction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureIds<T> findFutureIds() {
|
||||
return query.findFutureIds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureRowCount<T> findFutureCount() {
|
||||
return query.findFutureCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureList<T> findFutureList() {
|
||||
return query.findFutureList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PagedList<T> findPagedList() {
|
||||
return query.findPagedList();
|
||||
@@ -431,7 +446,7 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
for (SpiExpression expr : list) {
|
||||
expr.addBindValues(request);
|
||||
}
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ final class ExistsQueryExpression implements SpiExpression, UnsupportedDocStoreE
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
for (Object bindParam : bindParams) {
|
||||
request.addBindValue(bindParam);
|
||||
}
|
||||
|
||||
+1
-1
@@ -72,7 +72,7 @@ final class ExistsSqlQueryExpression implements SpiExpression, UnsupportedDocSto
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
for (Object bindParam : bindParams) {
|
||||
request.addBindValue(bindParam);
|
||||
}
|
||||
|
||||
@@ -49,6 +49,21 @@ public final class FilterExpressionList<T> extends DefaultExpressionList<T> {
|
||||
return rootQuery.filterMany(prop);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureIds<T> findFutureIds() {
|
||||
return rootQuery.findFutureIds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureList<T> findFutureList() {
|
||||
return rootQuery.findFutureList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureRowCount<T> findFutureCount() {
|
||||
return rootQuery.findFutureCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<T> findList() {
|
||||
return rootQuery.findList();
|
||||
|
||||
@@ -33,7 +33,7 @@ final class IdExpression extends NonPrepareExpression implements SpiExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
// 'flatten' EmbeddedId and multiple ID cases
|
||||
// into an array of the underlying scalar field values
|
||||
for (Object bindIdValue : request.descriptor().bindIdValues(value)) {
|
||||
|
||||
@@ -50,7 +50,7 @@ public final class IdInExpression extends NonPrepareExpression implements IdInCo
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
if (idCollection.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,10 +2,7 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.event.BeanQueryRequest;
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.NaturalKeyQueryData;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.api.*;
|
||||
import io.ebeaninternal.server.el.ElPropertyValue;
|
||||
import io.ebeaninternal.server.persist.MultiValueWrapper;
|
||||
|
||||
@@ -95,7 +92,7 @@ public final class InExpression extends AbstractExpression implements IdInCommon
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
if (empty) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3,10 +3,7 @@ package io.ebeaninternal.server.expression;
|
||||
import io.ebean.Pairs;
|
||||
import io.ebean.Pairs.Entry;
|
||||
import io.ebean.event.BeanQueryRequest;
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.NaturalKeyQueryData;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.api.*;
|
||||
import io.ebeaninternal.server.persist.MultiValueWrapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -53,8 +50,7 @@ final class InPairsExpression extends AbstractExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
// Note at this point entries may have been removed when used with l2 caching
|
||||
// ... for each l2 cache hit an entry was removed
|
||||
this.concatBindValues = new ArrayList<>(entries.size());
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionBind;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.el.ElPropertyValue;
|
||||
|
||||
@@ -25,7 +26,7 @@ final class InRangeExpression extends AbstractExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
ElPropertyValue prop = getElProp(request);
|
||||
if (prop != null && prop.isDbEncrypted()) {
|
||||
// bind the key twice, for both values
|
||||
|
||||
@@ -2,10 +2,7 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebean.InTuples;
|
||||
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 io.ebeaninternal.api.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -32,7 +29,7 @@ final class InTuplesExpression extends AbstractExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
for (Object[] entry : entries) {
|
||||
for (Object value : entry) {
|
||||
requireNonNull(value);
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebean.util.SplitName;
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.ManyWhereJoins;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.api.*;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.el.ElPropertyValue;
|
||||
|
||||
@@ -25,7 +22,7 @@ final class IsEmptyExpression extends AbstractExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
// no bind values
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionBind;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
|
||||
import java.util.Objects;
|
||||
@@ -91,7 +92,7 @@ final class JsonPathExpression extends AbstractExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
if (value != null) {
|
||||
// value is null for EXISTS/NOT EXISTS
|
||||
request.addBindValue(value);
|
||||
|
||||
+16
-1
@@ -122,7 +122,7 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
for (SpiExpression expr : exprList.internalList()) {
|
||||
expr.addBindValues(request);
|
||||
}
|
||||
@@ -328,6 +328,21 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
|
||||
return exprList.exists();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureIds<T> findFutureIds() {
|
||||
return exprList.findFutureIds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureList<T> findFutureList() {
|
||||
return exprList.findFutureList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FutureRowCount<T> findFutureCount() {
|
||||
return exprList.findFutureCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <A> List<A> findIds() {
|
||||
return exprList.findIds();
|
||||
|
||||
@@ -3,6 +3,7 @@ package io.ebeaninternal.server.expression;
|
||||
import io.ebean.LikeType;
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionBind;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.el.ElPropertyValue;
|
||||
|
||||
@@ -18,7 +19,7 @@ final class LikeExpression extends AbstractValueExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
ElPropertyValue prop = getElProp(request);
|
||||
if (prop != null && prop.isDbEncrypted()) {
|
||||
// bind the key as well as the value
|
||||
@@ -71,7 +72,7 @@ final class LikeExpression extends AbstractValueExpression {
|
||||
return strValue().equals(that.strValue());
|
||||
}
|
||||
|
||||
private static String getValue(String value, boolean caseInsensitive, LikeType type, SpiExpressionRequest request) {
|
||||
private static String getValue(String value, boolean caseInsensitive, LikeType type, SpiExpressionBind request) {
|
||||
if (caseInsensitive) {
|
||||
value = value.toLowerCase();
|
||||
}
|
||||
|
||||
@@ -2,12 +2,7 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebean.Expression;
|
||||
import io.ebean.event.BeanQueryRequest;
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.ManyWhereJoins;
|
||||
import io.ebeaninternal.api.NaturalKeyQueryData;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.api.SpiExpressionValidation;
|
||||
import io.ebeaninternal.api.*;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
|
||||
/**
|
||||
@@ -101,7 +96,7 @@ abstract class LogicExpression implements SpiExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
expOne.addBindValues(request);
|
||||
expTwo.addBindValues(request);
|
||||
}
|
||||
|
||||
+2
-2
@@ -3,6 +3,7 @@ package io.ebeaninternal.server.expression;
|
||||
import io.ebean.LikeType;
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionBind;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.el.ElPropertyValue;
|
||||
|
||||
@@ -16,8 +17,7 @@ final class NativeILikeExpression extends AbstractExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
ElPropertyValue prop = getElProp(request);
|
||||
if (prop != null && prop.isDbEncrypted()) {
|
||||
// bind the key as well as the value
|
||||
|
||||
@@ -69,7 +69,7 @@ final class NoopExpression implements SpiExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
|
||||
@@ -2,12 +2,7 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebean.Expression;
|
||||
import io.ebean.event.BeanQueryRequest;
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.ManyWhereJoins;
|
||||
import io.ebeaninternal.api.NaturalKeyQueryData;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.api.SpiExpressionValidation;
|
||||
import io.ebeaninternal.api.*;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
|
||||
final class NotExpression implements SpiExpression {
|
||||
@@ -59,7 +54,7 @@ final class NotExpression implements SpiExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
exp.addBindValues(request);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebean.util.SplitName;
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.ManyWhereJoins;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.api.*;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.el.ElPropertyValue;
|
||||
|
||||
@@ -43,7 +40,7 @@ final class NullExpression extends AbstractExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ final class RawExpression extends NonPrepareExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
if (values != null) {
|
||||
for (Object value : values) {
|
||||
if (value instanceof Collection<?>) {
|
||||
|
||||
@@ -2,10 +2,7 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.plugin.ExpressionPath;
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.NaturalKeyQueryData;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.api.*;
|
||||
import io.ebeaninternal.server.el.ElPropertyValue;
|
||||
|
||||
public final class SimpleExpression extends AbstractValueExpression {
|
||||
@@ -47,8 +44,7 @@ public final class SimpleExpression extends AbstractValueExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
ElPropertyValue prop = getElProp(request);
|
||||
if (prop != null) {
|
||||
if (prop.isAssocId()) {
|
||||
|
||||
@@ -74,7 +74,7 @@ final class SubQueryExpression extends AbstractExpression implements Unsupported
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
for (Object bindParam : bindParams) {
|
||||
request.addBindValue(bindParam);
|
||||
}
|
||||
|
||||
+2
-1
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionBind;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -42,7 +43,7 @@ final class SubQueryRawExpression extends AbstractExpression implements Unsuppor
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
public void addBindValues(SpiExpressionBind request) {
|
||||
for (Object bindParam : bindParams) {
|
||||
request.addBindValue(bindParam);
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.BitwiseOp;
|
||||
|
||||
/**
|
||||
@@ -9,7 +8,7 @@ import io.ebeaninternal.server.expression.BitwiseOp;
|
||||
abstract class BaseDbExpression implements DbExpressionHandler {
|
||||
|
||||
@Override
|
||||
public void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
|
||||
public void bitwise(DbExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
|
||||
final String bitOp = bitOp(operator);
|
||||
request.append('(').property(propName).append(' ').append(bitOp).append(" ? ").append(compare).append(" ?)");
|
||||
}
|
||||
@@ -28,7 +27,7 @@ abstract class BaseDbExpression implements DbExpressionHandler {
|
||||
/**
|
||||
* Common alternative where the bitwise operation is a function (specifically bitand is used - H2 and Oracle).
|
||||
*/
|
||||
protected void bitwiseFunction(SpiExpressionRequest request, String propName, BitwiseOp operator, String compare) {
|
||||
protected void bitwiseFunction(DbExpressionRequest request, String propName, BitwiseOp operator, String compare) {
|
||||
final String funcName = functionName(operator);
|
||||
request.append(funcName).append('(').property(propName).append(", ?) ").append(compare).append(" ?");
|
||||
}
|
||||
|
||||
+3
-4
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.Op;
|
||||
|
||||
/**
|
||||
@@ -9,17 +8,17 @@ import io.ebeaninternal.server.expression.Op;
|
||||
class BasicDbExpression extends BaseDbExpression {
|
||||
|
||||
@Override
|
||||
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
public void json(DbExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
throw new RuntimeException("JSON expressions only supported on Postgres and Oracle");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayContains(SpiExpressionRequest request, String propName, boolean contains, Object... values) {
|
||||
public void arrayContains(DbExpressionRequest request, String propName, boolean contains, Object... values) {
|
||||
throw new RuntimeException("ARRAY expressions only supported on Postgres");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty) {
|
||||
public void arrayIsEmpty(DbExpressionRequest request, String propName, boolean empty) {
|
||||
throw new RuntimeException("ARRAY expressions only supported on Postgres");
|
||||
}
|
||||
}
|
||||
|
||||
+4
-5
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.BitwiseOp;
|
||||
import io.ebeaninternal.server.expression.Op;
|
||||
|
||||
@@ -12,22 +11,22 @@ public interface DbExpressionHandler {
|
||||
/**
|
||||
* Write the db platform specific json expression.
|
||||
*/
|
||||
void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value);
|
||||
void json(DbExpressionRequest request, String propName, String path, Op operator, Object value);
|
||||
|
||||
/**
|
||||
* Add SQL for ARRAY CONTAINS expression.
|
||||
*/
|
||||
void arrayContains(SpiExpressionRequest request, String propName, boolean contains, Object... values);
|
||||
void arrayContains(DbExpressionRequest request, String propName, boolean contains, Object... values);
|
||||
|
||||
/**
|
||||
* Add SQL for ARRAY IS EMPTY expression.
|
||||
*/
|
||||
void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty);
|
||||
void arrayIsEmpty(DbExpressionRequest request, String propName, boolean empty);
|
||||
|
||||
/**
|
||||
* Add the bitwise expression.
|
||||
*/
|
||||
void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match);
|
||||
void bitwise(DbExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match);
|
||||
|
||||
/**
|
||||
* Performs a "CONCAT" operation for that platform.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user