mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d413b03dd | ||
|
|
ab45ad34e0 | ||
|
|
24b514f851 | ||
|
|
582fec7ce4 | ||
|
|
0b11c541c8 | ||
|
|
540ceab96f | ||
|
|
8b858a073a | ||
|
|
02dafc9838 | ||
|
|
0816810d3b | ||
|
|
1f6e2ee844 | ||
|
|
dc00765a98 | ||
|
|
a48b2f4ebe | ||
|
|
837563544f | ||
|
|
fd199f406b | ||
|
|
a48e96c7e9 | ||
|
|
7ba6e5f67d | ||
|
|
6ce42b1ca3 | ||
|
|
89617cefbe | ||
|
|
dd377621a4 | ||
|
|
d844855462 | ||
|
|
f68c25d5f3 | ||
|
|
61cfc7a979 | ||
|
|
3c98ee7f1b | ||
|
|
0738316f15 | ||
|
|
ceb83befa3 | ||
|
|
a0b04cceda | ||
|
|
03edfb5454 | ||
|
|
62015451df | ||
|
|
ed9113efe6 | ||
|
|
334793667e | ||
|
|
351a1c4739 | ||
|
|
b2de333dcc | ||
|
|
6091f7b683 | ||
|
|
43fb84cbc0 | ||
|
|
52a4e9e19b | ||
|
|
a2cdea24ed | ||
|
|
cd780208e5 | ||
|
|
9ce0e923d7 | ||
|
|
9e461e4708 | ||
|
|
5fa09a6f90 | ||
|
|
6babb2e6f5 | ||
|
|
26abe27e42 | ||
|
|
9b18d46b78 | ||
|
|
eed487ad26 | ||
|
|
c10865dfaf | ||
|
|
2352df309c | ||
|
|
feb2bd1e15 | ||
|
|
11c9bdfc6f | ||
|
|
4a6fc98395 | ||
|
|
7322030e90 | ||
|
|
77634fc3eb | ||
|
|
ed8d4b5fc4 | ||
|
|
187cc0903d | ||
|
|
1d7a14c8f4 | ||
|
|
c58b7d3da3 |
@@ -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.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-clickhouse</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-db2</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-hana</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-mariadb</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-mysql</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-nuodb</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-oracle</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
<properties>
|
||||
<postgis.jdbc.version>2.5.1</postgis.jdbc.version>
|
||||
<postgres.jdbc.version>42.6.0</postgres.jdbc.version>
|
||||
<postgres.jdbc.version>42.7.2</postgres.jdbc.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -22,13 +22,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -47,19 +47,19 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis-types</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlite</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlserver</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,31 +17,31 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-joda-time</artifactId>
|
||||
<version>13.24.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-jsonnode</artifactId>
|
||||
<version>13.24.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-mapper</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -60,13 +60,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-all</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</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.0.2</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.0.2</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();
|
||||
|
||||
@@ -87,6 +87,7 @@ public interface DatabaseBuilder {
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the Database.
|
||||
*/
|
||||
@@ -2208,6 +2209,15 @@ public interface DatabaseBuilder {
|
||||
@Deprecated
|
||||
DatabaseBuilder setLoadModuleInfo(boolean loadModuleInfo);
|
||||
|
||||
/**
|
||||
* Set if generated SQL SELECT should include the query label as an
|
||||
* inline SQL comment (to help reference back from the SQL to the code
|
||||
* that executed the query.
|
||||
*
|
||||
* @param includeLabelInSql When true include a SQL inline comment in generated SELECT queries.
|
||||
*/
|
||||
DatabaseConfig includeLabelInSql(boolean includeLabelInSql);
|
||||
|
||||
/**
|
||||
* Set the naming convention to apply to metrics names.
|
||||
*/
|
||||
@@ -2221,6 +2231,11 @@ public interface DatabaseBuilder {
|
||||
@Deprecated
|
||||
DatabaseBuilder setMetricNaming(Function<String, String> metricNaming);
|
||||
|
||||
/**
|
||||
* Sets the length check mode.
|
||||
*/
|
||||
DatabaseConfig lengthCheck(LengthCheck lengthCheck);
|
||||
|
||||
/**
|
||||
* Provides read access (getters) for the DatabaseBuilder configuration
|
||||
* that has been set.
|
||||
@@ -3098,10 +3113,20 @@ public interface DatabaseBuilder {
|
||||
*/
|
||||
boolean isLoadModuleInfo();
|
||||
|
||||
/**
|
||||
* Return true if generated sql select query should include an inline sql comment with the
|
||||
* query label or profile location label.
|
||||
*/
|
||||
boolean isIncludeLabelInSql();
|
||||
|
||||
/**
|
||||
* Return the naming convention to apply to metrics names.
|
||||
*/
|
||||
Function<String, String> getMetricNaming();
|
||||
|
||||
/**
|
||||
* Returns the length check mode.
|
||||
*/
|
||||
LengthCheck getLengthCheck();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1601,6 +1601,14 @@ public interface Query<T> extends CancelableQuery {
|
||||
*/
|
||||
Query<T> setLabel(String label);
|
||||
|
||||
/**
|
||||
* Set a SQL query hint.
|
||||
* <p>
|
||||
* This results in an inline comment that immediately follows
|
||||
* after the select keyword in the form: {@code /*+ hint *\/ }
|
||||
*/
|
||||
Query<T> setHint(String hint);
|
||||
|
||||
/**
|
||||
* Set to true if this query should execute against the doc store.
|
||||
* <p>
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package io.ebean.config;
|
||||
|
||||
import io.avaje.config.Config;
|
||||
import io.avaje.config.Configuration;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
@@ -19,16 +16,6 @@ public class ContainerConfig {
|
||||
private String podName;
|
||||
private int port;
|
||||
private Properties properties;
|
||||
private Configuration configuration;
|
||||
|
||||
public ContainerConfig() {
|
||||
this.configuration = Config.asConfiguration();
|
||||
this.active = configuration.getBool("ebean.cluster.active", active);
|
||||
this.serviceName = configuration.getNullable("ebean.cluster.serviceName", serviceName);
|
||||
this.namespace = configuration.getNullable("ebean.cluster.namespace", namespace);
|
||||
this.podName = configuration.getNullable("ebean.cluster.podName", podName);
|
||||
this.port = configuration.getInt("ebean.cluster.port", 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the service name.
|
||||
@@ -104,7 +91,7 @@ public class ContainerConfig {
|
||||
* Return the deployment properties.
|
||||
*/
|
||||
public Properties getProperties() {
|
||||
return properties != null ? properties : configuration.asProperties();
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,4 +101,25 @@ public class ContainerConfig {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the settings from properties.
|
||||
*/
|
||||
public void loadFromProperties(Properties properties) {
|
||||
this.properties = properties;
|
||||
this.active = getProperty(properties, "ebean.cluster.active", active);
|
||||
this.serviceName = properties.getProperty("ebean.cluster.serviceName", serviceName);
|
||||
this.namespace = properties.getProperty("ebean.cluster.namespace", namespace);
|
||||
this.podName = properties.getProperty("ebean.cluster.podName", podName);
|
||||
String portParam = properties.getProperty("ebean.cluster.port");
|
||||
if (portParam != null) {
|
||||
this.port = Integer.parseInt(portParam);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the boolean property setting.
|
||||
*/
|
||||
protected boolean getProperty(Properties properties, String key, boolean defaultValue) {
|
||||
return "true".equalsIgnoreCase(properties.getProperty(key, Boolean.toString(defaultValue)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,6 +125,12 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
*/
|
||||
private boolean loadModuleInfo = true;
|
||||
|
||||
/**
|
||||
* When true then include a sql comment in generated SELECT queries with the query
|
||||
* label or profile location label.
|
||||
*/
|
||||
private boolean includeLabelInSql;
|
||||
|
||||
/**
|
||||
* Interesting classes such as entities, embedded, ScalarTypes,
|
||||
* Listeners, Finders, Controllers, AttributeConverters etc.
|
||||
@@ -545,6 +551,8 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
|
||||
private String dumpMetricsOptions;
|
||||
|
||||
private LengthCheck lengthCheck = LengthCheck.OFF;
|
||||
|
||||
private Function<String, String> metricNaming = MetricNamingMatch.INSTANCE;
|
||||
|
||||
/**
|
||||
@@ -2131,6 +2139,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
readOnlyDatabase = p.getBoolean("readOnlyDatabase", readOnlyDatabase);
|
||||
autoPersistUpdates = p.getBoolean("autoPersistUpdates", autoPersistUpdates);
|
||||
loadModuleInfo = p.getBoolean("loadModuleInfo", loadModuleInfo);
|
||||
includeLabelInSql = p.getBoolean("includeLabelInSql", includeLabelInSql);
|
||||
maxCallStack = p.getInt("maxCallStack", maxCallStack);
|
||||
dumpMetricsOnShutdown = p.getBoolean("dumpMetricsOnShutdown", dumpMetricsOnShutdown);
|
||||
dumpMetricsOptions = p.get("dumpMetricsOptions", dumpMetricsOptions);
|
||||
@@ -2195,6 +2204,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
jdbcFetchSizeFindEach = p.getInt("jdbcFetchSizeFindEach", jdbcFetchSizeFindEach);
|
||||
jdbcFetchSizeFindList = p.getInt("jdbcFetchSizeFindList", jdbcFetchSizeFindList);
|
||||
databasePlatformName = p.get("databasePlatformName", databasePlatformName);
|
||||
lengthCheck = p.getEnum(LengthCheck.class, "lengthCheck", lengthCheck);
|
||||
|
||||
uuidVersion = p.getEnum(UuidVersion.class, "uuidVersion", uuidVersion);
|
||||
uuidStateFile = p.get("uuidStateFile", uuidStateFile);
|
||||
@@ -2544,6 +2554,11 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
return loadModuleInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludeLabelInSql() {
|
||||
return includeLabelInSql;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated - migrate to {@link #isLoadModuleInfo()}.
|
||||
*/
|
||||
@@ -2560,6 +2575,12 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseConfig includeLabelInSql(boolean includeLabelInSql) {
|
||||
this.includeLabelInSql = includeLabelInSql;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<String, String> getMetricNaming() {
|
||||
return metricNaming;
|
||||
@@ -2571,6 +2592,19 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the length check mode.
|
||||
*/
|
||||
public LengthCheck getLengthCheck() {
|
||||
return lengthCheck;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseConfig lengthCheck(LengthCheck lengthCheck) {
|
||||
this.lengthCheck = lengthCheck;
|
||||
return this;
|
||||
}
|
||||
|
||||
public enum UuidVersion {
|
||||
VERSION4,
|
||||
VERSION1,
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package io.ebean.config;
|
||||
|
||||
/**
|
||||
* Defines the length-check mode.
|
||||
*
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*/
|
||||
public enum LengthCheck {
|
||||
/**
|
||||
* By default, length checking is off. This means, strings/jsons and files are passed to the DB and the DB might or might not check the length.
|
||||
* The DB has to check the data length. Note this is not possible for certain datatypes (e.g. clob without size)
|
||||
*/
|
||||
OFF,
|
||||
/**
|
||||
* When enabling length check, ebean validates strings/json strings and files before saving them to DB.
|
||||
*/
|
||||
ON,
|
||||
/**
|
||||
* Same as "ON", but take the UTF8-bytelength for validation. This may be useful, if you have an UTF8 based charset (default for DB2)
|
||||
*/
|
||||
UTF8
|
||||
}
|
||||
@@ -769,4 +769,15 @@ public class DatabasePlatform {
|
||||
public boolean supportsNativeJavaTime() {
|
||||
return supportsNativeJavaTime;
|
||||
}
|
||||
|
||||
public String inlineSqlComment(String label) {
|
||||
if (label == null) {
|
||||
return "";
|
||||
}
|
||||
return "/* " + label + " */ ";
|
||||
}
|
||||
|
||||
public String inlineSqlHint(String hint) {
|
||||
return "/*+ " + hint + " */ ";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import java.sql.Driver;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
@@ -23,7 +24,7 @@ public final class ShutdownManager {
|
||||
|
||||
private static final System.Logger log = EbeanVersion.log;
|
||||
private static final ReentrantLock lock = new ReentrantLock();
|
||||
private static final List<Database> databases = new ArrayList<>();
|
||||
private static final List<Database> databases = Collections.synchronizedList(new ArrayList<>());
|
||||
private static final ShutdownHook shutdownHook = new ShutdownHook();
|
||||
|
||||
private static boolean stopping;
|
||||
@@ -177,12 +178,7 @@ public final class ShutdownManager {
|
||||
* Register an ebeanServer to be shutdown when the JVM is shutdown.
|
||||
*/
|
||||
public static void registerDatabase(Database server) {
|
||||
lock.lock();
|
||||
try {
|
||||
databases.add(server);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
databases.add(server);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -192,12 +188,7 @@ public final class ShutdownManager {
|
||||
* </p>
|
||||
*/
|
||||
public static void unregisterDatabase(Database server) {
|
||||
lock.lock();
|
||||
try {
|
||||
databases.remove(server);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
databases.remove(server);
|
||||
}
|
||||
|
||||
private static class ShutdownHook extends Thread {
|
||||
|
||||
@@ -22,6 +22,8 @@ public class JsonWriteOptions {
|
||||
|
||||
protected JsonConfig.Include include;
|
||||
|
||||
protected boolean includeLoadedImplicit = true;
|
||||
|
||||
protected Map<String, JsonWriteBeanVisitor<?>> visitorMap;
|
||||
|
||||
/**
|
||||
@@ -73,6 +75,20 @@ public class JsonWriteOptions {
|
||||
this.include = include;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should loaded properties be included implicit, if no other fetch path is specified (default = true).
|
||||
*/
|
||||
public boolean isIncludeLoadedImplicit() {
|
||||
return includeLoadedImplicit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set include loaded properties implicit (default = true).
|
||||
*/
|
||||
public void setIncludeLoadedImplicit(boolean includeLoadedImplicit) {
|
||||
this.includeLoadedImplicit = includeLoadedImplicit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a JsonWriteBeanVisitor for the root level.
|
||||
*/
|
||||
|
||||
@@ -75,6 +75,8 @@ class DatabaseConfigTest {
|
||||
props.setProperty("defaultServer", "false");
|
||||
props.setProperty("skipDataSourceCheck", "true");
|
||||
props.setProperty("readOnlyDatabase", "true");
|
||||
props.setProperty("lengthCheck", "ON");
|
||||
props.setProperty("includeLabelInSql", "true");
|
||||
|
||||
props.setProperty("queryPlan.enable", "true");
|
||||
props.setProperty("queryPlan.thresholdMicros", "10000");
|
||||
@@ -95,6 +97,8 @@ class DatabaseConfigTest {
|
||||
assertTrue(settings.isLoadModuleInfo());
|
||||
assertTrue(settings.skipDataSourceCheck());
|
||||
assertTrue(settings.readOnlyDatabase());
|
||||
assertTrue(settings.isIncludeLabelInSql());
|
||||
assertThat(settings.getLengthCheck()).isEqualTo(LengthCheck.ON);
|
||||
|
||||
assertTrue(settings.isIdGeneratorAutomatic());
|
||||
assertFalse(settings.getPlatformConfig().isCaseSensitiveCollation());
|
||||
@@ -128,8 +132,11 @@ class DatabaseConfigTest {
|
||||
|
||||
assertThat(settings.getMappingLocations()).containsExactly("classpath:/foo","bar");
|
||||
|
||||
config.setPersistBatch(PersistBatch.NONE);
|
||||
config.setPersistBatchOnCascade(PersistBatch.NONE);
|
||||
config.persistBatch(PersistBatch.NONE)
|
||||
.persistBatchOnCascade(PersistBatch.NONE)
|
||||
.lengthCheck(LengthCheck.ON)
|
||||
.lengthCheck(LengthCheck.UTF8);
|
||||
|
||||
|
||||
Properties props1 = new Properties();
|
||||
props1.setProperty("ebean.persistBatch", "ALL");
|
||||
@@ -146,6 +153,7 @@ class DatabaseConfigTest {
|
||||
|
||||
assertEquals(PersistBatch.ALL, settings.getPersistBatch());
|
||||
assertEquals(PersistBatch.ALL, settings.getPersistBatchOnCascade());
|
||||
assertEquals(LengthCheck.UTF8, settings.getLengthCheck());
|
||||
|
||||
config.setEnabledL2Regions("r0,orgs");
|
||||
assertEquals("r0,orgs", settings.getEnabledL2Regions());
|
||||
@@ -174,6 +182,8 @@ class DatabaseConfigTest {
|
||||
assertEquals(600, config.getQueryPlanCapturePeriodSecs());
|
||||
assertEquals(10000L, config.getQueryPlanCaptureMaxTimeMillis());
|
||||
assertEquals(10, config.getQueryPlanCaptureMaxCount());
|
||||
assertThat(config.getLengthCheck()).isEqualTo(LengthCheck.OFF);
|
||||
assertFalse(config.isIncludeLabelInSql());
|
||||
|
||||
config.setLoadModuleInfo(false);
|
||||
assertFalse(config.isAutoLoadModuleInfo());
|
||||
|
||||
+31
-31
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</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.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-joda-time</artifactId>
|
||||
<version>13.24.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-jsonnode</artifactId>
|
||||
<version>13.24.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-mapper</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>13.18.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-xml</artifactId>
|
||||
<version>13.18.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-autotune</artifactId>
|
||||
<version>13.18.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>kotlin-querybean-generator</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-redis</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-spring-txn</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- platforms -->
|
||||
@@ -193,79 +193,79 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-clickhouse</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-db2</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-h2</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-hana</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-mariadb</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-mysql</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-nuodb</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-oracle</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgres</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis-types</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-sqlite</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-sqlserver</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
@@ -16,7 +16,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -30,7 +30,7 @@
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.6.0</version>
|
||||
<version>42.7.2</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -174,4 +174,9 @@ public interface DataBinder {
|
||||
*/
|
||||
String popJson();
|
||||
|
||||
/**
|
||||
* Returns the last bound object (e.g. for BindValidation). Note for InputStreams you'll get an InputStreamInfo.
|
||||
*/
|
||||
Object popLastObject();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package io.ebean.core.type;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Helper to transports length info of DataBind.setBinaryStream(stream, length) to BindValidation
|
||||
*
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*/
|
||||
public final class InputStreamInfo {
|
||||
|
||||
private final InputStream stream;
|
||||
private final long length;
|
||||
|
||||
public InputStreamInfo(InputStream stream, long length) {
|
||||
this.stream = stream;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
public InputStream stream() {
|
||||
return stream;
|
||||
}
|
||||
|
||||
public long length() {
|
||||
return length;
|
||||
}
|
||||
}
|
||||
+8
-8
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core</artifactId>
|
||||
@@ -22,7 +22,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -46,13 +46,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>13.18.0</version>
|
||||
<version>14.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -151,7 +151,7 @@
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.6.0</version>
|
||||
<version>42.7.2</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
@@ -159,21 +159,21 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlserver</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</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), loadContext.isUseDocStore());
|
||||
query.setPersistenceContext(loadContext.persistenceContext());
|
||||
final var pc = loadContext.persistenceContext();
|
||||
many.addWhereParentIdIn(query, parentIdList(server, many, pc), loadContext.isUseDocStore());
|
||||
query.setPersistenceContext(pc);
|
||||
query.setLoadDescription(lazy ? "lazy" : "query", description());
|
||||
if (lazy) {
|
||||
query.setLazyLoadBatchSize(loadContext.batchSize());
|
||||
|
||||
@@ -3,13 +3,14 @@ package io.ebeaninternal.api;
|
||||
import io.ebeaninternal.server.core.SpiOrmQueryRequest;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.expression.platform.DbExpressionHandler;
|
||||
import io.ebeaninternal.server.expression.platform.DbExpressionRequest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Request object used for gathering expression sql and bind values.
|
||||
*/
|
||||
public interface SpiExpressionRequest {
|
||||
public interface SpiExpressionRequest extends DbExpressionRequest {
|
||||
|
||||
/**
|
||||
* Return the DB specific handler for JSON and ARRAY expressions.
|
||||
@@ -34,11 +35,13 @@ public interface SpiExpressionRequest {
|
||||
/**
|
||||
* Append to the expression sql without any parsing.
|
||||
*/
|
||||
@Override
|
||||
SpiExpressionRequest append(String expression);
|
||||
|
||||
/**
|
||||
* Append to the expression sql without any parsing.
|
||||
*/
|
||||
@Override
|
||||
SpiExpressionRequest append(char c);
|
||||
|
||||
/**
|
||||
@@ -47,6 +50,7 @@ public interface SpiExpressionRequest {
|
||||
* This is a fast path case when expression is a bean property path and falls back to using parse()
|
||||
* when that isn't the case.
|
||||
*/
|
||||
@Override
|
||||
SpiExpressionRequest property(String expression);
|
||||
|
||||
/**
|
||||
|
||||
@@ -226,6 +226,11 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
|
||||
*/
|
||||
ProfileLocation profileLocation();
|
||||
|
||||
/**
|
||||
* Return the SQL hint to include in the query.
|
||||
*/
|
||||
String hint();
|
||||
|
||||
/**
|
||||
* Return the label set on the query.
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -919,21 +919,27 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
}
|
||||
|
||||
private void controllerPost() {
|
||||
switch (type) {
|
||||
case INSERT:
|
||||
controller.postInsert(this);
|
||||
break;
|
||||
case UPDATE:
|
||||
controller.postUpdate(this);
|
||||
break;
|
||||
case DELETE_SOFT:
|
||||
controller.postSoftDelete(this);
|
||||
break;
|
||||
case DELETE:
|
||||
controller.postDelete(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
boolean old = transaction.isFlushOnQuery();
|
||||
transaction.setFlushOnQuery(false);
|
||||
try {
|
||||
switch (type) {
|
||||
case INSERT:
|
||||
controller.postInsert(this);
|
||||
break;
|
||||
case UPDATE:
|
||||
controller.postUpdate(this);
|
||||
break;
|
||||
case DELETE_SOFT:
|
||||
controller.postSoftDelete(this);
|
||||
break;
|
||||
case DELETE:
|
||||
controller.postDelete(this);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} finally {
|
||||
transaction.setFlushOnQuery(old);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -106,6 +106,7 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
|
||||
private final String asOfViewSuffix;
|
||||
private final boolean jacksonCorePresent;
|
||||
private final int queryPlanTTLSeconds;
|
||||
private final BindMaxLength bindMaxLength;
|
||||
private int entityBeanCount;
|
||||
private List<BeanDescriptor<?>> immutableDescriptorList;
|
||||
/**
|
||||
@@ -160,6 +161,19 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
|
||||
this.changeLogListener = config.changeLogListener(bootupClasses.getChangeLogListener());
|
||||
this.changeLogRegister = config.changeLogRegister(bootupClasses.getChangeLogRegister());
|
||||
this.jacksonCorePresent = config.isJacksonCorePresent();
|
||||
this.bindMaxLength = initMaxLength();
|
||||
}
|
||||
|
||||
BindMaxLength initMaxLength() {
|
||||
LengthCheck lengthCheck = this.config.getLengthCheck();
|
||||
switch (lengthCheck) {
|
||||
case OFF:
|
||||
return null;
|
||||
case UTF8:
|
||||
return BindMaxLength.ofUtf8();
|
||||
default:
|
||||
return BindMaxLength.ofStandard();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1501,6 +1515,10 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
|
||||
return list;
|
||||
}
|
||||
|
||||
public BindMaxLength bindMaxLength() {
|
||||
return bindMaxLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator to sort the BeanDescriptors by name.
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebeaninternal.server.deploy;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import io.ebean.DataIntegrityException;
|
||||
import io.ebean.ValuePair;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
@@ -40,8 +41,8 @@ import io.ebeanservice.docstore.api.mapping.DocMappingBuilder;
|
||||
import io.ebeanservice.docstore.api.mapping.DocPropertyMapping;
|
||||
import io.ebeanservice.docstore.api.mapping.DocPropertyOptions;
|
||||
import io.ebeanservice.docstore.api.support.DocStructure;
|
||||
|
||||
import jakarta.persistence.PersistenceException;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
@@ -166,6 +167,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
*/
|
||||
private final String dbComment;
|
||||
private final DbEncryptFunction dbEncryptFunction;
|
||||
private final BindMaxLength bindMaxLength;
|
||||
private int deployOrder;
|
||||
final boolean jsonSerialize;
|
||||
final boolean jsonDeserialize;
|
||||
@@ -258,6 +260,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
}
|
||||
this.jsonSerialize = deploy.isJsonSerialize();
|
||||
this.jsonDeserialize = deploy.isJsonDeserialize();
|
||||
this.bindMaxLength = deploy.bindMaxLength();
|
||||
}
|
||||
|
||||
private String tableAliasIntern(BeanDescriptor<?> descriptor, String s, boolean dbEncrypted, String dbColumn) {
|
||||
@@ -345,6 +348,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
this.elPlaceHolderEncrypted = override.replace(source.elPlaceHolderEncrypted, source.dbColumn);
|
||||
this.jsonSerialize = source.jsonSerialize;
|
||||
this.jsonDeserialize = source.jsonDeserialize;
|
||||
this.bindMaxLength = source.bindMaxLength;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -555,6 +559,18 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void bind(DataBind b, Object value) throws SQLException {
|
||||
scalarType.bind(b, value);
|
||||
if (bindMaxLength != null) {
|
||||
Object obj = b.popLastObject();
|
||||
long length = bindMaxLength.length(dbLength, obj);
|
||||
if (length > dbLength) {
|
||||
b.closeInputStreams();
|
||||
String s = String.valueOf(value); // take original bind value here.
|
||||
if (s.length() > 50) {
|
||||
s = s.substring(0, 47) + "...";
|
||||
}
|
||||
throw new DataIntegrityException("Cannot bind value '" + s + "' (effective length=" + length + ") to column '" + dbColumn + "' (length=" + dbLength + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings(value = "unchecked")
|
||||
@@ -1166,14 +1182,14 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
* Returns true if this <code>isLob()</code> or the type will effectively map to a lob.
|
||||
*/
|
||||
@Override
|
||||
public boolean isDbLob() {
|
||||
public boolean isLobForPlatform() {
|
||||
if (lob) {
|
||||
return true;
|
||||
}
|
||||
switch (dbType) {
|
||||
case DbPlatformType.JSON:
|
||||
case DbPlatformType.JSONB:
|
||||
return dbLength == 0; // must be analog to DbPlatformTypeMapping.lookup
|
||||
return dbLength == 0 || dbLength > 4000; // must be analog to DbPlatformTypeMapping.lookup
|
||||
case DbPlatformType.JSONBlob:
|
||||
case DbPlatformType.JSONClob:
|
||||
return true;
|
||||
|
||||
@@ -379,6 +379,9 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
for (ExportedProperty exportedProperty : exportedProperties) {
|
||||
row.addColumn(exportedProperty.getForeignDbColumn());
|
||||
}
|
||||
if (importedId == null) {
|
||||
throw new PersistenceException("Missing @Id property on bean related to ManyToMany " + fullName());
|
||||
}
|
||||
importedId.buildImport(row);
|
||||
return row.build();
|
||||
}
|
||||
@@ -585,10 +588,9 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the join properties from the parent bean to the child bean.
|
||||
* This is only valid for OneToMany and NOT valid for ManyToMany.
|
||||
* Set the parent bean to the child (update the relationship).
|
||||
*/
|
||||
public void setJoinValuesToChild(EntityBean parent, EntityBean child, Object mapKeyValue) {
|
||||
public void setParentToChild(EntityBean parent, EntityBean child, Object mapKeyValue) {
|
||||
if (mapKeyProperty != null) {
|
||||
mapKeyProperty.setValue(child, mapKeyValue);
|
||||
}
|
||||
@@ -599,6 +601,31 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the parent bean has been set to the child (updated the relationship).
|
||||
*/
|
||||
public boolean setParentToChild(EntityBean parent, EntityBean child, Object mapKeyValue, BeanDescriptor<?> parentDesc) {
|
||||
if (manyToMany
|
||||
|| childMasterProperty == null
|
||||
|| !child._ebean_getIntercept().isLoadedProperty(childMasterProperty.propertyIndex())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Object currentParent = childMasterProperty.getValue(child);
|
||||
if (currentParent != null) {
|
||||
Object newId = parentDesc.getId(parent);
|
||||
Object oldId = parentDesc.id(currentParent);
|
||||
if (Objects.equals(newId, oldId)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
childMasterProperty.setValueIntercept(child, parent);
|
||||
if (mapKeyProperty != null) {
|
||||
mapKeyProperty.setValue(child, mapKeyValue);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the order by clause used to order the fetching of the data for
|
||||
* this list, set or map.
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package io.ebeaninternal.server.deploy;
|
||||
|
||||
import io.ebean.core.type.InputStreamInfo;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* The max length check on bind values.
|
||||
*/
|
||||
public interface BindMaxLength {
|
||||
|
||||
/**
|
||||
* Return a UTF8 based implementation.
|
||||
*/
|
||||
static BindMaxLength ofUtf8() {
|
||||
return new UTF8();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a standard implementation.
|
||||
*/
|
||||
static BindMaxLength ofStandard() {
|
||||
return new Standard();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the length of the object.
|
||||
*/
|
||||
long length(int dbLength, Object obj);
|
||||
|
||||
/**
|
||||
* Length check based on UTF8 bytes.
|
||||
*/
|
||||
final class UTF8 implements BindMaxLength {
|
||||
|
||||
@Override
|
||||
public long length(int dbLength, Object obj) {
|
||||
if (obj == null) {
|
||||
return -1;
|
||||
} else if (obj instanceof String) {
|
||||
String s = (String) obj;
|
||||
return utf8String(dbLength, s);
|
||||
} else if (obj instanceof byte[]) {
|
||||
return ((byte[]) obj).length;
|
||||
} else if (obj instanceof InputStreamInfo) {
|
||||
return ((InputStreamInfo) obj).length();
|
||||
} else if ("org.postgresql.util.PGobject".equals(obj.getClass().getCanonicalName())) {
|
||||
String value = ((org.postgresql.util.PGobject) obj).getValue();
|
||||
return value == null ? -1 : utf8String(dbLength, value);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private static int utf8String(int dbLength, String s) {
|
||||
int stringLength = s.length();
|
||||
if (stringLength > dbLength) {
|
||||
return stringLength;
|
||||
} else if (stringLength * 4 <= dbLength) {
|
||||
return -1;
|
||||
} else {
|
||||
return s.getBytes(StandardCharsets.UTF_8).length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard string length implementation.
|
||||
*/
|
||||
final class Standard implements BindMaxLength {
|
||||
|
||||
@Override
|
||||
public long length(int dbLength, Object obj) {
|
||||
if (obj == null) {
|
||||
return -1;
|
||||
} else if (obj instanceof String) {
|
||||
return ((String) obj).length();
|
||||
} else if (obj instanceof byte[]) {
|
||||
return ((byte[]) obj).length;
|
||||
} else if (obj instanceof InputStreamInfo) {
|
||||
return ((InputStreamInfo) obj).length();
|
||||
} else if ("org.postgresql.util.PGobject".equals(obj.getClass().getCanonicalName())) {
|
||||
String value = ((org.postgresql.util.PGobject) obj).getValue();
|
||||
return value == null ? -1 : value.length();
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -63,7 +63,7 @@ class DynamicPropertyAggregationFormula extends DynamicPropertyBase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDbLob() {
|
||||
public boolean isLobForPlatform() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -1,10 +1,10 @@
|
||||
package io.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import io.ebean.DatabaseBuilder;
|
||||
import io.ebean.annotation.Cache;
|
||||
import io.ebean.annotation.DocStore;
|
||||
import io.ebean.annotation.DocStoreMode;
|
||||
import io.ebean.annotation.Identity;
|
||||
import io.ebean.DatabaseBuilder;
|
||||
import io.ebean.config.TableName;
|
||||
import io.ebean.config.dbplatform.IdType;
|
||||
import io.ebean.config.dbplatform.PlatformIdGenerator;
|
||||
@@ -21,7 +21,6 @@ import io.ebeaninternal.server.idgen.UuidV1IdGenerator;
|
||||
import io.ebeaninternal.server.idgen.UuidV1RndIdGenerator;
|
||||
import io.ebeaninternal.server.idgen.UuidV4IdGenerator;
|
||||
import io.ebeaninternal.server.rawsql.SpiRawSql;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
|
||||
@@ -139,6 +138,10 @@ public class DeployBeanDescriptor<T> {
|
||||
this.beanType = beanType;
|
||||
}
|
||||
|
||||
public BindMaxLength bindMaxLength() {
|
||||
return manager.bindMaxLength();
|
||||
}
|
||||
|
||||
private String[] readPropertyNames() {
|
||||
try {
|
||||
Field field = beanType.getField("_ebean_props");
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
package io.ebeaninternal.server.deploy.meta;
|
||||
|
||||
import io.avaje.lang.Nullable;
|
||||
import io.ebean.annotation.*;
|
||||
import io.ebean.config.ScalarTypeConverter;
|
||||
import io.ebean.config.dbplatform.DbDefaultValue;
|
||||
import io.ebean.config.dbplatform.DbEncrypt;
|
||||
import io.ebean.config.dbplatform.DbEncryptFunction;
|
||||
import io.ebean.config.dbplatform.ExtraDbTypes;
|
||||
import io.ebean.core.type.ScalarType;
|
||||
import io.ebean.util.AnnotationUtil;
|
||||
import io.ebeaninternal.server.core.InternString;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
import io.ebeaninternal.server.deploy.BindMaxLength;
|
||||
import io.ebeaninternal.server.deploy.DbMigrationInfo;
|
||||
import io.ebeaninternal.server.deploy.DeployDocPropertyOptions;
|
||||
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedProperty;
|
||||
@@ -1133,4 +1136,20 @@ public class DeployBeanProperty {
|
||||
boolean isJsonType() {
|
||||
return mutationDetection != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public BindMaxLength bindMaxLength() {
|
||||
if (dbLength == 0) {
|
||||
return null;
|
||||
}
|
||||
switch (dbType) {
|
||||
case Types.VARCHAR:
|
||||
case Types.BLOB:
|
||||
case ExtraDbTypes.JSON:
|
||||
return desc.bindMaxLength();
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+2
-3
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.BitwiseOp;
|
||||
|
||||
/**
|
||||
@@ -9,7 +8,7 @@ import io.ebeaninternal.server.expression.BitwiseOp;
|
||||
abstract class BaseDbExpression implements DbExpressionHandler {
|
||||
|
||||
@Override
|
||||
public void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
|
||||
public void bitwise(DbExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
|
||||
final String bitOp = bitOp(operator);
|
||||
request.append('(').property(propName).append(' ').append(bitOp).append(" ? ").append(compare).append(" ?)");
|
||||
}
|
||||
@@ -28,7 +27,7 @@ abstract class BaseDbExpression implements DbExpressionHandler {
|
||||
/**
|
||||
* Common alternative where the bitwise operation is a function (specifically bitand is used - H2 and Oracle).
|
||||
*/
|
||||
protected void bitwiseFunction(SpiExpressionRequest request, String propName, BitwiseOp operator, String compare) {
|
||||
protected void bitwiseFunction(DbExpressionRequest request, String propName, BitwiseOp operator, String compare) {
|
||||
final String funcName = functionName(operator);
|
||||
request.append(funcName).append('(').property(propName).append(", ?) ").append(compare).append(" ?");
|
||||
}
|
||||
|
||||
+3
-4
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.Op;
|
||||
|
||||
/**
|
||||
@@ -9,17 +8,17 @@ import io.ebeaninternal.server.expression.Op;
|
||||
class BasicDbExpression extends BaseDbExpression {
|
||||
|
||||
@Override
|
||||
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
public void json(DbExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
throw new RuntimeException("JSON expressions only supported on Postgres and Oracle");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayContains(SpiExpressionRequest request, String propName, boolean contains, Object... values) {
|
||||
public void arrayContains(DbExpressionRequest request, String propName, boolean contains, Object... values) {
|
||||
throw new RuntimeException("ARRAY expressions only supported on Postgres");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty) {
|
||||
public void arrayIsEmpty(DbExpressionRequest request, String propName, boolean empty) {
|
||||
throw new RuntimeException("ARRAY expressions only supported on Postgres");
|
||||
}
|
||||
}
|
||||
|
||||
+4
-5
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.BitwiseOp;
|
||||
import io.ebeaninternal.server.expression.Op;
|
||||
|
||||
@@ -12,22 +11,22 @@ public interface DbExpressionHandler {
|
||||
/**
|
||||
* Write the db platform specific json expression.
|
||||
*/
|
||||
void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value);
|
||||
void json(DbExpressionRequest request, String propName, String path, Op operator, Object value);
|
||||
|
||||
/**
|
||||
* Add SQL for ARRAY CONTAINS expression.
|
||||
*/
|
||||
void arrayContains(SpiExpressionRequest request, String propName, boolean contains, Object... values);
|
||||
void arrayContains(DbExpressionRequest request, String propName, boolean contains, Object... values);
|
||||
|
||||
/**
|
||||
* Add SQL for ARRAY IS EMPTY expression.
|
||||
*/
|
||||
void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty);
|
||||
void arrayIsEmpty(DbExpressionRequest request, String propName, boolean empty);
|
||||
|
||||
/**
|
||||
* Add the bitwise expression.
|
||||
*/
|
||||
void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match);
|
||||
void bitwise(DbExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match);
|
||||
|
||||
/**
|
||||
* Performs a "CONCAT" operation for that platform.
|
||||
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
/**
|
||||
* Request building the expression sql.
|
||||
*/
|
||||
public interface DbExpressionRequest {
|
||||
|
||||
/**
|
||||
* Append to the expression sql without any parsing.
|
||||
*/
|
||||
DbExpressionRequest append(String expression);
|
||||
|
||||
/**
|
||||
* Append to the expression sql without any parsing.
|
||||
*/
|
||||
DbExpressionRequest append(char c);
|
||||
|
||||
/**
|
||||
* Append to the expression sql with logical property parsing to db columns with logical path prefix.
|
||||
*/
|
||||
DbExpressionRequest property(String expression);
|
||||
}
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.BitwiseOp;
|
||||
|
||||
/**
|
||||
@@ -9,7 +8,7 @@ import io.ebeaninternal.server.expression.BitwiseOp;
|
||||
final class H2DbExpression extends BasicDbExpression {
|
||||
|
||||
@Override
|
||||
public void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
|
||||
public void bitwise(DbExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
|
||||
final String funcName = functionName(operator);
|
||||
request.append(funcName).append('(').property(propName).append(", cast(? as long)) ").append(compare).append(" cast(? as long)");
|
||||
}
|
||||
|
||||
+4
-5
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.BitwiseOp;
|
||||
import io.ebeaninternal.server.expression.Op;
|
||||
|
||||
@@ -10,17 +9,17 @@ import io.ebeaninternal.server.expression.Op;
|
||||
final class HanaDbExpression extends BaseDbExpression {
|
||||
|
||||
@Override
|
||||
public void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
|
||||
public void bitwise(DbExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
|
||||
bitwiseFunction(request, propName, operator, compare);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
public void json(DbExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
request.append("json_value(").property(propName).append(", '$.").append(path).append("')").append(operator.bind());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty) {
|
||||
public void arrayIsEmpty(DbExpressionRequest request, String propName, boolean empty) {
|
||||
request.append("cardinality(").property(propName).append(')');
|
||||
if (empty) {
|
||||
request.append(" = 0");
|
||||
@@ -41,7 +40,7 @@ final class HanaDbExpression extends BaseDbExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayContains(SpiExpressionRequest request, String propName, boolean contains, Object... values) {
|
||||
public void arrayContains(DbExpressionRequest request, String propName, boolean contains, Object... values) {
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
if (i > 0) {
|
||||
request.append(" and ");
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.Op;
|
||||
|
||||
/**
|
||||
@@ -9,7 +8,7 @@ import io.ebeaninternal.server.expression.Op;
|
||||
final class MariaDbExpression extends BasicDbExpression {
|
||||
|
||||
@Override
|
||||
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
public void json(DbExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
request.append('(').property(propName).append(" ->> '$.").append(path).append("')").append(operator.bind());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.Op;
|
||||
|
||||
/**
|
||||
@@ -9,7 +8,7 @@ import io.ebeaninternal.server.expression.Op;
|
||||
final class MySqlDbExpression extends BasicDbExpression {
|
||||
|
||||
@Override
|
||||
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
public void json(DbExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
request.append('(').property(propName).append(" ->> '$.").append(path).append("')").append(operator.bind());
|
||||
}
|
||||
|
||||
|
||||
+4
-5
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.BitwiseOp;
|
||||
import io.ebeaninternal.server.expression.Op;
|
||||
|
||||
@@ -15,7 +14,7 @@ final class OracleDbExpression extends BaseDbExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
public void json(DbExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
if (operator == Op.EXISTS) {
|
||||
request.append("json_exists(").property(propName).append(", '$.").append(path).append("')");
|
||||
} else if (operator == Op.NOT_EXISTS) {
|
||||
@@ -26,17 +25,17 @@ final class OracleDbExpression extends BaseDbExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
|
||||
public void bitwise(DbExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
|
||||
bitwiseFunction(request, propName, operator, compare);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayContains(SpiExpressionRequest request, String propName, boolean contains, Object... values) {
|
||||
public void arrayContains(DbExpressionRequest request, String propName, boolean contains, Object... values) {
|
||||
throw new IllegalStateException("ARRAY expressions not supported on Oracle");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty) {
|
||||
public void arrayIsEmpty(DbExpressionRequest request, String propName, boolean empty) {
|
||||
throw new IllegalStateException("ARRAY expressions not supported on Oracle");
|
||||
}
|
||||
}
|
||||
|
||||
+3
-4
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.Op;
|
||||
|
||||
/**
|
||||
@@ -14,7 +13,7 @@ final class PostgresDbExpression extends BaseDbExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
public void json(DbExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
String[] paths = path.split("\\.");
|
||||
if (paths.length == 1) {
|
||||
// (t0.content ->> 'title') = 'Some value'
|
||||
@@ -34,7 +33,7 @@ final class PostgresDbExpression extends BaseDbExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayContains(SpiExpressionRequest request, String propName, boolean contains, Object... values) {
|
||||
public void arrayContains(DbExpressionRequest request, String propName, boolean contains, Object... values) {
|
||||
if (!contains) {
|
||||
request.append("not (");
|
||||
}
|
||||
@@ -49,7 +48,7 @@ final class PostgresDbExpression extends BaseDbExpression {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty) {
|
||||
public void arrayIsEmpty(DbExpressionRequest request, String propName, boolean empty) {
|
||||
request.append("coalesce(cardinality(").property(propName).append("),0)");
|
||||
if (empty) {
|
||||
request.append(" = 0");
|
||||
|
||||
+3
-4
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.expression.Op;
|
||||
|
||||
/**
|
||||
@@ -9,19 +8,19 @@ import io.ebeaninternal.server.expression.Op;
|
||||
final class SqlServerDbExpression extends BaseDbExpression {
|
||||
|
||||
@Override
|
||||
public void json(final SpiExpressionRequest request, final String propName,
|
||||
public void json(final DbExpressionRequest request, final String propName,
|
||||
final String path, final Op operator, final Object value) {
|
||||
request.append("json_value(").property(propName).append(", '$.").append(path).append("')").append(operator.bind());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayContains(final SpiExpressionRequest request, final String propName,
|
||||
public void arrayContains(final DbExpressionRequest request, final String propName,
|
||||
final boolean contains, final Object... values) {
|
||||
throw new RuntimeException("ARRAY expressions not supported on Microsoft SQL Server");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayIsEmpty(final SpiExpressionRequest request, final String propName, final boolean empty) {
|
||||
public void arrayIsEmpty(final DbExpressionRequest request, final String propName, final boolean empty) {
|
||||
throw new RuntimeException("ARRAY expressions not supported on Microsoft SQL Server");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,7 +402,13 @@ public final class DJsonContext implements SpiJsonContext {
|
||||
private WriteJson createWriteJson(JsonGenerator gen, JsonWriteOptions options) {
|
||||
FetchPath pathProps = (options == null) ? null : options.getPathProperties();
|
||||
Map<String, JsonWriteBeanVisitor<?>> visitors = (options == null) ? null : options.getVisitorMap();
|
||||
return new WriteJson(server, gen, pathProps, visitors, determineObjectMapper(options), determineInclude(options));
|
||||
return new WriteJson(server,
|
||||
gen,
|
||||
pathProps,
|
||||
visitors,
|
||||
determineObjectMapper(options),
|
||||
determineInclude(options),
|
||||
options == null || options.isIncludeLoadedImplicit());
|
||||
}
|
||||
|
||||
private <T> void toJsonFromCollection(Collection<T> collection, String key, JsonGenerator gen, JsonWriteOptions options) throws IOException {
|
||||
@@ -490,4 +496,5 @@ public final class DJsonContext implements SpiJsonContext {
|
||||
JsonConfig.Include include = options.getInclude();
|
||||
return (include != null) ? include : defaultInclude;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,12 +31,15 @@ public final class WriteJson implements SpiJsonWriter {
|
||||
private final ArrayStack<Object> parentBeans;
|
||||
private final Object objectMapper;
|
||||
private final JsonConfig.Include include;
|
||||
private final boolean includeLoadedImplicit;
|
||||
|
||||
|
||||
/**
|
||||
* Construct for full bean use (normal).
|
||||
*/
|
||||
public WriteJson(SpiEbeanServer server, JsonGenerator generator, FetchPath fetchPath,
|
||||
Map<String, JsonWriteBeanVisitor<?>> visitors, Object objectMapper, JsonConfig.Include include) {
|
||||
Map<String, JsonWriteBeanVisitor<?>> visitors, Object objectMapper, JsonConfig.Include include,
|
||||
boolean includeLoadedImplicit) {
|
||||
|
||||
this.server = server;
|
||||
this.generator = generator;
|
||||
@@ -44,6 +47,7 @@ public final class WriteJson implements SpiJsonWriter {
|
||||
this.visitors = visitors;
|
||||
this.objectMapper = objectMapper;
|
||||
this.include = include;
|
||||
this.includeLoadedImplicit = includeLoadedImplicit;
|
||||
this.parentBeans = new ArrayStack<>();
|
||||
this.pathStack = new PathStack();
|
||||
}
|
||||
@@ -54,6 +58,7 @@ public final class WriteJson implements SpiJsonWriter {
|
||||
public WriteJson(JsonGenerator generator, JsonConfig.Include include) {
|
||||
this.generator = generator;
|
||||
this.include = include;
|
||||
this.includeLoadedImplicit = true;
|
||||
this.visitors = null;
|
||||
this.server = null;
|
||||
this.fetchPath = null;
|
||||
@@ -443,7 +448,7 @@ public final class WriteJson implements SpiJsonWriter {
|
||||
currentIncludeProps = null;
|
||||
}
|
||||
}
|
||||
return new WriteBean(desc, explicitAllProps, currentIncludeProps, bean, visitor);
|
||||
return new WriteBean(desc, explicitAllProps, includeLoadedImplicit, currentIncludeProps, bean, visitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -477,6 +482,7 @@ public final class WriteJson implements SpiJsonWriter {
|
||||
public static class WriteBean {
|
||||
|
||||
final boolean explicitAllProps;
|
||||
final boolean includeLoadedImplicit;
|
||||
final Set<String> currentIncludeProps;
|
||||
final BeanDescriptor<?> desc;
|
||||
final EntityBean currentBean;
|
||||
@@ -485,14 +491,15 @@ public final class WriteJson implements SpiJsonWriter {
|
||||
final JsonWriteBeanVisitor visitor;
|
||||
|
||||
WriteBean(BeanDescriptor<?> desc, EntityBean currentBean, JsonWriteBeanVisitor<?> visitor) {
|
||||
this(desc, false, null, currentBean, visitor);
|
||||
this(desc, false, true, null, currentBean, visitor);
|
||||
}
|
||||
|
||||
WriteBean(BeanDescriptor<?> desc, boolean explicitAllProps, Set<String> currentIncludeProps, EntityBean currentBean, JsonWriteBeanVisitor<?> visitor) {
|
||||
WriteBean(BeanDescriptor<?> desc, boolean explicitAllProps, boolean includeLoadedImplicit, Set<String> currentIncludeProps, EntityBean currentBean, JsonWriteBeanVisitor<?> visitor) {
|
||||
super();
|
||||
this.desc = desc;
|
||||
this.currentBean = currentBean;
|
||||
this.explicitAllProps = explicitAllProps;
|
||||
this.includeLoadedImplicit = includeLoadedImplicit;
|
||||
this.currentIncludeProps = currentIncludeProps;
|
||||
this.visitor = visitor;
|
||||
}
|
||||
@@ -507,9 +514,11 @@ public final class WriteJson implements SpiJsonWriter {
|
||||
if (currentIncludeProps != null) {
|
||||
// explicitly controlled by pathProperties
|
||||
return currentIncludeProps.contains(prop.name());
|
||||
} else {
|
||||
} else if (includeLoadedImplicit){
|
||||
// include only loaded properties
|
||||
return currentBean._ebean_getIntercept().isLoadedProperty(prop.propertyIndex());
|
||||
} else {
|
||||
return prop.isId();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -226,7 +226,7 @@ public final class BatchControl {
|
||||
void executeNow(ArrayList<PersistRequest> list) throws BatchedSqlException {
|
||||
boolean old = transaction.isFlushOnQuery();
|
||||
transaction.setFlushOnQuery(false);
|
||||
// disable flush on query due transsaction callbacks
|
||||
// disable flush on query due transaction callbacks
|
||||
try {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (i % batchSize == 0) {
|
||||
|
||||
@@ -172,7 +172,9 @@ final class SaveManyBeans extends SaveManyBase {
|
||||
} else if (ebi.isNewOrDirty()) {
|
||||
skipSavingThisBean = false;
|
||||
// set the parent bean to detailBean
|
||||
many.setJoinValuesToChild(parentBean, detail, mapKeyValue);
|
||||
many.setParentToChild(parentBean, detail, mapKeyValue);
|
||||
} else if (many.setParentToChild(parentBean, detail, mapKeyValue, request.descriptor())) {
|
||||
skipSavingThisBean = false;
|
||||
} else {
|
||||
skipSavingThisBean = saveRecurseSkippable;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package io.ebeaninternal.server.query;
|
||||
|
||||
import io.ebean.CountDistinctOrder;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.RawSql;
|
||||
import io.ebean.RawSqlBuilder;
|
||||
import io.ebean.*;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.config.dbplatform.SqlLimitRequest;
|
||||
@@ -52,11 +49,13 @@ final class CQueryBuilder {
|
||||
private final CQueryDraftSupport draftSupport;
|
||||
private final DatabasePlatform dbPlatform;
|
||||
private final boolean selectCountWithColumnAlias;
|
||||
private final boolean includeLabelInSql;
|
||||
|
||||
/**
|
||||
* Create the SqlGenSelect.
|
||||
*/
|
||||
CQueryBuilder(DatabasePlatform dbPlatform, Binder binder, CQueryHistorySupport historySupport, CQueryDraftSupport draftSupport) {
|
||||
CQueryBuilder(DatabaseBuilder.Settings config, DatabasePlatform dbPlatform, Binder binder, CQueryHistorySupport historySupport, CQueryDraftSupport draftSupport) {
|
||||
this.includeLabelInSql = config.isIncludeLabelInSql();
|
||||
this.dbPlatform = dbPlatform;
|
||||
this.binder = binder;
|
||||
this.draftSupport = draftSupport;
|
||||
@@ -596,7 +595,7 @@ final class CQueryBuilder {
|
||||
}
|
||||
|
||||
private void appendSelectDistinct() {
|
||||
sb.append("select ");
|
||||
sb.append("select ").append(hint()).append(inlineSqlComment());
|
||||
if (distinct && !countSingleAttribute) {
|
||||
if (request.isInlineCountDistinct()) {
|
||||
sb.append("count(");
|
||||
@@ -609,6 +608,30 @@ final class CQueryBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
private String hint() {
|
||||
String hint = query.hint();
|
||||
return hint == null ? "" : dbPlatform.inlineSqlHint(hint);
|
||||
}
|
||||
|
||||
private String inlineSqlComment() {
|
||||
if (!includeLabelInSql) {
|
||||
return "";
|
||||
}
|
||||
SpiQuery.Type type = query.type();
|
||||
if (type == SpiQuery.Type.SQ_EX || type == SpiQuery.Type.SQ_EXISTS) {
|
||||
return "";
|
||||
}
|
||||
final var label = query.label();
|
||||
if (label != null) {
|
||||
return dbPlatform.inlineSqlComment(label);
|
||||
}
|
||||
final var profileLocation = query.profileLocation();
|
||||
if (profileLocation != null) {
|
||||
return dbPlatform.inlineSqlComment(profileLocation.label());
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private void appendFrom() {
|
||||
if (selectClause == null || !selectClause.startsWith("update")) {
|
||||
sb.append(" from ");
|
||||
|
||||
@@ -44,7 +44,7 @@ public final class CQueryEngine {
|
||||
this.defaultFetchSizeFindList = config.getJdbcFetchSizeFindList();
|
||||
this.forwardOnlyHintOnFindIterate = dbPlatform.forwardOnlyHintOnFindIterate();
|
||||
this.historySupport = new CQueryHistorySupport(dbPlatform.historySupport(), asOfTableMapping, config.getAsOfSysPeriod());
|
||||
this.queryBuilder = new CQueryBuilder(dbPlatform, binder, historySupport, new CQueryDraftSupport(draftTableMap));
|
||||
this.queryBuilder = new CQueryBuilder(config, dbPlatform, binder, historySupport, new CQueryDraftSupport(draftTableMap));
|
||||
}
|
||||
|
||||
public int forwardOnlyFetchSize() {
|
||||
|
||||
@@ -133,6 +133,11 @@ final class DefaultFetchGroupQuery<T> implements SpiFetchGroupQuery<T>, SpiQuery
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> setHint(String hint) {
|
||||
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
|
||||
}
|
||||
|
||||
// Everything else deemed invalid
|
||||
|
||||
@Override
|
||||
|
||||
@@ -33,7 +33,7 @@ public interface STreeProperty extends ScalarDataReader<Object> {
|
||||
/**
|
||||
* Returns true, if this is a lob property from db-perspective.
|
||||
*/
|
||||
boolean isDbLob();
|
||||
boolean isLobForPlatform();
|
||||
|
||||
/**
|
||||
* Return true if the property is an embedded type.
|
||||
|
||||
@@ -48,7 +48,7 @@ public final class SqlTreeBuilder {
|
||||
private final SpiQuery.TemporalMode temporalMode;
|
||||
private SqlTreeNode rootNode;
|
||||
private boolean sqlDistinct;
|
||||
private final boolean distinctNoLobs;
|
||||
private final boolean platformDistinctNoLobs;
|
||||
private final SqlTreeCommon common;
|
||||
|
||||
/**
|
||||
@@ -63,7 +63,7 @@ public final class SqlTreeBuilder {
|
||||
this.query = null;
|
||||
this.subQuery = false;
|
||||
this.distinctOnPlatform = false;
|
||||
this.distinctNoLobs = false;
|
||||
this.platformDistinctNoLobs = false;
|
||||
this.queryDetail = queryDetail;
|
||||
this.predicates = predicates;
|
||||
this.temporalMode = SpiQuery.TemporalMode.CURRENT;
|
||||
@@ -98,7 +98,7 @@ public final class SqlTreeBuilder {
|
||||
this.predicates = predicates;
|
||||
this.alias = new SqlTreeAlias(request.baseTableAlias(), temporalMode);
|
||||
this.distinctOnPlatform = builder.isPlatformDistinctOn();
|
||||
this.distinctNoLobs = builder.isPlatformDistinctNoLobs();
|
||||
this.platformDistinctNoLobs = builder.isPlatformDistinctNoLobs();
|
||||
String fromForUpdate = builder.fromForUpdate(query);
|
||||
CQueryHistorySupport historySupport = builder.historySupport(query);
|
||||
CQueryDraftSupport draftSupport = builder.draftSupport(query);
|
||||
@@ -269,8 +269,8 @@ public final class SqlTreeBuilder {
|
||||
if (joinList != null) {
|
||||
joinList.add(selectNode);
|
||||
}
|
||||
if (sqlDistinct && distinctNoLobs) {
|
||||
selectNode.unselectLobs();
|
||||
if (sqlDistinct && platformDistinctNoLobs) {
|
||||
selectNode.unselectLobsForPlatform();
|
||||
}
|
||||
return selectNode;
|
||||
}
|
||||
|
||||
@@ -82,6 +82,6 @@ interface SqlTreeNode {
|
||||
/**
|
||||
* Unselect lobs (for distinct queries on DB2 and Oracle).
|
||||
*/
|
||||
default void unselectLobs() {
|
||||
default void unselectLobsForPlatform() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,16 +379,16 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
|
||||
|
||||
@Override
|
||||
public void unselectLobs() {
|
||||
public void unselectLobsForPlatform() {
|
||||
if (children != null) {
|
||||
for (SqlTreeNode child : children) {
|
||||
child.unselectLobs();
|
||||
child.unselectLobsForPlatform();
|
||||
}
|
||||
}
|
||||
if (hasLob()) {
|
||||
List<STreeProperty> lst = new ArrayList<>();
|
||||
for (STreeProperty prop : properties) {
|
||||
if (!prop.isDbLob()) {
|
||||
if (!prop.isLobForPlatform()) {
|
||||
lst.add(prop);
|
||||
}
|
||||
}
|
||||
@@ -399,7 +399,7 @@ class SqlTreeNodeBean implements SqlTreeNode {
|
||||
|
||||
private boolean hasLob() {
|
||||
for (STreeProperty prop : properties) {
|
||||
if (prop.isDbLob()) {
|
||||
if (prop.isLobForPlatform()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,6 +250,9 @@ public final class DefaultDtoQuery<T> extends AbstractQuery implements SpiDtoQue
|
||||
@Override
|
||||
public DtoQuery<T> setLabel(String label) {
|
||||
this.label = label;
|
||||
if (ormQuery != null) {
|
||||
ormQuery.setLabel(label);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
private ProfilingListener profilingListener;
|
||||
private Type type;
|
||||
private String label;
|
||||
private String hint;
|
||||
private Mode mode = Mode.NORMAL;
|
||||
private boolean usingFuture;
|
||||
private Object tenantId;
|
||||
@@ -235,6 +236,11 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
return label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String hint() {
|
||||
return hint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String planLabel() {
|
||||
if (label != null) {
|
||||
@@ -258,6 +264,12 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Query<T> setHint(String hint) {
|
||||
this.hint = hint;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isAutoTunable() {
|
||||
return nativeSql == null && beanDescriptor.isAutoTunable();
|
||||
@@ -732,6 +744,7 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
copy.timeout = timeout;
|
||||
copy.mapKey = mapKey;
|
||||
copy.id = id;
|
||||
copy.hint = hint;
|
||||
copy.label = label;
|
||||
copy.nativeSql = nativeSql;
|
||||
copy.useBeanCache = useBeanCache;
|
||||
@@ -1069,6 +1082,9 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
if (manualId) {
|
||||
sb.append("/md");
|
||||
}
|
||||
if (hint != null) {
|
||||
sb.append("/h:").append(hint);
|
||||
}
|
||||
if (distinct) {
|
||||
sb.append("/dt");
|
||||
}
|
||||
|
||||
@@ -29,6 +29,27 @@ public class OrmQueryPlanKeyTest extends BaseTest {
|
||||
assertSame(query().createQueryPlanKey(), query().createQueryPlanKey());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_hintIsDifferent_expect_different() {
|
||||
DefaultOrmQuery<Customer> q1 = query();
|
||||
q1.setHint("a");
|
||||
assertDifferent(q1, query());
|
||||
|
||||
DefaultOrmQuery<Customer> q2 = query();
|
||||
q2.setHint("b");
|
||||
assertDifferent(q1, q2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_hintIsSame() {
|
||||
DefaultOrmQuery<Customer> q1 = query();
|
||||
q1.setHint("b");
|
||||
DefaultOrmQuery<Customer> q2 = query();
|
||||
q2.setHint("b");
|
||||
|
||||
assertSame(q1, q2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_when_diffTableJoinNull() {
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean ddl generation</name>
|
||||
@@ -28,14 +28,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-all</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean postgis types</name>
|
||||
@@ -19,14 +19,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- provided scope -->
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.6.0</version>
|
||||
<version>42.7.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean querybean</name>
|
||||
@@ -17,7 +17,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -63,14 +63,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -108,6 +108,18 @@ public abstract class TQAssocBean<T, R, QB> extends TQAssoc<T, R> {
|
||||
return fetchWithProperties(FETCH_DEFAULT, properties);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch this association with config for the type of fetch and the specified properties.
|
||||
*
|
||||
* @param config Fetch configuration to define the type of fetch to use
|
||||
* @param properties The properties to fetch
|
||||
*/
|
||||
@SafeVarargs @SuppressWarnings("varargs")
|
||||
public final R fetch(FetchConfig config, TQProperty<QB,?>... properties) {
|
||||
return fetchWithProperties(config, properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Eagerly fetch this association using a 'query join' loading the specified properties.
|
||||
*/
|
||||
|
||||
@@ -912,6 +912,17 @@ public abstract class TQRootBean<T, R> {
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a SQL query hint.
|
||||
* <p>
|
||||
* This results in an inline comment that immediately follows
|
||||
* after the select keyword in the form: {@code /*+ hint *\/ }
|
||||
*/
|
||||
public R setHint(String hint) {
|
||||
query.setHint(hint);
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the profile location.
|
||||
* <p>
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.example.domain;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Version;
|
||||
|
||||
@Entity
|
||||
public class Alias {
|
||||
|
||||
@Id
|
||||
long id;
|
||||
@Version
|
||||
long version;
|
||||
}
|
||||
@@ -68,9 +68,9 @@ class MyInnerTest {
|
||||
|
||||
List<String> sql = LoggedSql.stop();
|
||||
assertThat(sql).hasSize(4);
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.one, t0.id, t0.one, t0.description from my_inner t0 where t0.one = ?;");
|
||||
assertThat(sql.get(1)).contains("select t0.id, t0.one, t0.id, t0.one, t0.description from my_inner t0 where t0.description = ?;");
|
||||
assertThat(sql.get(2)).contains("select t0.id, t0.one, t0.id, t0.one, t0.description from my_inner t0 where t0.id < ? and t0.description = ?;");
|
||||
assertThat(sql.get(3)).contains("select t0.id, t0.one, t0.id, t0.one, t0.description from my_inner t0 where t0.id < ? and t0.one > ? and t0.one >= ? and t0.one < ? and t0.one <= ? and t0.id > ?;");
|
||||
assertThat(sql.get(0)).contains("select /* MyInnerTest.insert_and_find:36 */ t0.id, t0.one, t0.id, t0.one, t0.description from my_inner t0 where t0.one = ?;");
|
||||
assertThat(sql.get(1)).contains("select /* MyInnerTest.insert_and_find:43 */ t0.id, t0.one, t0.id, t0.one, t0.description from my_inner t0 where t0.description = ?;");
|
||||
assertThat(sql.get(2)).contains("select /* MyInnerTest.insert_and_find:54 */ t0.id, t0.one, t0.id, t0.one, t0.description from my_inner t0 where t0.id < ? and t0.description = ?;");
|
||||
assertThat(sql.get(3)).contains("select /* MyInnerTest.insert_and_find:65 */ t0.id, t0.one, t0.id, t0.one, t0.description from my_inner t0 where t0.id < ? and t0.one > ? and t0.one >= ? and t0.one < ? and t0.one <= ? and t0.id > ?;");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ public class QCustomerAndOrTest {
|
||||
@Test
|
||||
public void testOrWithExists() {
|
||||
QCustomer query = Customer.find.typed()
|
||||
.setLabel("hiLabel")
|
||||
.alias("_cust")
|
||||
.or()
|
||||
.name.eq("Superman")
|
||||
@@ -72,12 +73,12 @@ public class QCustomerAndOrTest {
|
||||
.query()
|
||||
)
|
||||
.endOr()
|
||||
.select(QCustomer.alias().id);
|
||||
.select(QCustomer.Alias.id);
|
||||
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).isEqualTo(
|
||||
"select _cust.id from be_customer _cust where (" +
|
||||
"select /* hiLabel */ _cust.id from be_customer _cust where (" +
|
||||
"_cust.name = ? or exists (select 1 from be_contact contact where " +
|
||||
"contact.first_name = ? and contact.customer_id = _cust.id))"
|
||||
);
|
||||
|
||||
@@ -284,7 +284,7 @@ public class QCustomerTest {
|
||||
.query();
|
||||
|
||||
q.findList();
|
||||
assertThat(q.getGeneratedSql()).isEqualTo("select t0.id, t0.name, t1.id, t1.first_name, t1.last_name from be_customer t0 left join be_contact t1 on t1.customer_id = t0.id where t1.first_name like ? escape'|' and t1.email is not null order by t0.id");
|
||||
assertThat(q.getGeneratedSql()).isEqualTo("select /* QCustomerTest.filterMany */ t0.id, t0.name, t1.id, t1.first_name, t1.last_name from be_customer t0 left join be_contact t1 on t1.customer_id = t0.id where t1.first_name like ? escape'|' and t1.email is not null order by t0.id");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -296,7 +296,7 @@ public class QCustomerTest {
|
||||
.query();
|
||||
|
||||
q.findList();
|
||||
assertThat(q.getGeneratedSql()).isEqualTo("select t0.id, t0.name, t1.id, t1.first_name, t1.last_name from be_customer t0 left join be_contact t1 on t1.customer_id = t0.id where t1.first_name like ? escape'|' order by t0.id");
|
||||
assertThat(q.getGeneratedSql()).isEqualTo("select /* QCustomerTest.filterManySingle */ t0.id, t0.name, t1.id, t1.first_name, t1.last_name from be_customer t0 left join be_contact t1 on t1.customer_id = t0.id where t1.first_name like ? escape'|' order by t0.id");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.querytest;
|
||||
|
||||
import io.ebean.DB;
|
||||
import io.ebean.FetchConfig;
|
||||
import io.ebean.FetchGroup;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.test.LoggedSql;
|
||||
@@ -8,6 +9,7 @@ import org.example.domain.Customer;
|
||||
import org.example.domain.Order;
|
||||
import org.example.domain.OrderDetail;
|
||||
import org.example.domain.otherpackage.PhoneNumber;
|
||||
import org.example.domain.query.QContact;
|
||||
import org.example.domain.query.QCustomer;
|
||||
import org.example.domain.query.QOrder;
|
||||
import org.example.domain.query.QOrderDetail;
|
||||
@@ -20,16 +22,23 @@ import java.util.List;
|
||||
import static io.ebean.StdOperators.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class QOrderTest {
|
||||
class QOrderTest {
|
||||
|
||||
private static final QCustomer cu = QCustomer.alias();
|
||||
|
||||
private static final QOrder or = QOrder.alias();
|
||||
|
||||
private static final QContact co = QContact.alias();
|
||||
|
||||
private static final FetchGroup<Customer> fgC = QCustomer.forFetchGroup()
|
||||
.select(cu.name, cu.phoneNumber)
|
||||
.buildFetchGroup();
|
||||
|
||||
private static final FetchGroup<Customer> fgCustomerWithContacts = QCustomer.forFetchGroup()
|
||||
.select(cu.name, cu.phoneNumber)
|
||||
.contacts.fetch(FetchConfig.ofQuery(1000), co.firstName, co.lastName, co.email)
|
||||
.buildFetchGroup();
|
||||
|
||||
private static final FetchGroup<Order> fgNested1 = QOrder.forFetchGroup()
|
||||
.select(or.status, or.shipDate)
|
||||
.customer.fetch(fgC)
|
||||
@@ -71,7 +80,34 @@ public class QOrderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fetchCache() {
|
||||
void hint() {
|
||||
LoggedSql.start();
|
||||
new QCustomer()
|
||||
.setHint("FirstRows")
|
||||
.select(QCustomer.Alias.id, QCustomer.Alias.name)
|
||||
.findList();
|
||||
|
||||
List<String> sql = LoggedSql.stop();
|
||||
assertThat(sql).hasSize(1);
|
||||
assertThat(sql.get(0)).contains("select /*+ FirstRows */ /* QOrderTest.hint */ t0.id, t0.name from be_customer t0");
|
||||
}
|
||||
|
||||
@Test
|
||||
void fetchQueryWithBatch() {
|
||||
LoggedSql.start();
|
||||
|
||||
new QCustomer()
|
||||
.select(fgCustomerWithContacts)
|
||||
.findList();
|
||||
|
||||
final List<String> sql = LoggedSql.stop();
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql.get(0)).contains("select /* QOrderTest.fetchQueryWithBatch */ t0.id, t0.name, t0.phone_number from be_customer t0");
|
||||
assertThat(sql.get(1)).contains("select /* QOrderTest.fetchQueryWithBatch_contacts__query */ t0.customer_id, t0.id, t0.first_name, t0.last_name, t0.email from be_contact t0 where");
|
||||
}
|
||||
|
||||
@Test
|
||||
void fetchCache() {
|
||||
|
||||
new QOrder()
|
||||
.status.eq(Order.Status.NEW)
|
||||
@@ -85,7 +121,7 @@ public class QOrderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void viaFetchGraph() {
|
||||
void viaFetchGraph() {
|
||||
|
||||
DB.getDefault();
|
||||
LoggedSql.start();
|
||||
@@ -98,11 +134,11 @@ public class QOrderTest {
|
||||
|
||||
final List<String> sql = LoggedSql.stop();
|
||||
assertThat(sql).hasSize(1);
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.status, t0.ship_date, t0.customer_id from o_order t0 where");
|
||||
assertThat(sql.get(0)).contains("select /* QOrderTest.viaFetchGraph */ t0.id, t0.status, t0.ship_date, t0.customer_id from o_order t0 where");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void viaFetchGraph_withJoin() {
|
||||
void viaFetchGraph_withJoin() {
|
||||
|
||||
DB.getDefault();
|
||||
LoggedSql.start();
|
||||
@@ -115,11 +151,11 @@ public class QOrderTest {
|
||||
|
||||
final List<String> sql = LoggedSql.stop();
|
||||
assertThat(sql).hasSize(1);
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.status, t1.id, t1.name from o_order t0 join be_customer t1 on t1.id = t0.customer_id where");
|
||||
assertThat(sql.get(0)).contains("select /* QOrderTest.viaFetchGraph_withJoin */ t0.id, t0.status, t1.id, t1.name from o_order t0 join be_customer t1 on t1.id = t0.customer_id where");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void viaFetchGraph_withNested() {
|
||||
void viaFetchGraph_withNested() {
|
||||
|
||||
DB.getDefault();
|
||||
LoggedSql.start();
|
||||
@@ -131,13 +167,12 @@ public class QOrderTest {
|
||||
|
||||
final List<String> sql = LoggedSql.stop();
|
||||
assertThat(sql).hasSize(1);
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.status, t0.ship_date, t1.id, t1.name, t1.phone_number from o_order t0 join be_customer t1 on t1.id = t0.customer_id where");
|
||||
assertThat(sql.get(0)).contains("select /* QOrderTest.viaFetchGraph_withNested */ t0.id, t0.status, t0.ship_date, t1.id, t1.name, t1.phone_number from o_order t0 join be_customer t1 on t1.id = t0.customer_id where");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void viaFetchGraph_withNested_fetchQuery() {
|
||||
|
||||
DB.getDefault();
|
||||
void viaFetchGraph_withNested_fetchQuery() {
|
||||
DB.cacheManager().clearAll();
|
||||
LoggedSql.start();
|
||||
|
||||
final Order found = new QOrder()
|
||||
@@ -149,17 +184,16 @@ public class QOrderTest {
|
||||
|
||||
// assert fetching customer via fetchQuery
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.status, t0.customer_id from o_order t0 where t0.id = ?");
|
||||
assertThat(sql.get(1)).contains("select t0.id, t0.name, t0.phone_number from be_customer t0 where t0.id = ?");
|
||||
assertThat(sql.get(0)).contains("select /* QOrderTest.viaFetchGraph_withNested_fetchQuery */ t0.id, t0.status, t0.customer_id from o_order t0 where t0.id = ?");
|
||||
assertThat(sql.get(1)).contains("select /* QOrderTest.viaFetchGraph_withNested_fetchQuery_customer__query */ t0.id, t0.name, t0.phone_number from be_customer t0 where t0.id = ?");
|
||||
|
||||
assertThat(found.getCustomer().getPhoneNumber().getMsisdn()).isEqualTo("Ph1");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void viaFetchGraph_withNested_fetchCache() {
|
||||
|
||||
DB.getDefault();
|
||||
void viaFetchGraph_withNested_fetchCache() {
|
||||
DB.cacheManager().clearAll();
|
||||
|
||||
// ensure the customer is loaded in the L2 cache
|
||||
new QCustomer().id.eq(customer.getId()).findOne();
|
||||
@@ -178,11 +212,11 @@ public class QOrderTest {
|
||||
|
||||
// assert we only hit DB for order
|
||||
assertThat(sql).hasSize(1);
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.status, t0.customer_id from o_order t0 where t0.id = ?");
|
||||
assertThat(sql.get(0)).contains("select /* QOrderTest.viaFetchGraph_withNested_fetchQuery */ t0.id, t0.status, t0.customer_id from o_order t0 where t0.id = ?");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void select_partial() {
|
||||
void select_partial() {
|
||||
|
||||
DB.getDefault();
|
||||
LoggedSql.start();
|
||||
@@ -195,11 +229,11 @@ public class QOrderTest {
|
||||
|
||||
final List<String> sql = LoggedSql.stop();
|
||||
assertThat(sql).hasSize(1);
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.status, t0.order_date from o_order t0");
|
||||
assertThat(sql.get(0)).contains("select /* QOrderTest.select_partial */ t0.id, t0.status, t0.order_date from o_order t0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fetch_partial() {
|
||||
void fetch_partial() {
|
||||
|
||||
DB.getDefault();
|
||||
LoggedSql.start();
|
||||
@@ -214,12 +248,12 @@ public class QOrderTest {
|
||||
|
||||
final List<String> sql = LoggedSql.stop();
|
||||
assertThat(sql).hasSize(1);
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.status, t1.id, t1.email, t1.name from o_order t0 join be_customer t1 on t1.id = t0.customer_id");
|
||||
assertThat(sql.get(0)).contains("select /* QOrderTest.fetch_partial */ t0.id, t0.status, t1.id, t1.email, t1.name from o_order t0 join be_customer t1 on t1.id = t0.customer_id");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateQuery() {
|
||||
void updateQuery() {
|
||||
LoggedSql.start();
|
||||
new QOrder()
|
||||
.status.eq(Order.Status.COMPLETE)
|
||||
@@ -235,7 +269,7 @@ public class QOrderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stdExpression_iLikeConcatCoalesce() {
|
||||
void stdExpression_iLikeConcatCoalesce() {
|
||||
QOrder o = QOrder.alias();
|
||||
|
||||
// LOWER(CONCAT(COALESCE(a.name, ""), ":", a.description)) LIKE LOWER(:param)
|
||||
@@ -250,7 +284,7 @@ public class QOrderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stdExpression_gtCoalesce() {
|
||||
void stdExpression_gtCoalesce() {
|
||||
QOrder o = QOrder.alias();
|
||||
|
||||
Query<Order> query = new QOrder()
|
||||
@@ -265,7 +299,7 @@ public class QOrderTest {
|
||||
|
||||
String sql = query.getGeneratedSql();
|
||||
assertThat(sql).contains(" where (coalesce(t1.version,0) > ? or t0.id < ?)");
|
||||
assertThat(sql).isEqualTo("select t0.id, t0.status from o_order t0 join be_customer t1 on t1.id = t0.customer_id where (coalesce(t1.version,0) > ? or t0.id < ?)");
|
||||
assertThat(sql).isEqualTo("select /* QOrderTest.stdExpression_gtCoalesce */ t0.id, t0.status from o_order t0 join be_customer t1 on t1.id = t0.customer_id where (coalesce(t1.version,0) > ? or t0.id < ?)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -278,7 +312,7 @@ public class QOrderTest {
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered >= (select max(o.order_date) as foo from o_order o)");
|
||||
assertThat(query.getGeneratedSql()).contains("select /* QOrderTest.geSqlSubQuery */ t0.id from be_customer t0 where t0.registered >= (select max(o.order_date) as foo from o_order o)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -291,7 +325,7 @@ public class QOrderTest {
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered > (select max(o.order_date) as foo from o_order o)");
|
||||
assertThat(query.getGeneratedSql()).contains("select /* QOrderTest.gtSqlSubQuery */ t0.id from be_customer t0 where t0.registered > (select max(o.order_date) as foo from o_order o)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -304,7 +338,7 @@ public class QOrderTest {
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered <= (select max(o.order_date) as foo from o_order o)");
|
||||
assertThat(query.getGeneratedSql()).contains("select /* QOrderTest.leSqlSubQuery */ t0.id from be_customer t0 where t0.registered <= (select max(o.order_date) as foo from o_order o)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -317,7 +351,7 @@ public class QOrderTest {
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered < (select max(o.order_date) as foo from o_order o)");
|
||||
assertThat(query.getGeneratedSql()).contains("select /* QOrderTest.ltSqlSubQuery */ t0.id from be_customer t0 where t0.registered < (select max(o.order_date) as foo from o_order o)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -330,7 +364,7 @@ public class QOrderTest {
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered = (select max(o.order_date) as foo from o_order o)");
|
||||
assertThat(query.getGeneratedSql()).contains("select /* QOrderTest.eqSqlSubQuery */ t0.id from be_customer t0 where t0.registered = (select max(o.order_date) as foo from o_order o)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -343,7 +377,7 @@ public class QOrderTest {
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered <> (select max(o.order_date) as foo from o_order o)");
|
||||
assertThat(query.getGeneratedSql()).contains("select /* QOrderTest.neSqlSubQuery */ t0.id from be_customer t0 where t0.registered <> (select max(o.order_date) as foo from o_order o)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -361,7 +395,7 @@ public class QOrderTest {
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered >= (select max(t0.order_date) from o_order t0)");
|
||||
assertThat(query.getGeneratedSql()).contains("select /* QOrderTest.geSubQuery */ t0.id from be_customer t0 where t0.registered >= (select max(t0.order_date) from o_order t0)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -376,7 +410,7 @@ public class QOrderTest {
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.version > (select sum(t0.version) from o_order t0)");
|
||||
assertThat(query.getGeneratedSql()).contains("select /* QOrderTest.gtSubQuery */ t0.id from be_customer t0 where t0.version > (select sum(t0.version) from o_order t0)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -391,7 +425,7 @@ public class QOrderTest {
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered <= (select max(t0.order_date) from o_order t0)");
|
||||
assertThat(query.getGeneratedSql()).contains("select /* QOrderTest.leSubQuery */ t0.id from be_customer t0 where t0.registered <= (select max(t0.order_date) from o_order t0)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -406,7 +440,7 @@ public class QOrderTest {
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered < (select max(t0.order_date) from o_order t0)");
|
||||
assertThat(query.getGeneratedSql()).contains("select /* QOrderTest.ltSubQuery */ t0.id from be_customer t0 where t0.registered < (select max(t0.order_date) from o_order t0)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -421,7 +455,7 @@ public class QOrderTest {
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered = (select max(t0.order_date) from o_order t0)");
|
||||
assertThat(query.getGeneratedSql()).contains("select /* QOrderTest.eqSubQuery */ t0.id from be_customer t0 where t0.registered = (select max(t0.order_date) from o_order t0)");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -436,7 +470,7 @@ public class QOrderTest {
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered <> (select max(t0.order_date) from o_order t0)");
|
||||
assertThat(query.getGeneratedSql()).contains("select /* QOrderTest.neSubQuery */ t0.id from be_customer t0 where t0.registered <> (select max(t0.order_date) from o_order t0)");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -20,7 +20,7 @@ class QueryAlsoIfTest {
|
||||
.query();
|
||||
|
||||
q.findList();
|
||||
assertThat(q.getGeneratedSql()).isEqualTo("select t0.id, t0.name from be_customer t0 where t0.name is not null and t0.status = ?");
|
||||
assertThat(q.getGeneratedSql()).isEqualTo("select /* QueryAlsoIfTest.apply */ t0.id, t0.name from be_customer t0 where t0.name is not null and t0.status = ?");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -32,6 +32,6 @@ class QueryAlsoIfTest {
|
||||
.query();
|
||||
|
||||
q.findList();
|
||||
assertThat(q.getGeneratedSql()).isEqualTo("select t0.id, t0.name from be_customer t0 where t0.name is not null");
|
||||
assertThat(q.getGeneratedSql()).isEqualTo("select /* QueryAlsoIfTest.notApply */ t0.id, t0.name from be_customer t0 where t0.name is not null");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ ebean.ddl.run=true
|
||||
ebean.ddl.initSql=init-db.sql
|
||||
ebean.dumpMetricsOnShutdown=true
|
||||
ebean.dumpMetricsOptions=sql,hash,loc
|
||||
ebean.includeLabelInSql=true
|
||||
|
||||
datasource.default=h2
|
||||
|
||||
|
||||
+6
-6
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-redis</artifactId>
|
||||
@@ -22,28 +22,28 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
package org.integration;
|
||||
|
||||
import io.ebean.DatabaseBuilder;
|
||||
import io.ebean.redis.DuelCache;
|
||||
import org.domain.Person;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.redis.DuelCache;
|
||||
import org.domain.Person;
|
||||
import org.domain.query.QPerson;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -14,21 +11,21 @@ import javax.sql.DataSource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class ClusterTest {
|
||||
class ClusterTest {
|
||||
|
||||
private Database createOther(DataSource dataSource) {
|
||||
DatabaseBuilder config = new DatabaseConfig();
|
||||
config.setDataSource(dataSource);
|
||||
config.loadFromProperties();
|
||||
config.setDefaultServer(false);
|
||||
config.setName("other");
|
||||
config.setDdlGenerate(false);
|
||||
config.setDdlRun(false);
|
||||
return DatabaseFactory.create(config);
|
||||
return Database.builder()
|
||||
.dataSource(dataSource)
|
||||
.loadFromProperties()
|
||||
.defaultDatabase(false)
|
||||
.name("other")
|
||||
.ddlGenerate(false)
|
||||
.ddlRun(false)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBothNear() throws InterruptedException {
|
||||
void testBothNear() throws InterruptedException {
|
||||
// ensure the default server exists first
|
||||
final Database db = DB.getDefault();
|
||||
Database other = createOther(db.pluginApi().dataSource());
|
||||
@@ -61,7 +58,7 @@ public class ClusterTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws InterruptedException {
|
||||
void test() throws InterruptedException {
|
||||
// ensure the default server exists first
|
||||
final Database db = DB.getDefault();
|
||||
Database other = createOther(db.pluginApi().dataSource());
|
||||
@@ -116,6 +113,6 @@ public class ClusterTest {
|
||||
}
|
||||
|
||||
private void allowAsyncMessaging() throws InterruptedException {
|
||||
Thread.sleep(100);
|
||||
Thread.sleep(200);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-spring-txn</artifactId>
|
||||
@@ -28,7 +28,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
+12
-12
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean test</name>
|
||||
@@ -12,8 +12,8 @@
|
||||
<artifactId>ebean-test</artifactId>
|
||||
|
||||
<properties>
|
||||
<bytebuddy.version>1.14.9</bytebuddy.version>
|
||||
<assertj.version>3.24.2</assertj.version>
|
||||
<bytebuddy.version>1.14.12</bytebuddy.version>
|
||||
<assertj.version>3.25.3</assertj.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -33,20 +33,20 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -135,28 +135,28 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-joda-time</artifactId>
|
||||
<version>13.24.0</version>
|
||||
<version>14.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-jsonnode</artifactId>
|
||||
<version>13.24.0</version>
|
||||
<version>14.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-mapper</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-all</artifactId>
|
||||
<version>14.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -213,7 +213,7 @@
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.6.0</version>
|
||||
<version>42.7.2</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
@@ -293,7 +293,7 @@
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>1.3</version>
|
||||
<version>1.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -164,8 +164,14 @@ public class DtoQueryFromOrmTest extends BaseTestCase {
|
||||
|
||||
DtoQuery<ContactDto> query = DB.find(Contact.class)
|
||||
// we must explicitly add the id property for DTO query (if we want it)
|
||||
.select("id, email, " + concat("lastName", ", ", "firstName") + " as fullName").where().isNotNull("email")
|
||||
.isNotNull("lastName").order().asc("lastName").asDto(ContactDto.class).setLabel("explicitId")
|
||||
.setHint("SomeHint")
|
||||
.select("id, email, " + concat("lastName", ", ", "firstName") + " as fullName")
|
||||
.where()
|
||||
.isNotNull("email")
|
||||
.isNotNull("lastName")
|
||||
.orderBy().asc("lastName")
|
||||
.asDto(ContactDto.class)
|
||||
.setLabel("explicitId")
|
||||
.setRelaxedMode();
|
||||
|
||||
List<ContactDto> dtos = query.findList();
|
||||
@@ -178,7 +184,7 @@ public class DtoQueryFromOrmTest extends BaseTestCase {
|
||||
}
|
||||
|
||||
List<String> sql = LoggedSql.stop();
|
||||
assertSql(sql.get(0)).contains("select t0.id, t0.email, " + concat("t0.last_name", ", ", "t0.first_name")
|
||||
assertSql(sql.get(0)).contains("select /*+ SomeHint */ /* explicitId */ t0.id, t0.email, " + concat("t0.last_name", ", ", "t0.first_name")
|
||||
+ " fullName from contact t0 where t0.email is not null and t0.last_name is not null order by t0.last_name");
|
||||
}
|
||||
|
||||
|
||||
@@ -26,11 +26,12 @@ public class FetchGroupTest extends BaseTestCase {
|
||||
.query()
|
||||
.where()
|
||||
.ilike("name", "rob")
|
||||
.setLabel("hello")
|
||||
.select(fetch);
|
||||
|
||||
query.findList();
|
||||
|
||||
assertThat(sqlOf(query)).contains("select t0.id, t0.name, t0.status from");
|
||||
assertThat(sqlOf(query)).contains("select /* hello */ t0.id, t0.name, t0.status from");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -12,12 +12,20 @@ class ContainerConfigTest {
|
||||
|
||||
@Test
|
||||
void loadFromProperties() {
|
||||
ContainerConfig containerConfig = new ContainerConfig();
|
||||
Properties p = new Properties();
|
||||
p.setProperty("ebean.cluster.active", "true");
|
||||
p.setProperty("ebean.cluster.serviceName", "a");
|
||||
p.setProperty("ebean.cluster.namespace", "b");
|
||||
p.setProperty("ebean.cluster.podName", "c");
|
||||
p.setProperty("ebean.cluster.port", "42");
|
||||
|
||||
assertThat(containerConfig.isActive()).isFalse();
|
||||
assertThat(containerConfig.getServiceName()).isNull();
|
||||
assertThat(containerConfig.getNamespace()).isNull();
|
||||
assertThat(containerConfig.getPodName()).isNull();
|
||||
assertThat(containerConfig.getPort()).isEqualTo(0);
|
||||
ContainerConfig containerConfig = new ContainerConfig();
|
||||
containerConfig.loadFromProperties(p);
|
||||
|
||||
assertThat(containerConfig.isActive()).isTrue();
|
||||
assertThat(containerConfig.getServiceName()).isEqualTo("a");
|
||||
assertThat(containerConfig.getNamespace()).isEqualTo("b");
|
||||
assertThat(containerConfig.getPodName()).isEqualTo("c");
|
||||
assertThat(containerConfig.getPort()).isEqualTo(42);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ public class WriteJsonDirtyTest {
|
||||
JsonFactory jsonFactory = new JsonFactory();
|
||||
JsonGenerator generator = jsonFactory.createGenerator(writer);
|
||||
|
||||
WriteJson writeJson = new WriteJson(server, generator, null, null, null, null);
|
||||
WriteJson writeJson = new WriteJson(server, generator, null, null, null, null, true);
|
||||
descriptor.jsonWriteDirty(writeJson, entityBean, dirtyProperties);
|
||||
|
||||
generator.flush();
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
package org.tests.basic;
|
||||
|
||||
import io.ebean.DB;
|
||||
import io.ebean.DataIntegrityException;
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.model.json.EBasicJsonList;
|
||||
import org.tests.model.json.EBasicJsonMap;
|
||||
import org.tests.model.types.SomeFileBean;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
/**
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*/
|
||||
public class TestLength extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
void testFileSize() throws IOException {
|
||||
File f1 = File.createTempFile("testfile", "tmp");
|
||||
byte[] buf = new byte[1024];
|
||||
try (FileOutputStream fos = new FileOutputStream(f1)) {
|
||||
for (int i = 0; i < 100; i++) {
|
||||
fos.write(buf);
|
||||
}
|
||||
}
|
||||
|
||||
SomeFileBean sfb1 = new SomeFileBean();
|
||||
sfb1.setContent(f1);
|
||||
DB.save(sfb1);
|
||||
|
||||
try (FileOutputStream fos = new FileOutputStream(f1)) {
|
||||
for (int i = 0; i < 101; i++) {
|
||||
fos.write(buf);
|
||||
}
|
||||
}
|
||||
|
||||
SomeFileBean sfb2 = new SomeFileBean();
|
||||
sfb2.setContent(f1);
|
||||
assertThatThrownBy(() -> DB.save(sfb2)).isInstanceOf(DataIntegrityException.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The property 'EBasicJsonMap.content' is annotated with @DbJson(length=5000). So we assume, that we cannot save Json-objects
|
||||
* where the serialized form exceed that limit and we would expect an error on save.
|
||||
* The length check works for platforms like h2, as H2 uses a 'varchar(5000)'. So it is impossible to save such long jsons,
|
||||
* but it won't work for SqlServer, as here 'nvarchar(max)' is used. No validation happens at DB level and you might get very
|
||||
* large Json objects in your database. This mostly happens unintentionally (programming error, misconfiguration)
|
||||
* So they are in the database and they cannot be accessed by ebean any more, because there are new limits in Jackson:
|
||||
* - Max 5 Meg per string in 2.15.0
|
||||
* - Max 20 Meg per string in 2.15.1
|
||||
* see https://github.com/FasterXML/jackson-core/issues/1014
|
||||
*/
|
||||
@Test
|
||||
void testLongString() {
|
||||
// s is so big, that it could not be deserialized by jackson
|
||||
String s = new String(new char[20_000_001]).replace('\0', 'x');
|
||||
|
||||
EBasicJsonMap bean = new EBasicJsonMap();
|
||||
bean.setName("b1");
|
||||
bean.setContent(Map.of("string", s));
|
||||
|
||||
assertThatThrownBy(() -> {
|
||||
// we expect, that we can NOT save the bean, this is ensured by the bind validator.
|
||||
DB.save(bean);
|
||||
}).isInstanceOf(DataIntegrityException.class);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests the UTF8 validation.
|
||||
*/
|
||||
@Test
|
||||
void testUtf8() {
|
||||
|
||||
String s = new String(new char[40]).replace('\0', '€');
|
||||
|
||||
EBasicJsonList bean = new EBasicJsonList();
|
||||
bean.setName("b1");
|
||||
bean.setTags(List.of(s));
|
||||
|
||||
if (isDb2() || isOracle()) {
|
||||
// by default, DB2 && oracle uses bytes in varchar, so an '€' symbol needs 3 bytes
|
||||
assertThatThrownBy(() -> {
|
||||
// we expect, that we can NOT save the bean, this is ensured by the bind validator.
|
||||
DB.save(bean);
|
||||
}).isInstanceOf(DataIntegrityException.class);
|
||||
} else {
|
||||
DB.save(bean);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.tests.cascade;
|
||||
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class TestLazyLoadMany extends BaseTestCase {
|
||||
|
||||
COOne create(String parentName, int childCount) {
|
||||
COOne m0 = new COOne(parentName);
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
m0.getChildren().add(new COOneMany(parentName+"_"+i));
|
||||
}
|
||||
return m0;
|
||||
}
|
||||
@Test
|
||||
void loadAfterPCCleared() {
|
||||
|
||||
var m0 = create("tll-m0", 2);
|
||||
var m1 = create("tll-m1", 4);
|
||||
var m2 = create("tll-m2", 5);
|
||||
|
||||
DB.saveAll(m0, m1, m2);
|
||||
|
||||
try (Transaction transaction = DB.beginTransaction()) {
|
||||
List<COOne> children = DB.find(COOne.class)
|
||||
.setLazyLoadBatchSize(2)
|
||||
.where().startsWith("name", "tll-m")
|
||||
.findList();
|
||||
|
||||
assertThat(children).hasSize(3);
|
||||
assertThat(children.get(0).getChildren()).describedAs("invoke lazy loading on children").hasSize(2);
|
||||
|
||||
DB.sqlUpdate("update coone set name = ? where id = ?")
|
||||
.setParameters("new name", children.get(0).getId())
|
||||
.executeNow(); // clears the persistence context in 14.0.0+ due to #3295 #3301
|
||||
|
||||
// the children here were already lazy loaded
|
||||
assertThat(children.get(1).getChildren()).hasSize(4);
|
||||
// this invokes the lazy loading of children AFTER the persistence context was cleared
|
||||
assertThat(children.get(2).getChildren()).hasSize(5);
|
||||
|
||||
transaction.rollback();
|
||||
} finally {
|
||||
DB.deleteAll(List.of(m0, m1, m2));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package org.tests.json;
|
||||
|
||||
import io.ebean.DB;
|
||||
import io.ebean.DataIntegrityException;
|
||||
import org.assertj.core.api.SoftAssertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.model.json.EBasicJsonMap;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
class TestDbJsonLength {
|
||||
|
||||
|
||||
/**
|
||||
* The property 'EBasicJsonMap.content' is annotated with @DbJson(length=5000). So we assume, that we cannot save Json-objects
|
||||
* where the serialized form exceed that limit and we would expect an error on save.
|
||||
* The length check works for platforms like h2, as H2 uses a 'varchar(5000)'. So it is impossible to save such long jsons,
|
||||
* but it won't work for SqlServer, as here 'nvarchar(max)' is used. No validation happens at DB level and you might get very
|
||||
* large Json objects in your database. This mostly happens unintentionally (programming error, misconfiguration)
|
||||
* So they are in the database and they cannot be accessed by ebean any more, because there are new limits in Jackson:
|
||||
* - Max 5 Meg per string in 2.15.0
|
||||
* - Max 20 Meg per string in 2.15.1
|
||||
* see https://github.com/FasterXML/jackson-core/issues/1014
|
||||
*/
|
||||
@Test
|
||||
void testLongString() {
|
||||
// s is so big, that it could not be deserialized by jackson
|
||||
String s = new String(new char[20_000_001]).replace('\0', 'x');
|
||||
|
||||
EBasicJsonMap bean = new EBasicJsonMap();
|
||||
bean.setName("b1");
|
||||
bean.setContent(Map.of("string", s));
|
||||
|
||||
SoftAssertions softly = new SoftAssertions();
|
||||
|
||||
softly.assertThatThrownBy(() -> {
|
||||
DB.save(bean);
|
||||
}).isInstanceOf(DataIntegrityException.class);
|
||||
|
||||
|
||||
if (bean.getId() != null) {
|
||||
// we expect, that we could NOT save the bean, but this is not true for sqlServer.
|
||||
// we will get a javax.persistence.PersistenceException: Error loading on org.tests.model.json.EBasicJsonMap.content
|
||||
// when we try to load the bean back from DB
|
||||
DB.find(EBasicJsonMap.class, bean.getId());
|
||||
}
|
||||
|
||||
softly.assertAll();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.tests.json.include;
|
||||
|
||||
import io.ebean.DB;
|
||||
import io.ebean.FetchPath;
|
||||
import io.ebean.config.JsonConfig;
|
||||
import io.ebean.text.PathProperties;
|
||||
import io.ebean.text.json.JsonWriteOptions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.model.basic.Contact;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class TestJsonImplicitLoaded {
|
||||
|
||||
@Test
|
||||
void testToBeanToJson() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
FetchPath path = PathProperties.parse("*");
|
||||
Contact bean = DB.find(Contact.class).setId(1).apply(path).findOne();
|
||||
|
||||
JsonWriteOptions options = new JsonWriteOptions();
|
||||
options.setInclude(JsonConfig.Include.NON_NULL);
|
||||
options.setPathProperties(path);
|
||||
options.setIncludeLoadedImplicit(false);
|
||||
|
||||
String asJson = DB.json().toJson(bean, options);
|
||||
assertThat(asJson).contains("customer\":{\"id\":1}"); // hold only ID
|
||||
|
||||
bean.getCustomer().getName(); // lazy-load bean;
|
||||
asJson = DB.json().toJson(bean, options);
|
||||
assertThat(asJson).contains("customer\":{\"id\":1}"); // expect the same result
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -46,7 +46,7 @@ public class TestElementCollectionCascade extends BaseTestCase {
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.name, t0.version from ecsm_parent t0 where t0.id = ?");
|
||||
if (!isPostgresCompatible()) {
|
||||
assertThat(sql.get(1)).contains("select t0.ecsm_parent_id, t0.one_id, t0.name, t0.version from ecsm_child t0 where (t0.ecsm_parent_id) in (?)");
|
||||
assertThat(sql.get(2)).contains("select t0.host_id, t0.value from ecsm_values t0 where (t0.host_id) in (?,?)");
|
||||
assertThat(sql.get(2)).contains("select t0.host_id, t0.value from ecsm_values t0 where (t0.host_id) in (?,?,?,?,?)");
|
||||
}
|
||||
|
||||
Set<String> vals0 = childVals.get("c0");
|
||||
|
||||
@@ -18,7 +18,7 @@ public class EBasicJsonMap {
|
||||
|
||||
String name;
|
||||
|
||||
@DbJson
|
||||
@DbJson(length = 5000)
|
||||
Map<String, Object> content;
|
||||
|
||||
@OneToMany(mappedBy = "owner", cascade = CascadeType.ALL)
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package org.tests.model.types;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Lob;
|
||||
import jakarta.persistence.Version;
|
||||
import jakarta.persistence.*;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@Entity
|
||||
@@ -18,6 +16,7 @@ public class SomeFileBean {
|
||||
String name;
|
||||
|
||||
@Lob
|
||||
@Column(length = 100 * 1024) // limit to 100kb
|
||||
File content;
|
||||
|
||||
public Long getId() {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user