mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-09-20 19:17:55 +00:00
Compare commits
99
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4bcfa80df2 | ||
|
|
c583879d57 | ||
|
|
6d791c7b50 | ||
|
|
1afe42f4c6 | ||
|
|
4e7f3c13a0 | ||
|
|
d7366dec0f | ||
|
|
ceee1d7489 | ||
|
|
1b23319fa4 | ||
|
|
6f726973ea | ||
|
|
82284b19d5 | ||
|
|
798d01abd1 | ||
|
|
5136a5a708 | ||
|
|
fa25d7cc8a | ||
|
|
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 | ||
|
|
8ff5f7f72a | ||
|
|
71944bb8fa | ||
|
|
24888fc01e | ||
|
|
645d5bb613 | ||
|
|
4a6f1a39e0 | ||
|
|
40637bd68c | ||
|
|
8dd438be61 | ||
|
|
5e1ad29c5d | ||
|
|
9eeb137907 | ||
|
|
578a041c9e | ||
|
|
b0b2a0d320 | ||
|
|
de81dfc067 | ||
|
|
2bd53cb52b | ||
|
|
a6d792de64 | ||
|
|
c73d83ef33 | ||
|
|
9f1b4ba758 | ||
|
|
1f7117da25 | ||
|
|
f0ceab43bf | ||
|
|
1107e4ea4c | ||
|
|
4dd8a5dfea | ||
|
|
195edf0355 | ||
|
|
e9c438adab | ||
|
|
e45cf5fab9 | ||
|
|
1bf9d1dd4f | ||
|
|
657920c4a2 | ||
|
|
6c47107436 | ||
|
|
88cf4e001a | ||
|
|
7f1fcbcf92 | ||
|
|
95d5d5e467 | ||
|
|
2dde23d577 | ||
|
|
1ec26d13f9 | ||
|
|
bb1b55e897 | ||
|
|
fb07447df4 | ||
|
|
ad18b6573c | ||
|
|
11632c3a6e | ||
|
|
b066f9c072 | ||
|
|
1e38ed9efc | ||
|
|
2d48dd2fef | ||
|
|
60aa899a34 | ||
|
|
c38c75fdec | ||
|
|
cf275f4edd | ||
|
|
121f4afed8 | ||
|
|
c8621c3a29 | ||
|
|
f83da15d5e | ||
|
|
52729d9802 | ||
|
|
69c25309da | ||
|
|
723a12fd66 | ||
|
|
5cf74f1ee9 | ||
|
|
1fef4f7c11 | ||
|
|
ddb4b9d3e5 | ||
|
|
e6f92eaceb |
@@ -2,6 +2,7 @@
|
||||
name: Build
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
push:
|
||||
branches: master
|
||||
|
||||
@@ -4,7 +4,7 @@ name: Yugabyte
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '10 3 * * *'
|
||||
- cron: '10 3 * * 3'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
@@ -59,11 +59,6 @@ Work at the highest level of abstraction and drop down levels as needed.
|
||||
<img width="222px" src="https://group.foconis.com/download/ci/logo/png-72dpi/logo-quer/foconis-analytics-quer.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://www.payintech.com/" target="_blank">
|
||||
<img width="222px" src="https://ebean.io/images/sponsor_PayinTech-logo-noir.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://www.premium-minds.com" target="_blank">
|
||||
<img width="222px" src="https://ebean.io/images/logo-med-principal.png">
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-clickhouse</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-db2</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-hana</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-mariadb</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-mysql</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -22,13 +22,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -47,19 +47,19 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-net-postgis-types</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-nuodb</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-oracle</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -22,13 +22,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -47,19 +47,19 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis-types</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlite</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlserver</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -41,7 +41,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-mapper</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -60,13 +60,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-all</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>composites</artifactId>
|
||||
|
||||
+1
-18
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean api</name>
|
||||
@@ -86,23 +86,6 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- JAVAX-DEPENDENCY-START ___
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
____ JAVAX-DEPENDENCY-END -->
|
||||
<!-- JAKARTA-DEPENDENCY-START -->
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<version>6.0.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!-- JAKARTA-DEPENDENCY-END -->
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package io.ebean;
|
||||
|
||||
/**
|
||||
* Unsupported access of a property on an entity bean.
|
||||
* <p>
|
||||
* Attempted a lazy load operation on a bean that has disabled lazy loading
|
||||
* or attempt to mutate an unmodifiable bean.
|
||||
*/
|
||||
public class BeanAccessException extends UnsupportedOperationException {
|
||||
private static final long serialVersionUID = 1;
|
||||
|
||||
/**
|
||||
* Create with no message.
|
||||
*/
|
||||
public BeanAccessException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create with message.
|
||||
*/
|
||||
public BeanAccessException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -89,12 +89,7 @@ public interface BeanState {
|
||||
* <p>
|
||||
* If a setter is called on a readOnly bean it will throw an exception.
|
||||
*/
|
||||
boolean isReadOnly();
|
||||
|
||||
/**
|
||||
* Set the readOnly status for the bean.
|
||||
*/
|
||||
void setReadOnly(boolean readOnly);
|
||||
boolean isUnmodifiable();
|
||||
|
||||
/**
|
||||
* Advanced - Used to programmatically build a partially or fully loaded
|
||||
|
||||
@@ -605,7 +605,7 @@ public final class DB {
|
||||
* // find orders and their customers
|
||||
* List<Order> list = DB.find(Order.class)
|
||||
* .fetch("customer")
|
||||
* .order("id")
|
||||
* .orderBy("id")
|
||||
* .findList();
|
||||
*
|
||||
* // sort by customer name ascending, then by order shipDate
|
||||
|
||||
@@ -400,7 +400,7 @@ public interface Database {
|
||||
* // find orders and their customers
|
||||
* List<Order> list = database.find(Order.class)
|
||||
* .fetch("customer")
|
||||
* .order("id")
|
||||
* .orderBy("id")
|
||||
* .findList();
|
||||
*
|
||||
* // sort by customer name ascending, then by order shipDate
|
||||
@@ -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>
|
||||
|
||||
@@ -53,14 +53,6 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
Query<T> orderById(boolean orderById);
|
||||
|
||||
/**
|
||||
* @deprecated migrate to {@link #orderBy(String)}
|
||||
*/
|
||||
@Deprecated(since = "13.19", forRemoval = true)
|
||||
default ExpressionList<T> order(String orderByClause) {
|
||||
return orderBy(orderByClause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the order by clause replacing the existing order by clause if there is
|
||||
* one.
|
||||
@@ -71,14 +63,6 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> orderBy(String orderBy);
|
||||
|
||||
/**
|
||||
* @deprecated migrate to {@link #orderBy()}.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
default OrderBy<T> order() {
|
||||
return orderBy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the OrderBy so that you can append an ascending or descending
|
||||
* property to the order by clause.
|
||||
@@ -221,21 +205,6 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
int delete();
|
||||
|
||||
/**
|
||||
* @deprecated migrate to {@link #usingTransaction(Transaction)} then delete().
|
||||
* <p>
|
||||
* Execute as a delete query deleting the 'root level' beans that match the predicates
|
||||
* in the query.
|
||||
* <p>
|
||||
* Note that if the query includes joins then the generated delete statement may not be
|
||||
* optimal depending on the database platform.
|
||||
* </p>
|
||||
*
|
||||
* @return the number of rows that were deleted.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "13.1.0")
|
||||
int delete(Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute as a update query.
|
||||
*
|
||||
@@ -244,17 +213,6 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
int update();
|
||||
|
||||
/**
|
||||
* @deprecated migrate to {@link #usingTransaction(Transaction)} then update().
|
||||
* <p>
|
||||
* Execute as a update query with the given transaction.
|
||||
*
|
||||
* @return the number of rows that were updated.
|
||||
* @see UpdateQuery
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "13.1.0")
|
||||
int update(Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the query returning true if a row is found.
|
||||
* <p>
|
||||
@@ -355,7 +313,7 @@ public interface ExpressionList<T> {
|
||||
* List<String> names =
|
||||
* DB.find(Customer.class)
|
||||
* .select("name")
|
||||
* .order().asc("name")
|
||||
* .orderBy().asc("name")
|
||||
* .findSingleAttributeList();
|
||||
*
|
||||
* }</pre>
|
||||
@@ -368,7 +326,7 @@ public interface ExpressionList<T> {
|
||||
* .setDistinct(true)
|
||||
* .select("name")
|
||||
* .where().eq("status", Customer.Status.NEW)
|
||||
* .order().asc("name")
|
||||
* .orderBy().asc("name")
|
||||
* .setMaxRows(100)
|
||||
* .findSingleAttributeList();
|
||||
*
|
||||
@@ -1713,7 +1671,7 @@ public interface ExpressionList<T> {
|
||||
* .eq("status", Customer.Status.ACTIVE)
|
||||
* .gt("id", 0)
|
||||
* .endAnd()
|
||||
* .order().asc("name")
|
||||
* .orderBy().asc("name")
|
||||
* .findList();
|
||||
* }</pre>
|
||||
*/
|
||||
@@ -1734,7 +1692,7 @@ public interface ExpressionList<T> {
|
||||
* .or()
|
||||
* .eq("status", Customer.Status.ACTIVE)
|
||||
* .isNull("anniversary")
|
||||
* .order().asc("name")
|
||||
* .orderBy().asc("name")
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
@@ -1754,7 +1712,7 @@ public interface ExpressionList<T> {
|
||||
* .eq("status", Customer.Status.ACTIVE)
|
||||
* .gt("id", 0)
|
||||
* .endAnd()
|
||||
* .order().asc("name")
|
||||
* .orderBy().asc("name")
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
@@ -1788,7 +1746,7 @@ public interface ExpressionList<T> {
|
||||
* .gt("id", 1)
|
||||
* .eq("anniversary", onAfter)
|
||||
* .endNot()
|
||||
* .order()
|
||||
* .orderBy()
|
||||
* .asc("name")
|
||||
* .findList();
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -35,7 +35,7 @@ import java.util.List;
|
||||
* public List<Customer> findNew() {
|
||||
* return query().where()
|
||||
* .eq("status", Customer.Status.NEW)
|
||||
* .order("name")
|
||||
* .orderBy("name")
|
||||
* .findList()
|
||||
* }
|
||||
* }
|
||||
|
||||
@@ -61,7 +61,7 @@ package io.ebean;
|
||||
* .eq("status", Customer.Status.ACTIVE)
|
||||
* .gt("id", 0)
|
||||
* .endAnd()
|
||||
* .order().asc("name");
|
||||
* .orderBy().asc("name");
|
||||
*
|
||||
* q.findList();
|
||||
* String s = q.getGeneratedSql();
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
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 BeanAccessException {
|
||||
|
||||
/**
|
||||
* Create specifying the property that was being accessed.
|
||||
*/
|
||||
public LazyInitialisationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -16,4 +16,7 @@ public interface ModifyAwareType {
|
||||
*/
|
||||
void setMarkedDirty(boolean markedDirty);
|
||||
|
||||
default Object freeze() {
|
||||
return this; // throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import java.util.concurrent.Future;
|
||||
*
|
||||
* PagedList<Order> pagedList = DB.find(Order.class)
|
||||
* .where().eq("status", Order.Status.NEW)
|
||||
* .order().asc("id")
|
||||
* .orderBy().asc("id")
|
||||
* .setFirstRow(0)
|
||||
* .setMaxRows(50)
|
||||
* .findPagedList();
|
||||
|
||||
@@ -30,7 +30,7 @@ import java.util.Objects;
|
||||
* .where()
|
||||
* .eq("store", "def")
|
||||
* .inPairs(pairs) // IN clause with 'pairs' of values
|
||||
* .order("sku desc")
|
||||
* .orderBy("sku desc")
|
||||
*
|
||||
* // query expressions cover the natural key properties
|
||||
* // so we can choose to hit the L2 bean cache if we want
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.jspecify.annotations.NullMarked;
|
||||
* .where()
|
||||
* .like("customer.name","rob%")
|
||||
* .gt("orderDate",lastWeek)
|
||||
* .order("customer.id, id desc")
|
||||
* .orderBy("customer.id, id desc")
|
||||
* .setMaxRows(50)
|
||||
* .findList();
|
||||
*
|
||||
@@ -218,29 +218,6 @@ public interface Query<T> extends CancelableQuery, QueryBuilder<Query<T>, T> {
|
||||
*/
|
||||
boolean isCountDistinct();
|
||||
|
||||
/**
|
||||
* @deprecated migrate to {@link #usingTransaction(Transaction)} then delete().
|
||||
* <p>
|
||||
* Execute as a delete query returning the number of rows deleted using the given transaction.
|
||||
* <p>
|
||||
* Note that if the query includes joins then the generated delete statement may not be
|
||||
* optimal depending on the database platform.
|
||||
*
|
||||
* @return the number of beans/rows that were deleted.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "14.1.0")
|
||||
int delete(Transaction transaction);
|
||||
|
||||
/**
|
||||
* @deprecated migrate to {@link #usingTransaction(Transaction)} then update().
|
||||
* <p>
|
||||
* Execute the UpdateQuery returning the number of rows updated using the given transaction.
|
||||
*
|
||||
* @return the number of beans/rows updated.
|
||||
*/
|
||||
@Deprecated(forRemoval = true, since = "14.1.0")
|
||||
int update(Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the UpdateQuery returning the number of rows updated.
|
||||
*
|
||||
@@ -440,30 +417,6 @@ public interface Query<T> extends CancelableQuery, QueryBuilder<Query<T>, T> {
|
||||
*/
|
||||
Query<T> having(Expression addExpressionToHaving);
|
||||
|
||||
/**
|
||||
* @deprecated migrate to {@link #orderBy()}.
|
||||
*/
|
||||
@Deprecated(since = "13.19", forRemoval = true)
|
||||
default Query<T> order(String orderByClause) {
|
||||
return orderBy(orderByClause);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated migrate to {@link #orderBy()}.
|
||||
*/
|
||||
@Deprecated(since = "13.19", forRemoval = true)
|
||||
default OrderBy<T> order() {
|
||||
return orderBy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated migrate to {@link #setOrderBy(OrderBy)}.
|
||||
*/
|
||||
@Deprecated(since = "13.19", forRemoval = true)
|
||||
default Query<T> setOrder(OrderBy<T> orderBy) {
|
||||
return setOrderBy(orderBy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the OrderBy so that you can append an ascending or descending
|
||||
* property to the order by clause.
|
||||
|
||||
@@ -388,9 +388,13 @@ 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 read only.
|
||||
* 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}.
|
||||
*/
|
||||
SELF setReadOnly(boolean readOnly);
|
||||
SELF setUnmodifiable(boolean unmodifiable);
|
||||
|
||||
/**
|
||||
* Set a timeout on this query.
|
||||
|
||||
@@ -25,7 +25,7 @@ import java.util.Iterator;
|
||||
*
|
||||
* Query<Customer> query = database.find(Customer.class)
|
||||
* .where().gt("id", 0)
|
||||
* .order("id")
|
||||
* .orderBy("id")
|
||||
* .setMaxRows(2);
|
||||
*
|
||||
* QueryIterator<Customer> it = query.findIterate();
|
||||
|
||||
@@ -111,7 +111,7 @@ package io.ebean;
|
||||
* .fetch("order.customer", "name")
|
||||
* .where().gt("order.id", 0)
|
||||
* .having().gt("totalAmount", 20)
|
||||
* .order().desc("totalAmount")
|
||||
* .orderBy().desc("totalAmount")
|
||||
* .setMaxRows(10)
|
||||
* .findList();
|
||||
*
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package io.ebean;
|
||||
|
||||
/**
|
||||
* Attempted to modify a read only entity.
|
||||
*/
|
||||
public class UnmodifiableEntityException extends BeanAccessException {
|
||||
private static final long serialVersionUID = 1;
|
||||
|
||||
/**
|
||||
* Create with no message.
|
||||
*/
|
||||
public UnmodifiableEntityException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create with message.
|
||||
*/
|
||||
public UnmodifiableEntityException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -119,18 +119,6 @@ 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.
|
||||
*/
|
||||
@@ -237,7 +225,7 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
|
||||
boolean wasTouched();
|
||||
|
||||
/**
|
||||
* Return a shallow copy of this collection that is modifiable.
|
||||
* Freeze the collection returning an unmodifiable version.
|
||||
*/
|
||||
BeanCollection<E> shallowCopy();
|
||||
Object freeze();
|
||||
}
|
||||
|
||||
@@ -148,18 +148,6 @@ 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).
|
||||
*/
|
||||
@@ -393,11 +381,6 @@ public interface EntityBeanIntercept extends Serializable {
|
||||
*/
|
||||
void loadBean(int loadProperty);
|
||||
|
||||
/**
|
||||
* Invoke the lazy loading. This method is synchronised externally.
|
||||
*/
|
||||
void loadBeanInternal(int loadProperty, BeanLoader loader);
|
||||
|
||||
/**
|
||||
* Called when a BeanCollection is initialised automatically.
|
||||
*/
|
||||
@@ -552,4 +535,9 @@ 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();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
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,37 +1,44 @@
|
||||
package io.ebean.bean;
|
||||
|
||||
import io.ebean.LazyInitialisationException;
|
||||
import io.ebean.UnmodifiableEntityException;
|
||||
import io.ebean.ValuePair;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 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, loaded, dirty state, original values
|
||||
* required for updates such as per property changed, dirty state, original values
|
||||
* bean state etc.
|
||||
*/
|
||||
public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
public final class InterceptReadOnly extends InterceptBase {
|
||||
|
||||
private final EntityBean owner;
|
||||
private final boolean[] loaded;
|
||||
private boolean frozen;
|
||||
|
||||
/**
|
||||
* Create with a given entity.
|
||||
*/
|
||||
public InterceptReadOnly(Object ownerBean) {
|
||||
this.owner = (EntityBean) ownerBean;
|
||||
super(ownerBean);
|
||||
this.loaded = new boolean[owner._ebean_getPropertyNames().length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean freeze() {
|
||||
if (frozen) {
|
||||
return false;
|
||||
} else {
|
||||
frozen = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InterceptReadOnly{" + owner + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityBean owner() {
|
||||
return owner;
|
||||
return "InterceptReadOnly{frozen:" + frozen + " loaded:" + loadedPropertyNames() + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,18 +101,13 @@ public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
@@ -136,7 +138,14 @@ public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
|
||||
@Override
|
||||
public boolean hasIdOnly(int idIndex) {
|
||||
return false;
|
||||
for (int i = 0; i < loaded.length; i++) {
|
||||
if (i == idIndex) {
|
||||
if (!loaded[i]) return false;
|
||||
} else if (loaded[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -159,16 +168,6 @@ public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadOnly(boolean readOnly) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setForceUpdate(boolean forceUpdate) {
|
||||
|
||||
@@ -234,44 +233,38 @@ public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int findProperty(String propertyName) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String property(int propertyIndex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int propertyLength() {
|
||||
return 0;
|
||||
return loaded.length;
|
||||
}
|
||||
|
||||
@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 false;
|
||||
return loaded[propertyIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -321,7 +314,16 @@ public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
|
||||
@Override
|
||||
public Set<String> loadedPropertyNames() {
|
||||
return Collections.emptySet();
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -369,14 +371,11 @@ public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuilder loadedPropertyKey() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] loaded() {
|
||||
return new boolean[0];
|
||||
final boolean[] ret = new boolean[loaded.length];
|
||||
System.arraycopy(loaded, 0, ret, 0, ret.length);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -394,14 +393,9 @@ public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadBeanInternal(int loadProperty, BeanLoader loader) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialisedMany(int propertyIndex) {
|
||||
|
||||
loaded[propertyIndex] = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -416,12 +410,14 @@ public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
|
||||
@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
|
||||
@@ -436,57 +432,57 @@ public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
|
||||
@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
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebean.bean;
|
||||
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.LazyInitialisationException;
|
||||
import io.ebean.ValuePair;
|
||||
|
||||
import jakarta.persistence.EntityNotFoundException;
|
||||
@@ -22,7 +23,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 implements EntityBeanIntercept {
|
||||
public final class InterceptReadWrite extends InterceptBase {
|
||||
|
||||
private static final long serialVersionUID = -3664031775464862649L;
|
||||
|
||||
@@ -56,18 +57,13 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
private String ebeanServerName;
|
||||
private boolean deletedFromCollection;
|
||||
|
||||
/**
|
||||
* The actual entity bean that 'owns' this intercept.
|
||||
*/
|
||||
private final EntityBean owner;
|
||||
private EntityBean embeddedOwner;
|
||||
private int embeddedOwnerIndex;
|
||||
/**
|
||||
* One of NEW, REF, UPD.
|
||||
* One of NEW, REFERENCE, LOADED.
|
||||
*/
|
||||
private int state;
|
||||
private boolean forceUpdate;
|
||||
private boolean readOnly;
|
||||
private boolean dirty;
|
||||
/**
|
||||
* Flag set to disable lazy loading.
|
||||
@@ -77,7 +73,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
* 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;
|
||||
@@ -101,7 +96,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
* Create with a given entity.
|
||||
*/
|
||||
public InterceptReadWrite(Object ownerBean) {
|
||||
this.owner = (EntityBean) ownerBean;
|
||||
super(ownerBean);
|
||||
this.flags = new byte[owner._ebean_getPropertyNames().length];
|
||||
}
|
||||
|
||||
@@ -109,16 +104,20 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
* EXPERIMENTAL - Constructor only for use by serialization frameworks.
|
||||
*/
|
||||
public InterceptReadWrite() {
|
||||
this.owner = null;
|
||||
super();
|
||||
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;" : "") +
|
||||
@@ -131,11 +130,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityBean owner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceContext persistenceContext() {
|
||||
return persistenceContext;
|
||||
@@ -200,16 +194,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
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) {
|
||||
@@ -298,16 +282,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
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;
|
||||
@@ -411,25 +385,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
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;
|
||||
@@ -668,18 +623,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
}
|
||||
}
|
||||
|
||||
@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];
|
||||
@@ -703,12 +646,15 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
public void loadBean(int loadProperty) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (disableLazyLoad) {
|
||||
throw new LazyInitialisationException("Property not loaded: " + property(loadProperty));
|
||||
}
|
||||
if (beanLoader == null) {
|
||||
final Database database = DB.byName(ebeanServerName);
|
||||
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;
|
||||
@@ -726,8 +672,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadBeanInternal(int loadProperty, BeanLoader loader) {
|
||||
private void loadBeanInternal(int loadProperty, BeanLoader loader) {
|
||||
if ((flags[loadProperty] & FLAG_LOADED_PROP) != 0) {
|
||||
// race condition where multiple threads calling preGetter concurrently
|
||||
return;
|
||||
@@ -829,7 +774,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
@Override
|
||||
public void preGetter(int propertyIndex) {
|
||||
preGetterCallback(propertyIndex);
|
||||
if (state == STATE_NEW || disableLazyLoad) {
|
||||
if (state == STATE_NEW) {
|
||||
return;
|
||||
}
|
||||
if (!isLoadedProperty(propertyIndex)) {
|
||||
@@ -845,18 +790,12 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
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);
|
||||
|
||||
@@ -17,7 +17,6 @@ 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).
|
||||
@@ -55,7 +54,6 @@ 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
|
||||
@@ -103,22 +101,6 @@ 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
|
||||
// ---------------------------------------------------------
|
||||
@@ -212,14 +194,4 @@ 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,7 +2,6 @@ package io.ebean.common;
|
||||
|
||||
import io.ebean.bean.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@@ -39,6 +38,17 @@ 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);
|
||||
@@ -223,7 +233,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public void add(int index, E element) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
modifyAddition(element);
|
||||
@@ -238,7 +247,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public boolean add(E bean) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
if (list.add(bean)) {
|
||||
@@ -253,7 +261,6 @@ 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)
|
||||
@@ -264,7 +271,6 @@ 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)
|
||||
@@ -275,7 +281,6 @@ 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();
|
||||
@@ -320,9 +325,6 @@ 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());
|
||||
}
|
||||
@@ -338,9 +340,6 @@ 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());
|
||||
}
|
||||
@@ -350,9 +349,6 @@ 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));
|
||||
}
|
||||
@@ -368,7 +364,6 @@ 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);
|
||||
@@ -380,7 +375,6 @@ 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);
|
||||
@@ -394,7 +388,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> beans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
boolean changed = false;
|
||||
@@ -412,7 +405,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> retainBeans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
boolean changed = false;
|
||||
@@ -433,7 +425,6 @@ 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);
|
||||
@@ -453,9 +444,6 @@ 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));
|
||||
}
|
||||
@@ -475,67 +463,4 @@ 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,6 +37,11 @@ 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()) {
|
||||
@@ -217,7 +222,6 @@ 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
|
||||
@@ -243,9 +247,6 @@ 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();
|
||||
}
|
||||
|
||||
@@ -264,15 +265,11 @@ 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);
|
||||
@@ -289,7 +286,6 @@ 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()) {
|
||||
@@ -306,17 +302,16 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
|
||||
@Override
|
||||
public void addBean(E bean) {
|
||||
throw new IllegalStateException("Method not allowed on Map. Please use List instead.");
|
||||
throw new UnsupportedOperationException("Method not allowed on Map. Please use List instead.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeBean(E bean) {
|
||||
throw new IllegalStateException("Method not allowed on Map. Please use List instead.");
|
||||
throw new UnsupportedOperationException("Method not allowed on Map. Please use List instead.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public E remove(Object key) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
E o = map.remove(key);
|
||||
@@ -335,16 +330,6 @@ 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,10 +3,7 @@ package io.ebean.common;
|
||||
import io.ebean.bean.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Set capable of lazy loading and modification aware.
|
||||
@@ -38,6 +35,11 @@ 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);
|
||||
@@ -211,7 +213,6 @@ 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)) {
|
||||
@@ -226,7 +227,6 @@ 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,7 +244,6 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
checkReadOnly();
|
||||
initClear();
|
||||
if (modifyListening) {
|
||||
for (E bean : set) {
|
||||
@@ -275,9 +274,6 @@ 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());
|
||||
}
|
||||
@@ -286,7 +282,6 @@ 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)) {
|
||||
@@ -300,7 +295,6 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> beans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
boolean changed = false;
|
||||
@@ -317,7 +311,6 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> beans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
boolean changed = false;
|
||||
@@ -355,36 +348,4 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,185 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package io.ebean.config;
|
||||
|
||||
import io.ebean.plugin.Lookups;
|
||||
|
||||
/**
|
||||
* Helper to find classes taking into account the context class loader.
|
||||
*/
|
||||
@@ -73,9 +75,8 @@ public class ClassLoadConfig {
|
||||
*/
|
||||
public Object newInstance(String className) {
|
||||
try {
|
||||
Class<?> cls = forName(className);
|
||||
return cls.getDeclaredConstructor().newInstance();
|
||||
} catch (Exception e) {
|
||||
return Lookups.newDefaultInstance(forName(className));
|
||||
} catch (Throwable e) {
|
||||
throw new IllegalArgumentException("Error constructing " + className, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package io.ebean.config;
|
||||
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
|
||||
/**
|
||||
* Provides a Lookup instance for accessing entity/dto fields.
|
||||
*/
|
||||
public interface LookupProvider {
|
||||
|
||||
/**
|
||||
* Return the Lookup.
|
||||
*/
|
||||
Lookup provideLookup();
|
||||
|
||||
}
|
||||
@@ -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,5 +1,6 @@
|
||||
package io.ebean.event;
|
||||
|
||||
import io.ebean.plugin.Lookups;
|
||||
|
||||
/**
|
||||
* Helper to find classes taking into account the context class loader.
|
||||
@@ -12,8 +13,8 @@ class ClassUtil {
|
||||
static Object newInstance(String className) {
|
||||
try {
|
||||
Class<?> cls = forName(className);
|
||||
return cls.getDeclaredConstructor().newInstance();
|
||||
} catch (Exception e) {
|
||||
return Lookups.newDefaultInstance(cls);
|
||||
} catch (Throwable e) {
|
||||
String msg = "Error constructing " + className;
|
||||
throw new IllegalArgumentException(msg, e);
|
||||
}
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
package io.ebean.event;
|
||||
|
||||
import jakarta.servlet.ServletContextEvent;
|
||||
|
||||
/**
|
||||
* Deprecated for removal - no intention to replace. Create your own copy of this
|
||||
* ServletContextListener if needed for your application.
|
||||
* <p>
|
||||
* Listens for webserver server starting and stopping events.
|
||||
* <p>
|
||||
* This should be used when the deployment is into a servlet container where the webapp
|
||||
* can be shutdown or redeployed without the JVM stopping.
|
||||
* </p>
|
||||
* <p>
|
||||
* If deployment is into a container where the JVM is completely shutdown (like spring boot,
|
||||
* runnable war or when using a servlet container that only contains the single webapp and
|
||||
* the JVM is shutdown then this isn't required. Instead we can just rely on the JVM shutdown
|
||||
* hook that Ebean registers.
|
||||
* </p>
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public class ServletContextListener implements jakarta.servlet.ServletContextListener {
|
||||
|
||||
/**
|
||||
* The servlet container is stopping.
|
||||
*/
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent event) {
|
||||
ShutdownManager.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Do nothing on startup.
|
||||
*/
|
||||
@Override
|
||||
public void contextInitialized(ServletContextEvent event) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package io.ebean.plugin;
|
||||
|
||||
import io.ebean.DB;
|
||||
import io.ebean.TxScope;
|
||||
|
||||
/**
|
||||
* Helper object to make AOP generated code simpler.
|
||||
*/
|
||||
public final class AOPTransactionScope {
|
||||
private static boolean enabled = true;
|
||||
|
||||
/**
|
||||
* Entering an enhanced transactional method.
|
||||
*/
|
||||
public static void enter(TxScope txScope) {
|
||||
if (enabled) {
|
||||
server().scopedTransactionEnter(txScope);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exiting an enhanced transactional method.
|
||||
*/
|
||||
public static void exit(Object returnOrThrowable, int opCode) {
|
||||
if (enabled) {
|
||||
server().scopedTransactionExit(returnOrThrowable, opCode);
|
||||
}
|
||||
}
|
||||
|
||||
private static SpiServer server() {
|
||||
return (SpiServer) DB.getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines if the @Transactional does what is supposed to do or is disabled
|
||||
* (useful only unit testing)
|
||||
*
|
||||
* @param enabled if set to false, @Transactional will not create a transaction
|
||||
*/
|
||||
public static void setEnabled(boolean enabled) {
|
||||
AOPTransactionScope.enabled = enabled;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package io.ebean.plugin;
|
||||
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
import io.ebean.config.LookupProvider;
|
||||
|
||||
/**
|
||||
* Provides Lookup instances using potentially module specific Lookups.
|
||||
*/
|
||||
public final class Lookups {
|
||||
|
||||
private static final Map<String, Lookup> LOOKUP_MAP =
|
||||
ServiceLoader.load(LookupProvider.class).stream()
|
||||
.collect(toMap(p -> p.type().getModule().getName(), p -> p.get().provideLookup()));
|
||||
|
||||
private static final Lookup DEFAULT_LOOKUP = MethodHandles.publicLookup();
|
||||
|
||||
private static final MethodType VOID = MethodType.methodType(void.class);
|
||||
|
||||
/**
|
||||
* Return a Lookup ideally for the module associated with the given type.
|
||||
*/
|
||||
public static Lookup getLookup(Class<?> type) {
|
||||
return LOOKUP_MAP.getOrDefault(type.getModule().getName(), DEFAULT_LOOKUP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the default constructor and return a new instance for the given type
|
||||
* potentially using a module specific Lookup instance.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T newDefaultInstance(Class<?> type) throws Throwable {
|
||||
return (T) getLookup(type).findConstructor(type, VOID).invoke();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebean.plugin;
|
||||
|
||||
import io.ebean.Database;
|
||||
import io.ebean.TxScope;
|
||||
import io.ebean.bean.BeanLoader;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
import io.ebean.DatabaseBuilder;
|
||||
@@ -63,4 +64,15 @@ public interface SpiServer extends Database {
|
||||
* Typically due to serialisation or multiple stateless updates.
|
||||
*/
|
||||
void loadBean(EntityBeanIntercept ebi);
|
||||
|
||||
/**
|
||||
* Start an enhanced transactional method.
|
||||
*/
|
||||
void scopedTransactionEnter(TxScope txScope);
|
||||
|
||||
/**
|
||||
* Handle the end of an enhanced Transactional method.
|
||||
*/
|
||||
void scopedTransactionExit(Object returnOrThrowable, int opCode);
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* .fetch("billingAddress","line1, city")
|
||||
* .fetch("billingAddress.country", "*")
|
||||
* .fetch("contacts", "firstName,email")
|
||||
* .order().desc("id")
|
||||
* .orderBy().desc("id")
|
||||
* .findList();
|
||||
*
|
||||
* JsonContext json = DB.json();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
module io.ebean.api {
|
||||
|
||||
uses io.ebean.config.AutoConfigure;
|
||||
uses io.ebean.config.LookupProvider;
|
||||
uses io.ebean.datasource.DataSourceAlertFactory;
|
||||
uses io.ebean.service.BootstrapService;
|
||||
uses io.ebean.service.SpiJsonService;
|
||||
@@ -17,20 +18,19 @@ module io.ebean.api {
|
||||
requires static io.ebean.types;
|
||||
requires static com.fasterxml.jackson.core;
|
||||
requires static com.fasterxml.jackson.databind;
|
||||
requires static jakarta.servlet;
|
||||
|
||||
exports io.ebean;
|
||||
exports io.ebean.bean;
|
||||
exports io.ebean.cache;
|
||||
exports io.ebean.meta;
|
||||
exports io.ebean.common;
|
||||
exports io.ebean.config;
|
||||
exports io.ebean.config.dbplatform;
|
||||
exports io.ebean.docstore;
|
||||
exports io.ebean.event;
|
||||
exports io.ebean.event.readaudit;
|
||||
exports io.ebean.event.changelog;
|
||||
exports io.ebean.common;
|
||||
exports io.ebean.docstore;
|
||||
exports io.ebean.plugin;
|
||||
exports io.ebean.meta;
|
||||
exports io.ebean.metric;
|
||||
exports io.ebean.search;
|
||||
exports io.ebean.service;
|
||||
|
||||
@@ -1 +1 @@
|
||||
ebean-version: 148
|
||||
ebean-version: 149
|
||||
|
||||
+26
-26
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean bom</name>
|
||||
@@ -89,25 +89,25 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -125,13 +125,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-mapper</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -155,37 +155,37 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>kotlin-querybean-generator</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-redis</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-spring-txn</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- platforms -->
|
||||
@@ -193,79 +193,79 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-clickhouse</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-db2</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-h2</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-hana</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-mariadb</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-mysql</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-nuodb</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-oracle</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgres</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis-types</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-sqlite</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-sqlserver</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
@@ -16,7 +16,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -7,6 +7,8 @@ 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.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core</artifactId>
|
||||
@@ -22,7 +22,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -46,7 +46,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -159,21 +159,21 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlserver</artifactId>
|
||||
<version>14.8.1</version>
|
||||
<version>14.10.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -1,34 +1,25 @@
|
||||
package io.ebeaninternal.api;
|
||||
|
||||
import io.ebean.DB;
|
||||
import io.ebean.TxScope;
|
||||
import io.ebean.plugin.AOPTransactionScope;
|
||||
|
||||
/**
|
||||
* Helper object to make AOP generated code simpler.
|
||||
*/
|
||||
public final class HelpScopeTrans {
|
||||
private static boolean enabled = true;
|
||||
|
||||
/**
|
||||
* Entering an enhanced transactional method.
|
||||
*/
|
||||
public static void enter(TxScope txScope) {
|
||||
if (enabled) {
|
||||
server().scopedTransactionEnter(txScope);
|
||||
}
|
||||
AOPTransactionScope.enter(txScope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exiting an enhanced transactional method.
|
||||
*/
|
||||
public static void exit(Object returnOrThrowable, int opCode) {
|
||||
if (enabled) {
|
||||
server().scopedTransactionExit(returnOrThrowable, opCode);
|
||||
}
|
||||
}
|
||||
|
||||
private static SpiEbeanServer server() {
|
||||
return (SpiEbeanServer) DB.getDefault();
|
||||
AOPTransactionScope.exit(returnOrThrowable, opCode);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,6 +29,6 @@ public final class HelpScopeTrans {
|
||||
* @param enabled if set to false, @Transactional will not create a transaction
|
||||
*/
|
||||
public static void setEnabled(boolean enabled) {
|
||||
HelpScopeTrans.enabled = enabled;
|
||||
AOPTransactionScope.setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,4 +55,9 @@ 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);
|
||||
}
|
||||
|
||||
@@ -34,8 +34,8 @@ public final class ScopeTrans {
|
||||
* Explicit set of Exceptions that DO cause a rollback to occur.
|
||||
*/
|
||||
private final ArrayList<Class<? extends Throwable>> rollbackFor;
|
||||
private Boolean restoreBatch;
|
||||
private Boolean restoreBatchOnCascade;
|
||||
private boolean restoreBatch;
|
||||
private boolean restoreBatchOnCascade;
|
||||
private int restoreBatchSize;
|
||||
private Boolean restoreBatchGeneratedKeys;
|
||||
private boolean restoreBatchFlushOnQuery;
|
||||
@@ -61,7 +61,7 @@ public final class ScopeTrans {
|
||||
this.noRollbackFor = txScope.getNoRollbackFor();
|
||||
this.rollbackFor = txScope.getRollbackFor();
|
||||
if (transaction != null) {
|
||||
if (!created && txScope.isBatchSet() || txScope.isBatchOnCascadeSet() || txScope.isBatchSizeSet()) {
|
||||
if (!created) {
|
||||
restoreBatch = transaction.isBatchMode();
|
||||
restoreBatchOnCascade = transaction.isBatchOnCascade();
|
||||
restoreBatchSize = transaction.getBatchSize();
|
||||
@@ -142,16 +142,12 @@ public final class ScopeTrans {
|
||||
transaction.commit();
|
||||
} else {
|
||||
nestedCommit = true;
|
||||
transaction.flush();
|
||||
// restore the batch settings
|
||||
transaction.setFlushOnQuery(restoreBatchFlushOnQuery);
|
||||
if (restoreBatch != null) {
|
||||
transaction.setBatchMode(restoreBatch);
|
||||
}
|
||||
if (restoreBatchOnCascade != null) {
|
||||
transaction.setBatchOnCascade(restoreBatchOnCascade);
|
||||
}
|
||||
if (restoreBatchSize > 0) {
|
||||
transaction.setBatchSize(restoreBatchSize);
|
||||
}
|
||||
transaction.setBatchMode(restoreBatch);
|
||||
transaction.setBatchOnCascade(restoreBatchOnCascade);
|
||||
transaction.setBatchSize(restoreBatchSize);
|
||||
if (restoreBatchGeneratedKeys != null) {
|
||||
transaction.setGetGeneratedKeys(restoreBatchGeneratedKeys);
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ public final class ScopedTransaction extends SpiTransactionProxy {
|
||||
/**
|
||||
* Maybe rollback based on TxScope rollback on settings.
|
||||
*/
|
||||
public Exception caughtThrowable(Exception e) {
|
||||
public <T extends Exception> T caughtThrowable(T e) {
|
||||
return current.caughtThrowable(e);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -216,16 +216,6 @@ public interface SpiEbeanServer extends SpiServer, ExtendedServer, BeanCollectio
|
||||
*/
|
||||
void slowQueryCheck(long executionTimeMicros, int rowCount, SpiQuery<?> query);
|
||||
|
||||
/**
|
||||
* Start an enhanced transactional method.
|
||||
*/
|
||||
void scopedTransactionEnter(TxScope txScope);
|
||||
|
||||
/**
|
||||
* Handle the end of an enhanced Transactional method.
|
||||
*/
|
||||
void scopedTransactionExit(Object returnOrThrowable, int opCode);
|
||||
|
||||
/**
|
||||
* SqlQuery find single attribute.
|
||||
*/
|
||||
|
||||
@@ -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 read only.
|
||||
* Return true if the beans returned by this query should be unmodifiable.
|
||||
*/
|
||||
Boolean isReadOnly();
|
||||
boolean isUnmodifiable();
|
||||
|
||||
/**
|
||||
* Return the query timeout.
|
||||
|
||||
@@ -3,12 +3,7 @@ package io.ebeaninternal.json;
|
||||
import io.ebean.ModifyAwareType;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Modify aware wrapper of a list.
|
||||
@@ -52,6 +47,11 @@ 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,11 +3,7 @@ package io.ebeaninternal.json;
|
||||
import io.ebean.ModifyAwareType;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Map that is wraps an underlying map for the purpose of detecting changes.
|
||||
@@ -51,6 +47,11 @@ 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,10 +3,7 @@ package io.ebeaninternal.json;
|
||||
import io.ebean.ModifyAwareType;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Wraps a Set for the purposes of detecting modifications.
|
||||
@@ -33,6 +30,11 @@ 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();
|
||||
|
||||
+7
-10
@@ -2,6 +2,7 @@ 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;
|
||||
@@ -48,25 +49,21 @@ public final class CachedBeanDataFromBean {
|
||||
if (!desc.isCacheSharableBeans() || !beanEbi.isFullyLoadedBean()) {
|
||||
return null;
|
||||
}
|
||||
if (beanEbi.isReadOnly()) {
|
||||
if (beanEbi instanceof InterceptReadOnly) {
|
||||
return bean;
|
||||
}
|
||||
|
||||
// create a readOnly sharable instance by copying the data
|
||||
EntityBean sharableBean = desc.createEntityBean();
|
||||
EntityBean sharableBean = desc.createEntityBean2(true);
|
||||
BeanProperty idProp = desc.idProperty();
|
||||
if (idProp != null) {
|
||||
Object v = idProp.getValue(bean);
|
||||
idProp.setValue(sharableBean, v);
|
||||
}
|
||||
BeanProperty[] propertiesNonTransient = desc.propertiesNonTransient();
|
||||
for (BeanProperty aPropertiesNonTransient : propertiesNonTransient) {
|
||||
Object v = aPropertiesNonTransient.getValue(bean);
|
||||
aPropertiesNonTransient.setValue(sharableBean, v);
|
||||
for (BeanProperty nonTransient : desc.propertiesNonTransient()) {
|
||||
Object v = nonTransient.getValue(bean);
|
||||
nonTransient.setValue(sharableBean, v);
|
||||
}
|
||||
EntityBeanIntercept intercept = sharableBean._ebean_getIntercept();
|
||||
intercept.setReadOnly(true);
|
||||
intercept.setLoaded();
|
||||
desc.freeze(sharableBean);
|
||||
return sharableBean;
|
||||
}
|
||||
|
||||
|
||||
+3
-4
@@ -1,8 +1,6 @@
|
||||
package io.ebeaninternal.server.cache;
|
||||
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebean.bean.*;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
@@ -25,10 +23,11 @@ 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 {
|
||||
} else if (addManyReferences) {
|
||||
prop.createReferenceIfNull(bean);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,12 +67,8 @@ 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, readOnly)) {
|
||||
if (parentDesc.cacheManyPropLoad(many, beanCollection, parentKey)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -102,9 +98,6 @@ 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());
|
||||
}
|
||||
@@ -212,9 +205,6 @@ 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,6 +4,7 @@ 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;
|
||||
@@ -60,13 +61,8 @@ public final class DefaultBeanState implements BeanState {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return intercept.isReadOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadOnly(boolean readOnly) {
|
||||
intercept.setReadOnly(readOnly);
|
||||
public boolean isUnmodifiable() {
|
||||
return intercept instanceof InterceptReadOnly;
|
||||
}
|
||||
|
||||
@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,7 +8,6 @@ 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;
|
||||
@@ -83,7 +82,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;
|
||||
@@ -151,7 +150,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());
|
||||
@@ -413,19 +412,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
|
||||
@@ -620,7 +609,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
}
|
||||
InheritInfo inheritInfo = desc.inheritInfo();
|
||||
if (inheritInfo == null || inheritInfo.isConcrete()) {
|
||||
return (T) desc.contextRef(pc, null, false, id);
|
||||
return (T) desc.contextRef(pc, id);
|
||||
}
|
||||
return referenceFindOne(type, id, desc);
|
||||
}
|
||||
@@ -680,6 +669,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
return callable.call();
|
||||
} catch (Error e) {
|
||||
throw scopeTrans.caughtError(e);
|
||||
} catch (PersistenceException e) {
|
||||
throw scopeTrans.caughtThrowable(e);
|
||||
} catch (Exception e) {
|
||||
throw new PersistenceException(scopeTrans.caughtThrowable(e));
|
||||
} finally {
|
||||
@@ -699,6 +690,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
runnable.run();
|
||||
} catch (Error e) {
|
||||
throw t.caughtError(e);
|
||||
} catch (PersistenceException e) {
|
||||
throw t.caughtThrowable(e);
|
||||
} catch (Exception e) {
|
||||
throw new PersistenceException(t.caughtThrowable(e));
|
||||
} finally {
|
||||
@@ -1000,7 +993,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
return null;
|
||||
}
|
||||
// Hit the L2 bean cache
|
||||
return desc.cacheBeanGet(id, query.isReadOnly(), pc);
|
||||
return desc.cacheBeanGet(id, query.isUnmodifiable(), pc);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1211,11 +1204,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
SpiOrmQueryRequest<?> request = createQueryRequest(Type.ID_LIST, query);
|
||||
Object result = request.getFromQueryCache();
|
||||
if (result != null) {
|
||||
if (Boolean.FALSE.equals(request.query().isReadOnly())) {
|
||||
return new CopyOnFirstWriteList<>((List<A>) result);
|
||||
} else {
|
||||
return (List<A>) result;
|
||||
}
|
||||
return (List<A>) result;
|
||||
}
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
|
||||
@@ -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(server.dataTimeZone(), resultSet);
|
||||
this.dataReader = new RsetDataReader(false, 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);
|
||||
|
||||
@@ -25,9 +25,9 @@ public interface OrmQueryEngine {
|
||||
<T> T findId(OrmQueryRequest<T> request);
|
||||
|
||||
/**
|
||||
* Execute the findList, findSet, findMap query returning an appropriate BeanCollection.
|
||||
* Execute the findList, findSet, findMap query returning an appropriate Collection.
|
||||
*/
|
||||
<T> BeanCollection<T> findMany(OrmQueryRequest<T> request);
|
||||
<T> Object 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 cacheBeans;
|
||||
return query.isUnmodifiable() ? Collections.unmodifiableList(cacheBeans) : 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 map;
|
||||
return query.isUnmodifiable() ? Collections.unmodifiableMap(map) : map;
|
||||
}
|
||||
|
||||
private ElPropertyValue mapProperty() {
|
||||
@@ -583,7 +583,8 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
if (orderBy != null && !orderBy.isEmpty()) {
|
||||
beanDescriptor.sort(cacheBeans, orderBy.toStringFormat());
|
||||
}
|
||||
return new LinkedHashSet<>(cacheBeans);
|
||||
var set = new LinkedHashSet<>(cacheBeans);
|
||||
return query.isUnmodifiable() ? Collections.unmodifiableSet(set) : set;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -600,9 +601,12 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
//
|
||||
CacheIdLookup<T> idLookup = query.cacheIdLookup();
|
||||
if (idLookup != null) {
|
||||
BeanCacheResult<T> cacheResult = beanDescriptor.cacheIdLookup(persistenceContext, idLookup.idValues());
|
||||
BeanCacheResult<T> cacheResult = beanDescriptor.cacheIdLookup(persistenceContext, query.isUnmodifiable(), 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()) {
|
||||
@@ -613,7 +617,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, naturalKeySet.keys());
|
||||
BeanCacheResult<T> cacheResult = beanDescriptor.naturalKeyLookup(persistenceContext, query.isUnmodifiable(), naturalKeySet.keys());
|
||||
// adjust the query (IN clause) based on the cache hits
|
||||
this.cacheBeans = data.removeHits(cacheResult);
|
||||
return data.allHits();
|
||||
@@ -639,31 +643,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
return null;
|
||||
}
|
||||
|
||||
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;
|
||||
return beanDescriptor.queryCacheGet(cacheKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -780,4 +760,30 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,14 +11,15 @@ import io.ebean.event.changelog.ChangeLogPrepare;
|
||||
import io.ebean.event.changelog.ChangeLogRegister;
|
||||
import io.ebean.event.readaudit.ReadAuditLogger;
|
||||
import io.ebean.event.readaudit.ReadAuditPrepare;
|
||||
import io.ebean.plugin.Lookups;
|
||||
import io.ebean.util.AnnotationUtil;
|
||||
import io.ebeaninternal.api.CoreLog;
|
||||
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Table;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -94,9 +95,9 @@ public class BootupClasses implements Predicate<Class<?>> {
|
||||
public void runServerConfigStartup(DatabaseBuilder config) {
|
||||
for (Class<?> cls : serverConfigStartupCandidates) {
|
||||
try {
|
||||
ServerConfigStartup newInstance = (ServerConfigStartup) cls.getDeclaredConstructor().newInstance();
|
||||
ServerConfigStartup newInstance = Lookups.newDefaultInstance(cls);
|
||||
newInstance.onStart(config);
|
||||
} catch (Exception e) {
|
||||
} catch (Throwable e) {
|
||||
// assume that the desired behavior is to fail - add your own try catch if needed
|
||||
throw new IllegalStateException("Error running ServerConfigStartup " + cls, e);
|
||||
}
|
||||
@@ -206,12 +207,12 @@ public class BootupClasses implements Predicate<Class<?>> {
|
||||
*/
|
||||
private <T> T create(Class<T> cls, boolean logOnException) {
|
||||
try {
|
||||
return cls.getConstructor().newInstance();
|
||||
return Lookups.newDefaultInstance(cls);
|
||||
} catch (NoSuchMethodException e) {
|
||||
log.log(DEBUG, "Ignore/expected - no default constructor: {0}", e.getMessage());
|
||||
return null;
|
||||
|
||||
} catch (Exception e) {
|
||||
} catch (Throwable e) {
|
||||
if (logOnException) {
|
||||
// not expected but we log and carry on
|
||||
log.log(ERROR, "Error creating " + cls, e);
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.sql.SQLException;
|
||||
abstract class AssocOneHelp {
|
||||
|
||||
final BeanPropertyAssocOne<?> property;
|
||||
private final BeanDescriptor<?> target;
|
||||
protected final BeanDescriptor<?> target;
|
||||
private final String path;
|
||||
|
||||
AssocOneHelp(BeanPropertyAssocOne<?> property) {
|
||||
@@ -66,9 +66,8 @@ abstract class AssocOneHelp {
|
||||
if (existing != null) {
|
||||
return existing;
|
||||
}
|
||||
boolean disableLazyLoading = ctx.isDisableLazyLoading();
|
||||
Object ref = target.contextRef(pc, ctx.isReadOnly(), disableLazyLoading, id);
|
||||
if (!disableLazyLoading) {
|
||||
Object ref = target.contextRef(pc, id, ctx.unmodifiable(), ctx.isDisableLazyLoading());
|
||||
if (!ctx.unmodifiable() && !ctx.isDisableLazyLoading()) {
|
||||
ctx.register(path, ((EntityBean) ref)._ebean_getIntercept());
|
||||
}
|
||||
return ref;
|
||||
@@ -81,7 +80,6 @@ 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.createEntityBean();
|
||||
EntityBean embeddedBean = property.targetDescriptor.createEntityBean2(reader.unmodifiable());
|
||||
boolean notNull = false;
|
||||
for (BeanProperty property : property.embeddedProps) {
|
||||
Object value = property.readSet(reader, embeddedBean);
|
||||
@@ -53,7 +53,6 @@ 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;
|
||||
@@ -62,7 +61,7 @@ final class AssocOneHelpEmbedded extends AssocOneHelp {
|
||||
|
||||
@Override
|
||||
Object read(DbReadContext ctx) throws SQLException {
|
||||
EntityBean embeddedBean = property.targetDescriptor.createEntityBean();
|
||||
EntityBean embeddedBean = property.targetDescriptor.createEntityBean2(ctx.unmodifiable());
|
||||
boolean notNull = false;
|
||||
for (BeanProperty property : property.embeddedProps) {
|
||||
Object value = property.readSet(ctx, embeddedBean);
|
||||
@@ -70,12 +69,7 @@ final class AssocOneHelpEmbedded extends AssocOneHelp {
|
||||
notNull = true;
|
||||
}
|
||||
}
|
||||
if (notNull) {
|
||||
ctx.propagateState(embeddedBean);
|
||||
return embeddedBean;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return notNull ? embeddedBean : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -53,9 +53,8 @@ final class AssocOneHelpRefInherit extends AssocOneHelp {
|
||||
return existing;
|
||||
}
|
||||
// for inheritance hierarchy create the correct type for this row...
|
||||
boolean disableLazyLoading = ctx.isDisableLazyLoading();
|
||||
Object ref = desc.contextRef(pc, ctx.isReadOnly(), disableLazyLoading, id);
|
||||
if (!disableLazyLoading) {
|
||||
Object ref = desc.contextRef(pc, id, ctx.unmodifiable(), ctx.isDisableLazyLoading());
|
||||
if (!ctx.unmodifiable() && !ctx.isDisableLazyLoading()) {
|
||||
ctx.registerBeanInherit(property, ((EntityBean) ref)._ebean_getIntercept());
|
||||
}
|
||||
return ref;
|
||||
|
||||
@@ -23,6 +23,7 @@ import io.ebean.meta.QueryPlanInit;
|
||||
import io.ebean.plugin.BeanDocType;
|
||||
import io.ebean.plugin.BeanType;
|
||||
import io.ebean.plugin.ExpressionPath;
|
||||
import io.ebean.plugin.Lookups;
|
||||
import io.ebean.plugin.Property;
|
||||
import io.ebean.util.SplitName;
|
||||
import io.ebeaninternal.api.*;
|
||||
@@ -414,8 +415,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return (EntityBean) beanType.getDeclaredConstructor().newInstance();
|
||||
} catch (Exception e) {
|
||||
return Lookups.newDefaultInstance(beanType);
|
||||
} catch (Throwable e) {
|
||||
throw new IllegalStateException("Error trying to create the prototypeEntityBean for " + beanType, e);
|
||||
}
|
||||
}
|
||||
@@ -687,6 +688,22 @@ 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);
|
||||
}
|
||||
@@ -1189,8 +1206,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, Boolean readOnly) {
|
||||
return cacheHelp.manyPropLoad(many, bc, parentKey, readOnly);
|
||||
public boolean cacheManyPropLoad(BeanPropertyAssocMany<?> many, BeanCollection<?> bc, String parentKey) {
|
||||
return cacheHelp.manyPropLoad(many, bc, parentKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1239,8 +1256,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
/**
|
||||
* Load the entity bean as the correct bean type.
|
||||
*/
|
||||
EntityBean cacheBeanLoadDirect(Object id, Boolean readOnly, CachedBeanData data, PersistenceContext context) {
|
||||
return cacheHelp.loadBeanDirect(id, readOnly, data, context);
|
||||
EntityBean cacheBeanLoadDirect(Object id, boolean unmodifiable, CachedBeanData data, PersistenceContext context) {
|
||||
return cacheHelp.loadBeanDirect(id, unmodifiable, data, context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1278,8 +1295,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 readOnly, PersistenceContext context) {
|
||||
return cacheHelp.beanCacheGet(cacheKey(id), readOnly, context);
|
||||
public T cacheBeanGet(Object id, boolean unmodifiable, PersistenceContext context) {
|
||||
return cacheHelp.beanCacheGet(cacheKey(id), unmodifiable, context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1308,15 +1325,15 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
return cacheHelp.beanCacheLoad(bean, ebi, cacheKey(id), context);
|
||||
}
|
||||
|
||||
public BeanCacheResult<T> cacheIdLookup(PersistenceContext context, Collection<?> ids) {
|
||||
return cacheHelp.cacheIdLookup(context, ids);
|
||||
public BeanCacheResult<T> cacheIdLookup(PersistenceContext context, boolean unmodifiable, Collection<?> ids) {
|
||||
return cacheHelp.cacheIdLookup(context, unmodifiable, ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use natural key lookup to hit the bean cache.
|
||||
*/
|
||||
public BeanCacheResult<T> naturalKeyLookup(PersistenceContext context, Set<Object> keys) {
|
||||
return cacheHelp.naturalKeyLookup(context, keys);
|
||||
public BeanCacheResult<T> naturalKeyLookup(PersistenceContext context, boolean unmodifiable, Set<Object> keys) {
|
||||
return cacheHelp.naturalKeyLookup(context, unmodifiable, keys);
|
||||
}
|
||||
|
||||
public void cacheNaturalKeyPut(String key, String newKey) {
|
||||
@@ -1764,10 +1781,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(Boolean readOnly, Object id, PersistenceContext pc) {
|
||||
public EntityBean createReference(PersistenceContext pc, Object id) {
|
||||
Object refBean = contextGet(pc, id);
|
||||
if (refBean == null) {
|
||||
refBean = createReference(readOnly, false, id, pc);
|
||||
refBean = createReference(false, false, id, pc);
|
||||
}
|
||||
return (EntityBean) refBean;
|
||||
}
|
||||
@@ -1776,8 +1793,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
* Create a reference bean based on the id.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public T createReference(Boolean readOnly, boolean disableLazyLoad, Object id, PersistenceContext pc) {
|
||||
if (cacheSharableBeans && !disableLazyLoad && !Boolean.FALSE.equals(readOnly)) {
|
||||
public T createReference(boolean unmodifiable, boolean disableLazyLoad, Object id, PersistenceContext pc) {
|
||||
if (cacheSharableBeans && unmodifiable) {
|
||||
CachedBeanData d = cacheHelp.beanCacheGetData(cacheKey(id));
|
||||
if (d != null) {
|
||||
Object shareableBean = d.getSharableBean();
|
||||
@@ -1793,18 +1810,15 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
if (inheritInfo != null && !inheritInfo.isConcrete()) {
|
||||
return findReferenceBean(id, pc);
|
||||
}
|
||||
EntityBean eb = createEntityBean();
|
||||
EntityBean eb = createEntityBean2(unmodifiable);
|
||||
id = convertSetId(id, eb);
|
||||
EntityBeanIntercept ebi = eb._ebean_getIntercept();
|
||||
if (disableLazyLoad) {
|
||||
ebi.setDisableLazyLoad(true);
|
||||
} else {
|
||||
} else if (!unmodifiable) {
|
||||
ebi.setBeanLoader(refBeanLoader());
|
||||
}
|
||||
ebi.setReference(idPropertyIndex);
|
||||
if (Boolean.TRUE == readOnly) {
|
||||
ebi.setReadOnly(true);
|
||||
}
|
||||
if (pc != null) {
|
||||
contextPut(pc, id, eb);
|
||||
ebi.setPersistenceContext(pc);
|
||||
@@ -2029,11 +2043,12 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
return pc.putIfAbsent(rootBeanType, id, localBean);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2148,7 +2163,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.setValueIntercept(bean, idValue);
|
||||
idProperty.setValue(bean, idValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -3186,8 +3201,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
* provides unique ordering of the rows (so that the paging is predicable).
|
||||
*/
|
||||
public void appendOrderById(SpiQuery<T> query) {
|
||||
if (idProperty != null && !idProperty.isEmbedded() && !query.order().containsProperty(idProperty.name())) {
|
||||
query.order().asc(idProperty.name());
|
||||
if (idProperty != null && !idProperty.isEmbedded() && !query.orderBy().containsProperty(idProperty.name())) {
|
||||
query.orderBy().asc(idProperty.name());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+29
-33
@@ -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 readOnly) {
|
||||
boolean manyPropLoad(BeanPropertyAssocMany<?> many, BeanCollection<?> bc, String parentKey) {
|
||||
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(readOnly, id, persistenceContext);
|
||||
final EntityBean ref = targetDescriptor.createReference(persistenceContext, id);
|
||||
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, Collection<?> ids) {
|
||||
BeanCacheResult<T> cacheIdLookup(PersistenceContext context, boolean unmodifiable, 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(), false, context, cachedBeanData);
|
||||
T bean = convertToBean(entry.getKey(), unmodifiable, 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, Set<Object> keys) {
|
||||
BeanCacheResult<T> naturalKeyLookup(PersistenceContext context, boolean unmodifiable, 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, false, context, cachedBeanData);
|
||||
T bean = convertToBean(id, unmodifiable, 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 readOnly, PersistenceContext context) {
|
||||
T bean = beanCacheGetInternal(key, readOnly, context);
|
||||
if (bean != null) {
|
||||
T beanCacheGet(String key, boolean unmodifiable, PersistenceContext context) {
|
||||
T bean = beanCacheGetInternal(key, unmodifiable, context);
|
||||
if (bean != null && !unmodifiable) {
|
||||
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 readOnly, PersistenceContext context) {
|
||||
private T beanCacheGetInternal(String key, boolean unmodifiable, 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, readOnly, context, data);
|
||||
return convertToBean(key, unmodifiable, context, data);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private T convertToBean(Object id, Boolean readOnly, PersistenceContext context, CachedBeanData data) {
|
||||
if (cacheSharableBeans && !Boolean.FALSE.equals(readOnly)) {
|
||||
private T convertToBean(Object id, boolean unmodifiable, PersistenceContext context, CachedBeanData data) {
|
||||
if (cacheSharableBeans && unmodifiable) {
|
||||
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, readOnly, data, context);
|
||||
return (T) loadBean(id, unmodifiable, data, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the entity bean taking into account inheritance.
|
||||
*/
|
||||
private EntityBean loadBean(Object id, Boolean readOnly, CachedBeanData data, PersistenceContext context) {
|
||||
private EntityBean loadBean(Object id, boolean unmodifiable, CachedBeanData data, PersistenceContext context) {
|
||||
String discValue = data.getDiscValue();
|
||||
if (discValue == null) {
|
||||
return loadBeanDirect(id, readOnly, data, context);
|
||||
return loadBeanDirect(id, unmodifiable, data, context);
|
||||
} else {
|
||||
return rootDescriptor(discValue).cacheBeanLoadDirect(id, readOnly, data, context);
|
||||
return rootDescriptor(discValue).cacheBeanLoadDirect(id, unmodifiable, data, context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -625,26 +625,22 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
/**
|
||||
* Load the entity bean from cache data given this is the root bean type.
|
||||
*/
|
||||
EntityBean loadBeanDirect(Object id, Boolean readOnly, CachedBeanData data, PersistenceContext context) {
|
||||
EntityBean loadBeanDirect(Object id, boolean unmodifiable, CachedBeanData data, PersistenceContext context) {
|
||||
id = desc.convertId(id);
|
||||
EntityBean bean = null;
|
||||
if (context == null) {
|
||||
context = new DefaultPersistenceContext();
|
||||
} else {
|
||||
bean = (EntityBean) desc.contextGet(context, id);
|
||||
}
|
||||
EntityBean bean = context == null ? null : (EntityBean) desc.contextGet(context, id);;
|
||||
if (bean == null) {
|
||||
bean = desc.createEntityBean();
|
||||
bean = desc.createEntityBean2(unmodifiable);
|
||||
desc.setId(id, bean);
|
||||
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);
|
||||
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());
|
||||
}
|
||||
ebi.setPersistenceContext(context);
|
||||
}
|
||||
|
||||
CachedBeanDataToBean.load(desc, bean, data, context);
|
||||
|
||||
+3
-2
@@ -3,6 +3,7 @@ package io.ebeaninternal.server.deploy;
|
||||
import io.ebean.PersistenceIOException;
|
||||
import io.ebean.SqlUpdate;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.plugin.Lookups;
|
||||
import io.ebeaninternal.api.json.SpiJsonReader;
|
||||
import io.ebeaninternal.api.json.SpiJsonWriter;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
@@ -22,8 +23,8 @@ class BeanDescriptorElementEmbedded<T> extends BeanDescriptorElement<T> {
|
||||
BeanDescriptorElementEmbedded(BeanDescriptorMap owner, DeployBeanDescriptor<T> deploy, ElementHelp elementHelp) {
|
||||
super(owner, deploy, elementHelp);
|
||||
try {
|
||||
this.prototype = (EntityBean) beanType.getDeclaredConstructor().newInstance();
|
||||
} catch (Exception e) {
|
||||
this.prototype = Lookups.newDefaultInstance(beanType);
|
||||
} catch (Throwable e) {
|
||||
throw new IllegalStateException("Unable to create entity bean prototype for "+beanType);
|
||||
}
|
||||
BeanPropertyAssocOne<?>[] embedded = propertiesEmbedded();
|
||||
|
||||
@@ -1002,11 +1002,8 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
|
||||
if (!(mappedProp instanceof DeployBeanPropertyAssocOne<?>)) {
|
||||
throw new PersistenceException("Error on " + prop + ". mappedBy property " + targetDesc + "." + mappedBy + " is not a OneToOne?");
|
||||
}
|
||||
DeployBeanPropertyAssocOne<?> mappedAssocOne = (DeployBeanPropertyAssocOne<?>) mappedProp;
|
||||
if (!mappedAssocOne.isOneToOne()) {
|
||||
throw new PersistenceException("Error on " + prop + ". mappedBy property " + targetDesc + "." + mappedBy + " is not a OneToOne?");
|
||||
}
|
||||
return mappedAssocOne;
|
||||
// this is allowed to be a OneToOne or ManyToOne
|
||||
return (DeployBeanPropertyAssocOne<?>) mappedProp;
|
||||
}
|
||||
|
||||
private void checkUniDirectionalPrimaryKeyJoin(DeployBeanPropertyAssocOne<?> prop) {
|
||||
|
||||
@@ -2,6 +2,7 @@ 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;
|
||||
@@ -1519,4 +1520,15 @@ 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,7 +427,9 @@ public abstract class BeanPropertyAssoc<T> extends BeanProperty implements STree
|
||||
BeanProperty[] others = target.propertiesBaseScalar();
|
||||
if (descriptor.isRawSqlBased()) {
|
||||
String dbColumn = owner.dbColumn();
|
||||
return new ImportedIdSimple(owner, dbColumn, null, idProp, 0);
|
||||
if (dbColumn != null) {
|
||||
return new ImportedIdSimple(owner, dbColumn, null, idProp, 0);
|
||||
}
|
||||
}
|
||||
if (idProp == null) {
|
||||
return null;
|
||||
|
||||
@@ -1165,4 +1165,22 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -663,6 +663,14 @@ 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,16 +14,6 @@ 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.
|
||||
*/
|
||||
@@ -102,4 +92,14 @@ 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() {
|
||||
return descriptor.createEntityBean();
|
||||
public EntityBean createEntityBean(boolean unmodifiable) {
|
||||
return descriptor.createEntityBean2(unmodifiable);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user