mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-09-21 11:19:58 +00:00
Compare commits
72
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
42685335e3 | ||
|
|
478a2be405 | ||
|
|
ebcac9a503 | ||
|
|
996239c29f | ||
|
|
caf2772fb3 | ||
|
|
1482c4c84f | ||
|
|
792d52b794 | ||
|
|
aa4ea4904f | ||
|
|
bab839fb38 | ||
|
|
dde2567ccd | ||
|
|
7e4d070b75 | ||
|
|
3151e3f82b | ||
|
|
c630aaff0e | ||
|
|
67ec848f15 | ||
|
|
57f0734381 | ||
|
|
cbd5bf23c9 | ||
|
|
5dc664a63f | ||
|
|
d9b53677f2 | ||
|
|
f55c2cf3b6 | ||
|
|
c98def7ab7 | ||
|
|
705e158a70 | ||
|
|
569e782e99 | ||
|
|
265b92fb12 | ||
|
|
74311fad0a | ||
|
|
1eded5682a | ||
|
|
ff21bfe1de | ||
|
|
86db7fadfd | ||
|
|
e48b327967 | ||
|
|
964b3ccf8e | ||
|
|
eb6906ad2b | ||
|
|
86e5ea3627 | ||
|
|
3a5e8290e0 | ||
|
|
929604e33d | ||
|
|
2eed68ad61 | ||
|
|
f705560b8b | ||
|
|
a35db6bdee | ||
|
|
c13e09257c | ||
|
|
ed65433640 | ||
|
|
08890e9d5a | ||
|
|
4273c4af6a | ||
|
|
51424d9eea | ||
|
|
cf2ab33903 | ||
|
|
90d8b4fb04 | ||
|
|
ff4eeff264 | ||
|
|
64ba343e35 | ||
|
|
af3c59c0fd | ||
|
|
ae55d28026 | ||
|
|
ddffc8eee2 | ||
|
|
7f1a3a46cf | ||
|
|
a59f75a468 | ||
|
|
6f1c66ecd6 | ||
|
|
25f6fb6d6f | ||
|
|
852def8536 | ||
|
|
dfb29fd75f | ||
|
|
80c3501197 | ||
|
|
b4ff5748fc | ||
|
|
64f01f0543 | ||
|
|
fee6e0f480 | ||
|
|
50b44c4529 | ||
|
|
f0c2ba0e28 | ||
|
|
7643dc9b22 | ||
|
|
c49a1b3d71 | ||
|
|
11e783938c | ||
|
|
3845861e24 | ||
|
|
d04181865c | ||
|
|
00d7db31d6 | ||
|
|
6880b5673a | ||
|
|
e18b59a9dd | ||
|
|
cc48dced09 | ||
|
|
b13bdc95be | ||
|
|
0a5c3ced21 | ||
|
|
3ab3f81fa3 |
@@ -16,7 +16,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
java_version: [GA,EA,23]
|
||||
java_version: [GA,EA]
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-clickhouse</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-db2</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-hana</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-mariadb</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-mysql</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -22,13 +22,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -47,19 +47,19 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-net-postgis-types</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-nuodb</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-oracle</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -22,13 +22,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -47,19 +47,19 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis-types</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlite</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlserver</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -41,7 +41,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-mapper</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -60,13 +60,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-all</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>composites</artifactId>
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean api</name>
|
||||
@@ -35,7 +35,7 @@
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>avaje-config</artifactId>
|
||||
<version>3.12</version>
|
||||
<version>4.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -89,7 +89,12 @@ public interface BeanState {
|
||||
* <p>
|
||||
* If a setter is called on a readOnly bean it will throw an exception.
|
||||
*/
|
||||
boolean isUnmodifiable();
|
||||
boolean isReadOnly();
|
||||
|
||||
/**
|
||||
* Set the readOnly status for the bean.
|
||||
*/
|
||||
void setReadOnly(boolean readOnly);
|
||||
|
||||
/**
|
||||
* Advanced - Used to programmatically build a partially or fully loaded
|
||||
|
||||
@@ -772,18 +772,6 @@ public interface Database {
|
||||
*/
|
||||
<T> T reference(Class<T> beanType, Object id);
|
||||
|
||||
/**
|
||||
* Return the extended API for Database.
|
||||
* <p>
|
||||
* The extended API has the options for executing queries that take an explicit
|
||||
* transaction as an argument.
|
||||
* <p>
|
||||
* Typically, we only need to use the extended API when we do NOT want to use the
|
||||
* usual ThreadLocal based mechanism to obtain the current transaction but instead
|
||||
* supply the transaction explicitly.
|
||||
*/
|
||||
ExtendedServer extended();
|
||||
|
||||
/**
|
||||
* Either Insert or Update the bean depending on its state.
|
||||
* <p>
|
||||
|
||||
@@ -2019,6 +2019,11 @@ public interface DatabaseBuilder {
|
||||
@Deprecated
|
||||
DatabaseBuilder setQueryPlanTTLSeconds(int queryPlanTTLSeconds);
|
||||
|
||||
/**
|
||||
* Set the EXPLAIN (with options) to use for query plan capture.
|
||||
*/
|
||||
DatabaseBuilder queryPlanExplain(String queryPlanExplain);
|
||||
|
||||
/**
|
||||
* Create a new PlatformConfig based of the one held but with overridden properties by reading
|
||||
* properties with the given path and prefix.
|
||||
@@ -3044,6 +3049,11 @@ public interface DatabaseBuilder {
|
||||
*/
|
||||
int getQueryPlanTTLSeconds();
|
||||
|
||||
/**
|
||||
* Return the EXPLAIN (with options) to use for capturing query plans.
|
||||
*/
|
||||
String getQueryPlanExplain();
|
||||
|
||||
/**
|
||||
* Return mapping locations to search for xml mapping via class path search.
|
||||
*/
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
package io.ebean;
|
||||
|
||||
import java.time.Clock;
|
||||
|
||||
/**
|
||||
* The extended API for Database.
|
||||
*/
|
||||
public interface ExtendedServer {
|
||||
|
||||
/**
|
||||
* Deprecated but no yet determined suitable replacement (to support testing only change of clock).
|
||||
* <p>
|
||||
* Set the Clock to use for <code>@WhenCreated</code> and <code>@WhenModified</code>.
|
||||
* <p>
|
||||
* Note that we only expect to change the Clock for testing purposes.
|
||||
* </p>
|
||||
*/
|
||||
@Deprecated
|
||||
void setClock(Clock clock);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package io.ebean;
|
||||
|
||||
import jakarta.persistence.PersistenceException;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
/**
|
||||
* FutureMap represents the result of a background query execution that will
|
||||
* return a map of entities.
|
||||
* <p>
|
||||
* It extends the java.util.concurrent.Future with the ability to cancel the
|
||||
* query, check if it is finished and get the resulting list waiting for the
|
||||
* query to finish (ie. the standard features of java.util.concurrent.Future).
|
||||
* </p>
|
||||
* <p>
|
||||
* A simple example:
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // create a query to find all orders
|
||||
* Query<Long,Order> query = DB.find(Order.class)
|
||||
* .setMapKey("id");
|
||||
*
|
||||
* // execute the query in a background thread
|
||||
* // immediately returning the futureMap
|
||||
* FutureMap<Long,Order> futureMap = query.findFutureMap();
|
||||
*
|
||||
* // do something else ...
|
||||
*
|
||||
* if (!futureMap.isDone()){
|
||||
* // we can cancel the query execution. This will cancel
|
||||
* // the underlying query if that is supported by the JDBC
|
||||
* // driver and database
|
||||
* futureMap.cancel(true);
|
||||
* }
|
||||
*
|
||||
* if (!futureMap.isCancelled()){
|
||||
* // wait for the query to finish and return the map
|
||||
* Map<Long,Order> map = futureMap.get();
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
public interface FutureMap<K, T> extends Future<Map<K, T>> {
|
||||
|
||||
/**
|
||||
* Return the query that is being executed by a background thread.
|
||||
*/
|
||||
Query<T> getQuery();
|
||||
|
||||
/**
|
||||
* Same as {@link #get()} but wraps InterruptedException and ExecutionException in the
|
||||
* unchecked PersistenceException.
|
||||
*
|
||||
* @return The query list result
|
||||
* @throws PersistenceException when a InterruptedException or ExecutionException occurs.
|
||||
*/
|
||||
Map<K, T> getUnchecked();
|
||||
|
||||
/**
|
||||
* Same as {@link #get(long, TimeUnit)} but wraps InterruptedException
|
||||
* and ExecutionException in the unchecked PersistenceException.
|
||||
*
|
||||
* @return The query list result
|
||||
* @throws TimeoutException if the wait timed out
|
||||
* @throws PersistenceException if a InterruptedException or ExecutionException occurs.
|
||||
*/
|
||||
Map<K, T> getUnchecked(long timeout, TimeUnit unit) throws TimeoutException;
|
||||
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package io.ebean;
|
||||
|
||||
/**
|
||||
* Thrown when trying to access a property that isn't loaded on an entity
|
||||
* that is unmodifiable or has disabled lazy loading.
|
||||
* <p>
|
||||
* On a normal mutable entity accessing the property would invoke lazy loading. On
|
||||
* a unmodifiable entity with lazy loading disabled, accessing an unloaded property
|
||||
* throws this LazyInitialisationException instead.
|
||||
*/
|
||||
public class LazyInitialisationException extends UnmodifiableEntityException {
|
||||
|
||||
/**
|
||||
* Create specifying the property that was being accessed.
|
||||
*/
|
||||
public LazyInitialisationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,4 @@ public interface ModifyAwareType {
|
||||
*/
|
||||
void setMarkedDirty(boolean markedDirty);
|
||||
|
||||
default Object freeze() {
|
||||
return this; // throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,13 +388,9 @@ public interface QueryBuilder<SELF extends QueryBuilder<SELF, T>, T> extends Que
|
||||
SELF setUseDocStore(boolean useDocStore);
|
||||
|
||||
/**
|
||||
* When set to true when you want the returned beans to be unmodifiable read only.
|
||||
* <p>
|
||||
* This means that the returning graph can't be mutated via setters, all the collections
|
||||
* are unmodifiable collections, lazy loading is disabled and that the query uses
|
||||
* {@link PersistenceContextScope#QUERY}.
|
||||
* When set to true when you want the returned beans to be read only.
|
||||
*/
|
||||
SELF setUnmodifiable(boolean unmodifiable);
|
||||
SELF setReadOnly(boolean readOnly);
|
||||
|
||||
/**
|
||||
* Set a timeout on this query.
|
||||
@@ -956,6 +952,16 @@ public interface QueryBuilder<SELF extends QueryBuilder<SELF, T>, T> extends Que
|
||||
*/
|
||||
FutureList<T> findFutureList();
|
||||
|
||||
/**
|
||||
* Execute find map query in a background thread.
|
||||
* <p>
|
||||
* This query will execute in it's own PersistenceContext and using its own transaction.
|
||||
* What that means is that it will not share any bean instances with other queries.
|
||||
*
|
||||
* @return a Future object for the map result of the query
|
||||
*/
|
||||
<K> FutureMap<K,T> findFutureMap();
|
||||
|
||||
/**
|
||||
* Return a PagedList for this query using firstRow and maxRows.
|
||||
* <p>
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
package io.ebean;
|
||||
|
||||
/**
|
||||
* Attempted to modify a read only entity.
|
||||
*/
|
||||
public class UnmodifiableEntityException extends UnsupportedOperationException {
|
||||
private static final long serialVersionUID = 1;
|
||||
|
||||
/**
|
||||
* Create with no message.
|
||||
*/
|
||||
public UnmodifiableEntityException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create with message.
|
||||
*/
|
||||
public UnmodifiableEntityException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -119,6 +119,18 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
|
||||
*/
|
||||
void setLoader(BeanCollectionLoader beanLoader);
|
||||
|
||||
/**
|
||||
* Set to true if you want the BeanCollection to be treated as read only. This
|
||||
* means no elements can be added or removed etc.
|
||||
*/
|
||||
void setReadOnly(boolean readOnly);
|
||||
|
||||
/**
|
||||
* Return true if the collection should be treated as readOnly and no elements
|
||||
* can be added or removed etc.
|
||||
*/
|
||||
boolean isReadOnly();
|
||||
|
||||
/**
|
||||
* Add the bean to the collection. This is disallowed for BeanMap.
|
||||
*/
|
||||
@@ -225,7 +237,7 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
|
||||
boolean wasTouched();
|
||||
|
||||
/**
|
||||
* Freeze the collection returning an unmodifiable version.
|
||||
* Return a shallow copy of this collection that is modifiable.
|
||||
*/
|
||||
Object freeze();
|
||||
BeanCollection<E> shallowCopy();
|
||||
}
|
||||
|
||||
@@ -148,6 +148,18 @@ public interface EntityBeanIntercept extends Serializable {
|
||||
*/
|
||||
boolean isLoadedFromCache();
|
||||
|
||||
/**
|
||||
* Return true if the bean should be treated as readOnly. If a setter method
|
||||
* is called when it is readOnly an Exception is thrown.
|
||||
*/
|
||||
boolean isReadOnly();
|
||||
|
||||
/**
|
||||
* Set the readOnly status. If readOnly then calls to setter methods through
|
||||
* an exception.
|
||||
*/
|
||||
void setReadOnly(boolean readOnly);
|
||||
|
||||
/**
|
||||
* Set the bean to be updated when persisted (for merge).
|
||||
*/
|
||||
@@ -540,9 +552,4 @@ public interface EntityBeanIntercept extends Serializable {
|
||||
* Update the 'next' mutable info returning the content that was obtained via dirty detection.
|
||||
*/
|
||||
String mutableNext(int propertyIndex);
|
||||
|
||||
/**
|
||||
* Return true if this entity bean should be frozen. Used to handle recursive freezing.
|
||||
*/
|
||||
boolean freeze();
|
||||
}
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
package io.ebean.bean;
|
||||
|
||||
/**
|
||||
* Common base features for EntityBeanIntercept.
|
||||
*/
|
||||
abstract class InterceptBase implements EntityBeanIntercept {
|
||||
|
||||
final EntityBean owner;
|
||||
boolean fullyLoadedBean;
|
||||
|
||||
/**
|
||||
* Create with a given entity.
|
||||
*/
|
||||
InterceptBase(Object ownerBean) {
|
||||
this.owner = (EntityBean) ownerBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL - Constructor only for use by serialization frameworks.
|
||||
*/
|
||||
InterceptBase() {
|
||||
this.owner = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final EntityBean owner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isFullyLoadedBean() {
|
||||
return fullyLoadedBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setFullyLoadedBean(boolean fullyLoadedBean) {
|
||||
this.fullyLoadedBean = fullyLoadedBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String property(int propertyIndex) {
|
||||
if (propertyIndex == -1) {
|
||||
return null;
|
||||
}
|
||||
return owner._ebean_getPropertyName(propertyIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int findProperty(String propertyName) {
|
||||
final String[] names = owner._ebean_getPropertyNames();
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
if (names[i].equals(propertyName)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final StringBuilder loadedPropertyKey() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final int len = propertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (isLoadedProperty(i)) {
|
||||
sb.append(i).append(',');
|
||||
}
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +1,37 @@
|
||||
package io.ebean.bean;
|
||||
|
||||
import io.ebean.LazyInitialisationException;
|
||||
import io.ebean.UnmodifiableEntityException;
|
||||
import io.ebean.ValuePair;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* EntityBeanIntercept optimised for read only use.
|
||||
* <p>
|
||||
* For the read only use this intercept doesn't need to hold any state that is normally
|
||||
* required for updates such as per property changed, dirty state, original values
|
||||
* required for updates such as per property changed, loaded, dirty state, original values
|
||||
* bean state etc.
|
||||
*/
|
||||
public final class InterceptReadOnly extends InterceptBase {
|
||||
public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
|
||||
private final boolean[] loaded;
|
||||
private boolean frozen;
|
||||
private final EntityBean owner;
|
||||
|
||||
/**
|
||||
* Create with a given entity.
|
||||
*/
|
||||
public InterceptReadOnly(Object ownerBean) {
|
||||
super(ownerBean);
|
||||
this.loaded = new boolean[owner._ebean_getPropertyNames().length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean freeze() {
|
||||
if (frozen) {
|
||||
return false;
|
||||
} else {
|
||||
frozen = true;
|
||||
return true;
|
||||
}
|
||||
this.owner = (EntityBean) ownerBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InterceptReadOnly{frozen:" + frozen + " loaded:" + loadedPropertyNames() + '}';
|
||||
return "InterceptReadOnly{" + owner + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityBean owner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -101,13 +94,18 @@ public final class InterceptReadOnly extends InterceptBase {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFullyLoadedBean() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFullyLoadedBean(boolean fullyLoadedBean) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPartial() {
|
||||
for (boolean flag : loaded) {
|
||||
if (!flag) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -138,14 +136,7 @@ public final class InterceptReadOnly extends InterceptBase {
|
||||
|
||||
@Override
|
||||
public boolean hasIdOnly(int idIndex) {
|
||||
for (int i = 0; i < loaded.length; i++) {
|
||||
if (i == idIndex) {
|
||||
if (!loaded[i]) return false;
|
||||
} else if (loaded[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -168,6 +159,16 @@ public final class InterceptReadOnly extends InterceptBase {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadOnly(boolean readOnly) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setForceUpdate(boolean forceUpdate) {
|
||||
|
||||
@@ -233,38 +234,44 @@ public final class InterceptReadOnly extends InterceptBase {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int findProperty(String propertyName) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String property(int propertyIndex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int propertyLength() {
|
||||
return loaded.length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPropertyLoaded(String propertyName, boolean loaded) {
|
||||
final int position = findProperty(propertyName);
|
||||
if (position == -1) {
|
||||
throw new IllegalArgumentException("Property not found - " + propertyName);
|
||||
}
|
||||
this.loaded[position] = loaded;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPropertyUnloaded(int propertyIndex) {
|
||||
loaded[propertyIndex] = false;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoadedProperty(int propertyIndex) {
|
||||
loaded[propertyIndex] = true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoadedPropertyAll() {
|
||||
Arrays.fill(loaded, true);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoadedProperty(int propertyIndex) {
|
||||
return loaded[propertyIndex];
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -314,16 +321,7 @@ public final class InterceptReadOnly extends InterceptBase {
|
||||
|
||||
@Override
|
||||
public Set<String> loadedPropertyNames() {
|
||||
if (fullyLoadedBean) {
|
||||
return null;
|
||||
}
|
||||
final Set<String> props = new LinkedHashSet<>();
|
||||
for (int i = 0; i < loaded.length; i++) {
|
||||
if (loaded[i]) {
|
||||
props.add(property(i));
|
||||
}
|
||||
}
|
||||
return props;
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -371,11 +369,14 @@ public final class InterceptReadOnly extends InterceptBase {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuilder loadedPropertyKey() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] loaded() {
|
||||
final boolean[] ret = new boolean[loaded.length];
|
||||
System.arraycopy(loaded, 0, ret, 0, ret.length);
|
||||
return ret;
|
||||
return new boolean[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -400,7 +401,7 @@ public final class InterceptReadOnly extends InterceptBase {
|
||||
|
||||
@Override
|
||||
public void initialisedMany(int propertyIndex) {
|
||||
loaded[propertyIndex] = true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -415,14 +416,12 @@ public final class InterceptReadOnly extends InterceptBase {
|
||||
|
||||
@Override
|
||||
public void preGetter(int propertyIndex) {
|
||||
if (!loaded[propertyIndex]) {
|
||||
throw new LazyInitialisationException("Property not loaded: " + property(propertyIndex));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetterMany(boolean interceptField, int propertyIndex, Object oldValue, Object newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -437,57 +436,57 @@ public final class InterceptReadOnly extends InterceptBase {
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, Object oldValue, Object newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, boolean oldValue, boolean newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, int oldValue, int newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, long oldValue, long newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, double oldValue, double newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, float oldValue, float newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, short oldValue, short newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, char oldValue, char newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, byte oldValue, byte newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, char[] oldValue, char[] newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, byte[] oldValue, byte[] newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
* This provides the mechanisms to support deferred fetching of reference beans
|
||||
* and oldValues generation for concurrency checking.
|
||||
*/
|
||||
public final class InterceptReadWrite extends InterceptBase {
|
||||
public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
|
||||
private static final long serialVersionUID = -3664031775464862649L;
|
||||
|
||||
@@ -56,6 +56,10 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
private String ebeanServerName;
|
||||
private boolean deletedFromCollection;
|
||||
|
||||
/**
|
||||
* The actual entity bean that 'owns' this intercept.
|
||||
*/
|
||||
private final EntityBean owner;
|
||||
private EntityBean embeddedOwner;
|
||||
private int embeddedOwnerIndex;
|
||||
/**
|
||||
@@ -63,6 +67,7 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
*/
|
||||
private int state;
|
||||
private boolean forceUpdate;
|
||||
private boolean readOnly;
|
||||
private boolean dirty;
|
||||
/**
|
||||
* Flag set to disable lazy loading.
|
||||
@@ -72,6 +77,7 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
* Flag set when lazy loading failed due to the underlying bean being deleted in the DB.
|
||||
*/
|
||||
private boolean lazyLoadFailure;
|
||||
private boolean fullyLoadedBean;
|
||||
private boolean loadedFromCache;
|
||||
private final byte[] flags;
|
||||
private Object[] origValues;
|
||||
@@ -95,7 +101,7 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
* Create with a given entity.
|
||||
*/
|
||||
public InterceptReadWrite(Object ownerBean) {
|
||||
super(ownerBean);
|
||||
this.owner = (EntityBean) ownerBean;
|
||||
this.flags = new byte[owner._ebean_getPropertyNames().length];
|
||||
}
|
||||
|
||||
@@ -103,20 +109,16 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
* EXPERIMENTAL - Constructor only for use by serialization frameworks.
|
||||
*/
|
||||
public InterceptReadWrite() {
|
||||
super();
|
||||
this.owner = null;
|
||||
this.flags = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean freeze() {
|
||||
throw new UnsupportedOperationException("never expected");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InterceptReadWrite@" + hashCode() + "{state=" + state +
|
||||
(dirty ? " dirty;" : "") +
|
||||
(forceUpdate ? " forceUpdate;" : "") +
|
||||
(readOnly ? " readOnly;" : "") +
|
||||
(disableLazyLoad ? " disableLazyLoad;" : "") +
|
||||
(lazyLoadFailure ? " lazyLoadFailure;" : "") +
|
||||
(fullyLoadedBean ? " fullyLoadedBean;" : "") +
|
||||
@@ -129,6 +131,11 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityBean owner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceContext persistenceContext() {
|
||||
return persistenceContext;
|
||||
@@ -193,6 +200,16 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
this.ebeanServerName = beanLoader.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFullyLoadedBean() {
|
||||
return fullyLoadedBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFullyLoadedBean(boolean fullyLoadedBean) {
|
||||
this.fullyLoadedBean = fullyLoadedBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPartial() {
|
||||
for (byte flag : flags) {
|
||||
@@ -281,6 +298,16 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
return loadedFromCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadOnly(boolean readOnly) {
|
||||
this.readOnly = readOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setForceUpdate(boolean forceUpdate) {
|
||||
this.forceUpdate = forceUpdate;
|
||||
@@ -384,6 +411,25 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
return origValues[propertyIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int findProperty(String propertyName) {
|
||||
final String[] names = owner._ebean_getPropertyNames();
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
if (names[i].equals(propertyName)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String property(int propertyIndex) {
|
||||
if (propertyIndex == -1) {
|
||||
return null;
|
||||
}
|
||||
return owner._ebean_getPropertyName(propertyIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int propertyLength() {
|
||||
return flags.length;
|
||||
@@ -622,6 +668,18 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuilder loadedPropertyKey() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final int len = propertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (isLoadedProperty(i)) {
|
||||
sb.append(i).append(',');
|
||||
}
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] loaded() {
|
||||
final boolean[] ret = new boolean[flags.length];
|
||||
@@ -650,7 +708,7 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
if (database == null) {
|
||||
throw new PersistenceException(ebeanServerName == null ? "No registered default server" : "Database [" + ebeanServerName + "] is not registered");
|
||||
}
|
||||
// For stand-alone reference bean or after deserialisation lazy load
|
||||
// For stand alone reference bean or after deserialisation lazy load
|
||||
// using the ebeanServer. Synchronise only on the bean.
|
||||
loadBeanInternal(loadProperty, database.pluginApi().beanLoader());
|
||||
return;
|
||||
@@ -787,12 +845,18 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
if (state == STATE_NEW) {
|
||||
setLoadedProperty(propertyIndex);
|
||||
} else {
|
||||
if (readOnly) {
|
||||
throw new IllegalStateException("This bean is readOnly");
|
||||
}
|
||||
setChangeLoaded(propertyIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChangedPropertyValue(int propertyIndex, boolean setDirtyState, Object origValue) {
|
||||
if (readOnly) {
|
||||
throw new IllegalStateException("This bean is readOnly");
|
||||
}
|
||||
setChangedProperty(propertyIndex);
|
||||
if (setDirtyState) {
|
||||
setOriginalValue(propertyIndex, origValue);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.ebean.cache;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -10,11 +11,11 @@ import java.util.Set;
|
||||
* the query cache entry is treated as invalid.
|
||||
* </p>
|
||||
*/
|
||||
public class QueryCacheEntry {
|
||||
public final class QueryCacheEntry {
|
||||
|
||||
private final Object value;
|
||||
private final Set<String> dependentTables;
|
||||
private final long timestamp;
|
||||
private final Instant timestamp;
|
||||
|
||||
/**
|
||||
* Create with dependent tables and timestamp.
|
||||
@@ -23,7 +24,7 @@ public class QueryCacheEntry {
|
||||
* @param dependentTables The extra tables the query is dependent on (joins to)
|
||||
* @param timestamp The timestamp that the query uses to check for modifications
|
||||
*/
|
||||
public QueryCacheEntry(Object value, Set<String> dependentTables, long timestamp) {
|
||||
public QueryCacheEntry(Object value, Set<String> dependentTables, Instant timestamp) {
|
||||
this.value = value;
|
||||
this.dependentTables = dependentTables;
|
||||
this.timestamp = timestamp;
|
||||
@@ -32,21 +33,21 @@ public class QueryCacheEntry {
|
||||
/**
|
||||
* Return the actual query result.
|
||||
*/
|
||||
public Object getValue() {
|
||||
public Object value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the tables the query result is dependent on.
|
||||
*/
|
||||
public Set<String> getDependentTables() {
|
||||
public Set<String> dependentTables() {
|
||||
return dependentTables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the timestamp used to check for modifications on the dependent tables.
|
||||
*/
|
||||
public long getTimestamp() {
|
||||
public Instant timestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
private static final long serialVersionUID = 3365725236140187588L;
|
||||
|
||||
protected final ReentrantLock lock = new ReentrantLock();
|
||||
protected boolean readOnly;
|
||||
protected boolean disableLazyLoad;
|
||||
/**
|
||||
* The Database this is associated with. (used for lazy fetch).
|
||||
@@ -54,6 +55,7 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
this.ebeanServerName = loader.name();
|
||||
this.ownerBean = ownerBean;
|
||||
this.propertyName = propertyName;
|
||||
this.readOnly = ownerBean != null && ownerBean._ebean_getIntercept().isReadOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -101,6 +103,22 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
this.ebeanServerName = loader.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadOnly(boolean readOnly) {
|
||||
this.readOnly = readOnly;
|
||||
}
|
||||
|
||||
void checkReadOnly() {
|
||||
if (readOnly) {
|
||||
throw new IllegalStateException("This collection is in ReadOnly mode");
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Support for modify additions deletions etc - ManyToMany
|
||||
// ---------------------------------------------------------
|
||||
@@ -194,4 +212,14 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
return modifyHolder != null && modifyHolder.wasTouched();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all relevant properties for a clone. See {@link #shallowCopy()}
|
||||
*/
|
||||
protected void setFromOriginal(AbstractBeanCollection<E> other) {
|
||||
this.disableLazyLoad = other.disableLazyLoad;
|
||||
this.ebeanServerName = other.ebeanServerName;
|
||||
this.loader = other.loader;
|
||||
this.ownerBean = other.ownerBean;
|
||||
this.propertyName = other.propertyName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebean.common;
|
||||
|
||||
import io.ebean.bean.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@@ -38,17 +39,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
super(loader, ownerBean, propertyName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<E> freeze() {
|
||||
if (list == null) {
|
||||
return null;
|
||||
} else if (list.isEmpty()) {
|
||||
return List.of();
|
||||
} else {
|
||||
return Collections.unmodifiableList(list);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toString(ToStringBuilder builder) {
|
||||
builder.addCollection(list);
|
||||
@@ -233,6 +223,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public void add(int index, E element) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
modifyAddition(element);
|
||||
@@ -247,6 +238,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public boolean add(E bean) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
if (list.add(bean)) {
|
||||
@@ -261,6 +253,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends E> beans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
// all elements in c are added (no contains checking)
|
||||
@@ -271,6 +264,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, Collection<? extends E> beans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
// all elements in c are added (no contains checking)
|
||||
@@ -281,6 +275,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
checkReadOnly();
|
||||
// TODO: when clear() and not initialised could be more clever
|
||||
// and fetch just the Id's
|
||||
initClear();
|
||||
@@ -325,6 +320,9 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
init();
|
||||
if (readOnly) {
|
||||
return new ReadOnlyListIterator<>(list.listIterator());
|
||||
}
|
||||
if (modifyListening) {
|
||||
return new ModifyIterator<>(this, list.iterator());
|
||||
}
|
||||
@@ -340,6 +338,9 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
@Override
|
||||
public ListIterator<E> listIterator() {
|
||||
init();
|
||||
if (readOnly) {
|
||||
return new ReadOnlyListIterator<>(list.listIterator());
|
||||
}
|
||||
if (modifyListening) {
|
||||
return new ModifyListIterator<>(this, list.listIterator());
|
||||
}
|
||||
@@ -349,6 +350,9 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
@Override
|
||||
public ListIterator<E> listIterator(int index) {
|
||||
init();
|
||||
if (readOnly) {
|
||||
return new ReadOnlyListIterator<>(list.listIterator(index));
|
||||
}
|
||||
if (modifyListening) {
|
||||
return new ModifyListIterator<>(this, list.listIterator(index));
|
||||
}
|
||||
@@ -364,6 +368,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public E remove(int index) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
E o = list.remove(index);
|
||||
@@ -375,6 +380,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public boolean remove(Object bean) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
boolean isRemove = list.remove(bean);
|
||||
@@ -388,6 +394,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> beans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
boolean changed = false;
|
||||
@@ -405,6 +412,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> retainBeans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
boolean changed = false;
|
||||
@@ -425,6 +433,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public E set(int index, E element) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
E o = list.set(index, element);
|
||||
@@ -444,6 +453,9 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
@Override
|
||||
public List<E> subList(int fromIndex, int toIndex) {
|
||||
init();
|
||||
if (readOnly) {
|
||||
return Collections.unmodifiableList(list.subList(fromIndex, toIndex));
|
||||
}
|
||||
if (modifyListening) {
|
||||
return new ModifyList<>(this, list.subList(fromIndex, toIndex));
|
||||
}
|
||||
@@ -463,4 +475,67 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
return list.toArray(array);
|
||||
}
|
||||
|
||||
private static final class ReadOnlyListIterator<E> implements ListIterator<E>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 3097271091406323699L;
|
||||
|
||||
private final ListIterator<E> i;
|
||||
|
||||
ReadOnlyListIterator(ListIterator<E> i) {
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(E o) {
|
||||
throw new IllegalStateException("This collection is in ReadOnly mode");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new IllegalStateException("This collection is in ReadOnly mode");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(E o) {
|
||||
throw new IllegalStateException("This collection is in ReadOnly mode");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return i.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPrevious() {
|
||||
return i.hasPrevious();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
return i.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextIndex() {
|
||||
return i.nextIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E previous() {
|
||||
return i.previous();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int previousIndex() {
|
||||
return i.previousIndex();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollection<E> shallowCopy() {
|
||||
BeanList<E> copy = new BeanList<>(new CopyOnFirstWriteList<>(list));
|
||||
copy.setFromOriginal(this);
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,11 +37,6 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
super(ebeanServer, ownerBean, propertyName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<K, E> freeze() {
|
||||
return map == null ? null : Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toString(ToStringBuilder builder) {
|
||||
if (map == null || map.isEmpty()) {
|
||||
@@ -222,6 +217,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
checkReadOnly();
|
||||
initClear();
|
||||
if (modifyListening) {
|
||||
// add all beans to the removal list
|
||||
@@ -247,6 +243,9 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
@Override
|
||||
public Set<Entry<K, E>> entrySet() {
|
||||
init();
|
||||
if (readOnly) {
|
||||
return Collections.unmodifiableSet(map.entrySet());
|
||||
}
|
||||
return modifyListening ? new ModifyEntrySet<>(this, map.entrySet()) : map.entrySet();
|
||||
}
|
||||
|
||||
@@ -265,11 +264,15 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
init();
|
||||
if (readOnly) {
|
||||
return Collections.unmodifiableSet(map.keySet());
|
||||
}
|
||||
return modifyListening ? new ModifyKeySet<>(this, map.keySet()) : map.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E put(K key, E value) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
E oldBean = map.put(key, value);
|
||||
@@ -286,6 +289,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
|
||||
@Override
|
||||
public void putAll(Map<? extends K, ? extends E> puts) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
for (Entry<? extends K, ? extends E> entry : puts.entrySet()) {
|
||||
@@ -302,16 +306,17 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
|
||||
@Override
|
||||
public void addBean(E bean) {
|
||||
throw new UnsupportedOperationException("Method not allowed on Map. Please use List instead.");
|
||||
throw new IllegalStateException("Method not allowed on Map. Please use List instead.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeBean(E bean) {
|
||||
throw new UnsupportedOperationException("Method not allowed on Map. Please use List instead.");
|
||||
throw new IllegalStateException("Method not allowed on Map. Please use List instead.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public E remove(Object key) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
E o = map.remove(key);
|
||||
@@ -330,6 +335,16 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
@Override
|
||||
public Collection<E> values() {
|
||||
init();
|
||||
if (readOnly) {
|
||||
return Collections.unmodifiableCollection(map.values());
|
||||
}
|
||||
return modifyListening ? new ModifyCollection<>(this, map.values()) : map.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollection<E> shallowCopy() {
|
||||
BeanMap<K, E> copy = new BeanMap<>(new LinkedHashMap<>(map));
|
||||
copy.setFromOriginal(this);
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@ package io.ebean.common;
|
||||
import io.ebean.bean.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Set capable of lazy loading and modification aware.
|
||||
@@ -35,11 +38,6 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
super(loader, ownerBean, propertyName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<E> freeze() {
|
||||
return set == null ? null : Collections.unmodifiableSet(set);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toString(ToStringBuilder builder) {
|
||||
builder.addCollection(set);
|
||||
@@ -213,6 +211,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
|
||||
@Override
|
||||
public boolean add(E bean) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
if (set.add(bean)) {
|
||||
@@ -227,6 +226,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends E> beans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
boolean changed = false;
|
||||
@@ -244,6 +244,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
checkReadOnly();
|
||||
initClear();
|
||||
if (modifyListening) {
|
||||
for (E bean : set) {
|
||||
@@ -274,6 +275,9 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
init();
|
||||
if (readOnly) {
|
||||
return new ReadOnlyIterator<>(set.iterator());
|
||||
}
|
||||
if (modifyListening) {
|
||||
return new ModifyIterator<>(this, set.iterator());
|
||||
}
|
||||
@@ -282,6 +286,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
|
||||
@Override
|
||||
public boolean remove(Object bean) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
if (set.remove(bean)) {
|
||||
@@ -295,6 +300,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> beans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
boolean changed = false;
|
||||
@@ -311,6 +317,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> beans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
boolean changed = false;
|
||||
@@ -348,4 +355,36 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
return set.toArray(array);
|
||||
}
|
||||
|
||||
private static final class ReadOnlyIterator<E> implements Iterator<E>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 2577697326745352605L;
|
||||
|
||||
private final Iterator<E> it;
|
||||
|
||||
ReadOnlyIterator(Iterator<E> it) {
|
||||
this.it = it;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return it.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
return it.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new IllegalStateException("This collection is in ReadOnly mode");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollection<E> shallowCopy() {
|
||||
BeanSet<E> copy = new BeanSet<>(new LinkedHashSet<>(set));
|
||||
copy.setFromOriginal(this);
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
package io.ebean.common;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
/**
|
||||
* List that copies itself on first write access. Needed to keep memory footprint low and the ability
|
||||
* to modify lists from cache.
|
||||
*
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*/
|
||||
public final class CopyOnFirstWriteList<E> extends AbstractList<E> implements List<E>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
/**
|
||||
* The underlying List implementation.
|
||||
*/
|
||||
private List<E> list;
|
||||
|
||||
public CopyOnFirstWriteList(List<E> list) {
|
||||
super();
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
private volatile boolean copied = false;
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return list.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return list.contains(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return list.toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T[] toArray(T[] a) {
|
||||
return list.toArray(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(E e) {
|
||||
checkCopyOnWrite();
|
||||
return list.add(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
checkCopyOnWrite();
|
||||
return list.remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
return list.containsAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends E> c) {
|
||||
checkCopyOnWrite();
|
||||
return list.addAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, Collection<? extends E> c) {
|
||||
checkCopyOnWrite();
|
||||
return list.addAll(index, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
checkCopyOnWrite();
|
||||
return list.removeAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
checkCopyOnWrite();
|
||||
return list.retainAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceAll(UnaryOperator<E> operator) {
|
||||
checkCopyOnWrite();
|
||||
list.replaceAll(operator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeIf(Predicate<? super E> filter) {
|
||||
checkCopyOnWrite();
|
||||
return list.removeIf(filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(Comparator<? super E> c) {
|
||||
checkCopyOnWrite();
|
||||
list.sort(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
if (!copied) {
|
||||
list = new ArrayList<>();
|
||||
copied = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return list.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return list.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E get(int index) {
|
||||
return list.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E set(int index, E element) {
|
||||
checkCopyOnWrite();
|
||||
return list.set(index, element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int index, E element) {
|
||||
checkCopyOnWrite();
|
||||
list.add(index, element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E remove(int index) {
|
||||
checkCopyOnWrite();
|
||||
return list.remove(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(Object o) {
|
||||
return list.indexOf(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lastIndexOf(Object o) {
|
||||
return list.lastIndexOf(o);
|
||||
}
|
||||
|
||||
private void checkCopyOnWrite() {
|
||||
if (!copied) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (!copied) {
|
||||
list = new ArrayList<>(list);
|
||||
copied = true;
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -481,6 +481,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
* Time to live for query plans - defaults to 5 minutes.
|
||||
*/
|
||||
private int queryPlanTTLSeconds = 60 * 5;
|
||||
private String queryPlanExplain;
|
||||
|
||||
/**
|
||||
* Set to true to globally disable L2 caching (typically for performance testing).
|
||||
@@ -2151,6 +2152,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
queryPlanCapturePeriodSecs = p.getLong("queryPlan.capturePeriodSecs", queryPlanCapturePeriodSecs);
|
||||
queryPlanCaptureMaxTimeMillis = p.getLong("queryPlan.captureMaxTimeMillis", queryPlanCaptureMaxTimeMillis);
|
||||
queryPlanCaptureMaxCount = p.getInt("queryPlan.captureMaxCount", queryPlanCaptureMaxCount);
|
||||
queryPlanExplain = p.get("queryPlan.explain", queryPlanExplain);
|
||||
docStoreOnly = p.getBoolean("docStoreOnly", docStoreOnly);
|
||||
disableL2Cache = p.getBoolean("disableL2Cache", disableL2Cache);
|
||||
localOnlyL2Cache = p.getBoolean("localOnlyL2Cache", localOnlyL2Cache);
|
||||
@@ -2402,6 +2404,17 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
return queryPlanTTLSeconds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryPlanExplain() {
|
||||
return queryPlanExplain;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseBuilder queryPlanExplain(String queryPlanExplain) {
|
||||
this.queryPlanExplain = queryPlanExplain;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseConfig setQueryPlanTTLSeconds(int queryPlanTTLSeconds) {
|
||||
this.queryPlanTTLSeconds = queryPlanTTLSeconds;
|
||||
|
||||
@@ -172,7 +172,6 @@ public class DbPlatformType implements ExtraDbTypes {
|
||||
* </p>
|
||||
*/
|
||||
public String renderType(int deployLength, int deployScale, boolean strict) {
|
||||
|
||||
int len = deployLength != 0 ? deployLength : defaultLength;
|
||||
if (len > maxLength) {
|
||||
return fallback.renderType(deployLength, deployScale, strict);
|
||||
@@ -182,7 +181,6 @@ public class DbPlatformType implements ExtraDbTypes {
|
||||
if ((canHaveLength || !strict) && len > 0) {
|
||||
renderLengthScale(len, deployScale, sb);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
|
||||
if (newIds.isEmpty()) {
|
||||
throw new PersistenceException("Always expecting more than 1 row from " + sql);
|
||||
}
|
||||
|
||||
connection.commit();
|
||||
return newIds;
|
||||
|
||||
} catch (SQLException e) {
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
package io.ebean.meta;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* Initiate query plan collection for plans by their hash or all query plans.
|
||||
*/
|
||||
public class QueryPlanInit {
|
||||
|
||||
private final Map<String,Long> hashes = new HashMap<>();
|
||||
|
||||
private boolean all;
|
||||
|
||||
private Set<String> hashes = new HashSet<>();
|
||||
|
||||
private long thresholdMicros;
|
||||
private long defaultThresholdMicros;
|
||||
|
||||
/**
|
||||
* Return true if this initiates bind collection on all query plans.
|
||||
@@ -29,39 +30,74 @@ public class QueryPlanInit {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the query execution time threshold which must be exceeded to initiate
|
||||
* Return the default query execution time threshold which must be exceeded to initiate
|
||||
* query plan collection.
|
||||
*/
|
||||
public long thresholdMicros() {
|
||||
return thresholdMicros;
|
||||
return defaultThresholdMicros;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the query execution time threshold which must be exceeded to initiate
|
||||
* Set the default query execution time threshold which must be exceeded to initiate
|
||||
* query plan collection.
|
||||
*/
|
||||
public void thresholdMicros(long thresholdMicros) {
|
||||
this.thresholdMicros = thresholdMicros;
|
||||
this.defaultThresholdMicros = thresholdMicros;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the query plan should be initiated based on it's hash.
|
||||
*/
|
||||
public boolean includeHash(String hash) {
|
||||
return all || hashes.contains(hash);
|
||||
return all || hashes.containsKey(hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the specific hashes that we want to collect query plans on.
|
||||
*
|
||||
* @param hash The hash of the query plan.
|
||||
* @param thresholdMicros The threshold in micros to use.
|
||||
*/
|
||||
public Set<String> hashes() {
|
||||
return hashes;
|
||||
public void add(String hash, long thresholdMicros) {
|
||||
requireNonNull(hash);
|
||||
if (!"all".equals(hash)) {
|
||||
hashes.put(hash, thresholdMicros);
|
||||
} else {
|
||||
all = true;
|
||||
if (thresholdMicros > 0) {
|
||||
defaultThresholdMicros = thresholdMicros;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the specific hashes that we want to collect query plans on.
|
||||
* Remove a hash from this request.
|
||||
*/
|
||||
public void hashes(Set<String> hashes) {
|
||||
this.hashes = hashes;
|
||||
public void remove(String hash) {
|
||||
hashes.remove(hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the threshold in micros to use for the given hash.
|
||||
*/
|
||||
public long thresholdMicros(String hash) {
|
||||
Long threshold = hashes.get(hash);
|
||||
return threshold == null || threshold < 1 ? defaultThresholdMicros : threshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if there are no registered hashes and not collect <em>All</em> plans.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return !all && hashes.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "QueryPlanInit{" +
|
||||
"all=" + all +
|
||||
", hashes=" + hashes +
|
||||
", thresholdMicros=" + defaultThresholdMicros +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ class DatabaseConfigTest {
|
||||
props.setProperty("queryPlan.capturePeriodSecs", "42");
|
||||
props.setProperty("queryPlan.captureMaxTimeMillis", "560");
|
||||
props.setProperty("queryPlan.captureMaxCount", "7");
|
||||
props.setProperty("queryPlan.explain", "explain (verbose)");
|
||||
|
||||
config.loadFromProperties(props);
|
||||
|
||||
@@ -129,15 +130,18 @@ class DatabaseConfigTest {
|
||||
assertEquals(42, settings.getQueryPlanCapturePeriodSecs());
|
||||
assertEquals(560, settings.getQueryPlanCaptureMaxTimeMillis());
|
||||
assertEquals(7, settings.getQueryPlanCaptureMaxCount());
|
||||
assertEquals("explain (verbose)", settings.getQueryPlanExplain());
|
||||
|
||||
assertThat(settings.getMappingLocations()).containsExactly("classpath:/foo","bar");
|
||||
|
||||
config.persistBatch(PersistBatch.NONE)
|
||||
.persistBatchOnCascade(PersistBatch.NONE)
|
||||
.lengthCheck(LengthCheck.ON)
|
||||
.lengthCheck(LengthCheck.UTF8);
|
||||
.lengthCheck(LengthCheck.UTF8)
|
||||
.queryPlanExplain("explain (buffers)");
|
||||
|
||||
|
||||
assertThat(config.settings().getQueryPlanExplain()).isEqualTo("explain (buffers)");
|
||||
Properties props1 = new Properties();
|
||||
props1.setProperty("ebean.persistBatch", "ALL");
|
||||
props1.setProperty("ebean.persistBatchOnCascade", "ALL");
|
||||
@@ -182,6 +186,7 @@ class DatabaseConfigTest {
|
||||
assertEquals(600, config.getQueryPlanCapturePeriodSecs());
|
||||
assertEquals(10000L, config.getQueryPlanCaptureMaxTimeMillis());
|
||||
assertEquals(10, config.getQueryPlanCaptureMaxCount());
|
||||
assertThat(config.getQueryPlanExplain()).isNull();
|
||||
assertThat(config.getLengthCheck()).isEqualTo(LengthCheck.OFF);
|
||||
assertTrue(config.isIncludeLabelInSql());
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package io.ebean.meta;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class QueryPlanInitTest {
|
||||
|
||||
@Test
|
||||
void initialQueryPlanInit() {
|
||||
var init = new QueryPlanInit();
|
||||
assertThat(init.isEmpty()).isTrue();
|
||||
assertThat(init.isAll()).isFalse();
|
||||
assertThat(init.thresholdMicros()).isEqualTo(0L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void add_all() {
|
||||
var init = new QueryPlanInit();
|
||||
init.add("all", 57L);
|
||||
|
||||
assertThat(init.isEmpty()).isFalse();
|
||||
assertThat(init.isAll()).isTrue();
|
||||
assertThat(init.thresholdMicros()).isEqualTo(57L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void addWithThresholds() {
|
||||
var init = new QueryPlanInit();
|
||||
init.thresholdMicros(1000);
|
||||
init.add("xOne", 0);
|
||||
init.add("xTwo", 2000L);
|
||||
|
||||
assertThat(init.isEmpty()).isFalse();
|
||||
assertThat(init.isAll()).isFalse();
|
||||
assertThat(init.includeHash("xJunk")).isFalse();
|
||||
assertThat(init.includeHash("xOne")).isTrue();
|
||||
assertThat(init.includeHash("xTwo")).isTrue();
|
||||
assertThat(init.thresholdMicros("xJunk")).isEqualTo(1000L);
|
||||
assertThat(init.thresholdMicros("xOne")).isEqualTo(1000L);
|
||||
assertThat(init.thresholdMicros("xTwo")).isEqualTo(2000L);
|
||||
}
|
||||
}
|
||||
+26
-26
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean bom</name>
|
||||
@@ -89,25 +89,25 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -125,13 +125,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-mapper</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -155,37 +155,37 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>kotlin-querybean-generator</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-redis</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-spring-txn</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- platforms -->
|
||||
@@ -193,79 +193,79 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-clickhouse</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-db2</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-h2</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-hana</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-mariadb</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-mysql</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-nuodb</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-oracle</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgres</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis-types</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-sqlite</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-sqlserver</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
@@ -16,7 +16,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -7,8 +7,6 @@ import java.sql.SQLException;
|
||||
|
||||
public interface DataReader {
|
||||
|
||||
boolean unmodifiable();
|
||||
|
||||
void close() throws SQLException;
|
||||
|
||||
boolean next() throws SQLException;
|
||||
|
||||
+6
-6
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core</artifactId>
|
||||
@@ -22,7 +22,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -46,7 +46,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -159,21 +159,21 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlserver</artifactId>
|
||||
<version>14.9.0</version>
|
||||
<version>14.11.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -55,9 +55,4 @@ public interface LoadContext {
|
||||
* Use soft-references for streaming queries, so unreachable entries can be garbage collected.
|
||||
*/
|
||||
void useReferences(boolean useReferences);
|
||||
|
||||
/**
|
||||
* Return true to include a many as a secondary query for unmodified.
|
||||
*/
|
||||
boolean includeSecondary(BeanPropertyAssocMany<?> many);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import java.util.stream.Stream;
|
||||
/**
|
||||
* Service Provider extension to EbeanServer.
|
||||
*/
|
||||
public interface SpiEbeanServer extends SpiServer, ExtendedServer, BeanCollectionLoader {
|
||||
public interface SpiEbeanServer extends SpiServer, BeanCollectionLoader {
|
||||
|
||||
/**
|
||||
* Return the NOW time from the Clock.
|
||||
@@ -348,6 +348,8 @@ public interface SpiEbeanServer extends SpiServer, ExtendedServer, BeanCollectio
|
||||
|
||||
<T> FutureList<T> findFutureList(SpiQuery<T> query);
|
||||
|
||||
<K, T> FutureMap<K, T> findFutureMap(SpiQuery<T> query);
|
||||
|
||||
<T> PagedList<T> findPagedList(SpiQuery<T> query);
|
||||
|
||||
<T> Set<T> findSet(SpiQuery<T> query);
|
||||
|
||||
@@ -780,9 +780,9 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
|
||||
CacheMode queryCacheMode();
|
||||
|
||||
/**
|
||||
* Return true if the beans returned by this query should be unmodifiable.
|
||||
* Return true if the beans returned by this query should be read only.
|
||||
*/
|
||||
boolean isUnmodifiable();
|
||||
Boolean isReadOnly();
|
||||
|
||||
/**
|
||||
* Return the query timeout.
|
||||
|
||||
@@ -14,6 +14,7 @@ import io.ebeanservice.docstore.api.DocStoreTransaction;
|
||||
import jakarta.persistence.PersistenceException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.time.Instant;
|
||||
|
||||
/**
|
||||
* Extends Transaction with additional API required on server.
|
||||
@@ -95,7 +96,7 @@ public interface SpiTransaction extends Transaction {
|
||||
/**
|
||||
* Return the start timestamp for the transaction (JVM side).
|
||||
*/
|
||||
long startNanoTime();
|
||||
Instant startTime();
|
||||
|
||||
/**
|
||||
* Return true if this transaction has updateAllLoadedProperties set.
|
||||
|
||||
@@ -14,6 +14,7 @@ import io.ebeanservice.docstore.api.DocStoreTransaction;
|
||||
import jakarta.persistence.PersistenceException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.time.Instant;
|
||||
|
||||
/**
|
||||
* Proxy for an underlying SpiTransaction (most of the API).
|
||||
@@ -28,8 +29,8 @@ public abstract class SpiTransactionProxy implements SpiTransaction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long startNanoTime() {
|
||||
return transaction.startNanoTime();
|
||||
public Instant startTime() {
|
||||
return transaction.startTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,7 +3,12 @@ package io.ebeaninternal.json;
|
||||
import io.ebean.ModifyAwareType;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Modify aware wrapper of a list.
|
||||
@@ -47,11 +52,6 @@ public final class ModifyAwareList<E> implements List<E>, ModifyAwareType, Seria
|
||||
return list.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<E> freeze() {
|
||||
return Collections.unmodifiableList(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMarkedDirty() {
|
||||
return owner.isMarkedDirty();
|
||||
|
||||
@@ -3,7 +3,11 @@ package io.ebeaninternal.json;
|
||||
import io.ebean.ModifyAwareType;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Map that is wraps an underlying map for the purpose of detecting changes.
|
||||
@@ -47,11 +51,6 @@ public final class ModifyAwareMap<K, V> implements Map<K, V>, ModifyAwareType, S
|
||||
return map.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<K, V> freeze() {
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMarkedDirty() {
|
||||
return owner.isMarkedDirty();
|
||||
|
||||
@@ -3,7 +3,10 @@ package io.ebeaninternal.json;
|
||||
import io.ebean.ModifyAwareType;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Wraps a Set for the purposes of detecting modifications.
|
||||
@@ -30,11 +33,6 @@ public final class ModifyAwareSet<E> implements Set<E>, ModifyAwareType, Seriali
|
||||
this.set = underlying;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<E> freeze() {
|
||||
return Collections.unmodifiableSet(set);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMarkedDirty() {
|
||||
return owner.isMarkedDirty();
|
||||
|
||||
+10
-7
@@ -2,7 +2,6 @@ package io.ebeaninternal.server.cache;
|
||||
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
import io.ebean.bean.InterceptReadOnly;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
@@ -49,21 +48,25 @@ public final class CachedBeanDataFromBean {
|
||||
if (!desc.isCacheSharableBeans() || !beanEbi.isFullyLoadedBean()) {
|
||||
return null;
|
||||
}
|
||||
if (beanEbi instanceof InterceptReadOnly) {
|
||||
if (beanEbi.isReadOnly()) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
// create a readOnly sharable instance by copying the data
|
||||
EntityBean sharableBean = desc.createEntityBean2(true);
|
||||
EntityBean sharableBean = desc.createEntityBean();
|
||||
BeanProperty idProp = desc.idProperty();
|
||||
if (idProp != null) {
|
||||
Object v = idProp.getValue(bean);
|
||||
idProp.setValue(sharableBean, v);
|
||||
}
|
||||
for (BeanProperty nonTransient : desc.propertiesNonTransient()) {
|
||||
Object v = nonTransient.getValue(bean);
|
||||
nonTransient.setValue(sharableBean, v);
|
||||
BeanProperty[] propertiesNonTransient = desc.propertiesNonTransient();
|
||||
for (BeanProperty aPropertiesNonTransient : propertiesNonTransient) {
|
||||
Object v = aPropertiesNonTransient.getValue(bean);
|
||||
aPropertiesNonTransient.setValue(sharableBean, v);
|
||||
}
|
||||
desc.freeze(sharableBean);
|
||||
EntityBeanIntercept intercept = sharableBean._ebean_getIntercept();
|
||||
intercept.setReadOnly(true);
|
||||
intercept.setLoaded();
|
||||
return sharableBean;
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -1,6 +1,8 @@
|
||||
package io.ebeaninternal.server.cache;
|
||||
|
||||
import io.ebean.bean.*;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
@@ -23,11 +25,10 @@ public final class CachedBeanDataToBean {
|
||||
for (BeanProperty prop : desc.propertiesNonMany()) {
|
||||
loadProperty(bean, cacheBeanData, ebi, prop, context);
|
||||
}
|
||||
final boolean addManyReferences = ebi instanceof InterceptReadWrite;
|
||||
for (BeanPropertyAssocMany<?> prop : desc.propertiesMany()) {
|
||||
if (prop.isElementCollection()) {
|
||||
loadProperty(bean, cacheBeanData, ebi, prop, context);
|
||||
} else if (addManyReferences) {
|
||||
} else {
|
||||
prop.createReferenceIfNull(bean);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ public class DefaultServerQueryCache extends DefaultServerCache {
|
||||
|
||||
@Override
|
||||
protected Object unwrapEntry(CacheEntry entry) {
|
||||
return ((QueryCacheEntry) entry.getValue()).getValue();
|
||||
return ((QueryCacheEntry) entry.getValue()).value();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import java.time.Clock;
|
||||
|
||||
/**
|
||||
* Wraps the Clock such that we can change the Clock for testing purposes.
|
||||
*/
|
||||
public class ClockService {
|
||||
|
||||
private Clock clock;
|
||||
|
||||
public ClockService(Clock clock) {
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the clock for testing purposes.
|
||||
*/
|
||||
public void setClock(Clock clock) {
|
||||
this.clock = clock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Clock current timestamp in millis.
|
||||
*/
|
||||
public long nowMillis() {
|
||||
return clock.millis();
|
||||
}
|
||||
}
|
||||
@@ -77,7 +77,12 @@ public class DatabasePlatformFactory {
|
||||
*/
|
||||
private DatabasePlatform byDataSource(DataSource dataSource) {
|
||||
try (Connection connection = dataSource.getConnection()) {
|
||||
return byDatabaseMeta(connection.getMetaData(), connection);
|
||||
DatabasePlatform platform = byDatabaseMeta(connection.getMetaData(), connection);
|
||||
if (!connection.getAutoCommit()) {
|
||||
// we must roll back before close.
|
||||
connection.rollback();
|
||||
}
|
||||
return platform;
|
||||
} catch (SQLException ex) {
|
||||
throw new PersistenceException(ex);
|
||||
}
|
||||
|
||||
@@ -67,8 +67,12 @@ final class DefaultBeanLoader {
|
||||
parentDesc.contextPutIfAbsent(pc, parentId, parentBean);
|
||||
boolean useManyIdCache = beanCollection != null && parentDesc.isManyPropCaching() && many.isUseCache();
|
||||
if (useManyIdCache) {
|
||||
Boolean readOnly = null;
|
||||
if (ebi.isReadOnly()) {
|
||||
readOnly = Boolean.TRUE;
|
||||
}
|
||||
final String parentKey = parentDesc.cacheKey(parentId);
|
||||
if (parentDesc.cacheManyPropLoad(many, beanCollection, parentKey)) {
|
||||
if (parentDesc.cacheManyPropLoad(many, beanCollection, parentKey, readOnly)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -98,6 +102,9 @@ final class DefaultBeanLoader {
|
||||
query.setMode(Mode.LAZYLOAD_MANY);
|
||||
query.setLazyLoadManyPath(many.name());
|
||||
query.setPersistenceContext(pc);
|
||||
if (ebi.isReadOnly()) {
|
||||
query.setReadOnly(true);
|
||||
}
|
||||
if (many.hasOrderColumn()) {
|
||||
query.orderBy(many.path() + "." + many.fetchOrderBy());
|
||||
}
|
||||
@@ -205,6 +212,9 @@ final class DefaultBeanLoader {
|
||||
// make sure the query doesn't use the cache
|
||||
query.setBeanCacheMode(CacheMode.OFF);
|
||||
}
|
||||
if (ebi.isReadOnly()) {
|
||||
query.setReadOnly(true);
|
||||
}
|
||||
if (Mode.REFRESH_BEAN == mode) {
|
||||
// explicitly state to load all properties on REFRESH.
|
||||
// Lobs default to fetch lazy so this forces lobs to be
|
||||
|
||||
@@ -4,7 +4,6 @@ import io.ebean.BeanState;
|
||||
import io.ebean.ValuePair;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
import io.ebean.bean.InterceptReadOnly;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -61,8 +60,13 @@ public final class DefaultBeanState implements BeanState {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUnmodifiable() {
|
||||
return intercept instanceof InterceptReadOnly;
|
||||
public boolean isReadOnly() {
|
||||
return intercept.isReadOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadOnly(boolean readOnly) {
|
||||
intercept.setReadOnly(readOnly);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -262,6 +262,8 @@ public final class DefaultContainer implements SpiContainer {
|
||||
try (Connection connection = config.getDataSource().getConnection()) {
|
||||
if (connection.getAutoCommit()) {
|
||||
log.log(WARNING, "DataSource [{0}] has autoCommit defaulting to true!", config.getName());
|
||||
} else {
|
||||
connection.rollback();
|
||||
}
|
||||
return true;
|
||||
} catch (SQLException ex) {
|
||||
|
||||
@@ -8,6 +8,7 @@ import io.ebean.annotation.TxIsolation;
|
||||
import io.ebean.bean.*;
|
||||
import io.ebean.bean.PersistenceContext.WithOption;
|
||||
import io.ebean.cache.ServerCacheManager;
|
||||
import io.ebean.common.CopyOnFirstWriteList;
|
||||
import io.ebean.config.*;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.event.BeanPersistController;
|
||||
@@ -82,7 +83,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
private final QueryPlanManager queryPlanManager;
|
||||
private final ExtraMetrics extraMetrics;
|
||||
private final DataTimeZone dataTimeZone;
|
||||
private final ClockService clockService;
|
||||
private final Clock clock;
|
||||
private final CallOriginFactory callStackFactory;
|
||||
private final Persister persister;
|
||||
private final OrmQueryEngine queryEngine;
|
||||
@@ -150,7 +151,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
this.beanLoader = new DefaultBeanLoader(this);
|
||||
this.jsonContext = config.createJsonContext(this);
|
||||
this.dataTimeZone = config.getDataTimeZone();
|
||||
this.clockService = config.getClockService();
|
||||
this.clock = config.clock();
|
||||
|
||||
DocStoreIntegration docStoreComponents = config.createDocStoreIntegration(this);
|
||||
this.transactionManager = config.createTransactionManager(this, docStoreComponents.updateProcessor());
|
||||
@@ -412,19 +413,9 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
return serverName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedServer extended() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long clockNow() {
|
||||
return clockService.nowMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClock(Clock clock) {
|
||||
this.clockService.setClock(clock);
|
||||
return clock.millis();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -619,7 +610,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
InheritInfo inheritInfo = desc.inheritInfo();
|
||||
if (inheritInfo == null || inheritInfo.isConcrete()) {
|
||||
return (T) desc.contextRef(pc, id);
|
||||
return (T) desc.contextRef(pc, null, false, id);
|
||||
}
|
||||
return referenceFindOne(type, id, desc);
|
||||
}
|
||||
@@ -1003,7 +994,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
return null;
|
||||
}
|
||||
// Hit the L2 bean cache
|
||||
return desc.cacheBeanGet(id, query.isUnmodifiable(), pc);
|
||||
return desc.cacheBeanGet(id, query.isReadOnly(), pc);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1214,7 +1205,11 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
SpiOrmQueryRequest<?> request = createQueryRequest(Type.ID_LIST, query);
|
||||
Object result = request.getFromQueryCache();
|
||||
if (result != null) {
|
||||
return (List<A>) result;
|
||||
if (Boolean.FALSE.equals(request.query().isReadOnly())) {
|
||||
return new CopyOnFirstWriteList<>((List<A>) result);
|
||||
} else {
|
||||
return (List<A>) result;
|
||||
}
|
||||
}
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
@@ -1259,66 +1254,55 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
}
|
||||
|
||||
private <T> SpiQuery<T> configureForFuture(SpiQuery<T> query) {
|
||||
query.usingFuture();
|
||||
if (query.transaction() == null) {
|
||||
// use a current transaction if active
|
||||
query.usingTransaction(currentServerTransaction());
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> FutureRowCount<T> findFutureCount(SpiQuery<T> query) {
|
||||
SpiQuery<T> copy = query.copy();
|
||||
copy.usingFuture();
|
||||
boolean createdTransaction = false;
|
||||
SpiTransaction transaction = query.transaction();
|
||||
if (transaction == null) {
|
||||
transaction = currentServerTransaction();
|
||||
if (transaction == null) {
|
||||
transaction = (SpiTransaction) createTransaction();
|
||||
createdTransaction = true;
|
||||
}
|
||||
copy.usingTransaction(transaction);
|
||||
}
|
||||
var queryFuture = new QueryFutureRowCount<>(new CallableQueryCount<>(this, copy, createdTransaction));
|
||||
SpiQuery<T> copy = configureForFuture(query.copy());
|
||||
var queryFuture = new QueryFutureRowCount<>(new CallableQueryCount<>(this, copy));
|
||||
backgroundExecutor.execute(queryFuture.futureTask());
|
||||
return queryFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> FutureIds<T> findFutureIds(SpiQuery<T> query) {
|
||||
SpiQuery<T> copy = query.copy();
|
||||
copy.usingFuture();
|
||||
boolean createdTransaction = false;
|
||||
SpiTransaction transaction = query.transaction();
|
||||
if (transaction == null) {
|
||||
transaction = currentServerTransaction();
|
||||
if (transaction == null) {
|
||||
transaction = (SpiTransaction) createTransaction();
|
||||
createdTransaction = true;
|
||||
}
|
||||
copy.usingTransaction(transaction);
|
||||
}
|
||||
QueryFutureIds<T> queryFuture = new QueryFutureIds<>(new CallableQueryIds<>(this, copy, createdTransaction));
|
||||
SpiQuery<T> copy = configureForFuture(query.copy());
|
||||
final var queryFuture = new QueryFutureIds<T>(new CallableQueryIds<>(this, copy));
|
||||
backgroundExecutor.execute(queryFuture.futureTask());
|
||||
return queryFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> FutureList<T> findFutureList(SpiQuery<T> query) {
|
||||
SpiQuery<T> spiQuery = query.copy();
|
||||
spiQuery.usingFuture();
|
||||
// FutureList query always run in it's own persistence content
|
||||
SpiQuery<T> spiQuery = configureForFuture(query.copy());
|
||||
// FutureList query always run in its own persistence content
|
||||
spiQuery.setPersistenceContext(new DefaultPersistenceContext());
|
||||
if (!spiQuery.isDisableReadAudit()) {
|
||||
BeanDescriptor<T> desc = descriptorManager.descriptor(spiQuery.getBeanType());
|
||||
desc.readAuditFutureList(spiQuery);
|
||||
}
|
||||
// Create a new transaction solely to execute the findList() at some future time
|
||||
boolean createdTransaction = false;
|
||||
SpiTransaction transaction = query.transaction();
|
||||
if (transaction == null) {
|
||||
transaction = currentServerTransaction();
|
||||
if (transaction == null) {
|
||||
transaction = (SpiTransaction) createTransaction();
|
||||
createdTransaction = true;
|
||||
}
|
||||
spiQuery.usingTransaction(transaction);
|
||||
final var queryFuture = new QueryFutureList<T>(new CallableQueryList<>(this, spiQuery));
|
||||
backgroundExecutor.execute(queryFuture.futureTask());
|
||||
return queryFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K, T> FutureMap<K, T> findFutureMap(SpiQuery<T> query) {
|
||||
SpiQuery<T> spiQuery = configureForFuture(query.copy());
|
||||
// FutureMap query always run in it's own persistence content
|
||||
spiQuery.setPersistenceContext(new DefaultPersistenceContext());
|
||||
if (!spiQuery.isDisableReadAudit()) {
|
||||
BeanDescriptor<T> desc = descriptorManager.descriptor(spiQuery.getBeanType());
|
||||
desc.readAuditFutureList(spiQuery);
|
||||
}
|
||||
QueryFutureList<T> queryFuture = new QueryFutureList<>(new CallableQueryList<>(this, spiQuery, createdTransaction));
|
||||
final var queryFuture = new QueryFutureMap<K, T>(new CallableQueryMap<>(this, spiQuery));
|
||||
backgroundExecutor.execute(queryFuture.futureTask());
|
||||
return queryFuture;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ public final class DtoQueryRequest<T> extends AbstractSqlQueryRequest {
|
||||
@Override
|
||||
protected void setResultSet(ResultSet resultSet, Object queryPlanKey) throws SQLException {
|
||||
this.resultSet = resultSet;
|
||||
this.dataReader = new RsetDataReader(false, server.dataTimeZone(), resultSet);
|
||||
this.dataReader = new RsetDataReader(server.dataTimeZone(), resultSet);
|
||||
obtainPlan(queryPlanKey);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ import io.ebeanservice.docstore.api.DocStoreIntegration;
|
||||
import io.ebeanservice.docstore.api.DocStoreUpdateProcessor;
|
||||
import io.ebeanservice.docstore.none.NoneDocStoreFactory;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.util.*;
|
||||
|
||||
import static java.lang.System.Logger.Level.*;
|
||||
@@ -75,7 +76,7 @@ public final class InternalConfiguration {
|
||||
private final DeployInherit deployInherit;
|
||||
private final TypeManager typeManager;
|
||||
private final DtoBeanManager dtoBeanManager;
|
||||
private final ClockService clockService;
|
||||
private final Clock clock;
|
||||
private final DataTimeZone dataTimeZone;
|
||||
private final Binder binder;
|
||||
private final DeployCreateProperties deployCreateProperties;
|
||||
@@ -103,7 +104,7 @@ public final class InternalConfiguration {
|
||||
this.online = online;
|
||||
this.config = config;
|
||||
this.jacksonCorePresent = config.getClassLoadConfig().isJacksonCorePresent();
|
||||
this.clockService = new ClockService(config.settings().getClock());
|
||||
this.clock = config.settings().getClock();
|
||||
this.tableModState = new TableModState();
|
||||
this.logManager = initLogManager();
|
||||
this.docStoreFactory = initDocStoreFactory(service(DocStoreFactory.class));
|
||||
@@ -189,8 +190,8 @@ public final class InternalConfiguration {
|
||||
return docStoreFactory;
|
||||
}
|
||||
|
||||
ClockService getClockService() {
|
||||
return clockService;
|
||||
Clock clock() {
|
||||
return clock;
|
||||
}
|
||||
|
||||
public ExtraMetrics getExtraMetrics() {
|
||||
@@ -391,7 +392,7 @@ public final class InternalConfiguration {
|
||||
TransactionManagerOptions options =
|
||||
new TransactionManagerOptions(server, notifyL2CacheInForeground, config, scopeManager, clusterManager, backgroundExecutor,
|
||||
indexUpdateProcessor, beanDescriptorManager, dataSource(), profileHandler(), logManager,
|
||||
tableModState, cacheNotify, clockService);
|
||||
tableModState, cacheNotify);
|
||||
|
||||
if (config.isDocStoreOnly()) {
|
||||
return new DocStoreTransactionManager(options);
|
||||
@@ -584,27 +585,32 @@ public final class InternalConfiguration {
|
||||
return QueryPlanManager.NOOP;
|
||||
}
|
||||
long threshold = config.getQueryPlanThresholdMicros();
|
||||
return new CQueryPlanManager(transactionManager, threshold, queryPlanLogger(databasePlatform.platform()), extraMetrics);
|
||||
return new CQueryPlanManager(transactionManager, threshold, queryPlanLogger(databasePlatform.platform(), config), extraMetrics);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the logger to log query plans for the given platform.
|
||||
*/
|
||||
QueryPlanLogger queryPlanLogger(Platform platform) {
|
||||
QueryPlanLogger queryPlanLogger(Platform platform, DatabaseBuilder.Settings config) {
|
||||
switch (platform.base()) {
|
||||
case SQLSERVER:
|
||||
return new QueryPlanLoggerSqlServer();
|
||||
case ORACLE:
|
||||
return new QueryPlanLoggerOracle();
|
||||
case POSTGRES:
|
||||
return new QueryPlanLoggerExplain("explain (analyze, buffers) ");
|
||||
return new QueryPlanLoggerExplain(explain(config, "explain (analyze, costs, verbose, buffers) "));
|
||||
case YUGABYTE:
|
||||
return new QueryPlanLoggerExplain("explain (analyze, buffers, dist) ");
|
||||
return new QueryPlanLoggerExplain(explain(config,"explain (analyze, buffers, dist) "));
|
||||
default:
|
||||
return new QueryPlanLoggerExplain("explain ");
|
||||
return new QueryPlanLoggerExplain(explain(config,"explain "));
|
||||
}
|
||||
}
|
||||
|
||||
private static String explain(DatabaseBuilder.Settings config, String defaultExplain) {
|
||||
String explain = config.getQueryPlanExplain();
|
||||
return explain == null ? defaultExplain : explain + ' ';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DDL generator.
|
||||
*/
|
||||
|
||||
@@ -25,9 +25,9 @@ public interface OrmQueryEngine {
|
||||
<T> T findId(OrmQueryRequest<T> request);
|
||||
|
||||
/**
|
||||
* Execute the findList, findSet, findMap query returning an appropriate Collection.
|
||||
* Execute the findList, findSet, findMap query returning an appropriate BeanCollection.
|
||||
*/
|
||||
<T> Object findMany(OrmQueryRequest<T> request);
|
||||
<T> BeanCollection<T> findMany(OrmQueryRequest<T> request);
|
||||
|
||||
/**
|
||||
* Execute the findSingleAttributeCollection query.
|
||||
|
||||
@@ -2,11 +2,11 @@ package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebean.*;
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebean.cache.QueryCacheEntry;
|
||||
import io.ebean.common.BeanList;
|
||||
import io.ebean.common.BeanMap;
|
||||
import io.ebean.common.CopyOnFirstWriteList;
|
||||
import io.ebean.event.BeanFindController;
|
||||
import io.ebean.event.BeanQueryAdapter;
|
||||
import io.ebean.text.json.JsonReadOptions;
|
||||
@@ -546,7 +546,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
if (orderBy != null && !orderBy.isEmpty()) {
|
||||
beanDescriptor.sort(cacheBeans, orderBy.toStringFormat());
|
||||
}
|
||||
return query.isUnmodifiable() ? Collections.unmodifiableList(cacheBeans) : cacheBeans;
|
||||
return cacheBeans;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -565,7 +565,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
for (T bean : cacheBeans) {
|
||||
map.put((K) property.pathGet(bean), bean);
|
||||
}
|
||||
return query.isUnmodifiable() ? Collections.unmodifiableMap(map) : map;
|
||||
return map;
|
||||
}
|
||||
|
||||
private ElPropertyValue mapProperty() {
|
||||
@@ -583,8 +583,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
if (orderBy != null && !orderBy.isEmpty()) {
|
||||
beanDescriptor.sort(cacheBeans, orderBy.toStringFormat());
|
||||
}
|
||||
var set = new LinkedHashSet<>(cacheBeans);
|
||||
return query.isUnmodifiable() ? Collections.unmodifiableSet(set) : set;
|
||||
return new LinkedHashSet<>(cacheBeans);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -601,12 +600,9 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
//
|
||||
CacheIdLookup<T> idLookup = query.cacheIdLookup();
|
||||
if (idLookup != null) {
|
||||
BeanCacheResult<T> cacheResult = beanDescriptor.cacheIdLookup(persistenceContext, query.isUnmodifiable(), idLookup.idValues());
|
||||
BeanCacheResult<T> cacheResult = beanDescriptor.cacheIdLookup(persistenceContext, idLookup.idValues());
|
||||
// adjust the query (IN clause) based on the cache hits
|
||||
this.cacheBeans = idLookup.removeHits(cacheResult);
|
||||
if (query.isUnmodifiable()) {
|
||||
unmodifiableFreeze(cacheBeans);
|
||||
}
|
||||
return idLookup.allHits();
|
||||
}
|
||||
if (!beanDescriptor.isNaturalKeyCaching()) {
|
||||
@@ -617,7 +613,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
NaturalKeySet naturalKeySet = data.buildKeys();
|
||||
if (naturalKeySet != null) {
|
||||
// use the natural keys to lookup Ids to then hit the bean cache
|
||||
BeanCacheResult<T> cacheResult = beanDescriptor.naturalKeyLookup(persistenceContext, query.isUnmodifiable(), naturalKeySet.keys());
|
||||
BeanCacheResult<T> cacheResult = beanDescriptor.naturalKeyLookup(persistenceContext, naturalKeySet.keys());
|
||||
// adjust the query (IN clause) based on the cache hits
|
||||
this.cacheBeans = data.removeHits(cacheResult);
|
||||
return data.allHits();
|
||||
@@ -643,7 +639,31 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
return null;
|
||||
}
|
||||
|
||||
return beanDescriptor.queryCacheGet(cacheKey);
|
||||
Object cached = beanDescriptor.queryCacheGet(cacheKey);
|
||||
if (cached != null && isAuditReads() && readAuditQueryType()) {
|
||||
if (cached instanceof BeanCollection) {
|
||||
// raw sql can't use L2 cache so normal queries only in here
|
||||
Collection<T> actualDetails = ((BeanCollection<T>) cached).actualDetails();
|
||||
List<Object> ids = new ArrayList<>(actualDetails.size());
|
||||
for (T bean : actualDetails) {
|
||||
ids.add(beanDescriptor.idForJson(bean));
|
||||
}
|
||||
beanDescriptor.readAuditMany(queryPlanKey.partialKey(), "l2-query-cache", ids);
|
||||
}
|
||||
}
|
||||
if (Boolean.FALSE.equals(query.isReadOnly())) {
|
||||
// return shallow copies if readonly is explicitly set to false
|
||||
if (cached instanceof BeanCollection) {
|
||||
cached = ((BeanCollection<?>) cached).shallowCopy();
|
||||
} else if (cached instanceof List) {
|
||||
cached = new CopyOnFirstWriteList<>((List<?>) cached);
|
||||
} else if (cached instanceof Set) {
|
||||
cached = new LinkedHashSet<>((Set<?>) cached);
|
||||
} else if (cached instanceof Map) {
|
||||
cached = new LinkedHashMap<>((Map<?, ?>) cached);
|
||||
}
|
||||
}
|
||||
return cached;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -665,7 +685,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
}
|
||||
|
||||
public void putToQueryCache(Object result) {
|
||||
beanDescriptor.queryCachePut(cacheKey, new QueryCacheEntry(result, dependentTables, transaction.startNanoTime()));
|
||||
beanDescriptor.queryCachePut(cacheKey, new QueryCacheEntry(result, dependentTables, transaction.startTime()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -760,30 +780,4 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
beanDescriptor.contextClear(transaction.persistenceContext());
|
||||
}
|
||||
}
|
||||
|
||||
public void unmodifiableFreeze(Collection<T> beans) {
|
||||
if (query.isUnmodifiable()) {
|
||||
if (beans != null) {
|
||||
for (T bean : beans) {
|
||||
beanDescriptor.freeze((EntityBean) bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void unmodifiableFreeze(BeanCollection<T> beanCollection) {
|
||||
if (query.isUnmodifiable()) {
|
||||
if (beanCollection != null) {
|
||||
for (T bean : beanCollection.actualDetails()) {
|
||||
beanDescriptor.freeze((EntityBean) bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void unmodifiableFreeze(EntityBean bean) {
|
||||
if (query.isUnmodifiable() && bean != null) {
|
||||
beanDescriptor.freeze(bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.sql.SQLException;
|
||||
abstract class AssocOneHelp {
|
||||
|
||||
final BeanPropertyAssocOne<?> property;
|
||||
protected final BeanDescriptor<?> target;
|
||||
private final BeanDescriptor<?> target;
|
||||
private final String path;
|
||||
|
||||
AssocOneHelp(BeanPropertyAssocOne<?> property) {
|
||||
@@ -66,8 +66,9 @@ abstract class AssocOneHelp {
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
}
|
||||
Object ref = target.contextRef(pc, id, ctx.unmodifiable(), ctx.isDisableLazyLoading());
|
||||
if (!ctx.unmodifiable() && !ctx.isDisableLazyLoading()) {
|
||||
boolean disableLazyLoading = ctx.isDisableLazyLoading();
|
||||
Object ref = target.contextRef(pc, ctx.isReadOnly(), disableLazyLoading, id);
|
||||
if (!disableLazyLoading) {
|
||||
ctx.register(path, ((EntityBean) ref)._ebean_getIntercept());
|
||||
}
|
||||
return ref;
|
||||
@@ -80,6 +81,7 @@ abstract class AssocOneHelp {
|
||||
Object val = read(ctx);
|
||||
if (bean != null) {
|
||||
property.setValue(bean, val);
|
||||
ctx.propagateState(val);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ final class AssocOneHelpEmbedded extends AssocOneHelp {
|
||||
|
||||
@Override
|
||||
Object read(DataReader reader) throws SQLException {
|
||||
EntityBean embeddedBean = property.targetDescriptor.createEntityBean2(reader.unmodifiable());
|
||||
EntityBean embeddedBean = property.targetDescriptor.createEntityBean();
|
||||
boolean notNull = false;
|
||||
for (BeanProperty property : property.embeddedProps) {
|
||||
Object value = property.readSet(reader, embeddedBean);
|
||||
@@ -53,6 +53,7 @@ final class AssocOneHelpEmbedded extends AssocOneHelp {
|
||||
if (bean != null) {
|
||||
// set back to the parent bean
|
||||
property.setValue(bean, dbVal);
|
||||
ctx.propagateState(dbVal);
|
||||
return dbVal;
|
||||
} else {
|
||||
return null;
|
||||
@@ -61,7 +62,7 @@ final class AssocOneHelpEmbedded extends AssocOneHelp {
|
||||
|
||||
@Override
|
||||
Object read(DbReadContext ctx) throws SQLException {
|
||||
EntityBean embeddedBean = property.targetDescriptor.createEntityBean2(ctx.unmodifiable());
|
||||
EntityBean embeddedBean = property.targetDescriptor.createEntityBean();
|
||||
boolean notNull = false;
|
||||
for (BeanProperty property : property.embeddedProps) {
|
||||
Object value = property.readSet(ctx, embeddedBean);
|
||||
@@ -69,7 +70,12 @@ final class AssocOneHelpEmbedded extends AssocOneHelp {
|
||||
notNull = true;
|
||||
}
|
||||
}
|
||||
return notNull ? embeddedBean : null;
|
||||
if (notNull) {
|
||||
ctx.propagateState(embeddedBean);
|
||||
return embeddedBean;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -53,8 +53,9 @@ final class AssocOneHelpRefInherit extends AssocOneHelp {
|
||||
return existing;
|
||||
}
|
||||
// for inheritance hierarchy create the correct type for this row...
|
||||
Object ref = desc.contextRef(pc, id, ctx.unmodifiable(), ctx.isDisableLazyLoading());
|
||||
if (!ctx.unmodifiable() && !ctx.isDisableLazyLoading()) {
|
||||
boolean disableLazyLoading = ctx.isDisableLazyLoading();
|
||||
Object ref = desc.contextRef(pc, ctx.isReadOnly(), disableLazyLoading, id);
|
||||
if (!disableLazyLoading) {
|
||||
ctx.registerBeanInherit(property, ((EntityBean) ref)._ebean_getIntercept());
|
||||
}
|
||||
return ref;
|
||||
|
||||
@@ -688,22 +688,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeze(EntityBean entityBean) {
|
||||
if (entityBean._ebean_getIntercept().freeze()) {
|
||||
// recursively freeze the graph for this entityBean
|
||||
for (BeanProperty beanProperty : propertiesMutable) {
|
||||
beanProperty.freeze(entityBean);
|
||||
}
|
||||
for (BeanPropertyAssocOne<?> one : propertiesOne) {
|
||||
one.freeze(entityBean);
|
||||
}
|
||||
for (BeanPropertyAssocMany<?> many : propertiesMany) {
|
||||
many.freeze(entityBean);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void metricPersistBatch(PersistRequest.Type type, long startNanos, int size) {
|
||||
iudMetrics.addBatch(type, startNanos, size);
|
||||
}
|
||||
@@ -1206,8 +1190,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
/**
|
||||
* Try to load the beanCollection from cache return true if successful.
|
||||
*/
|
||||
public boolean cacheManyPropLoad(BeanPropertyAssocMany<?> many, BeanCollection<?> bc, String parentKey) {
|
||||
return cacheHelp.manyPropLoad(many, bc, parentKey);
|
||||
public boolean cacheManyPropLoad(BeanPropertyAssocMany<?> many, BeanCollection<?> bc, String parentKey, Boolean readOnly) {
|
||||
return cacheHelp.manyPropLoad(many, bc, parentKey, readOnly);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1256,8 +1240,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
/**
|
||||
* Load the entity bean as the correct bean type.
|
||||
*/
|
||||
EntityBean cacheBeanLoadDirect(Object id, boolean unmodifiable, CachedBeanData data, PersistenceContext context) {
|
||||
return cacheHelp.loadBeanDirect(id, unmodifiable, data, context);
|
||||
EntityBean cacheBeanLoadDirect(Object id, Boolean readOnly, CachedBeanData data, PersistenceContext context) {
|
||||
return cacheHelp.loadBeanDirect(id, readOnly, data, context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1295,8 +1279,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
/**
|
||||
* Return a bean from the bean cache (or null).
|
||||
*/
|
||||
public T cacheBeanGet(Object id, boolean unmodifiable, PersistenceContext context) {
|
||||
return cacheHelp.beanCacheGet(cacheKey(id), unmodifiable, context);
|
||||
public T cacheBeanGet(Object id, Boolean readOnly, PersistenceContext context) {
|
||||
return cacheHelp.beanCacheGet(cacheKey(id), readOnly, context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1325,15 +1309,15 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
return cacheHelp.beanCacheLoad(bean, ebi, cacheKey(id), context);
|
||||
}
|
||||
|
||||
public BeanCacheResult<T> cacheIdLookup(PersistenceContext context, boolean unmodifiable, Collection<?> ids) {
|
||||
return cacheHelp.cacheIdLookup(context, unmodifiable, ids);
|
||||
public BeanCacheResult<T> cacheIdLookup(PersistenceContext context, Collection<?> ids) {
|
||||
return cacheHelp.cacheIdLookup(context, ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use natural key lookup to hit the bean cache.
|
||||
*/
|
||||
public BeanCacheResult<T> naturalKeyLookup(PersistenceContext context, boolean unmodifiable, Set<Object> keys) {
|
||||
return cacheHelp.naturalKeyLookup(context, unmodifiable, keys);
|
||||
public BeanCacheResult<T> naturalKeyLookup(PersistenceContext context, Set<Object> keys) {
|
||||
return cacheHelp.naturalKeyLookup(context, keys);
|
||||
}
|
||||
|
||||
public void cacheNaturalKeyPut(String key, String newKey) {
|
||||
@@ -1471,7 +1455,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
void queryPlanInit(QueryPlanInit request, List<MetaQueryPlan> list) {
|
||||
for (CQueryPlan queryPlan : queryPlanCache.values()) {
|
||||
if (request.includeHash(queryPlan.hash())) {
|
||||
queryPlan.queryPlanInit(request.thresholdMicros());
|
||||
queryPlan.queryPlanInit(request.thresholdMicros(queryPlan.hash()));
|
||||
list.add(queryPlan.createMeta(null, null));
|
||||
}
|
||||
}
|
||||
@@ -1781,10 +1765,10 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
/**
|
||||
* Create a reference with a check for the bean in the persistence context.
|
||||
*/
|
||||
public EntityBean createReference(PersistenceContext pc, Object id) {
|
||||
public EntityBean createReference(Boolean readOnly, Object id, PersistenceContext pc) {
|
||||
Object refBean = contextGet(pc, id);
|
||||
if (refBean == null) {
|
||||
refBean = createReference(false, false, id, pc);
|
||||
refBean = createReference(readOnly, false, id, pc);
|
||||
}
|
||||
return (EntityBean) refBean;
|
||||
}
|
||||
@@ -1793,8 +1777,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
* Create a reference bean based on the id.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T createReference(boolean unmodifiable, boolean disableLazyLoad, Object id, PersistenceContext pc) {
|
||||
if (cacheSharableBeans && unmodifiable) {
|
||||
public T createReference(Boolean readOnly, boolean disableLazyLoad, Object id, PersistenceContext pc) {
|
||||
if (cacheSharableBeans && !disableLazyLoad && !Boolean.FALSE.equals(readOnly)) {
|
||||
CachedBeanData d = cacheHelp.beanCacheGetData(cacheKey(id));
|
||||
if (d != null) {
|
||||
Object shareableBean = d.getSharableBean();
|
||||
@@ -1810,15 +1794,18 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
if (inheritInfo != null && !inheritInfo.isConcrete()) {
|
||||
return findReferenceBean(id, pc);
|
||||
}
|
||||
EntityBean eb = createEntityBean2(unmodifiable);
|
||||
EntityBean eb = createEntityBean();
|
||||
id = convertSetId(id, eb);
|
||||
EntityBeanIntercept ebi = eb._ebean_getIntercept();
|
||||
if (disableLazyLoad) {
|
||||
ebi.setDisableLazyLoad(true);
|
||||
} else if (!unmodifiable) {
|
||||
} else {
|
||||
ebi.setBeanLoader(refBeanLoader());
|
||||
}
|
||||
ebi.setReference(idPropertyIndex);
|
||||
if (Boolean.TRUE == readOnly) {
|
||||
ebi.setReadOnly(true);
|
||||
}
|
||||
if (pc != null) {
|
||||
contextPut(pc, id, eb);
|
||||
ebi.setPersistenceContext(pc);
|
||||
@@ -2043,12 +2030,11 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
return pc.putIfAbsent(rootBeanType, id, localBean);
|
||||
}
|
||||
|
||||
public Object contextRef(PersistenceContext pc, Object id) {
|
||||
return createReference(false, false, id, pc);
|
||||
}
|
||||
|
||||
public Object contextRef(PersistenceContext pc, Object id, boolean unmodifiable, boolean disableLazyLoad) {
|
||||
return createReference(unmodifiable, disableLazyLoad, id, pc);
|
||||
/**
|
||||
* Create a reference bean and put it in the persistence context (and return it).
|
||||
*/
|
||||
public Object contextRef(PersistenceContext pc, Boolean readOnly, boolean disableLazyLoad, Object id) {
|
||||
return createReference(readOnly, disableLazyLoad, id, pc);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2163,7 +2149,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
* Set the Id value to the bean (without type conversion).
|
||||
*/
|
||||
public void setId(Object idValue, EntityBean bean) {
|
||||
idProperty.setValue(bean, idValue);
|
||||
idProperty.setValueIntercept(bean, idValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+33
-29
@@ -261,7 +261,7 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
/**
|
||||
* Try to load the bean collection from cache return true if successful.
|
||||
*/
|
||||
boolean manyPropLoad(BeanPropertyAssocMany<?> many, BeanCollection<?> bc, String parentKey) {
|
||||
boolean manyPropLoad(BeanPropertyAssocMany<?> many, BeanCollection<?> bc, String parentKey, Boolean readOnly) {
|
||||
if (many.isElementCollection()) {
|
||||
// held as part of the bean cache so skip
|
||||
return false;
|
||||
@@ -280,7 +280,7 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
bc.checkEmptyLazyLoad();
|
||||
int i = 0;
|
||||
for (Object id : idList) {
|
||||
final EntityBean ref = targetDescriptor.createReference(persistenceContext, id);
|
||||
final EntityBean ref = targetDescriptor.createReference(readOnly, id, persistenceContext);
|
||||
if (many.hasOrderColumn()) {
|
||||
ref._ebean_getIntercept().setSortOrder(++i);
|
||||
}
|
||||
@@ -344,7 +344,7 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
/**
|
||||
* Hit the bean cache with the given ids returning the hits.
|
||||
*/
|
||||
BeanCacheResult<T> cacheIdLookup(PersistenceContext context, boolean unmodifiable, Collection<?> ids) {
|
||||
BeanCacheResult<T> cacheIdLookup(PersistenceContext context, Collection<?> ids) {
|
||||
Set<Object> keys = new HashSet<>(ids.size());
|
||||
for (Object id : ids) {
|
||||
keys.add(desc.cacheKey(id));
|
||||
@@ -359,7 +359,7 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
BeanCacheResult<T> result = new BeanCacheResult<>();
|
||||
for (Map.Entry<Object, Object> entry : beanDataMap.entrySet()) {
|
||||
CachedBeanData cachedBeanData = (CachedBeanData) entry.getValue();
|
||||
T bean = convertToBean(entry.getKey(), unmodifiable, context, cachedBeanData);
|
||||
T bean = convertToBean(entry.getKey(), false, context, cachedBeanData);
|
||||
result.add(bean, desc.id(bean));
|
||||
}
|
||||
return result;
|
||||
@@ -368,7 +368,7 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
/**
|
||||
* Use natural keys to hit the bean cache and return resulting hits.
|
||||
*/
|
||||
BeanCacheResult<T> naturalKeyLookup(PersistenceContext context, boolean unmodifiable, Set<Object> keys) {
|
||||
BeanCacheResult<T> naturalKeyLookup(PersistenceContext context, Set<Object> keys) {
|
||||
if (context == null) {
|
||||
context = new DefaultPersistenceContext();
|
||||
}
|
||||
@@ -399,7 +399,7 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
for (Map.Entry<Object, Object> entry : beanDataMap.entrySet()) {
|
||||
Object id = entry.getKey();
|
||||
CachedBeanData cachedBeanData = (CachedBeanData) entry.getValue();
|
||||
T bean = convertToBean(id, unmodifiable, context, cachedBeanData);
|
||||
T bean = convertToBean(id, false, context, cachedBeanData);
|
||||
Object naturalKey = reverseMap.get(id);
|
||||
result.add(bean, naturalKey);
|
||||
}
|
||||
@@ -561,9 +561,9 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
return (CachedBeanData) getBeanCache().get(key);
|
||||
}
|
||||
|
||||
T beanCacheGet(String key, boolean unmodifiable, PersistenceContext context) {
|
||||
T bean = beanCacheGetInternal(key, unmodifiable, context);
|
||||
if (bean != null && !unmodifiable) {
|
||||
T beanCacheGet(String key, Boolean readOnly, PersistenceContext context) {
|
||||
T bean = beanCacheGetInternal(key, readOnly, context);
|
||||
if (bean != null) {
|
||||
setupContext(bean, context);
|
||||
}
|
||||
return bean;
|
||||
@@ -572,7 +572,7 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
/**
|
||||
* Return a bean from the bean cache.
|
||||
*/
|
||||
private T beanCacheGetInternal(String key, boolean unmodifiable, PersistenceContext context) {
|
||||
private T beanCacheGetInternal(String key, Boolean readOnly, PersistenceContext context) {
|
||||
CachedBeanData data = (CachedBeanData) getBeanCache().get(key);
|
||||
if (data == null) {
|
||||
if (beanLog.isLoggable(TRACE)) {
|
||||
@@ -583,12 +583,12 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
if (beanLog.isLoggable(TRACE)) {
|
||||
beanLog.log(TRACE, " GET {0}({1}) - hit", cacheName, key);
|
||||
}
|
||||
return convertToBean(key, unmodifiable, context, data);
|
||||
return convertToBean(key, readOnly, context, data);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private T convertToBean(Object id, boolean unmodifiable, PersistenceContext context, CachedBeanData data) {
|
||||
if (cacheSharableBeans && unmodifiable) {
|
||||
private T convertToBean(Object id, Boolean readOnly, PersistenceContext context, CachedBeanData data) {
|
||||
if (cacheSharableBeans && !Boolean.FALSE.equals(readOnly)) {
|
||||
Object bean = data.getSharableBean();
|
||||
if (bean != null) {
|
||||
if (beanLog.isLoggable(TRACE)) {
|
||||
@@ -600,18 +600,18 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
return (T) bean;
|
||||
}
|
||||
}
|
||||
return (T) loadBean(id, unmodifiable, data, context);
|
||||
return (T) loadBean(id, readOnly, data, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the entity bean taking into account inheritance.
|
||||
*/
|
||||
private EntityBean loadBean(Object id, boolean unmodifiable, CachedBeanData data, PersistenceContext context) {
|
||||
private EntityBean loadBean(Object id, Boolean readOnly, CachedBeanData data, PersistenceContext context) {
|
||||
String discValue = data.getDiscValue();
|
||||
if (discValue == null) {
|
||||
return loadBeanDirect(id, unmodifiable, data, context);
|
||||
return loadBeanDirect(id, readOnly, data, context);
|
||||
} else {
|
||||
return rootDescriptor(discValue).cacheBeanLoadDirect(id, unmodifiable, data, context);
|
||||
return rootDescriptor(discValue).cacheBeanLoadDirect(id, readOnly, data, context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -625,22 +625,26 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
/**
|
||||
* Load the entity bean from cache data given this is the root bean type.
|
||||
*/
|
||||
EntityBean loadBeanDirect(Object id, boolean unmodifiable, CachedBeanData data, PersistenceContext context) {
|
||||
EntityBean loadBeanDirect(Object id, Boolean readOnly, CachedBeanData data, PersistenceContext context) {
|
||||
id = desc.convertId(id);
|
||||
EntityBean bean = context == null ? null : (EntityBean) desc.contextGet(context, id);;
|
||||
EntityBean bean = null;
|
||||
if (context == null) {
|
||||
context = new DefaultPersistenceContext();
|
||||
} else {
|
||||
bean = (EntityBean) desc.contextGet(context, id);
|
||||
}
|
||||
if (bean == null) {
|
||||
bean = desc.createEntityBean2(unmodifiable);
|
||||
bean = desc.createEntityBean();
|
||||
desc.setId(id, bean);
|
||||
if (!unmodifiable) {
|
||||
if (context == null) {
|
||||
context = new DefaultPersistenceContext();
|
||||
}
|
||||
desc.contextPut(context, id, bean);
|
||||
EntityBeanIntercept ebi = bean._ebean_getIntercept();
|
||||
ebi.setPersistenceContext(context);
|
||||
// Not using loadContext here so no batch lazy loading for these beans
|
||||
ebi.setBeanLoader(desc.l2BeanLoader());
|
||||
desc.contextPut(context, id, bean);
|
||||
|
||||
EntityBeanIntercept ebi = bean._ebean_getIntercept();
|
||||
// Not using loadContext here so no batch lazy loading for these beans
|
||||
ebi.setBeanLoader(desc.l2BeanLoader());
|
||||
if (Boolean.TRUE.equals(readOnly)) {
|
||||
ebi.setReadOnly(true);
|
||||
}
|
||||
ebi.setPersistenceContext(context);
|
||||
}
|
||||
|
||||
CachedBeanDataToBean.load(desc, bean, data, context);
|
||||
|
||||
@@ -2,7 +2,6 @@ package io.ebeaninternal.server.deploy;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import io.ebean.DataIntegrityException;
|
||||
import io.ebean.ModifyAwareType;
|
||||
import io.ebean.ValuePair;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
@@ -1520,15 +1519,4 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
desc.registerColumn(dbColumn, path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Freeze mutable types (like DbArray).
|
||||
*/
|
||||
public void freeze(EntityBean entityBean) {
|
||||
Object value = getValue(entityBean);
|
||||
if (value instanceof ModifyAwareType) {
|
||||
ModifyAwareType bc = (ModifyAwareType) value;
|
||||
setValue(entityBean, bc.freeze());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1165,22 +1165,4 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeze(EntityBean entityBean) {
|
||||
Object value = getValue(entityBean);
|
||||
if (value instanceof BeanCollection) {
|
||||
BeanCollection<?> beanCollection = (BeanCollection<?>) value;
|
||||
Collection<?> entities = beanCollection.actualDetails();
|
||||
if (entities != null) {
|
||||
for (Object actualEntry : entities) {
|
||||
targetDescriptor.freeze((EntityBean) actualEntry);
|
||||
}
|
||||
}
|
||||
setValue(entityBean, beanCollection.freeze());
|
||||
} else if (value == null) {
|
||||
// make it an error to access the collection (no lazy loading allowed)
|
||||
entityBean._ebean_getIntercept().setPropertyUnloaded(propertyIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.deploy;
|
||||
|
||||
import io.ebean.Query;
|
||||
import io.ebean.SqlUpdate;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.ValuePair;
|
||||
@@ -125,6 +124,10 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
// no imported or exported information
|
||||
} else if (!oneToOneExported) {
|
||||
importedId = createImportedId(this, targetDescriptor, tableJoin);
|
||||
if (importedId == null) {
|
||||
throw new PersistenceException("Cannot find imported id for " + fullName() + " from " + targetDescriptor
|
||||
+ ". If using native-image, possibly missing reflect-config for the Id property.");
|
||||
}
|
||||
if (importedId.isScalar()) {
|
||||
// limit JoinColumn mapping to the @Id / primary key
|
||||
TableJoinColumn[] columns = tableJoin.columns();
|
||||
@@ -663,14 +666,6 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
setValue(entityBean, targetDescriptor.createRef(tenantId, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void freeze(EntityBean entityBean) {
|
||||
Object value = getValue(entityBean);
|
||||
if (value instanceof EntityBean) {
|
||||
targetDescriptor.freeze((EntityBean) value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(EntityBean bean, Object value) {
|
||||
super.setValue(bean, value);
|
||||
|
||||
@@ -14,6 +14,16 @@ import java.util.Map;
|
||||
*/
|
||||
public interface DbReadContext {
|
||||
|
||||
/**
|
||||
* Return the state of the object graph.
|
||||
*/
|
||||
Boolean isReadOnly();
|
||||
|
||||
/**
|
||||
* Propagate the state to the bean.
|
||||
*/
|
||||
void propagateState(Object e);
|
||||
|
||||
/**
|
||||
* Return the DataReader.
|
||||
*/
|
||||
@@ -92,14 +102,4 @@ public interface DbReadContext {
|
||||
*/
|
||||
void handleLoadError(String fullName, Exception e);
|
||||
|
||||
/**
|
||||
* Return true if this many property should be included in unmodifiable
|
||||
* query via a secondary query.
|
||||
*/
|
||||
boolean includeSecondary(BeanPropertyAssocMany<?> many);
|
||||
|
||||
/**
|
||||
* Return true if we are loading unmodifiable beans.
|
||||
*/
|
||||
boolean unmodifiable();
|
||||
}
|
||||
|
||||
@@ -228,8 +228,8 @@ public final class InheritInfo {
|
||||
/**
|
||||
* Create an EntityBean for this type.
|
||||
*/
|
||||
public EntityBean createEntityBean(boolean unmodifiable) {
|
||||
return descriptor.createEntityBean2(unmodifiable);
|
||||
public EntityBean createEntityBean() {
|
||||
return descriptor.createEntityBean();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,6 +20,7 @@ public final class TableJoinColumn {
|
||||
private final String foreignSqlFormula;
|
||||
private final boolean insertable;
|
||||
private final boolean updateable;
|
||||
private final boolean nullable;
|
||||
/**
|
||||
* Hash for including in a query plan
|
||||
*/
|
||||
@@ -34,7 +35,8 @@ public final class TableJoinColumn {
|
||||
this.localSqlFormula = InternString.intern(deploy.getLocalSqlFormula());
|
||||
this.foreignSqlFormula = InternString.intern(deploy.getForeignSqlFormula());
|
||||
this.insertable = deploy.isInsertable();
|
||||
this.updateable = deploy.isUpdateable();
|
||||
this.updateable = deploy.isUpdatable();
|
||||
this.nullable = deploy.isNullable();
|
||||
this.queryHash = hash();
|
||||
}
|
||||
|
||||
@@ -45,6 +47,7 @@ public final class TableJoinColumn {
|
||||
this.foreignSqlFormula = null;
|
||||
this.insertable = source.isInsertable();
|
||||
this.updateable = source.isUpdateable();
|
||||
this.nullable = source.isNullable();
|
||||
this.queryHash = hash();
|
||||
}
|
||||
|
||||
@@ -115,6 +118,13 @@ public final class TableJoinColumn {
|
||||
return updateable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if this column is nullable.
|
||||
*/
|
||||
public boolean isNullable() {
|
||||
return nullable;
|
||||
}
|
||||
|
||||
public String getLocalSqlFormula() {
|
||||
return localSqlFormula;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package io.ebeaninternal.server.deploy.id;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.util.SplitName;
|
||||
import io.ebeaninternal.api.SpiExpressionBind;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.core.DefaultSqlUpdate;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
@@ -323,7 +324,7 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
|
||||
@Override
|
||||
public Object read(DbReadContext ctx) throws SQLException {
|
||||
final EntityBean embId = idDesc.createEntityBean2(ctx.unmodifiable());
|
||||
final EntityBean embId = idDesc.createEntityBean();
|
||||
boolean nullValue = true;
|
||||
for (BeanProperty prop : props) {
|
||||
final Object value = prop.read(ctx);
|
||||
|
||||
@@ -245,8 +245,7 @@ public final class IdBinderSimple implements IdBinder {
|
||||
idValue = scalarType.toBeanType(idValue);
|
||||
}
|
||||
if (bean != null) {
|
||||
// not using interception to support unmodifiable entities
|
||||
idProperty.setValue(bean, idValue);
|
||||
idProperty.setValueIntercept(bean, idValue);
|
||||
}
|
||||
return idValue;
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ public final class DeployTableJoin {
|
||||
// only add the join column details when name or referencedColumnName is specified
|
||||
String ref = deploy.convertQuotes(jc.referencedColumnName());
|
||||
String nam = deploy.convertQuotes(jc.name());
|
||||
addJoinColumn(new DeployTableJoinColumn(order, ref, nam, jc.insertable(), jc.updatable(), beanTable));
|
||||
addJoinColumn(new DeployTableJoinColumn(order, ref, nam, jc.insertable(), jc.updatable(), jc.nullable(), beanTable));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
-12
@@ -25,7 +25,8 @@ public final class DeployTableJoinColumn {
|
||||
*/
|
||||
private String foreignSqlFormula;
|
||||
private boolean insertable;
|
||||
private boolean updateable;
|
||||
private boolean updatable;
|
||||
private boolean nullable;
|
||||
|
||||
/**
|
||||
* Construct when automatically determining the join.
|
||||
@@ -34,21 +35,24 @@ public final class DeployTableJoinColumn {
|
||||
* </p>
|
||||
*/
|
||||
public DeployTableJoinColumn(String localDbColumn, String foreignDbColumn) {
|
||||
this(localDbColumn, foreignDbColumn, true, true);
|
||||
this(localDbColumn, foreignDbColumn, true, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct with explicit insertable and updateable flags.
|
||||
*/
|
||||
public DeployTableJoinColumn(String localDbColumn, String foreignDbColumn, boolean insertable, boolean updateable) {
|
||||
public DeployTableJoinColumn(String localDbColumn, String foreignDbColumn,
|
||||
boolean insertable, boolean updatable, boolean nullable) {
|
||||
this.localDbColumn = nullEmptyString(localDbColumn);
|
||||
this.foreignDbColumn = nullEmptyString(foreignDbColumn);
|
||||
this.insertable = insertable;
|
||||
this.updateable = updateable;
|
||||
this.updatable = updatable;
|
||||
this.nullable = nullable;
|
||||
}
|
||||
|
||||
public DeployTableJoinColumn(boolean order, String ref, String name, boolean insertable, boolean updateable, BeanTable beanTable) {
|
||||
this(ref, name, insertable, updateable);
|
||||
public DeployTableJoinColumn(boolean order, String ref, String name,
|
||||
boolean insertable, boolean updatable, boolean nullable, BeanTable beanTable) {
|
||||
this(ref, name, insertable, updatable, nullable);
|
||||
setReferencedColumn(beanTable);
|
||||
if (!order) {
|
||||
reverse();
|
||||
@@ -60,7 +64,7 @@ public final class DeployTableJoinColumn {
|
||||
this.localSqlFormula = localSqlFormula;
|
||||
this.localDbColumn = null;
|
||||
this.insertable = false;
|
||||
this.updateable = false;
|
||||
this.updatable = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +77,7 @@ public final class DeployTableJoinColumn {
|
||||
this.foreignSqlFormula = foreignSqlFormula;
|
||||
this.foreignDbColumn = null;
|
||||
this.insertable = false;
|
||||
this.updateable = false;
|
||||
this.updatable = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,12 +125,12 @@ public final class DeployTableJoinColumn {
|
||||
// but will leave it like this for now
|
||||
DeployTableJoinColumn ret;
|
||||
if (reverse) {
|
||||
ret = new DeployTableJoinColumn(foreignDbColumn, localDbColumn, insertable, updateable);
|
||||
ret = new DeployTableJoinColumn(foreignDbColumn, localDbColumn, insertable, updatable, nullable);
|
||||
ret.setLocalSqlFormula(foreignSqlFormula);
|
||||
ret.setForeignSqlFormula(localSqlFormula);
|
||||
|
||||
} else {
|
||||
ret = new DeployTableJoinColumn(localDbColumn, foreignDbColumn, insertable, updateable);
|
||||
ret = new DeployTableJoinColumn(localDbColumn, foreignDbColumn, insertable, updatable, nullable);
|
||||
ret.setLocalSqlFormula(localSqlFormula);
|
||||
ret.setForeignSqlFormula(foreignSqlFormula);
|
||||
}
|
||||
@@ -148,8 +152,8 @@ public final class DeployTableJoinColumn {
|
||||
/**
|
||||
* Return true if this column should be updateable.
|
||||
*/
|
||||
public boolean isUpdateable() {
|
||||
return updateable;
|
||||
public boolean isUpdatable() {
|
||||
return updatable;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,4 +177,7 @@ public final class DeployTableJoinColumn {
|
||||
this.localDbColumn = localDbColumn;
|
||||
}
|
||||
|
||||
public boolean isNullable() {
|
||||
return nullable;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -223,7 +223,7 @@ final class AnnotationAssocOnes extends AnnotationAssoc {
|
||||
BeanTable baseBeanTable = factory.beanTable(info.getDescriptor().getBeanType());
|
||||
String localPrimaryKey = baseBeanTable.getIdColumn();
|
||||
String foreignColumn = getBeanTable(prop).getIdColumn();
|
||||
prop.getTableJoin().addJoinColumn(new DeployTableJoinColumn(localPrimaryKey, foreignColumn, false, false));
|
||||
prop.getTableJoin().addJoinColumn(new DeployTableJoinColumn(localPrimaryKey, foreignColumn, false, false, prop.isNullable()));
|
||||
}
|
||||
|
||||
private void readEmbedded(DeployBeanPropertyAssocOne<?> prop, Embedded embedded) {
|
||||
|
||||
@@ -11,7 +11,9 @@ import io.ebeaninternal.server.el.ElPropertyValue;
|
||||
import io.ebeaninternal.server.querydefn.OrmQueryProperties;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Default implementation of LoadContext.
|
||||
@@ -25,7 +27,7 @@ public final class DLoadContext implements LoadContext {
|
||||
private final DLoadBeanContext rootBeanContext;
|
||||
private final boolean asDraft;
|
||||
private final Timestamp asOf;
|
||||
private final boolean unmodifiable;
|
||||
private final Boolean readOnly;
|
||||
private final CacheMode useBeanCache;
|
||||
private final int defaultBatchSize;
|
||||
private final boolean disableLazyLoading;
|
||||
@@ -46,7 +48,6 @@ public final class DLoadContext implements LoadContext {
|
||||
boolean useReferences;
|
||||
private List<OrmQueryProperties> secQuery;
|
||||
private Object tenantId;
|
||||
private final Set<BeanProperty> secondaryProperties;
|
||||
|
||||
/**
|
||||
* Construct for use with JSON marshalling (doc store).
|
||||
@@ -61,7 +62,7 @@ public final class DLoadContext implements LoadContext {
|
||||
this.useBeanCache = CacheMode.OFF;
|
||||
this.asDraft = false;
|
||||
this.asOf = null;
|
||||
this.unmodifiable = false;
|
||||
this.readOnly = false;
|
||||
this.disableLazyLoading = false;
|
||||
this.disableReadAudit = false;
|
||||
this.includeSoftDeletes = false;
|
||||
@@ -70,7 +71,6 @@ public final class DLoadContext implements LoadContext {
|
||||
this.profileLocation = null;
|
||||
this.profilingListener = null;
|
||||
this.rootBeanContext = new DLoadBeanContext(this, rootDescriptor, null, null);
|
||||
this.secondaryProperties = null;
|
||||
}
|
||||
|
||||
private ObjectGraphOrigin initOrigin() {
|
||||
@@ -90,14 +90,13 @@ public final class DLoadContext implements LoadContext {
|
||||
this.asOf = query.getAsOf();
|
||||
this.asDraft = query.isAsDraft();
|
||||
this.includeSoftDeletes = query.isIncludeSoftDeletes() && query.mode() == SpiQuery.Mode.NORMAL;
|
||||
this.unmodifiable = query.isUnmodifiable();
|
||||
this.readOnly = query.isReadOnly();
|
||||
this.disableReadAudit = query.isDisableReadAudit();
|
||||
this.disableLazyLoading = query.isDisableLazyLoading();
|
||||
this.useBeanCache = query.beanCacheMode();
|
||||
this.profilingListener = query.profilingListener();
|
||||
this.planLabel = query.planLabel();
|
||||
this.profileLocation = query.profileLocation();
|
||||
this.secondaryProperties = query.isUnmodifiable() ? new HashSet<>() : null;
|
||||
|
||||
ObjectGraphNode parentNode = query.parentNode();
|
||||
if (parentNode != null) {
|
||||
@@ -157,14 +156,6 @@ public final class DLoadContext implements LoadContext {
|
||||
ElPropertyValue elGetValue = rootDescriptor.elGetValue(props.getPath());
|
||||
boolean many = elGetValue.beanProperty().containsMany();
|
||||
registerSecondaryNode(many, props);
|
||||
if (many && secondaryProperties != null) {
|
||||
secondaryProperties.add(elGetValue.beanProperty());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean includeSecondary(BeanPropertyAssocMany<?> many) {
|
||||
return secondaryProperties != null && secondaryProperties.contains(many);
|
||||
}
|
||||
|
||||
boolean isBeanCacheGet() {
|
||||
@@ -239,6 +230,14 @@ public final class DLoadContext implements LoadContext {
|
||||
return ebeanServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the parent state which defines the sharedInstance and readOnly status
|
||||
* which needs to be propagated to other beans and collections.
|
||||
*/
|
||||
Boolean isReadOnly() {
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceContext persistenceContext() {
|
||||
return persistenceContext;
|
||||
@@ -321,7 +320,9 @@ public final class DLoadContext implements LoadContext {
|
||||
if (useDocStore && docStoreMapped) {
|
||||
query.setUseDocStore(true);
|
||||
}
|
||||
query.setUnmodifiable(unmodifiable);
|
||||
if (readOnly != null) {
|
||||
query.setReadOnly(readOnly);
|
||||
}
|
||||
query.setDisableLazyLoading(disableLazyLoading);
|
||||
query.asOf(asOf);
|
||||
if (asDraft) {
|
||||
|
||||
@@ -198,7 +198,7 @@ final class DLoadManyContext extends DLoadBaseContext implements LoadManyContext
|
||||
BeanDescriptor<?> parentDesc = context.desc.descriptor(ownerBean.getClass());
|
||||
Object parentId = parentDesc.getId(ownerBean);
|
||||
final String parentKey = parentDesc.cacheKey(parentId);
|
||||
if (parentDesc.cacheManyPropLoad(context.property, bc, parentKey)) {
|
||||
if (parentDesc.cacheManyPropLoad(context.property, bc, parentKey, context.parent.isReadOnly())) {
|
||||
// we loaded the bean collection from cache so remove it from the buffer
|
||||
if (removeFromBuffer(bc)) {
|
||||
bc.setLoader(context.parent.server());
|
||||
|
||||
@@ -401,7 +401,7 @@ public final class Binder {
|
||||
return new DataBind(dataTimeZone, stmt, connection);
|
||||
}
|
||||
|
||||
public DataReader createDataReader(boolean unmodifiable, ResultSet resultSet) {
|
||||
return new RsetDataReader(unmodifiable, dataTimeZone, resultSet);
|
||||
public DataReader createDataReader(ResultSet resultSet) {
|
||||
return new RsetDataReader(dataTimeZone, resultSet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,6 @@ public final class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfi
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
private final boolean loadContextBean;
|
||||
private final boolean unmodifiable;
|
||||
|
||||
/**
|
||||
* The resultSet rows read.
|
||||
@@ -153,6 +152,8 @@ public final class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfi
|
||||
|
||||
private final ProfilingListener profilingListener;
|
||||
|
||||
private final Boolean readOnly;
|
||||
|
||||
private long profileOffset;
|
||||
private long startNano;
|
||||
|
||||
@@ -185,6 +186,7 @@ public final class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfi
|
||||
this.queryMode = query.mode();
|
||||
this.loadContextBean = queryMode.isLoadContextBean() || query.getForUpdateLockType() != null;
|
||||
this.lazyLoadManyProperty = query.lazyLoadMany();
|
||||
this.readOnly = query.isReadOnly();
|
||||
this.disableLazyLoading = query.isDisableLazyLoading();
|
||||
this.objectGraphNode = query.parentNode();
|
||||
this.profilingListener = query.profilingListener();
|
||||
@@ -205,7 +207,6 @@ public final class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfi
|
||||
} else {
|
||||
this.help = createHelp(request);
|
||||
}
|
||||
this.unmodifiable = request.query().isUnmodifiable();
|
||||
this.collection = (help != null ? help.createEmptyNoParent() : null);
|
||||
}
|
||||
|
||||
@@ -238,8 +239,17 @@ public final class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfi
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean unmodifiable() {
|
||||
return unmodifiable;
|
||||
public Boolean isReadOnly() {
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propagateState(Object e) {
|
||||
if (Boolean.TRUE.equals(readOnly)) {
|
||||
if (e instanceof EntityBean) {
|
||||
((EntityBean) e)._ebean_getIntercept().setReadOnly(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -289,7 +299,7 @@ public final class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfi
|
||||
if (resultSet == null) {
|
||||
return false;
|
||||
}
|
||||
dataReader = queryPlan.createDataReader(query.isUnmodifiable(), resultSet);
|
||||
dataReader = queryPlan.createDataReader(resultSet);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -464,14 +474,6 @@ public final class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfi
|
||||
return result;
|
||||
}
|
||||
|
||||
EntityBean nextBean() {
|
||||
EntityBean bean = next();
|
||||
if (unmodifiable) {
|
||||
request.unmodifiableFreeze(bean);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
EntityBean next() {
|
||||
if (audit) {
|
||||
auditNextBean();
|
||||
@@ -601,11 +603,6 @@ public final class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfi
|
||||
request.loadContext().register(path(many.name()), many, bc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean includeSecondary(BeanPropertyAssocMany<?> many) {
|
||||
return request.loadContext().includeSecondary(many);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is a raw sql query as opposed to Ebean generated sql.
|
||||
*/
|
||||
|
||||
@@ -107,9 +107,15 @@ public final class CQueryEngine {
|
||||
if (collection instanceof List) {
|
||||
collection = (A) Collections.unmodifiableList((List<?>) collection);
|
||||
request.putToQueryCache(collection);
|
||||
if (Boolean.FALSE.equals(request.query().isReadOnly())) {
|
||||
collection = (A) new ArrayList<>(collection);
|
||||
}
|
||||
} else if (collection instanceof Set) {
|
||||
collection = (A) Collections.unmodifiableSet((Set<?>) collection);
|
||||
request.putToQueryCache(collection);
|
||||
if (Boolean.FALSE.equals(request.query().isReadOnly())) {
|
||||
collection = (A) new LinkedHashSet<>(collection);
|
||||
}
|
||||
}
|
||||
}
|
||||
return collection;
|
||||
@@ -352,7 +358,6 @@ public final class CQueryEngine {
|
||||
if (request.isQueryCachePut()) {
|
||||
request.addDependentTables(cquery.dependentTables());
|
||||
}
|
||||
request.unmodifiableFreeze(beanCollection);
|
||||
return beanCollection;
|
||||
|
||||
} catch (SQLException e) {
|
||||
@@ -385,7 +390,6 @@ public final class CQueryEngine {
|
||||
cquery.auditFind(bean);
|
||||
}
|
||||
request.executeSecondaryQueries(false);
|
||||
request.unmodifiableFreeze(bean);
|
||||
return (T) bean;
|
||||
} catch (SQLException e) {
|
||||
throw cquery.createPersistenceException(e);
|
||||
|
||||
+1
-1
@@ -137,7 +137,7 @@ final class CQueryFetchSingleAttribute implements SpiProfileTransactionEvent, Ca
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
dataReader = new RsetDataReader(query.isUnmodifiable(), request.dataTimeZone(), pstmt.executeQuery());
|
||||
dataReader = new RsetDataReader(request.dataTimeZone(), pstmt.executeQuery());
|
||||
query.checkCancelled();
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ final class CQueryIteratorSimple<T> implements QueryIterator<T> {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public T next() {
|
||||
return (T) cquery.nextBean();
|
||||
return (T) cquery.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -44,7 +44,6 @@ final class CQueryIteratorWithBuffer<T> implements QueryIterator<T> {
|
||||
}
|
||||
request.executeSecondaryQueries(true);
|
||||
}
|
||||
request.unmodifiableFreeze(buffer);
|
||||
ret = !buffer.isEmpty();
|
||||
return ret;
|
||||
} catch (SQLException e) {
|
||||
|
||||
@@ -205,8 +205,8 @@ public class CQueryPlan implements SpiQueryPlan {
|
||||
return new DQueryPlanOutput(beanType(), name, hash, sql, profileLocation, bind, planString);
|
||||
}
|
||||
|
||||
public DataReader createDataReader(boolean unmodifiable, ResultSet rset) {
|
||||
return new RsetDataReader(unmodifiable, dataTimeZone, rset);
|
||||
public DataReader createDataReader(ResultSet rset) {
|
||||
return new RsetDataReader(dataTimeZone, rset);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -63,6 +63,13 @@ public final class CQueryPlanManager implements QueryPlanManager {
|
||||
while (req.hasNext()) {
|
||||
req.nextCapture();
|
||||
}
|
||||
if (!connection.getAutoCommit()) {
|
||||
// CHECKME: commit or rollback here?
|
||||
// arguments for rollback: the collecting should never modify data.
|
||||
// if there are collectors that may copy the plan into tables, it's up to the collector to
|
||||
// commit the transaction.
|
||||
connection.rollback();
|
||||
}
|
||||
return req.plans();
|
||||
} catch (SQLException e) {
|
||||
CoreLog.log.log(ERROR, "Error during query plan collection", e);
|
||||
|
||||
@@ -22,8 +22,8 @@ final class CQueryPlanRawSql extends CQueryPlan {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataReader createDataReader(boolean unmodifiable, ResultSet rset) {
|
||||
return new RsetDataReaderIndexed(unmodifiable, dataTimeZone, rset, rsetIndexPositions);
|
||||
public DataReader createDataReader(ResultSet rset) {
|
||||
return new RsetDataReaderIndexed(dataTimeZone, rset, rsetIndexPositions);
|
||||
}
|
||||
|
||||
private int[] createIndexPositions(OrmQueryRequest<?> request, SqlTree sqlTree) {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.query;
|
||||
|
||||
import io.ebean.Transaction;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
|
||||
@@ -11,11 +10,9 @@ abstract class CallableQuery<T> {
|
||||
|
||||
final SpiQuery<T> query;
|
||||
final SpiEbeanServer server;
|
||||
final Transaction transaction;
|
||||
|
||||
CallableQuery(SpiEbeanServer server, SpiQuery<T> query) {
|
||||
this.server = server;
|
||||
this.query = query;
|
||||
this.transaction = query.transaction();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,15 +10,8 @@ import java.util.concurrent.Callable;
|
||||
*/
|
||||
public final class CallableQueryCount<T> extends CallableQuery<T> implements Callable<Integer> {
|
||||
|
||||
private final boolean createdTransaction;
|
||||
|
||||
/**
|
||||
* Note that the transaction passed in is always a new transaction solely to
|
||||
* find the row count so it must be cleaned up by this CallableQueryRowCount.
|
||||
*/
|
||||
public CallableQueryCount(SpiEbeanServer server, SpiQuery<T> query, boolean createdTransaction) {
|
||||
public CallableQueryCount(SpiEbeanServer server, SpiQuery<T> query) {
|
||||
super(server, query);
|
||||
this.createdTransaction = createdTransaction;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -26,13 +19,7 @@ public final class CallableQueryCount<T> extends CallableQuery<T> implements Cal
|
||||
*/
|
||||
@Override
|
||||
public Integer call() {
|
||||
try {
|
||||
return server.findCountWithCopy(query);
|
||||
} finally {
|
||||
if (createdTransaction) {
|
||||
transaction.end();
|
||||
}
|
||||
}
|
||||
return server.findCountWithCopy(query);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,28 +11,16 @@ import java.util.concurrent.Callable;
|
||||
*/
|
||||
public final class CallableQueryIds<T> extends CallableQuery<T> implements Callable<List<Object>> {
|
||||
|
||||
private final boolean createdTransaction;
|
||||
|
||||
public CallableQueryIds(SpiEbeanServer server, SpiQuery<T> query, boolean createdTransaction) {
|
||||
public CallableQueryIds(SpiEbeanServer server, SpiQuery<T> query) {
|
||||
super(server, query);
|
||||
this.createdTransaction = createdTransaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the find Id's query returning the list of Id's.
|
||||
*/
|
||||
@Override
|
||||
public List<Object> call() {
|
||||
// we have already made a copy of the query
|
||||
// this way the same query instance is available to the
|
||||
// QueryFutureIds (as so has access to the List before it is done)
|
||||
try {
|
||||
return server.findIdsWithCopy(query);
|
||||
} finally {
|
||||
if (createdTransaction) {
|
||||
transaction.end();
|
||||
}
|
||||
}
|
||||
return server.findIdsWithCopy(query);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user