mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
587
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e29e032693 | ||
|
|
9fc2ec044d | ||
|
|
b739326fca | ||
|
|
88fd4f5569 | ||
|
|
4cca3bfa98 | ||
|
|
8f8d031d91 | ||
|
|
7a327cb644 | ||
|
|
1696caadd4 | ||
|
|
e5dceda4b9 | ||
|
|
eab56d323b | ||
|
|
0b00a14fd3 | ||
|
|
c1d57c6b10 | ||
|
|
1049435f86 | ||
|
|
cee879d2f3 | ||
|
|
93ff2ef2e4 | ||
|
|
d389ac680f | ||
|
|
d582e63c25 | ||
|
|
cb9295658c | ||
|
|
dbc1ab7a57 | ||
|
|
bb9532f42e | ||
|
|
632f04c76b | ||
|
|
bc02eeac57 | ||
|
|
d6dc147497 | ||
|
|
a15e1ae0a7 | ||
|
|
8b98335e2e | ||
|
|
01e07dd2be | ||
|
|
3ac8d6e1d3 | ||
|
|
66143280fa | ||
|
|
e95442d8ec | ||
|
|
aafde53b81 | ||
|
|
0887480865 | ||
|
|
4ff8df9538 | ||
|
|
ddb63c1488 | ||
|
|
aab2dff49c | ||
|
|
d017b2ef39 | ||
|
|
70a967a3a7 | ||
|
|
796edae614 | ||
|
|
50bb7086ac | ||
|
|
af8cf9c6c7 | ||
|
|
6227b081cf | ||
|
|
42645f7236 | ||
|
|
eae8bbac82 | ||
|
|
43451c5342 | ||
|
|
a6f27ca19f | ||
|
|
a7462e86c8 | ||
|
|
0ddcfec70d | ||
|
|
bf70470b9a | ||
|
|
23c5bd65cf | ||
|
|
30aa05a243 | ||
|
|
4ce70e401d | ||
|
|
a2f49a544c | ||
|
|
4d4065c54b | ||
|
|
d072dd52cf | ||
|
|
25b9b37ac0 | ||
|
|
5ea5b55882 | ||
|
|
b69c00b01e | ||
|
|
aa53742a07 | ||
|
|
7c2a77081b | ||
|
|
57c0bceb63 | ||
|
|
8cb43788dc | ||
|
|
921ee9f8a1 | ||
|
|
058e16d1a8 | ||
|
|
a5f9beabdf | ||
|
|
0ed6ccf499 | ||
|
|
fe67abce83 | ||
|
|
7fba9adc43 | ||
|
|
4557bdfa6f | ||
|
|
7a7dbae313 | ||
|
|
12c5e9ea5d | ||
|
|
239a444d4c | ||
|
|
f770b66f42 | ||
|
|
6311d0bf4e | ||
|
|
491d6a5461 | ||
|
|
b142319da0 | ||
|
|
ac21fcb5cf | ||
|
|
455914fb52 | ||
|
|
2419c6ab34 | ||
|
|
8a0403ef6b | ||
|
|
e0afeea6c4 | ||
|
|
dd8b4f6416 | ||
|
|
97482c3372 | ||
|
|
d2e36fc1d2 | ||
|
|
99acd6d64f | ||
|
|
6fe6b8ba64 | ||
|
|
c2b947d2e6 | ||
|
|
7d6b25ff59 | ||
|
|
d9cef737e3 | ||
|
|
2f18e97a44 | ||
|
|
bf3c1629f7 | ||
|
|
1062adede4 | ||
|
|
47c9a434bb | ||
|
|
b2bfca7ec6 | ||
|
|
5d84f10110 | ||
|
|
847ce5db88 | ||
|
|
afdfbd6173 | ||
|
|
c0007d3c1a | ||
|
|
aa27aedca9 | ||
|
|
172c1d10a1 | ||
|
|
da6f7d671b | ||
|
|
6e10d641b2 | ||
|
|
c5dca69482 | ||
|
|
371a50176e | ||
|
|
56fed3ad87 | ||
|
|
9a65731be9 | ||
|
|
34b011f683 | ||
|
|
69c721b66e | ||
|
|
f2a578cd76 | ||
|
|
1e34d65675 | ||
|
|
60db0b0999 | ||
|
|
3bfb6dbc20 | ||
|
|
d4d9bb204d | ||
|
|
bedb841fa9 | ||
|
|
c4c4663144 | ||
|
|
b392db866c | ||
|
|
3556f9a42b | ||
|
|
0345ca9f18 | ||
|
|
eacc4b907d | ||
|
|
09cb5da3d3 | ||
|
|
b22791c15b | ||
|
|
df3eda411a | ||
|
|
5b10c053de | ||
|
|
bf2d75e55e | ||
|
|
6f7efe6922 | ||
|
|
90e321ddbd | ||
|
|
9649d71082 | ||
|
|
932337d83d | ||
|
|
7e4bde8d34 | ||
|
|
01e8b5f471 | ||
|
|
68a6da22be | ||
|
|
986f3b5bca | ||
|
|
4b1bb9d1ee | ||
|
|
ec340c0abe | ||
|
|
b062ec050c | ||
|
|
965f4c6227 | ||
|
|
bdc4022211 | ||
|
|
7edfe3607d | ||
|
|
e1731b87ec | ||
|
|
ebadc92f63 | ||
|
|
ea56ec7435 | ||
|
|
3b990fb6e1 | ||
|
|
96b4fbea4b | ||
|
|
9161e17476 | ||
|
|
190a2c47e9 | ||
|
|
d096706685 | ||
|
|
7521cb530e | ||
|
|
dde9b507ce | ||
|
|
183416a640 | ||
|
|
826e8518ea | ||
|
|
55587b12aa | ||
|
|
285a94e5fe | ||
|
|
16a05528b7 | ||
|
|
b4f4ef3c1b | ||
|
|
cd407ee467 | ||
|
|
9ee63144e5 | ||
|
|
0413d89a9e | ||
|
|
f33e54d8ba | ||
|
|
a2b19d46e1 | ||
|
|
4163b4dc25 | ||
|
|
12220d4322 | ||
|
|
14262d4c25 | ||
|
|
f3ec4a78c9 | ||
|
|
f7a0ae8b4a | ||
|
|
3c6d17c9a5 | ||
|
|
885ba0fdd2 | ||
|
|
f3b0e34b67 | ||
|
|
4109fab0d8 | ||
|
|
0688061f5c | ||
|
|
82c12b1565 | ||
|
|
ebc0fabbdb | ||
|
|
587b2e3075 | ||
|
|
ec82dd3da9 | ||
|
|
3e190b34f5 | ||
|
|
e059ad9172 | ||
|
|
1297324fa9 | ||
|
|
e2b7434d98 | ||
|
|
ada8df5755 | ||
|
|
843b90cbba | ||
|
|
6b263919d5 | ||
|
|
965c1e803f | ||
|
|
a13bc481b8 | ||
|
|
fc7379aabc | ||
|
|
a17683c549 | ||
|
|
eeacad0fb9 | ||
|
|
c51140b59a | ||
|
|
f1817a0dbb | ||
|
|
5b05510bb9 | ||
|
|
b676476cd2 | ||
|
|
709f8ed05f | ||
|
|
31282416d8 | ||
|
|
385c84ae6f | ||
|
|
2d24020202 | ||
|
|
1a2aba3f56 | ||
|
|
f50f0192d1 | ||
|
|
12b8b4b955 | ||
|
|
c267366578 | ||
|
|
18e49cc1ce | ||
|
|
1ce4b1a994 | ||
|
|
f3c87e488a | ||
|
|
f24c698cd5 | ||
|
|
144a3b54bb | ||
|
|
ec7c7048db | ||
|
|
fd2e542c0b | ||
|
|
11e8e3696f | ||
|
|
d08f7af1e0 | ||
|
|
60dfaab22c | ||
|
|
75fa7cb7fd | ||
|
|
e47b1737a8 | ||
|
|
e1ad210bb0 | ||
|
|
ac3edbedf4 | ||
|
|
2dc48cf08d | ||
|
|
ede1ad0a4c | ||
|
|
3e8f76cd6d | ||
|
|
cd6df2be39 | ||
|
|
7091e972fc | ||
|
|
c8ae3c5ef6 | ||
|
|
54e8c4df8a | ||
|
|
e18c190905 | ||
|
|
181dc73d39 | ||
|
|
7ed2de9178 | ||
|
|
8c101fd0a4 | ||
|
|
43213ead05 | ||
|
|
0ef5c65c94 | ||
|
|
c610f95b2d | ||
|
|
c4484c758e | ||
|
|
ee615836ba | ||
|
|
fea7de42d5 | ||
|
|
4787303160 | ||
|
|
801d419f51 | ||
|
|
3579557200 | ||
|
|
202d785710 | ||
|
|
7ca72a39b1 | ||
|
|
f34e0f5f2b | ||
|
|
d98a31fa6b | ||
|
|
9a82dbb3e6 | ||
|
|
a76442641b | ||
|
|
2043fdf7e1 | ||
|
|
a06f7bea41 | ||
|
|
db34afe867 | ||
|
|
589ee7a5ea | ||
|
|
4ba26ee7b7 | ||
|
|
71223895ac | ||
|
|
928b90122f | ||
|
|
d601a88d82 | ||
|
|
443e826f61 | ||
|
|
2691221168 | ||
|
|
e62bb3dc6b | ||
|
|
604099429e | ||
|
|
11dc7f64ba | ||
|
|
ceea705a76 | ||
|
|
d9f7531e81 | ||
|
|
7bd7640c63 | ||
|
|
ca1636ff9e | ||
|
|
ea741d0169 | ||
|
|
c43e2e6956 | ||
|
|
03004452ac | ||
|
|
a470877017 | ||
|
|
777d322222 | ||
|
|
4cebb367de | ||
|
|
1f0ac1f1c1 | ||
|
|
1fad6e910c | ||
|
|
822fb7325a | ||
|
|
20e0eb1021 | ||
|
|
20becf951d | ||
|
|
5aa8557168 | ||
|
|
c66d248e96 | ||
|
|
0d8e7c852b | ||
|
|
991c6d6b5c | ||
|
|
2bc5d3d325 | ||
|
|
5ad8e7ead4 | ||
|
|
8832bbc57f | ||
|
|
86483ff947 | ||
|
|
92d7a7562f | ||
|
|
52fe3cf3c8 | ||
|
|
94fb6414fa | ||
|
|
d0270dbc6a | ||
|
|
11a047bf8e | ||
|
|
eb70c7e196 | ||
|
|
b497b8635b | ||
|
|
5e595ec5f8 | ||
|
|
49b86d07d3 | ||
|
|
11eed4cfe9 | ||
|
|
4aef0ad459 | ||
|
|
21cd74d0ca | ||
|
|
6c262f1df5 | ||
|
|
f32ace4e5a | ||
|
|
e54b7052e0 | ||
|
|
b40d448955 | ||
|
|
33bccd3bcb | ||
|
|
705e4f4098 | ||
|
|
1642833fdb | ||
|
|
492bb98e0e | ||
|
|
a8456f90db | ||
|
|
103b75172d | ||
|
|
0baa3a0eac | ||
|
|
f26e4b5381 | ||
|
|
60ef87b269 | ||
|
|
3d4de4dee5 | ||
|
|
c621435a28 | ||
|
|
7408483a43 | ||
|
|
7e265f7bde | ||
|
|
4d15535381 | ||
|
|
787c2f90f2 | ||
|
|
e590a2149d | ||
|
|
8c77740aa7 | ||
|
|
29582b57f7 | ||
|
|
2763f333d4 | ||
|
|
8840628d34 | ||
|
|
6fb28d7ded | ||
|
|
be810aa568 | ||
|
|
8a698bd71e | ||
|
|
baa0594501 | ||
|
|
e82b8c80f0 | ||
|
|
f8e54be9a6 | ||
|
|
d3137be984 | ||
|
|
824cfa27be | ||
|
|
66cb6d5e7d | ||
|
|
8f432aa0a9 | ||
|
|
4aa4137abe | ||
|
|
f4bb4e1b6a | ||
|
|
7af4e166a4 | ||
|
|
1fa488d870 | ||
|
|
37a3a51b6b | ||
|
|
6a6e8f906f | ||
|
|
55bc498f9d | ||
|
|
4ee784c68f | ||
|
|
fc757c087a | ||
|
|
884dd939b7 | ||
|
|
6fd2f556db | ||
|
|
4e088a40d9 | ||
|
|
8ba66af878 | ||
|
|
441f51ed79 | ||
|
|
9ee891dc66 | ||
|
|
87ffcbf23e | ||
|
|
adfc54200f | ||
|
|
3c36b43449 | ||
|
|
9be1dcff6c | ||
|
|
37dff62fa9 | ||
|
|
4fd462b1c8 | ||
|
|
33ac1923ff | ||
|
|
0b87ae5eac | ||
|
|
678743cc10 | ||
|
|
c8345ce093 | ||
|
|
f3af43a9ce | ||
|
|
1df2ccb1c6 | ||
|
|
3add4472ef | ||
|
|
4613f63c66 | ||
|
|
612295fb9d | ||
|
|
64405ade52 | ||
|
|
ce5f1b25f5 | ||
|
|
ae4f50e7b3 | ||
|
|
c9120be347 | ||
|
|
b189e67b4c | ||
|
|
5d5c275c79 | ||
|
|
52f31a7a8e | ||
|
|
6697aecd48 | ||
|
|
348c075a14 | ||
|
|
bf2420702c | ||
|
|
16832ac67a | ||
|
|
47bd2ff03d | ||
|
|
850f1c1469 | ||
|
|
622a90c7d5 | ||
|
|
4c317f11ae | ||
|
|
01bce5cfa6 | ||
|
|
2158925d3c | ||
|
|
2aff6403a2 | ||
|
|
3c4d600187 | ||
|
|
f60ccb9b90 | ||
|
|
2a6108087c | ||
|
|
0da86a82ae | ||
|
|
643b0499c4 | ||
|
|
676bac390e | ||
|
|
79740accfa | ||
|
|
77c6f1cb9f | ||
|
|
538361d5fd | ||
|
|
b17593ba3c | ||
|
|
eb00690b30 | ||
|
|
a772e65d32 | ||
|
|
66f7f69ec7 | ||
|
|
ad52711fe1 | ||
|
|
d6fdb4ee34 | ||
|
|
4977aa2ad1 | ||
|
|
74c7268d2f | ||
|
|
42fc419759 | ||
|
|
4fb3b9cddc | ||
|
|
c60077174e | ||
|
|
5e893dd2ad | ||
|
|
9eb54da2dc | ||
|
|
bb6ff866c7 | ||
|
|
2d719c5b37 | ||
|
|
9d54b264ad | ||
|
|
65b282a056 | ||
|
|
fc174c8988 | ||
|
|
06802896ef | ||
|
|
7f13ac9e5e | ||
|
|
4a1374d22d | ||
|
|
4ee8d647b7 | ||
|
|
59793f3c01 | ||
|
|
f7f383d8f3 | ||
|
|
562a3959b6 | ||
|
|
bb1275f4f9 | ||
|
|
7fde6b9331 | ||
|
|
3e97a4005a | ||
|
|
c271760230 | ||
|
|
f7c1845f0c | ||
|
|
9b04f20ed3 | ||
|
|
62b6b6293b | ||
|
|
6d8a1c9398 | ||
|
|
303039735f | ||
|
|
6bcf5c6881 | ||
|
|
0527f45f5a | ||
|
|
ba397bbb0c | ||
|
|
a617d58902 | ||
|
|
7fc4a229ae | ||
|
|
f53d31aa2e | ||
|
|
b889b6a6b0 | ||
|
|
f9b55a06b8 | ||
|
|
09d772a5e5 | ||
|
|
f7035eb228 | ||
|
|
1bf09ddd38 | ||
|
|
a8bf27da55 | ||
|
|
ee8bb5ef75 | ||
|
|
bcfd9cab1d | ||
|
|
2a5fd7f3a9 | ||
|
|
f8c37772d4 | ||
|
|
d988dbe69d | ||
|
|
bd7499a505 | ||
|
|
5cb9b9b237 | ||
|
|
819d391495 | ||
|
|
1f0ed629a7 | ||
|
|
91044d0a75 | ||
|
|
57736185d0 | ||
|
|
8992980689 | ||
|
|
f341ff0167 | ||
|
|
abfa841ed7 | ||
|
|
e68adf53bc | ||
|
|
562d175de1 | ||
|
|
b5cef354ad | ||
|
|
dd6a473008 | ||
|
|
09a887aeb7 | ||
|
|
53c903fa48 | ||
|
|
548454c90d | ||
|
|
94bab5f83b | ||
|
|
78965c1ac4 | ||
|
|
00b0fcaeb3 | ||
|
|
f7905c8e94 | ||
|
|
7ab7b612f6 | ||
|
|
ce1d2803ce | ||
|
|
9b066e4eac | ||
|
|
e1f9d106f0 | ||
|
|
e40a539406 | ||
|
|
bb73c30bb7 | ||
|
|
2e16f05a70 | ||
|
|
1837c3443d | ||
|
|
bd1060ff28 | ||
|
|
c9968a9662 | ||
|
|
e3001e8bdd | ||
|
|
82bb2b4567 | ||
|
|
f483002e39 | ||
|
|
c2a87a0c88 | ||
|
|
733886c70b | ||
|
|
899fdca995 | ||
|
|
4731ee034e | ||
|
|
e6faf9efd1 | ||
|
|
d75d1fce43 | ||
|
|
ef3980a3ee | ||
|
|
2a1c170aa4 | ||
|
|
d65e769dd7 | ||
|
|
2bb5a85bd6 | ||
|
|
98aee9ca62 | ||
|
|
c86f965d36 | ||
|
|
ef1143bb70 | ||
|
|
81e445e386 | ||
|
|
2cbbbc4419 | ||
|
|
632f43016e | ||
|
|
fe62ad2ea2 | ||
|
|
f416309863 | ||
|
|
dcf5e7a15c | ||
|
|
af4f70e3a7 | ||
|
|
79dde23ec6 | ||
|
|
e4d0341e67 | ||
|
|
907b182931 | ||
|
|
1a26cd717f | ||
|
|
7bfacb095b | ||
|
|
6315edfc21 | ||
|
|
464f48d717 | ||
|
|
eacfaf3403 | ||
|
|
36d8028045 | ||
|
|
297c1d7abb | ||
|
|
5a73c85e6e | ||
|
|
68138bc009 | ||
|
|
8c7df3212a | ||
|
|
5ebad53072 | ||
|
|
640824ae31 | ||
|
|
6acf93c978 | ||
|
|
6897e06dcd | ||
|
|
d036af8d1a | ||
|
|
b77c62e0db | ||
|
|
bbf46bb0ec | ||
|
|
6aa4337b27 | ||
|
|
99d7a4e4b4 | ||
|
|
b7da2cbd97 | ||
|
|
b4ae721998 | ||
|
|
3bb4126e26 | ||
|
|
de439e7695 | ||
|
|
e5ec72df5c | ||
|
|
98a89156bf | ||
|
|
dc65475dbb | ||
|
|
bab637667d | ||
|
|
cc64ff5f10 | ||
|
|
ab87174e5b | ||
|
|
a6fdc42934 | ||
|
|
4c16b85e85 | ||
|
|
9e3d6c6a08 | ||
|
|
d567872813 | ||
|
|
7069d3f600 | ||
|
|
b2f8b7c711 | ||
|
|
4092ea307e | ||
|
|
01f64ef9f9 | ||
|
|
f1a48b182e | ||
|
|
8ac5467856 | ||
|
|
758f84f573 | ||
|
|
2073fefc92 | ||
|
|
5b98d8d9c2 | ||
|
|
8e59e72983 | ||
|
|
b56d68dac7 | ||
|
|
e0c3a92b60 | ||
|
|
213562fcf1 | ||
|
|
d3a09b93c0 | ||
|
|
536ea57369 | ||
|
|
ac1dd4cbab | ||
|
|
bc33e05906 | ||
|
|
8ecc407cb0 | ||
|
|
2672dff512 | ||
|
|
74d907bbce | ||
|
|
53aacabce7 | ||
|
|
ab9cdd8f5b | ||
|
|
b3d439ed11 | ||
|
|
d57657c209 | ||
|
|
dd080c5933 | ||
|
|
0be98d7989 | ||
|
|
fca54dbbe3 | ||
|
|
7ec5fe6a85 | ||
|
|
9ea5505214 | ||
|
|
75d3b566a7 | ||
|
|
e38059f52c | ||
|
|
72331aa945 | ||
|
|
e497c54f82 | ||
|
|
b44091ff3a | ||
|
|
2ab889f889 | ||
|
|
23541e661e | ||
|
|
6778e37652 | ||
|
|
5eac31283d | ||
|
|
38016773d4 | ||
|
|
ad80eb267f | ||
|
|
449e0832e0 | ||
|
|
f28f5c9a01 | ||
|
|
9dd28d8879 | ||
|
|
b47eec99a5 | ||
|
|
99bb55efa0 | ||
|
|
4408eb618a | ||
|
|
9ccd1b1b27 | ||
|
|
0c1657fef5 | ||
|
|
ee393c6485 | ||
|
|
7f68b9d846 | ||
|
|
2035a3344e | ||
|
|
ade36582a0 | ||
|
|
a4b8be61e3 | ||
|
|
b7feb62ecd | ||
|
|
7e48f7c8eb | ||
|
|
501f8111fe | ||
|
|
d8f4503d98 | ||
|
|
0d83978c58 | ||
|
|
69e56be459 | ||
|
|
35a721039d | ||
|
|
98b4ac5029 | ||
|
|
fe874c946d | ||
|
|
53386e9bf4 | ||
|
|
5435055f5c | ||
|
|
583e10f5c6 | ||
|
|
5393d709a3 | ||
|
|
fc1c9392aa | ||
|
|
6b2c48d4f6 | ||
|
|
400ae3cf4b | ||
|
|
f22a322104 | ||
|
|
e98ff952bf | ||
|
|
573e1b553c | ||
|
|
40a4546ac6 |
@@ -1,9 +1,3 @@
|
||||
|
||||
GITHUB ISSUES ARE STRICTLY CONTROLLED FOR THIS PROJECT.
|
||||
|
||||
Refer to http://ebean-orm.github.io/support for the policies controlling the use of github issues.
|
||||
Please post issues to the Ebean group https://groups.google.com/forum/#!forum/ebean first.
|
||||
|
||||
## Expected behavior
|
||||
|
||||
## Actual behavior
|
||||
|
||||
+1
-1
@@ -293,6 +293,6 @@ ebean.tenant.schemaProvider
|
||||
ebean.updateAllPropertiesInBatch
|
||||
ebean.updateChangesOnly
|
||||
ebean.updatesDeleteMissingChildren
|
||||
ebean.useJavaxValidationNotNull
|
||||
ebean.useValidationNotNull
|
||||
ebean.useJtaTransactionManager
|
||||
|
||||
|
||||
+11
-17
@@ -4,18 +4,13 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.6.3</version>
|
||||
<version>12.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean api</name>
|
||||
<description>ebean api</description>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
|
||||
<properties>
|
||||
<jackson-core.version>2.11.3</jackson-core.version>
|
||||
<jackson-databind.version>2.11.3</jackson-databind.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!--
|
||||
@@ -55,7 +50,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-annotation</artifactId>
|
||||
<version>6.15</version>
|
||||
<version>7.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -74,7 +69,7 @@
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>${jackson-core.version}</version>
|
||||
<version>${jackson.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
@@ -82,7 +77,7 @@
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson-databind.version}</version>
|
||||
<version>${jackson.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
@@ -102,14 +97,6 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- provided scope to read validation annotations Size etc -->
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<version>1.1.0.Final</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
@@ -117,6 +104,13 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.11.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean api</name>
|
||||
<description>ebean api</description>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!--
|
||||
Projects are expected to explicit depend on version
|
||||
of slf4j that they want to use
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.30</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>avaje-config</artifactId>
|
||||
<version>1.3</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
Class retention Nonnull and Nullable annotations
|
||||
to assist with IDE auto-completion with Ebean API
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>avaje-jsr305</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>persistence-api</artifactId>
|
||||
<version>2.2.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-annotation</artifactId>
|
||||
<version>7.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-types</artifactId>
|
||||
<version>2.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-datasource-api</artifactId>
|
||||
<version>${ebean-datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Jackson core used internally by Ebean -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- provided scope for JsonNode support -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Provided scope so that the H2HistoryTrigger can live in Ebean core
|
||||
and not require a separate module for it -->
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>1.4.199</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.transaction</groupId>
|
||||
<artifactId>jta</artifactId>
|
||||
<version>1.1</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -14,7 +14,7 @@ import java.util.Optional;
|
||||
*
|
||||
* public class CustomerFinder extends BeanFinder<Long,Customer> {
|
||||
*
|
||||
* @Inject
|
||||
* @Inject
|
||||
* public CustomerFinder(Database database) {
|
||||
* super(Customer.class, database);
|
||||
* }
|
||||
@@ -79,11 +79,11 @@ public abstract class BeanFinder<I,T> {
|
||||
/**
|
||||
* Creates an entity reference for this ID.
|
||||
* <p>
|
||||
* Equivalent to {@link Database#getReference(Class, Object)}
|
||||
* Equivalent to {@link Database#reference(Class, Object)}
|
||||
*/
|
||||
@Nonnull
|
||||
public T ref(I id) {
|
||||
return db().getReference(type, id);
|
||||
return db().reference(type, id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,10 +9,10 @@ import java.util.Collection;
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* @Repository
|
||||
* @Repository
|
||||
* public class CustomerRepository extends BeanRepository<Long,Customer> {
|
||||
*
|
||||
* @Inject
|
||||
* @Inject
|
||||
* public CustomerRepository(Database server) {
|
||||
* super(Customer.class, server);
|
||||
* }
|
||||
|
||||
@@ -57,7 +57,7 @@ public interface BeanState {
|
||||
*
|
||||
* // set loaded state on the email property to false so that
|
||||
* // the email property is not included in a stateless update
|
||||
* DB.getBeanState(user).setPropertyLoaded("email", false);
|
||||
* DB.beanState(user).setPropertyLoaded("email", false);
|
||||
*
|
||||
* user.update();
|
||||
*
|
||||
@@ -72,25 +72,47 @@ public interface BeanState {
|
||||
* bean.
|
||||
* <p>
|
||||
* Accessing another property will cause lazy loading to occur.
|
||||
* </p>
|
||||
*/
|
||||
Set<String> getLoadedProps();
|
||||
Set<String> loadedProps();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to loadedProps().
|
||||
*/
|
||||
@Deprecated
|
||||
default Set<String> getLoadedProps() {
|
||||
return loadedProps();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the set of changed properties.
|
||||
*/
|
||||
Set<String> getChangedProps();
|
||||
Set<String> changedProps();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to changedProps().
|
||||
*/
|
||||
@Deprecated
|
||||
default Set<String> getChangedProps() {
|
||||
return changedProps();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a map of the updated properties and their new and old values.
|
||||
*/
|
||||
Map<String, ValuePair> getDirtyValues();
|
||||
Map<String, ValuePair> dirtyValues();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to dirtyValues().
|
||||
*/
|
||||
@Deprecated
|
||||
default Map<String, ValuePair> getDirtyValues() {
|
||||
return dirtyValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the bean is readOnly.
|
||||
* <p>
|
||||
* If a setter is called on a readOnly bean it will throw an exception.
|
||||
* </p>
|
||||
*/
|
||||
boolean isReadOnly();
|
||||
|
||||
@@ -114,8 +136,29 @@ public interface BeanState {
|
||||
void resetForInsert();
|
||||
|
||||
/**
|
||||
* Returns a map with load erros.
|
||||
* Returns a map with load errors.
|
||||
*/
|
||||
@Nullable
|
||||
Map<String, Exception> getLoadErrors();
|
||||
Map<String, Exception> loadErrors();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to loadErrors().
|
||||
*/
|
||||
@Deprecated
|
||||
default Map<String, Exception> getLoadErrors() {
|
||||
return loadErrors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the sort order value for an order column.
|
||||
*/
|
||||
int sortOrder();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to sortOrder().
|
||||
*/
|
||||
@Deprecated
|
||||
default int getSortOrder() {
|
||||
return sortOrder();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package io.ebean;
|
||||
|
||||
/**
|
||||
* Defines a cancelable query.
|
||||
* <p>
|
||||
* Typically holds a representation of the PreparedStatement to perform the
|
||||
* actual cancel.
|
||||
* </p>
|
||||
*/
|
||||
public interface CancelableQuery {
|
||||
|
||||
/**
|
||||
* Cancel the query.
|
||||
* <p>
|
||||
* For JDBC this translates to calling cancel on the PreparedStatement.
|
||||
* </p>
|
||||
*/
|
||||
void cancel();
|
||||
}
|
||||
@@ -126,8 +126,16 @@ public final class DB {
|
||||
* an expression that uses OR like Expression e = Expr.or(..., ...);
|
||||
* </p>
|
||||
*/
|
||||
public static ExpressionFactory expressionFactory() {
|
||||
return getDefault().expressionFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated migrate to expressionFactory().
|
||||
*/
|
||||
@Deprecated
|
||||
public static ExpressionFactory getExpressionFactory() {
|
||||
return getDefault().getExpressionFactory();
|
||||
return expressionFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -650,8 +658,16 @@ public final class DB {
|
||||
* @param beanType the type of entity bean
|
||||
* @param id the id value
|
||||
*/
|
||||
public static <T> T reference(Class<T> beanType, Object id) {
|
||||
return getDefault().reference(beanType, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated migrate to beanId().
|
||||
*/
|
||||
@Deprecated
|
||||
public static <T> T getReference(Class<T> beanType, Object id) {
|
||||
return getDefault().getReference(beanType, id);
|
||||
return reference(beanType, id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -660,14 +676,12 @@ public final class DB {
|
||||
* <ul>
|
||||
* <li>asc - ascending order (which is the default)</li>
|
||||
* <li>desc - Descending order</li>
|
||||
* <li>nullsHigh - Treat null values as high/large values (which is the
|
||||
* default)</li>
|
||||
* <li>nullsHigh - Treat null values as high/large values (which is the default)</li>
|
||||
* <li>nullsLow- Treat null values as low/very small values</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* If you leave off any keywords the defaults are ascending order and treating
|
||||
* nulls as high values.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that the sorting uses a Comparator and Collections.sort(); and does
|
||||
* not invoke a DB query.
|
||||
@@ -1231,30 +1245,77 @@ public final class DB {
|
||||
* This will return null if the bean is not an enhanced entity bean.
|
||||
* </p>
|
||||
*/
|
||||
public static BeanState beanState(Object bean) {
|
||||
return getDefault().beanState(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated migrate to beanState().
|
||||
*/
|
||||
@Deprecated
|
||||
public static BeanState getBeanState(Object bean) {
|
||||
return getDefault().getBeanState(bean);
|
||||
return beanState(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value of the Id property for a given bean.
|
||||
*/
|
||||
public static Object beanId(Object bean) {
|
||||
return getDefault().beanId(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated migrate to beanId().
|
||||
*/
|
||||
@Deprecated
|
||||
public static Object getBeanId(Object bean) {
|
||||
return getDefault().getBeanId(bean);
|
||||
return beanId(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and lock the bean using {@code select for update}.
|
||||
* <p>
|
||||
* This should be executed inside a transaction.
|
||||
* <p>
|
||||
* The bean needs to have an ID property set and can be a reference bean (only has ID)
|
||||
* or partially or fully populated bean. This will load all the properties of the bean
|
||||
* from the database using {@code select for update}.
|
||||
*
|
||||
* @param bean The entity bean that we wish to obtain a database lock on.
|
||||
*/
|
||||
public static void lock(Object bean) {
|
||||
getDefault().lock(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated migrate to cacheManager().
|
||||
*/
|
||||
@Deprecated
|
||||
public static ServerCacheManager getServerCacheManager() {
|
||||
return getDefault().cacheManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the manager of the level 2 cache ("L2" cache).
|
||||
*/
|
||||
public static ServerCacheManager getServerCacheManager() {
|
||||
return getDefault().getServerCacheManager();
|
||||
public static ServerCacheManager cacheManager() {
|
||||
return getDefault().cacheManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BackgroundExecutor service for asynchronous processing of
|
||||
* queries.
|
||||
*/
|
||||
public static BackgroundExecutor backgroundExecutor() {
|
||||
return getDefault().backgroundExecutor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated migrate to backgroundExecutor().
|
||||
*/
|
||||
@Deprecated
|
||||
public static BackgroundExecutor getBackgroundExecutor() {
|
||||
return getDefault().getBackgroundExecutor();
|
||||
return backgroundExecutor();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -120,34 +120,82 @@ public interface Database {
|
||||
/**
|
||||
* Return AutoTune which is used to control the AutoTune service at runtime.
|
||||
*/
|
||||
AutoTune getAutoTune();
|
||||
AutoTune autoTune();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to autoTune().
|
||||
*/
|
||||
@Deprecated
|
||||
default AutoTune getAutoTune() {
|
||||
return autoTune();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the associated DataSource for this Database instance.
|
||||
*/
|
||||
DataSource getDataSource();
|
||||
DataSource dataSource();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to dataSource().
|
||||
*/
|
||||
@Deprecated
|
||||
default DataSource getDataSource() {
|
||||
return dataSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the associated read only DataSource for this Database instance (can be null).
|
||||
*/
|
||||
DataSource getReadOnlyDataSource();
|
||||
DataSource readOnlyDataSource();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to readOnlyDataSource().
|
||||
*/
|
||||
@Deprecated
|
||||
default DataSource getReadOnlyDataSource() {
|
||||
return readOnlyDataSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name. This is used with {@link DB#byName(String)} to get a
|
||||
* Database that was registered with the DB singleton.
|
||||
*/
|
||||
String getName();
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to name().
|
||||
*/
|
||||
@Deprecated
|
||||
default String getName() {
|
||||
return name();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ExpressionFactory for this database.
|
||||
*/
|
||||
ExpressionFactory getExpressionFactory();
|
||||
ExpressionFactory expressionFactory();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to expressionFactory().
|
||||
*/
|
||||
@Deprecated
|
||||
default ExpressionFactory getExpressionFactory() {
|
||||
return expressionFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the MetaInfoManager which is used to get meta data from the Database
|
||||
* such as query execution statistics.
|
||||
*/
|
||||
MetaInfoManager getMetaInfoManager();
|
||||
MetaInfoManager metaInfo();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to metaInfo().
|
||||
*/
|
||||
@Deprecated
|
||||
default MetaInfoManager getMetaInfoManager() {
|
||||
return metaInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the platform used for this database instance.
|
||||
@@ -166,12 +214,28 @@ public interface Database {
|
||||
*
|
||||
* @return platform for this database instance
|
||||
*/
|
||||
Platform getPlatform();
|
||||
Platform platform();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to platform().
|
||||
*/
|
||||
@Deprecated
|
||||
default Platform getPlatform() {
|
||||
return platform();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the extended API intended for use by plugins.
|
||||
*/
|
||||
SpiServer getPluginApi();
|
||||
SpiServer pluginApi();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to pluginApi().
|
||||
*/
|
||||
@Deprecated
|
||||
default SpiServer getPluginApi() {
|
||||
return pluginApi();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BeanState for a given entity bean.
|
||||
@@ -179,12 +243,28 @@ public interface Database {
|
||||
* This will return null if the bean is not an enhanced entity bean.
|
||||
* </p>
|
||||
*/
|
||||
BeanState getBeanState(Object bean);
|
||||
BeanState beanState(Object bean);
|
||||
|
||||
/**
|
||||
* Deprecated migrate to beanState().
|
||||
*/
|
||||
@Deprecated
|
||||
default BeanState getBeanState(Object bean) {
|
||||
return beanState(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value of the Id property for a given bean.
|
||||
*/
|
||||
Object getBeanId(Object bean);
|
||||
Object beanId(Object bean);
|
||||
|
||||
/**
|
||||
* Deprecated migrate to beanId().
|
||||
*/
|
||||
@Deprecated
|
||||
default Object getBeanId(Object bean) {
|
||||
return beanId(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Id value onto the bean converting the type of the id value if necessary.
|
||||
@@ -196,7 +276,15 @@ public interface Database {
|
||||
* @param bean The entity bean to set the id value on.
|
||||
* @param id The id value to set.
|
||||
*/
|
||||
Object setBeanId(Object bean, Object id);
|
||||
Object beanId(Object bean, Object id);
|
||||
|
||||
/**
|
||||
* Deprecated migrate to beanId().
|
||||
*/
|
||||
@Deprecated
|
||||
default Object setBeanId(Object bean, Object id) {
|
||||
return beanId(bean, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a map of the differences between two objects of the same type.
|
||||
@@ -862,7 +950,15 @@ public interface Database {
|
||||
* @param id the id value
|
||||
*/
|
||||
@Nonnull
|
||||
<T> T getReference(Class<T> beanType, Object id);
|
||||
<T> T reference(Class<T> beanType, Object id);
|
||||
|
||||
/**
|
||||
* Deprecated migrate to reference().
|
||||
*/
|
||||
@Deprecated
|
||||
default <T> T getReference(Class<T> beanType, Object id) {
|
||||
return reference(beanType, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the extended API for Database.
|
||||
@@ -897,7 +993,7 @@ public interface Database {
|
||||
* <pre>{@code
|
||||
* public class Order { ...
|
||||
*
|
||||
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
|
||||
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
|
||||
* List<OrderDetail> details;
|
||||
* ...
|
||||
* }
|
||||
@@ -1431,13 +1527,29 @@ public interface Database {
|
||||
/**
|
||||
* Return the manager of the server cache ("L2" cache).
|
||||
*/
|
||||
ServerCacheManager getServerCacheManager();
|
||||
ServerCacheManager cacheManager();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to cacheManager().
|
||||
*/
|
||||
@Deprecated
|
||||
default ServerCacheManager getServerCacheManager() {
|
||||
return cacheManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BackgroundExecutor service for asynchronous processing of
|
||||
* queries.
|
||||
*/
|
||||
BackgroundExecutor getBackgroundExecutor();
|
||||
BackgroundExecutor backgroundExecutor();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to backgroundExecutor().
|
||||
*/
|
||||
@Deprecated
|
||||
default BackgroundExecutor getBackgroundExecutor() {
|
||||
return backgroundExecutor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JsonContext for reading/writing JSON.
|
||||
@@ -1602,6 +1714,20 @@ public interface Database {
|
||||
*/
|
||||
<T> Set<String> validateQuery(Query<T> query);
|
||||
|
||||
/**
|
||||
* Load and lock the bean using {@code select for update}.
|
||||
* <p>
|
||||
* This should be executed inside a transaction and results in the bean being loaded or
|
||||
* refreshed from the database and a database row lock held via {@code select for update}.
|
||||
* <p>
|
||||
* The bean needs to have an ID property set and can be a reference bean (only has ID)
|
||||
* or partially or fully populated bean. This will load all the properties of the bean
|
||||
* from the database using {@code select for update} obtaining a database row lock (using WAIT).
|
||||
*
|
||||
* @param bean The entity bean that we wish to obtain a database lock on.
|
||||
*/
|
||||
void lock(Object bean);
|
||||
|
||||
/**
|
||||
* Truncate all the given tables.
|
||||
*/
|
||||
|
||||
@@ -16,23 +16,21 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
* <p>
|
||||
* This uses either DatabaseConfig or properties in the application.properties file to
|
||||
* configure and create a Database instance.
|
||||
* </p>
|
||||
* <p>
|
||||
* The Database instance can either be registered with the DB singleton or
|
||||
* not. The DB singleton effectively holds a map of Database by a name.
|
||||
* If the Database is registered with the DB singleton you can retrieve it
|
||||
* later via {@link DB#byName(String)}.
|
||||
* </p>
|
||||
* <p>
|
||||
* One Database can be nominated as the 'default/primary' Database. Many
|
||||
* methods on the DB singleton such as {@link DB#find(Class)} are just a
|
||||
* convenient way of using the 'default/primary' Database.
|
||||
* </p>
|
||||
*/
|
||||
public class DatabaseFactory {
|
||||
|
||||
private static final ReentrantLock lock = new ReentrantLock();
|
||||
private static SpiContainer container;
|
||||
private static String defaultServerName;
|
||||
|
||||
static {
|
||||
EbeanVersion.getVersion();
|
||||
@@ -47,7 +45,7 @@ public class DatabaseFactory {
|
||||
public static void initialiseContainer(ContainerConfig containerConfig) {
|
||||
lock.lock();
|
||||
try {
|
||||
getContainer(containerConfig);
|
||||
container(containerConfig);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
@@ -59,7 +57,7 @@ public class DatabaseFactory {
|
||||
public static Database create(String name) {
|
||||
lock.lock();
|
||||
try {
|
||||
return getContainer(null).createServer(name);
|
||||
return container(null).createServer(name);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
@@ -67,6 +65,16 @@ public class DatabaseFactory {
|
||||
|
||||
/**
|
||||
* Create using the DatabaseConfig object to configure the database.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* DatabaseConfig config = new DatabaseConfig();
|
||||
* config.setName("db");
|
||||
* config.loadProperties();
|
||||
*
|
||||
* Database database = DatabaseFactory.create(config);
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
public static Database create(DatabaseConfig config) {
|
||||
lock.lock();
|
||||
@@ -76,6 +84,12 @@ public class DatabaseFactory {
|
||||
}
|
||||
Database server = createInternal(config);
|
||||
if (config.isRegister()) {
|
||||
if (config.isDefaultServer()) {
|
||||
if (defaultServerName != null && !defaultServerName.equals(config.getName())) {
|
||||
throw new IllegalStateException("Registering [" + config.getName() + "] as the default server but [" + defaultServerName + "] is already registered as the default");
|
||||
}
|
||||
defaultServerName = config.getName();
|
||||
}
|
||||
DbPrimary.setSkip(true);
|
||||
DbContext.getInstance().register(server, config.isDefaultServer());
|
||||
}
|
||||
@@ -108,7 +122,6 @@ public class DatabaseFactory {
|
||||
* Shutdown gracefully all Database instances cleaning up any resources as required.
|
||||
* <p>
|
||||
* This is typically invoked via JVM shutdown hook and not explicitly called.
|
||||
* </p>
|
||||
*/
|
||||
public static void shutdown() {
|
||||
lock.lock();
|
||||
@@ -120,15 +133,15 @@ public class DatabaseFactory {
|
||||
}
|
||||
|
||||
private static Database createInternal(DatabaseConfig config) {
|
||||
return getContainer(config.getContainerConfig()).createServer(config);
|
||||
return container(config.getContainerConfig()).createServer(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the EbeanContainer initialising it if necessary.
|
||||
* Return the SpiContainer initialising it if necessary.
|
||||
*
|
||||
* @param containerConfig the configuration controlling clustering communication
|
||||
*/
|
||||
private static SpiContainer getContainer(ContainerConfig containerConfig) {
|
||||
private static SpiContainer container(ContainerConfig containerConfig) {
|
||||
// thread safe in that all calling methods hold lock
|
||||
if (container != null) {
|
||||
return container;
|
||||
|
||||
@@ -115,7 +115,7 @@ final class DbContext {
|
||||
* Register a server so we can get it by its name.
|
||||
*/
|
||||
void register(Database server, boolean isDefault) {
|
||||
registerWithName(server.getName(), server, isDefault);
|
||||
registerWithName(server.name(), server, isDefault);
|
||||
}
|
||||
|
||||
private void registerWithName(String name, Database server, boolean isDefault) {
|
||||
|
||||
@@ -149,7 +149,7 @@ public interface DocumentStore {
|
||||
* .setUseDocStore(true)
|
||||
* .where()... // perhaps add predicates
|
||||
* .findEachWhile(new Predicate<Order>() {
|
||||
* @Override
|
||||
* @Override
|
||||
* public void accept(Order bean) {
|
||||
* // process the bean
|
||||
*
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Query for performing native SQL queries that return DTO Bean's.
|
||||
@@ -37,7 +38,7 @@ import java.util.function.Predicate;
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
public interface DtoQuery<T> {
|
||||
public interface DtoQuery<T> extends CancelableQuery {
|
||||
|
||||
/**
|
||||
* Execute the query returning a list.
|
||||
@@ -45,6 +46,26 @@ public interface DtoQuery<T> {
|
||||
@Nonnull
|
||||
List<T> findList();
|
||||
|
||||
/**
|
||||
* Execute the query iterating a row at a time.
|
||||
* <p>
|
||||
* Note that the QueryIterator holds resources related to the underlying
|
||||
* resultSet and potentially connection and MUST be closed. We should use
|
||||
* QueryIterator in a <em>try with resource block</em>.
|
||||
*/
|
||||
@Nonnull
|
||||
QueryIterator<T> findIterate();
|
||||
|
||||
/**
|
||||
* Execute the query returning a Stream.
|
||||
* <p>
|
||||
* Note that the Stream holds resources related to the underlying
|
||||
* resultSet and potentially connection and MUST be closed. We should use
|
||||
* the Stream in a <em>try with resource block</em>.
|
||||
*/
|
||||
@Nonnull
|
||||
Stream<T> findStream();
|
||||
|
||||
/**
|
||||
* Execute the query iterating a row at a time.
|
||||
* <p>
|
||||
@@ -53,6 +74,17 @@ public interface DtoQuery<T> {
|
||||
*/
|
||||
void findEach(Consumer<T> consumer);
|
||||
|
||||
/**
|
||||
* Execute the query iterating the results and batching them for the consumer.
|
||||
* <p>
|
||||
* This runs like findEach streaming results from the database but just collects the results
|
||||
* into batches to pass to the consumer.
|
||||
*
|
||||
* @param batch The number of dto beans to collect before given them to the consumer
|
||||
* @param consumer The consumer to process the batch of DTO beans
|
||||
*/
|
||||
void findEach(int batch, Consumer<List<T>> consumer);
|
||||
|
||||
/**
|
||||
* Execute the query iterating a row at a time with the ability to stop consuming part way through.
|
||||
* <p>
|
||||
|
||||
@@ -103,7 +103,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static ExpressionFactory getExpressionFactory() {
|
||||
return getDefault().getExpressionFactory();
|
||||
return getDefault().expressionFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -346,7 +346,7 @@ public final class Ebean {
|
||||
* <pre>{@code
|
||||
* public class Order { ...
|
||||
*
|
||||
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
|
||||
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
|
||||
* List<OrderDetail> details;
|
||||
* ...
|
||||
* }
|
||||
@@ -642,7 +642,7 @@ public final class Ebean {
|
||||
* @param id the id value
|
||||
*/
|
||||
public static <T> T getReference(Class<T> beanType, Object id) {
|
||||
return getDefault().getReference(beanType, id);
|
||||
return getDefault().reference(beanType, id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1201,14 +1201,14 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static BeanState getBeanState(Object bean) {
|
||||
return getDefault().getBeanState(bean);
|
||||
return getDefault().beanState(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the manager of the server cache ("L2" cache).
|
||||
*/
|
||||
public static ServerCacheManager getServerCacheManager() {
|
||||
return getDefault().getServerCacheManager();
|
||||
return getDefault().cacheManager();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1216,7 +1216,7 @@ public final class Ebean {
|
||||
* queries.
|
||||
*/
|
||||
public static BackgroundExecutor getBackgroundExecutor() {
|
||||
return getDefault().getBackgroundExecutor();
|
||||
return getDefault().backgroundExecutor();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,7 +16,7 @@ import java.util.Map;
|
||||
* This provides a convenient way to create expressions for the default
|
||||
* database.
|
||||
* <p>
|
||||
* See also {@link DB#getExpressionFactory()}
|
||||
* See also {@link DB#expressionFactory()}
|
||||
* </p>
|
||||
* <p>
|
||||
* Creates standard common expressions for using in a Query Where or Having
|
||||
@@ -34,14 +34,14 @@ public class Expr {
|
||||
* Equal To - property equal to the given value.
|
||||
*/
|
||||
public static Expression eq(String propertyName, Object value) {
|
||||
return DB.getExpressionFactory().eq(propertyName, value);
|
||||
return DB.expressionFactory().eq(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not Equal To - property not equal to the given value.
|
||||
*/
|
||||
public static Expression ne(String propertyName, Object value) {
|
||||
return DB.getExpressionFactory().ne(propertyName, value);
|
||||
return DB.expressionFactory().ne(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,7 +49,7 @@ public class Expr {
|
||||
* using a lower() function to make it case insensitive).
|
||||
*/
|
||||
public static Expression ieq(String propertyName, String value) {
|
||||
return DB.getExpressionFactory().ieq(propertyName, value);
|
||||
return DB.expressionFactory().ieq(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,28 +59,28 @@ public class Expr {
|
||||
* </p>
|
||||
*/
|
||||
public static Expression inRange(String propertyName, Object value1, Object value2) {
|
||||
return DB.getExpressionFactory().inRange(propertyName, value1, value2);
|
||||
return DB.expressionFactory().inRange(propertyName, value1, value2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Between - property between the two given values.
|
||||
*/
|
||||
public static Expression between(String propertyName, Object value1, Object value2) {
|
||||
return DB.getExpressionFactory().between(propertyName, value1, value2);
|
||||
return DB.expressionFactory().between(propertyName, value1, value2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Between - value between two given properties.
|
||||
*/
|
||||
public static Expression between(String lowProperty, String highProperty, Object value) {
|
||||
return DB.getExpressionFactory().betweenProperties(lowProperty, highProperty, value);
|
||||
return DB.expressionFactory().betweenProperties(lowProperty, highProperty, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater Than - property greater than the given value.
|
||||
*/
|
||||
public static Expression gt(String propertyName, Object value) {
|
||||
return DB.getExpressionFactory().gt(propertyName, value);
|
||||
return DB.expressionFactory().gt(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,42 +88,42 @@ public class Expr {
|
||||
* value.
|
||||
*/
|
||||
public static Expression ge(String propertyName, Object value) {
|
||||
return DB.getExpressionFactory().ge(propertyName, value);
|
||||
return DB.expressionFactory().ge(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Less Than - property less than the given value.
|
||||
*/
|
||||
public static Expression lt(String propertyName, Object value) {
|
||||
return DB.getExpressionFactory().lt(propertyName, value);
|
||||
return DB.expressionFactory().lt(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Less Than or Equal to - property less than or equal to the given value.
|
||||
*/
|
||||
public static Expression le(String propertyName, Object value) {
|
||||
return DB.getExpressionFactory().le(propertyName, value);
|
||||
return DB.expressionFactory().le(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is Null - property is null.
|
||||
*/
|
||||
public static Expression isNull(String propertyName) {
|
||||
return DB.getExpressionFactory().isNull(propertyName);
|
||||
return DB.expressionFactory().isNull(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is Not Null - property is not null.
|
||||
*/
|
||||
public static Expression isNotNull(String propertyName) {
|
||||
return DB.getExpressionFactory().isNotNull(propertyName);
|
||||
return DB.expressionFactory().isNotNull(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Case insensitive {@link #exampleLike(Object)}
|
||||
*/
|
||||
public static ExampleExpression iexampleLike(Object example) {
|
||||
return DB.getExpressionFactory().iexampleLike(example);
|
||||
return DB.expressionFactory().iexampleLike(example);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,14 +131,14 @@ public class Expr {
|
||||
* LikeType.RAW (you need to add you own wildcards % and _).
|
||||
*/
|
||||
public static ExampleExpression exampleLike(Object example) {
|
||||
return DB.getExpressionFactory().exampleLike(example);
|
||||
return DB.expressionFactory().exampleLike(example);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the query by Example expression specifying more options.
|
||||
*/
|
||||
public static ExampleExpression exampleLike(Object example, boolean caseInsensitive, LikeType likeType) {
|
||||
return DB.getExpressionFactory().exampleLike(example, caseInsensitive, likeType);
|
||||
return DB.expressionFactory().exampleLike(example, caseInsensitive, likeType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,7 +146,7 @@ public class Expr {
|
||||
* characters % (percentage) and _ (underscore).
|
||||
*/
|
||||
public static Expression like(String propertyName, String value) {
|
||||
return DB.getExpressionFactory().like(propertyName, value);
|
||||
return DB.expressionFactory().like(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,14 +155,14 @@ public class Expr {
|
||||
* a lower() function to make the expression case insensitive.
|
||||
*/
|
||||
public static Expression ilike(String propertyName, String value) {
|
||||
return DB.getExpressionFactory().ilike(propertyName, value);
|
||||
return DB.expressionFactory().ilike(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts With - property like value%.
|
||||
*/
|
||||
public static Expression startsWith(String propertyName, String value) {
|
||||
return DB.getExpressionFactory().startsWith(propertyName, value);
|
||||
return DB.expressionFactory().startsWith(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,14 +170,14 @@ public class Expr {
|
||||
* lower() function to make the expression case insensitive.
|
||||
*/
|
||||
public static Expression istartsWith(String propertyName, String value) {
|
||||
return DB.getExpressionFactory().istartsWith(propertyName, value);
|
||||
return DB.expressionFactory().istartsWith(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends With - property like %value.
|
||||
*/
|
||||
public static Expression endsWith(String propertyName, String value) {
|
||||
return DB.getExpressionFactory().endsWith(propertyName, value);
|
||||
return DB.expressionFactory().endsWith(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,14 +185,14 @@ public class Expr {
|
||||
* function to make the expression case insensitive.
|
||||
*/
|
||||
public static Expression iendsWith(String propertyName, String value) {
|
||||
return DB.getExpressionFactory().iendsWith(propertyName, value);
|
||||
return DB.expressionFactory().iendsWith(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains - property like %value%.
|
||||
*/
|
||||
public static Expression contains(String propertyName, String value) {
|
||||
return DB.getExpressionFactory().contains(propertyName, value);
|
||||
return DB.expressionFactory().contains(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -200,42 +200,42 @@ public class Expr {
|
||||
* function to make the expression case insensitive.
|
||||
*/
|
||||
public static Expression icontains(String propertyName, String value) {
|
||||
return DB.getExpressionFactory().icontains(propertyName, value);
|
||||
return DB.expressionFactory().icontains(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* For collection properties that are empty (have not existing elements).
|
||||
*/
|
||||
public static Expression isEmpty(String propertyName) {
|
||||
return DB.getExpressionFactory().isEmpty(propertyName);
|
||||
return DB.expressionFactory().isEmpty(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* For collection properties that are not empty (have existing elements).
|
||||
*/
|
||||
public static Expression isNotEmpty(String propertyName) {
|
||||
return DB.getExpressionFactory().isNotEmpty(propertyName);
|
||||
return DB.expressionFactory().isNotEmpty(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* In - property has a value in the array of values.
|
||||
*/
|
||||
public static Expression in(String propertyName, Object[] values) {
|
||||
return DB.getExpressionFactory().in(propertyName, values);
|
||||
return DB.expressionFactory().in(propertyName, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* In - using a subQuery.
|
||||
*/
|
||||
public static Expression in(String propertyName, Query<?> subQuery) {
|
||||
return DB.getExpressionFactory().in(propertyName, subQuery);
|
||||
return DB.expressionFactory().in(propertyName, subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* In - property has a value in the collection of values.
|
||||
*/
|
||||
public static Expression in(String propertyName, Collection<?> values) {
|
||||
return DB.getExpressionFactory().in(propertyName, values);
|
||||
return DB.expressionFactory().in(propertyName, values);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,14 +272,14 @@ public class Expr {
|
||||
* }</pre>
|
||||
*/
|
||||
public static Expression inOrEmpty(String propertyName, Collection<?> values) {
|
||||
return DB.getExpressionFactory().inOrEmpty(propertyName, values);
|
||||
return DB.expressionFactory().inOrEmpty(propertyName, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Id Equal to - ID property is equal to the value.
|
||||
*/
|
||||
public static Expression idEq(Object value) {
|
||||
return DB.getExpressionFactory().idEq(value);
|
||||
return DB.expressionFactory().idEq(value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -292,7 +292,7 @@ public class Expr {
|
||||
* @param propertyMap a map keyed by property names.
|
||||
*/
|
||||
public static Expression allEq(Map<String, Object> propertyMap) {
|
||||
return DB.getExpressionFactory().allEq(propertyMap);
|
||||
return DB.expressionFactory().allEq(propertyMap);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -303,7 +303,7 @@ public class Expr {
|
||||
* </p>
|
||||
*/
|
||||
public static Expression raw(String raw, Object value) {
|
||||
return DB.getExpressionFactory().raw(raw, value);
|
||||
return DB.expressionFactory().raw(raw, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,53 +314,48 @@ public class Expr {
|
||||
* </p>
|
||||
*/
|
||||
public static Expression raw(String raw, Object[] values) {
|
||||
return DB.getExpressionFactory().raw(raw, values);
|
||||
return DB.expressionFactory().raw(raw, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add raw expression with no parameters.
|
||||
*/
|
||||
public static Expression raw(String raw) {
|
||||
return DB.getExpressionFactory().raw(raw);
|
||||
return DB.expressionFactory().raw(raw);
|
||||
}
|
||||
|
||||
/**
|
||||
* And - join two expressions with a logical and.
|
||||
*/
|
||||
public static Expression and(Expression expOne, Expression expTwo) {
|
||||
|
||||
return DB.getExpressionFactory().and(expOne, expTwo);
|
||||
return DB.expressionFactory().and(expOne, expTwo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Or - join two expressions with a logical or.
|
||||
*/
|
||||
public static Expression or(Expression expOne, Expression expTwo) {
|
||||
|
||||
return DB.getExpressionFactory().or(expOne, expTwo);
|
||||
return DB.expressionFactory().or(expOne, expTwo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Negate the expression (prefix it with NOT).
|
||||
*/
|
||||
public static Expression not(Expression exp) {
|
||||
|
||||
return DB.getExpressionFactory().not(exp);
|
||||
return DB.expressionFactory().not(exp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of expressions that will be joined by AND's.
|
||||
*/
|
||||
public static <T> Junction<T> conjunction(Query<T> query) {
|
||||
|
||||
return DB.getExpressionFactory().conjunction(query);
|
||||
return DB.expressionFactory().conjunction(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of expressions that will be joined by OR's.
|
||||
*/
|
||||
public static <T> Junction<T> disjunction(Query<T> query) {
|
||||
|
||||
return DB.getExpressionFactory().disjunction(query);
|
||||
return DB.expressionFactory().disjunction(query);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ public interface ExpressionFactory {
|
||||
Expression gtOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Greater than or Equal to OR Null <code> >= or null </code>
|
||||
* Greater than or Equal to OR Null ({@code >= or null })
|
||||
* <p>
|
||||
* A convenient expression combining GE and Is Null. Most often useful for range
|
||||
* expressions where the top range value is nullable.
|
||||
@@ -227,7 +227,7 @@ public interface ExpressionFactory {
|
||||
Expression ltOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Less Than or Equal to OR Null <code> <= or null </code>
|
||||
* Less Than or Equal to OR Null ({@code <= or null })
|
||||
* <p>
|
||||
* A convenient expression combining LE and Is Null. Most often useful for range
|
||||
* expressions where the bottom range value is nullable.
|
||||
|
||||
@@ -196,13 +196,6 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
Query<T> forUpdate();
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to withLock().
|
||||
* Execute using "for update" with given lock type (currently Postgres only).
|
||||
*/
|
||||
@Deprecated
|
||||
Query<T> forUpdate(Query.LockType lockType);
|
||||
|
||||
/**
|
||||
* Execute using "for update" clause with No Wait option.
|
||||
* <p>
|
||||
@@ -211,13 +204,6 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
Query<T> forUpdateNoWait();
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to withLock().
|
||||
* Execute using "for update nowait" with given lock type (currently Postgres only).
|
||||
*/
|
||||
@Deprecated
|
||||
Query<T> forUpdateNoWait(Query.LockType lockType);
|
||||
|
||||
/**
|
||||
* Execute using "for update" clause with Skip Locked option.
|
||||
* <p>
|
||||
@@ -226,13 +212,6 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
Query<T> forUpdateSkipLocked();
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to withLock().
|
||||
* Execute using "for update skip locked" with given lock type (currently Postgres only).
|
||||
*/
|
||||
@Deprecated
|
||||
Query<T> forUpdateSkipLocked(Query.LockType lockType);
|
||||
|
||||
/**
|
||||
* Execute the query including soft deleted rows.
|
||||
*/
|
||||
@@ -328,6 +307,13 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
void findEach(Consumer<T> consumer);
|
||||
|
||||
/**
|
||||
* Execute findEach with a batch consumer.
|
||||
*
|
||||
* @see Query#findEach(int, Consumer)
|
||||
*/
|
||||
void findEach(int batch, Consumer<List<T>> consumer);
|
||||
|
||||
/**
|
||||
* Execute the query processing the beans one at a time with the ability to
|
||||
* stop processing before reading all the beans.
|
||||
@@ -930,7 +916,7 @@ public interface ExpressionList<T> {
|
||||
ExpressionList<T> gtOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Greater Than or Equal to OR Null - <code> >= or null </code>.
|
||||
* Greater Than or Equal to OR Null - ({@code >= or null }).
|
||||
*/
|
||||
ExpressionList<T> geOrNull(String propertyName, Object value);
|
||||
|
||||
@@ -951,7 +937,7 @@ public interface ExpressionList<T> {
|
||||
ExpressionList<T> ltOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Less Than or Equal to OR Null - <code> <= or null </code>.
|
||||
* Less Than or Equal to OR Null - ({@code <= or null }).
|
||||
*/
|
||||
ExpressionList<T> leOrNull(String propertyName, Object value);
|
||||
|
||||
@@ -1685,7 +1671,7 @@ public interface ExpressionList<T> {
|
||||
ExpressionList<T> endAnd();
|
||||
|
||||
/**
|
||||
* End a AND junction - synonym for endJunction().
|
||||
* End a OR junction - synonym for endJunction().
|
||||
*/
|
||||
ExpressionList<T> endOr();
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ public interface ExtendedServer {
|
||||
*
|
||||
* @return True if the query finds a matching row in the database
|
||||
*/
|
||||
<T> boolean exists(Query<?> ormQuery, Transaction transaction);
|
||||
<T> boolean exists(Query<T> ormQuery, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Return the number of 'top level' or 'root' entities this query should return.
|
||||
@@ -159,6 +159,13 @@ public interface ExtendedServer {
|
||||
*/
|
||||
<T> void findEach(Query<T> query, Consumer<T> consumer, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute findEach with batch consumer.
|
||||
*
|
||||
* @see Query#findEach(int, Consumer)
|
||||
*/
|
||||
<T> void findEach(Query<T> query, int batch, Consumer<List<T>> consumer, Transaction t);
|
||||
|
||||
/**
|
||||
* Execute the query visiting the each bean one at a time.
|
||||
* <p>
|
||||
|
||||
@@ -3,30 +3,13 @@ package io.ebean;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Defines the configuration options for a "query fetch" or a
|
||||
* "lazy loading fetch". This gives you the ability to use multiple smaller
|
||||
* queries to populate an object graph as opposed to a single large query.
|
||||
* <p>
|
||||
* The primary goal is to provide efficient ways of loading complex object
|
||||
* graphs avoiding SQL Cartesian product and issues around populating object
|
||||
* graphs that have multiple *ToMany relationships.
|
||||
* </p>
|
||||
* <p>
|
||||
* It also provides the ability to control the lazy loading queries (batch size,
|
||||
* selected properties and fetches) to avoid N+1 queries etc.
|
||||
* <p>
|
||||
* There can also be cases loading across a single OneToMany where 2 SQL queries
|
||||
* using Ebean FetchConfig.query() can be more efficient than one SQL query.
|
||||
* When the "One" side is wide (lots of columns) and the cardinality difference
|
||||
* is high (a lot of "Many" beans per "One" bean) then this can be more
|
||||
* efficient loaded as 2 SQL queries.
|
||||
* </p>
|
||||
* Defines how a relationship is fetched via either normal SQL join,
|
||||
* a eager secondary query, via lazy loading or via eagerly hitting L2 cache.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
* // Normal fetch join results in a single SQL query
|
||||
* List<Order> list = DB.find(Order.class).fetch("details").findList();
|
||||
*
|
||||
* // Find Orders join details using a single SQL query
|
||||
* }</pre>
|
||||
* <p>
|
||||
* Example: Using a "query join" instead of a "fetch join" we instead use 2 SQL queries
|
||||
@@ -37,103 +20,13 @@ import java.io.Serializable;
|
||||
* // This will use 2 SQL queries to build this object graph
|
||||
* List<Order> list =
|
||||
* DB.find(Order.class)
|
||||
* .fetch("details", new FetchConfig().query())
|
||||
* .fetch("details", FetchConfig.ofQuery())
|
||||
* .findList();
|
||||
*
|
||||
* // query 1) find order
|
||||
* // query 2) find orderDetails where order.id in (?,?...) // first 100 order id's
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* Example: Using 2 "query joins"
|
||||
* </p>
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // This will use 3 SQL queries to build this object graph
|
||||
* List<Order> list =
|
||||
* DB.find(Order.class)
|
||||
* .fetch("details", new FetchConfig().query())
|
||||
* .fetch("customer", new FetchConfig().queryFirst(5))
|
||||
* .findList();
|
||||
*
|
||||
* // query 1) find order
|
||||
* // query 2) find orderDetails where order.id in (?,?...) // first 100 order id's
|
||||
* // query 3) find customer where id in (?,?,?,?,?) // first 5 customers
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* Example: Using "query joins" and partial objects
|
||||
* </p>
|
||||
* <p>
|
||||
*
|
||||
* <pre>{@code
|
||||
* // This will use 3 SQL queries to build this object graph
|
||||
* List<Order> list =
|
||||
* DB.find(Order.class)
|
||||
* .select("status, shipDate")
|
||||
* .fetch("details", "quantity, price", new FetchConfig().query())
|
||||
* .fetch("details.product", "sku, name")
|
||||
* .fetch("customer", "name", new FetchConfig().queryFirst(5))
|
||||
* .fetch("customer.contacts")
|
||||
* .fetch("customer.shippingAddress")
|
||||
* .findList();
|
||||
*
|
||||
* // query 1) find order (status, shipDate)
|
||||
* // query 2) find orderDetail (quantity, price) fetch product (sku, name) where
|
||||
* // order.id in (?,? ...)
|
||||
* // query 3) find customer (name) fetch contacts (*) fetch shippingAddress (*)
|
||||
* // where id in (?,?,?,?,?)
|
||||
*
|
||||
* // Note: the fetch of "details.product" is automatically included into the
|
||||
* // fetch of "details"
|
||||
* //
|
||||
* // Note: the fetch of "customer.contacts" and "customer.shippingAddress"
|
||||
* // are automatically included in the fetch of "customer"
|
||||
* }</pre>
|
||||
* <p>
|
||||
* You can use query() and lazy together on a single join. The query is executed
|
||||
* immediately and the lazy defines the batch size to use for further lazy
|
||||
* loading (if lazy loading is invoked).
|
||||
* </p>
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<Order> list =
|
||||
* DB.find(Order.class)
|
||||
* .fetch("customer", new FetchConfig().query(10).lazy(5))
|
||||
* .findList();
|
||||
*
|
||||
* // query 1) find order
|
||||
* // query 2) find customer where id in (?,?,?,?,?,?,?,?,?,?) // first 10 customers
|
||||
* // .. then if lazy loading of customers is invoked
|
||||
* // .. use a batch size of 5 to load the customers
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* <p>
|
||||
* Example of controlling the lazy loading query:
|
||||
* </p>
|
||||
* <p>
|
||||
* This gives us the ability to optimise the lazy loading query for a given use
|
||||
* case.
|
||||
* </p>
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<Order> list = DB.find(Order.class)
|
||||
* .fetch("customer","name", new FetchConfig().lazy(5))
|
||||
* .fetch("customer.contacts","contactName, phone, email")
|
||||
* .fetch("customer.shippingAddress")
|
||||
* .where().eq("status",Order.Status.NEW)
|
||||
* .findList();
|
||||
*
|
||||
* // query 1) find order where status = Order.Status.NEW
|
||||
* //
|
||||
* // .. if lazy loading of customers is invoked
|
||||
* // .. use a batch size of 5 to load the customers
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @author mario
|
||||
* @author rbygrave
|
||||
@@ -142,149 +35,209 @@ public class FetchConfig implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private int lazyBatchSize = -1;
|
||||
private static final int JOIN_MODE = 0;
|
||||
private static final int QUERY_MODE = 1;
|
||||
private static final int LAZY_MODE = 2;
|
||||
private static final int CACHE_MODE = 3;
|
||||
|
||||
private int queryBatchSize = -1;
|
||||
|
||||
private boolean queryAll;
|
||||
|
||||
private boolean cache;
|
||||
private int mode;
|
||||
private int batchSize;
|
||||
private int hashCode;
|
||||
|
||||
/**
|
||||
* Construct the fetch configuration object.
|
||||
* Deprecated - migrate to one of the static factory methods like {@link FetchConfig#ofQuery()}
|
||||
* <p>
|
||||
* Construct using default JOIN mode.
|
||||
*/
|
||||
@Deprecated
|
||||
public FetchConfig() {
|
||||
//this.mode = JOIN_MODE;
|
||||
this.batchSize = 100;
|
||||
this.hashCode = 1000;
|
||||
}
|
||||
|
||||
private FetchConfig(int mode, int batchSize) {
|
||||
this.mode = mode;
|
||||
this.batchSize = batchSize;
|
||||
this.hashCode = mode + 10 * batchSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that this path should be lazy loaded using the default batch load
|
||||
* size.
|
||||
* Return FetchConfig to eagerly fetch the relationship using L2 cache.
|
||||
* <p>
|
||||
* Any cache misses will be loaded by secondary query to the database.
|
||||
*/
|
||||
public static FetchConfig ofCache() {
|
||||
return new FetchConfig(CACHE_MODE, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return FetchConfig to eagerly fetch the relationship using a secondary query.
|
||||
*/
|
||||
public static FetchConfig ofQuery() {
|
||||
return new FetchConfig(QUERY_MODE, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return FetchConfig to eagerly fetch the relationship using a secondary with a given batch size.
|
||||
*/
|
||||
public static FetchConfig ofQuery(int batchSize) {
|
||||
return new FetchConfig(QUERY_MODE, batchSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return FetchConfig to lazily load the relationship.
|
||||
*/
|
||||
public static FetchConfig ofLazy() {
|
||||
return new FetchConfig(LAZY_MODE, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return FetchConfig to lazily load the relationship specifying the batch size.
|
||||
*/
|
||||
public static FetchConfig ofLazy(int batchSize) {
|
||||
return new FetchConfig(LAZY_MODE, batchSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return FetchConfig to fetch the relationship using SQL join.
|
||||
*/
|
||||
public static FetchConfig ofDefault() {
|
||||
return new FetchConfig(JOIN_MODE, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* We want to migrate away from mutating FetchConfig to a fully immutable FetchConfig.
|
||||
*/
|
||||
private FetchConfig mutate(int mode, int batchSize) {
|
||||
if (batchSize < 0) {
|
||||
throw new IllegalArgumentException("batch size " + batchSize + " must be > 0");
|
||||
}
|
||||
this.mode = mode;
|
||||
this.batchSize = batchSize;
|
||||
this.hashCode = mode + 10 * batchSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to FetchConfig.ofLazy().
|
||||
*/
|
||||
@Deprecated
|
||||
public FetchConfig lazy() {
|
||||
this.lazyBatchSize = 0;
|
||||
this.queryAll = false;
|
||||
return this;
|
||||
return mutate(LAZY_MODE, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that this path should be lazy loaded with a specified batch size.
|
||||
*
|
||||
* @param lazyBatchSize the batch size for lazy loading
|
||||
* Deprecated - migrate to FetchConfig.ofLazy(batchSize).
|
||||
*/
|
||||
public FetchConfig lazy(int lazyBatchSize) {
|
||||
this.lazyBatchSize = lazyBatchSize;
|
||||
this.queryAll = false;
|
||||
return this;
|
||||
@Deprecated
|
||||
public FetchConfig lazy(int batchSize) {
|
||||
return mutate(LAZY_MODE, batchSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to FetchConfig.ofQuery().
|
||||
* <p>
|
||||
* Eagerly fetch the beans in this path as a separate query (rather than as
|
||||
* part of the main query).
|
||||
* <p>
|
||||
* This will use the default batch size for separate query which is 100.
|
||||
* </p>
|
||||
*/
|
||||
@Deprecated
|
||||
public FetchConfig query() {
|
||||
this.queryBatchSize = 0;
|
||||
this.queryAll = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Eagerly fetch the beans fetching the beans from the L2 bean cache
|
||||
* and using the DB for beans not in the cache.
|
||||
*/
|
||||
public FetchConfig cache() {
|
||||
this.cache = true;
|
||||
this.queryBatchSize = 0;
|
||||
this.queryAll = true;
|
||||
return this;
|
||||
return mutate(QUERY_MODE, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to FetchConfig.ofQuery(batchSize).
|
||||
* <p>
|
||||
* Eagerly fetch the beans in this path as a separate query (rather than as
|
||||
* part of the main query).
|
||||
* <p>
|
||||
* The queryBatchSize is the number of parent id's that this separate query
|
||||
* will load per batch.
|
||||
* </p>
|
||||
* <p>
|
||||
* This will load all beans on this path eagerly unless a {@link #lazy(int)}
|
||||
* is also used.
|
||||
* </p>
|
||||
*
|
||||
* @param queryBatchSize the batch size used to load beans on this path
|
||||
* @param batchSize the batch size used to load beans on this path
|
||||
*/
|
||||
public FetchConfig query(int queryBatchSize) {
|
||||
this.queryBatchSize = queryBatchSize;
|
||||
// queryAll true as long as a lazy batch size has not already been set
|
||||
this.queryAll = (lazyBatchSize == -1);
|
||||
return this;
|
||||
@Deprecated
|
||||
public FetchConfig query(int batchSize) {
|
||||
return mutate(QUERY_MODE, batchSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to FetchConfig.ofQuery(batchSize).
|
||||
* <p>
|
||||
* Eagerly fetch the first batch of beans on this path.
|
||||
* This is similar to {@link #query(int)} but only fetches the first batch.
|
||||
* <p>
|
||||
* If there are more parent beans than the batch size then they will not be
|
||||
* loaded eagerly but instead use lazy loading.
|
||||
* </p>
|
||||
*
|
||||
* @param queryBatchSize the number of parent beans this path is populated for
|
||||
* @param batchSize the number of parent beans this path is populated for
|
||||
*/
|
||||
public FetchConfig queryFirst(int queryBatchSize) {
|
||||
this.queryBatchSize = queryBatchSize;
|
||||
this.queryAll = false;
|
||||
return this;
|
||||
@Deprecated
|
||||
public FetchConfig queryFirst(int batchSize) {
|
||||
return query(batchSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the batch size for lazy loading.
|
||||
* Deprecated - migrate to FetchConfig.ofCache().
|
||||
* <p>
|
||||
* Eagerly fetch the beans fetching the beans from the L2 bean cache
|
||||
* and using the DB for beans not in the cache.
|
||||
*/
|
||||
public int getLazyBatchSize() {
|
||||
return lazyBatchSize;
|
||||
@Deprecated
|
||||
public FetchConfig cache() {
|
||||
return mutate(CACHE_MODE, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the batch size for separate query load.
|
||||
* Return the batch size for fetching.
|
||||
*/
|
||||
public int getQueryBatchSize() {
|
||||
return queryBatchSize;
|
||||
public int getBatchSize() {
|
||||
return batchSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the query fetch should fetch 'all' rather than just the
|
||||
* 'first' batch.
|
||||
*/
|
||||
public boolean isQueryAll() {
|
||||
return queryAll;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this uses L2 bean cache.
|
||||
* Return true if the fetch should use the L2 cache.
|
||||
*/
|
||||
public boolean isCache() {
|
||||
return cache;
|
||||
return mode == CACHE_MODE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the fetch should be a eager secondary query.
|
||||
*/
|
||||
public boolean isQuery() {
|
||||
return mode == QUERY_MODE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the fetch should be a lazy query.
|
||||
*/
|
||||
public boolean isLazy() {
|
||||
return mode == LAZY_MODE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the fetch should try to use SQL join.
|
||||
*/
|
||||
public boolean isJoin() {
|
||||
return mode == JOIN_MODE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
FetchConfig that = (FetchConfig) o;
|
||||
if (lazyBatchSize != that.lazyBatchSize) return false;
|
||||
if (queryBatchSize != that.queryBatchSize) return false;
|
||||
if (cache != that.cache) return false;
|
||||
return queryAll == that.queryAll;
|
||||
return (hashCode == ((FetchConfig) o).hashCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = lazyBatchSize;
|
||||
result = 92821 * result + queryBatchSize;
|
||||
result = 92821 * result + (queryAll ? 1 : 0);
|
||||
result = 92821 * result + (cache ? 1 : 0);
|
||||
return result;
|
||||
return hashCode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ import java.util.List;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @Entity
|
||||
* @Entity
|
||||
* public class Customer extends BaseModel {
|
||||
*
|
||||
* public static final CustomerFinder find = new CustomerFinder();
|
||||
@@ -80,7 +80,7 @@ public class Finder<I, T> {
|
||||
* // ... add extra customer specific finder methods
|
||||
* }
|
||||
*
|
||||
* @Entity
|
||||
* @Entity
|
||||
* public class Customer extends BaseModel {
|
||||
*
|
||||
* public static final CustomerFinder find = new CustomerFinder();
|
||||
@@ -137,11 +137,11 @@ public class Finder<I, T> {
|
||||
/**
|
||||
* Creates an entity reference for this ID.
|
||||
* <p>
|
||||
* Equivalent to {@link Database#getReference(Class, Object)}
|
||||
* Equivalent to {@link Database#reference(Class, Object)}
|
||||
*/
|
||||
@Nonnull
|
||||
public T ref(I id) {
|
||||
return db().getReference(type, id);
|
||||
return db().reference(type, id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,16 +32,16 @@ import io.ebean.bean.EntityBean;
|
||||
* // Typically there is a common base model that has some
|
||||
* // common properties like the ones below
|
||||
*
|
||||
* @MappedSuperclass
|
||||
* @MappedSuperclass
|
||||
* public class BaseModel extends Model {
|
||||
*
|
||||
* @Id Long id;
|
||||
* @Id Long id;
|
||||
*
|
||||
* @Version Long version;
|
||||
* @Version Long version;
|
||||
*
|
||||
* @WhenCreated Timestamp whenCreated;
|
||||
* @WhenCreated Timestamp whenCreated;
|
||||
*
|
||||
* @WhenUpdated Timestamp whenUpdated;
|
||||
* @WhenUpdated Timestamp whenUpdated;
|
||||
*
|
||||
* ...
|
||||
* }
|
||||
@@ -52,7 +52,7 @@ import io.ebean.bean.EntityBean;
|
||||
*
|
||||
* // Extend the mappedSuperclass
|
||||
*
|
||||
* @Entity @Table(name="o_account")
|
||||
* @Entity @Table(name="o_account")
|
||||
* public class Customer extends BaseModel {
|
||||
*
|
||||
* String name;
|
||||
|
||||
@@ -16,7 +16,7 @@ import java.util.Objects;
|
||||
* on the Query object.
|
||||
* </p>
|
||||
*/
|
||||
public final class OrderBy<T> implements Serializable {
|
||||
public class OrderBy<T> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 9157089257745730539L;
|
||||
|
||||
@@ -69,7 +69,6 @@ public final class OrderBy<T> implements Serializable {
|
||||
* Add a property with ascending order to this OrderBy.
|
||||
*/
|
||||
public Query<T> asc(String propertyName) {
|
||||
|
||||
list.add(new Property(propertyName, true));
|
||||
return query;
|
||||
}
|
||||
@@ -98,7 +97,6 @@ public final class OrderBy<T> implements Serializable {
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if the property is known to be contained in the order by clause.
|
||||
*/
|
||||
@@ -207,7 +205,6 @@ public final class OrderBy<T> implements Serializable {
|
||||
if (!(obj instanceof OrderBy<?>)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
OrderBy<?> e = (OrderBy<?>) obj;
|
||||
return e.list.equals(list);
|
||||
}
|
||||
@@ -249,7 +246,7 @@ public final class OrderBy<T> implements Serializable {
|
||||
/**
|
||||
* A property and its ascending descending order.
|
||||
*/
|
||||
public static final class Property implements Serializable {
|
||||
public static class Property implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1546009780322478077L;
|
||||
|
||||
@@ -415,13 +412,10 @@ public final class OrderBy<T> implements Serializable {
|
||||
}
|
||||
|
||||
private void parse(String orderByClause) {
|
||||
|
||||
if (orderByClause == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String[] chunks = orderByClause.split(",");
|
||||
for (String chunk : chunks) {
|
||||
for (String chunk : orderByClause.split(",")) {
|
||||
Property p = parseProperty(chunk);
|
||||
if (p != null) {
|
||||
list.add(p);
|
||||
@@ -467,8 +461,7 @@ public final class OrderBy<T> implements Serializable {
|
||||
if (s.startsWith("desc")) {
|
||||
return false;
|
||||
}
|
||||
String m = "Expecting [" + s + "] to be asc or desc?";
|
||||
throw new RuntimeException(m);
|
||||
throw new RuntimeException("Expecting [" + s + "] to be asc or desc?");
|
||||
}
|
||||
|
||||
private boolean isEmptyString(String s) {
|
||||
|
||||
@@ -18,7 +18,7 @@ import java.util.List;
|
||||
*
|
||||
* // where a bean is annotated with a complex
|
||||
* // natural key made of several properties
|
||||
* @Cache(naturalKey = {"store","code","sku"})
|
||||
* @Cache(naturalKey = {"store","code","sku"})
|
||||
*
|
||||
*
|
||||
* Pairs pairs = new Pairs("sku", "code");
|
||||
|
||||
@@ -177,7 +177,7 @@ import java.util.stream.Stream;
|
||||
*
|
||||
* @param <T> the type of Entity bean this query will fetch.
|
||||
*/
|
||||
public interface Query<T> {
|
||||
public interface Query<T> extends CancelableQuery {
|
||||
|
||||
/**
|
||||
* The lock type (strength) to use with query FOR UPDATE row locking.
|
||||
@@ -291,15 +291,6 @@ public interface Query<T> {
|
||||
*/
|
||||
UpdateQuery<T> asUpdate();
|
||||
|
||||
/**
|
||||
* Cancel the query execution if supported by the underlying database and
|
||||
* driver.
|
||||
* <p>
|
||||
* This must be called from a different thread to the query executor.
|
||||
* </p>
|
||||
*/
|
||||
void cancel();
|
||||
|
||||
/**
|
||||
* Return a copy of the query.
|
||||
* <p>
|
||||
@@ -514,7 +505,7 @@ public interface Query<T> {
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* fetch(path, fetchProperties, new FetchConfig().query())
|
||||
* fetch(path, fetchProperties, FetchConfig.ofQuery())
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
@@ -548,7 +539,7 @@ public interface Query<T> {
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* fetch(path, fetchProperties, new FetchConfig().lazy())
|
||||
* fetch(path, fetchProperties, FetchConfig.ofLazy())
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
@@ -573,7 +564,7 @@ public interface Query<T> {
|
||||
* // fetch customers (their id, name and status)
|
||||
* List<Customer> customers = DB.find(Customer.class)
|
||||
* .select("name, status")
|
||||
* .fetch("contacts", "firstName,lastName,email", new FetchConfig().lazy(10))
|
||||
* .fetch("contacts", "firstName,lastName,email", FetchConfig.ofLazy(10))
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
@@ -610,7 +601,7 @@ public interface Query<T> {
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* fetch(path, new FetchConfig().query())
|
||||
* fetch(path, FetchConfig.ofQuery())
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
@@ -639,7 +630,7 @@ public interface Query<T> {
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* fetch(path, new FetchConfig().lazy())
|
||||
* fetch(path, FetchConfig.ofLazy())
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
@@ -662,7 +653,7 @@ public interface Query<T> {
|
||||
* // fetch customers (their id, name and status)
|
||||
* List<Customer> customers = DB.find(Customer.class)
|
||||
* // lazy fetch contacts with a batch size of 100
|
||||
* .fetch("contacts", new FetchConfig().lazy(100))
|
||||
* .fetch("contacts", FetchConfig.ofLazy(100))
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
@@ -810,7 +801,7 @@ public interface Query<T> {
|
||||
* </p>
|
||||
* <p>
|
||||
* This method is functionally equivalent to findIterate() but instead of using an
|
||||
* iterator uses the Consumer interface which is better suited to use with Java8 closures.
|
||||
* iterator uses the Consumer interface which is better suited to use with closures.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -829,6 +820,21 @@ public interface Query<T> {
|
||||
*/
|
||||
void findEach(Consumer<T> consumer);
|
||||
|
||||
/**
|
||||
* Execute findEach streaming query batching the results for consuming.
|
||||
* <p>
|
||||
* This query execution will stream the results and is suited to consuming
|
||||
* large numbers of results from the database.
|
||||
* <p>
|
||||
* Typically we use this batch consumer when we want to do further processing on
|
||||
* the beans and want to do that processing in batch form, for example - 100 at
|
||||
* a time.
|
||||
*
|
||||
* @param batch The number of beans processed in the batch
|
||||
* @param consumer Process the batch of beans
|
||||
*/
|
||||
void findEach(int batch, Consumer<List<T>> consumer);
|
||||
|
||||
/**
|
||||
* Execute the query using callbacks to a visitor to process the resulting
|
||||
* beans one at a time.
|
||||
@@ -839,12 +845,12 @@ public interface Query<T> {
|
||||
* </p>
|
||||
* <p>
|
||||
* This method is functionally equivalent to findIterate() but instead of using an
|
||||
* iterator uses the Predicate (SAM) interface which is better suited to use with Java8 closures.
|
||||
* iterator uses the Predicate interface which is better suited to use with closures.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* DB.find(Customer.class)
|
||||
* .fetch("contacts", new FetchConfig().query(2))
|
||||
* .fetchQuery("contacts")
|
||||
* .where().eq("status", Status.NEW)
|
||||
* .order().asc("id")
|
||||
* .setMaxRows(2000)
|
||||
@@ -1673,12 +1679,6 @@ public interface Query<T> {
|
||||
*/
|
||||
Query<T> forUpdate();
|
||||
|
||||
/**
|
||||
* Execute using "for update" with given lock type (currently Postgres only).
|
||||
*/
|
||||
@Deprecated
|
||||
Query<T> forUpdate(LockType lockType);
|
||||
|
||||
/**
|
||||
* Execute using "for update" clause with "no wait" option.
|
||||
* <p>
|
||||
@@ -1688,12 +1688,6 @@ public interface Query<T> {
|
||||
*/
|
||||
Query<T> forUpdateNoWait();
|
||||
|
||||
/**
|
||||
* Execute using "for update nowait" with given lock type (currently Postgres only).
|
||||
*/
|
||||
@Deprecated
|
||||
Query<T> forUpdateNoWait(LockType lockType);
|
||||
|
||||
/**
|
||||
* Execute using "for update" clause with "skip locked" option.
|
||||
* <p>
|
||||
@@ -1703,12 +1697,6 @@ public interface Query<T> {
|
||||
*/
|
||||
Query<T> forUpdateSkipLocked();
|
||||
|
||||
/**
|
||||
* Execute using "for update skip locked" with given lock type (currently Postgres only).
|
||||
*/
|
||||
@Deprecated
|
||||
Query<T> forUpdateSkipLocked(LockType lockType);
|
||||
|
||||
/**
|
||||
* Return true if this query has forUpdate set.
|
||||
*/
|
||||
|
||||
@@ -56,7 +56,7 @@ import java.util.Iterator;
|
||||
*
|
||||
* @param <T> the type of entity bean in the iteration
|
||||
*/
|
||||
public interface QueryIterator<T> extends Iterator<T>, java.io.Closeable {
|
||||
public interface QueryIterator<T> extends Iterator<T>, AutoCloseable {
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if the iteration has more elements.
|
||||
@@ -70,12 +70,6 @@ public interface QueryIterator<T> extends Iterator<T>, java.io.Closeable {
|
||||
@Override
|
||||
T next();
|
||||
|
||||
/**
|
||||
* Remove is not allowed.
|
||||
*/
|
||||
@Override
|
||||
void remove();
|
||||
|
||||
/**
|
||||
* Close the underlying resources held by this iterator.
|
||||
*/
|
||||
|
||||
@@ -41,14 +41,14 @@ package io.ebean;
|
||||
* <h3>Example OrderAggregate</h3>
|
||||
* <pre>{@code
|
||||
* ...
|
||||
* // @Sql indicates to that this bean
|
||||
* // @Sql indicates to that this bean
|
||||
* // is based on RawSql rather than a table
|
||||
*
|
||||
* @Entity
|
||||
* @Sql
|
||||
* @Entity
|
||||
* @Sql
|
||||
* public class OrderAggregate {
|
||||
*
|
||||
* @OneToOne
|
||||
* @OneToOne
|
||||
* Order order;
|
||||
*
|
||||
* Double totalAmount;
|
||||
@@ -107,7 +107,7 @@ package io.ebean;
|
||||
*
|
||||
* List<OrderAggregate> orders = DB.find(OrderAggregate.class)
|
||||
* .setRawSql(rawSql)
|
||||
* .fetch("order", "status,orderDate", new FetchConfig().query())
|
||||
* .fetch("order", "status,orderDate", FetchConfig.ofQuery())
|
||||
* .fetch("order.customer", "name")
|
||||
* .where().gt("order.id", 0)
|
||||
* .having().gt("totalAmount", 20)
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.sql.SQLException;
|
||||
* //
|
||||
* class CustomerMapper implements RowMapper<CustomerDto> {
|
||||
*
|
||||
* @Override
|
||||
* @Override
|
||||
* public CustomerDto map(ResultSet rset, int rowNum) throws SQLException {
|
||||
*
|
||||
* long id = rset.getLong(1);
|
||||
|
||||
@@ -37,7 +37,7 @@ import java.util.function.Predicate;
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
public interface SqlQuery extends Serializable {
|
||||
public interface SqlQuery extends Serializable, CancelableQuery {
|
||||
|
||||
/**
|
||||
* Execute the query returning a list.
|
||||
@@ -365,5 +365,10 @@ public interface SqlQuery extends Serializable {
|
||||
* Return the list of values.
|
||||
*/
|
||||
List<T> findList();
|
||||
|
||||
/**
|
||||
* Find streaming the result effectively consuming a row at a time.
|
||||
*/
|
||||
void findEach(Consumer<T> consumer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +59,14 @@ public interface Transaction extends AutoCloseable {
|
||||
*/
|
||||
void register(TransactionCallback callback);
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL - turn on automatic persistence of dirty beans and batchMode true.
|
||||
* <p>
|
||||
* With this turned on beans that are dirty in the persistence context
|
||||
* are automatically persisted on flush() and commit().
|
||||
*/
|
||||
void setAutoPersistUpdates(boolean autoPersistUpdates);
|
||||
|
||||
/**
|
||||
* Set a label on the transaction.
|
||||
* <p>
|
||||
@@ -339,15 +347,12 @@ public interface Transaction extends AutoCloseable {
|
||||
* The batch is automatically flushed when it hits the batch size and also when we
|
||||
* execute queries or when we mix UpdateSql and CallableSql with save and delete of
|
||||
* beans.
|
||||
* </p>
|
||||
* <p>
|
||||
* We use {@link #flush()} to explicitly flush the batch and we can use
|
||||
* {@link #setFlushOnQuery(boolean)} and {@link #setFlushOnMixed(boolean)}
|
||||
* to control the automatic flushing behaviour.
|
||||
* </p>
|
||||
* <p>
|
||||
* Example: batch processing of CallableSql executing every 10 rows
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -392,14 +397,11 @@ public interface Transaction extends AutoCloseable {
|
||||
* <p>
|
||||
* This only takes effect when batch mode on the transaction has not already meant that
|
||||
* JDBC batch mode is being used.
|
||||
* </p>
|
||||
* <p>
|
||||
* This is useful when the single save() or delete() cascades. For example, inserting a 'master' cascades
|
||||
* and inserts a collection of 'detail' beans. The detail beans can be inserted using JDBC batch.
|
||||
* </p>
|
||||
* <p>
|
||||
* This is effectively already turned on for all platforms apart from older Sql Server.
|
||||
* </p>
|
||||
*
|
||||
* @param batchMode the batch mode to use per save(), insert(), update() or delete()
|
||||
* @see io.ebean.config.DatabaseConfig#setPersistBatchOnCascade(PersistBatch)
|
||||
@@ -422,15 +424,19 @@ public interface Transaction extends AutoCloseable {
|
||||
int getBatchSize();
|
||||
|
||||
/**
|
||||
* Specify if you want batched inserts to use getGeneratedKeys.
|
||||
* Specify if we want batched inserts to use getGeneratedKeys.
|
||||
* <p>
|
||||
* By default batched inserts will try to use getGeneratedKeys if it is
|
||||
* supported by the underlying jdbc driver and database.
|
||||
* </p>
|
||||
* <p>
|
||||
* You may want to turn getGeneratedKeys off when you are inserting a large
|
||||
* number of objects and you don't care about getting back the ids.
|
||||
* </p>
|
||||
* We want to turn off getGeneratedKeys when we are inserting a large
|
||||
* number of objects and we don't care about getting back the ids. In this
|
||||
* way we avoid the extra cost of getting back the generated id values
|
||||
* from the database.
|
||||
* <p>
|
||||
* Note that when we do turn off getGeneratedKeys then we have the limitation
|
||||
* that after a bean has been inserted we are unable to then mutate the bean
|
||||
* and update it in the same transaction as we have not obtained it's id value.
|
||||
*/
|
||||
void setGetGeneratedKeys(boolean getGeneratedKeys);
|
||||
|
||||
@@ -449,13 +455,11 @@ public interface Transaction extends AutoCloseable {
|
||||
* <p>
|
||||
* If you want to execute both WITHOUT having the batch automatically flush
|
||||
* you need to call this with batchFlushOnMixed = false.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that UpdateSql and CallableSql are ALWAYS executed first (before the
|
||||
* beans are executed). This is because the UpdateSql and CallableSql have
|
||||
* already been bound to their PreparedStatements. The beans on the other hand
|
||||
* have a 2 step process (delayed binding).
|
||||
* </p>
|
||||
*/
|
||||
void setFlushOnMixed(boolean batchFlushOnMixed);
|
||||
|
||||
@@ -473,7 +477,6 @@ public interface Transaction extends AutoCloseable {
|
||||
* <p>
|
||||
* Calling this method with batchFlushOnQuery = false means that you can
|
||||
* execute a query and the batch will not be automatically flushed.
|
||||
* </p>
|
||||
*/
|
||||
void setFlushOnQuery(boolean batchFlushOnQuery);
|
||||
|
||||
@@ -490,7 +493,6 @@ public interface Transaction extends AutoCloseable {
|
||||
* should be flushed prior to executing a query.
|
||||
* <p>
|
||||
* The default is for this to be true.
|
||||
* </p>
|
||||
*/
|
||||
boolean isFlushOnQuery();
|
||||
|
||||
@@ -507,7 +509,6 @@ public interface Transaction extends AutoCloseable {
|
||||
* flush the batch if you like.
|
||||
* <p>
|
||||
* Flushing occurs automatically when:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>the batch size is reached</li>
|
||||
* <li>A query is executed on the same transaction</li>
|
||||
@@ -519,11 +520,11 @@ public interface Transaction extends AutoCloseable {
|
||||
void flush() throws PersistenceException;
|
||||
|
||||
/**
|
||||
* This is a synonym for flush() and will be deprecated.
|
||||
* Deprecated - migrate to flush().
|
||||
* <p>
|
||||
* flush() is preferred as it matches the JPA flush() method.
|
||||
* </p>
|
||||
*/
|
||||
@Deprecated
|
||||
void flushBatch() throws PersistenceException;
|
||||
|
||||
/**
|
||||
@@ -533,29 +534,32 @@ public interface Transaction extends AutoCloseable {
|
||||
* commit() rollback() and end() methods on the Transaction should still be
|
||||
* used. Calling these methods on the Connection would be a big no no unless
|
||||
* you know what you are doing.
|
||||
* </p>
|
||||
* <p>
|
||||
* Examples of when a developer may wish to use the connection directly are:
|
||||
* Savepoints, advanced CLOB BLOB use and advanced stored procedure calls.
|
||||
* </p>
|
||||
*/
|
||||
Connection getConnection();
|
||||
Connection connection();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to connection().
|
||||
*/
|
||||
@Deprecated
|
||||
default Connection getConnection() {
|
||||
return connection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add table modification information to the TransactionEvent.
|
||||
* <p>
|
||||
* Use this in conjunction with getConnection() and raw JDBC.
|
||||
* </p>
|
||||
* <p>
|
||||
* This effectively informs Ebean of the data that has been changed by the
|
||||
* transaction and this information is normally automatically handled by Ebean
|
||||
* when you save entity beans or use UpdateSql etc.
|
||||
* </p>
|
||||
* <p>
|
||||
* If you use raw JDBC then you can use this method to inform Ebean for the
|
||||
* tables that have been modified. Ebean uses this information to keep its
|
||||
* caches in synch and maintain text indexes.
|
||||
* </p>
|
||||
*/
|
||||
void addModification(String tableName, boolean inserts, boolean updates, boolean deletes);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebean;
|
||||
|
||||
import io.ebean.annotation.PersistBatch;
|
||||
import io.ebean.annotation.TxIsolation;
|
||||
import io.ebean.annotation.TxOption;
|
||||
import io.ebean.annotation.TxType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -33,6 +34,8 @@ public final class TxScope {
|
||||
|
||||
private TxIsolation isolation;
|
||||
|
||||
private TxOption autoPersistUpdates;
|
||||
|
||||
private PersistBatch batch;
|
||||
|
||||
private PersistBatch batchOnCascade;
|
||||
@@ -123,6 +126,13 @@ public final class TxScope {
|
||||
+ "] serverName[" + serverName + "] rollbackFor[" + rollbackFor + "] noRollbackFor[" + noRollbackFor + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the AutoPersistUpdates mode as a nullable Boolean.
|
||||
*/
|
||||
public Boolean getAutoPersistUpdates() {
|
||||
return autoPersistUpdates == null ? null : autoPersistUpdates.asBoolean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if PersistBatch has been set.
|
||||
*/
|
||||
@@ -176,6 +186,14 @@ public final class TxScope {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the autoPersistUpdates mode.
|
||||
*/
|
||||
public TxScope setAutoPersistUpdates(TxOption autoPersistUpdates) {
|
||||
this.autoPersistUpdates = autoPersistUpdates;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the transaction profile id.
|
||||
*/
|
||||
|
||||
@@ -13,23 +13,23 @@ package io.ebean;
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
* ...
|
||||
* @NamedUpdates(value = {
|
||||
* @NamedUpdate(
|
||||
* @NamedUpdates(value = {
|
||||
* @NamedUpdate(
|
||||
* name = "setTitle",
|
||||
* notifyCache = false,
|
||||
* update = "update topic set title = :title, postCount = :count where id = :id"),
|
||||
* @NamedUpdate(
|
||||
* @NamedUpdate(
|
||||
* name = "setPostCount",
|
||||
* notifyCache = false,
|
||||
* update = "update f_topic set post_count = :postCount where id = :id"),
|
||||
* @NamedUpdate(
|
||||
* @NamedUpdate(
|
||||
* name = "incrementPostCount",
|
||||
* notifyCache = false,
|
||||
* update = "update Topic set postCount = postCount + 1 where id = :id")
|
||||
* //update = "update f_topic set post_count = post_count + 1 where id = :id")
|
||||
* })
|
||||
* @Entity
|
||||
* @Table(name = "f_topic")
|
||||
* @Entity
|
||||
* @Table(name = "f_topic")
|
||||
* public class Topic {
|
||||
* ...
|
||||
* }
|
||||
|
||||
@@ -13,12 +13,10 @@ import java.util.Set;
|
||||
* from the Map Set or List. The purpose of gathering the additions and removals
|
||||
* is to support persisting ManyToMany objects. The additions and removals
|
||||
* become inserts and deletes from the intersection table.
|
||||
* </p>
|
||||
* <p>
|
||||
* Technically this is <em>NOT</em> an extension of
|
||||
* <em>java.util.Collection</em>. The reason being that java.util.Map is not a
|
||||
* Collection. I realise this makes this name confusing so I apologise for that.
|
||||
* </p>
|
||||
*/
|
||||
public interface BeanCollection<E> extends Serializable {
|
||||
|
||||
@@ -68,7 +66,6 @@ public interface BeanCollection<E> extends Serializable {
|
||||
* Return true if the collection is uninitialised or is empty without any held modifications.
|
||||
* <p>
|
||||
* Returning true means can safely skip cascade save for this bean collection.
|
||||
* </p>
|
||||
*/
|
||||
boolean isSkipSave();
|
||||
|
||||
@@ -93,7 +90,6 @@ public interface BeanCollection<E> extends Serializable {
|
||||
* <p>
|
||||
* That is, if the collection was not loaded due to filterMany predicates etc
|
||||
* then make sure the collection is set to empty.
|
||||
* </p>
|
||||
*/
|
||||
boolean checkEmptyLazyLoad();
|
||||
|
||||
@@ -136,10 +132,7 @@ public interface BeanCollection<E> extends Serializable {
|
||||
boolean isReadOnly();
|
||||
|
||||
/**
|
||||
* Add the bean to the collection.
|
||||
* <p>
|
||||
* This is disallowed for BeanMap.
|
||||
* </p>
|
||||
* Add the bean to the collection. This is disallowed for BeanMap.
|
||||
*/
|
||||
void internalAdd(Object bean);
|
||||
|
||||
@@ -168,7 +161,6 @@ public interface BeanCollection<E> extends Serializable {
|
||||
* Map.Entry.
|
||||
* <p>
|
||||
* For maps this returns the entrySet as we need the keys of the map.
|
||||
* </p>
|
||||
*/
|
||||
Collection<?> getActualEntries();
|
||||
|
||||
@@ -185,6 +177,11 @@ public interface BeanCollection<E> extends Serializable {
|
||||
*/
|
||||
boolean isReference();
|
||||
|
||||
/**
|
||||
* Return true if the collection is modify listening and has modifications.
|
||||
*/
|
||||
boolean hasModifications();
|
||||
|
||||
/**
|
||||
* Set modify listening on or off. This is used to keep track of objects that
|
||||
* have been added to or removed from the list set or map.
|
||||
@@ -192,7 +189,6 @@ public interface BeanCollection<E> extends Serializable {
|
||||
* This is required only for ManyToMany collections. The additions and
|
||||
* deletions are used to insert or delete entries from the intersection table.
|
||||
* Otherwise modifyListening is false.
|
||||
* </p>
|
||||
*/
|
||||
void setModifyListening(ModifyListenMode modifyListenMode);
|
||||
|
||||
@@ -206,7 +202,6 @@ public interface BeanCollection<E> extends Serializable {
|
||||
* <p>
|
||||
* This will potentially end up as an insert into a intersection table for a
|
||||
* ManyToMany.
|
||||
* </p>
|
||||
*/
|
||||
void modifyAddition(E bean);
|
||||
|
||||
@@ -215,7 +210,6 @@ public interface BeanCollection<E> extends Serializable {
|
||||
* <p>
|
||||
* This will potentially end up as an delete from an intersection table for a
|
||||
* ManyToMany.
|
||||
* </p>
|
||||
*/
|
||||
void modifyRemoval(Object bean);
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ public interface BeanCollectionLoader {
|
||||
/**
|
||||
* Return the name of the associated Database.
|
||||
*/
|
||||
String getName();
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Invoke the lazy loading for this bean collection.
|
||||
|
||||
@@ -27,17 +27,6 @@ public interface EntityBean extends Serializable {
|
||||
throw new NotEnhancedException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the enhancement marker value.
|
||||
* <p>
|
||||
* This is the class name of the enhanced class and used to check that all
|
||||
* entity classes are enhanced (specifically not just a super class).
|
||||
* </p>
|
||||
*/
|
||||
default String _ebean_getMarker() {
|
||||
throw new NotEnhancedException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a new entity bean instance.
|
||||
*/
|
||||
|
||||
@@ -32,39 +32,52 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
private static final int STATE_REFERENCE = 1;
|
||||
private static final int STATE_LOADED = 2;
|
||||
|
||||
/**
|
||||
* Used when a bean is partially filled.
|
||||
*/
|
||||
private static final byte FLAG_LOADED_PROP = 1;
|
||||
private static final byte FLAG_CHANGED_PROP = 2;
|
||||
private static final byte FLAG_CHANGEDLOADED_PROP = 3;
|
||||
/**
|
||||
* Flags indicating if a property is a dirty embedded bean. Used to distinguish
|
||||
* between an embedded bean being completely overwritten and one of its
|
||||
* embedded properties being made dirty.
|
||||
*/
|
||||
private static final byte FLAG_EMBEDDED_DIRTY = 4;
|
||||
/**
|
||||
* Flags indicating if a property is a dirty embedded bean. Used to distinguish
|
||||
* between an embedded bean being completely overwritten and one of its
|
||||
* embedded properties being made dirty.
|
||||
*/
|
||||
private static final byte FLAG_ORIG_VALUE_SET = 8;
|
||||
|
||||
/**
|
||||
* Flags indicating if the mutable hash is set.
|
||||
*/
|
||||
private static final byte FLAG_MUTABLE_HASH_SET = 16;
|
||||
|
||||
private transient final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
private transient NodeUsageCollector nodeUsageCollector;
|
||||
|
||||
private transient PersistenceContext persistenceContext;
|
||||
|
||||
private transient BeanLoader beanLoader;
|
||||
|
||||
private transient PreGetterCallback preGetterCallback;
|
||||
|
||||
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.
|
||||
*/
|
||||
private int state;
|
||||
|
||||
private boolean forceUpdate;
|
||||
|
||||
private boolean readOnly;
|
||||
|
||||
private boolean dirty;
|
||||
|
||||
/**
|
||||
* Flag set to disable lazy loading - typically for SQL "report" type entity beans.
|
||||
*/
|
||||
@@ -74,41 +87,26 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* Flag set when lazy loading failed due to the underlying bean being deleted in the DB.
|
||||
*/
|
||||
private boolean lazyLoadFailure;
|
||||
|
||||
/**
|
||||
* Used when a bean is partially filled.
|
||||
*/
|
||||
private static final byte FLAG_LOADED_PROP = 1;
|
||||
|
||||
/**
|
||||
* Set of changed properties.
|
||||
*/
|
||||
private static final byte FLAG_CHANGED_PROP = 2;
|
||||
|
||||
/**
|
||||
* Flags indicating if a property is a dirty embedded bean. Used to distinguish
|
||||
* between an embedded bean being completely overwritten and one of its
|
||||
* embedded properties being made dirty.
|
||||
*/
|
||||
private static final byte FLAG_EMBEDDED_DIRTY = 4;
|
||||
|
||||
/**
|
||||
* Flags indicating if a property is a dirty embedded bean. Used to distinguish
|
||||
* between an embedded bean being completely overwritten and one of its
|
||||
* embedded properties being made dirty.
|
||||
*/
|
||||
private static final byte FLAG_ORIG_VALUE_SET = 8;
|
||||
|
||||
private final byte[] flags;
|
||||
|
||||
private boolean fullyLoadedBean;
|
||||
private boolean loadedFromCache;
|
||||
private final byte[] flags;
|
||||
private Object[] origValues;
|
||||
private Exception[] loadErrors;
|
||||
private int lazyLoadProperty = -1;
|
||||
private Object ownerId;
|
||||
private int sortOrder;
|
||||
|
||||
/**
|
||||
* Holds information of json loaded jackson beans (e.g. the original json or checksum).
|
||||
*/
|
||||
private MutableValueInfo[] mutableInfo;
|
||||
|
||||
/**
|
||||
* Holds json content determined at point of dirty check.
|
||||
* Stored here on dirty check such that we only convert to json once.
|
||||
*/
|
||||
private MutableValueNext[] mutableNext;
|
||||
|
||||
/**
|
||||
* Create a intercept with a given entity.
|
||||
*/
|
||||
@@ -246,6 +244,17 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* if any embedded beans are either new or dirty (and hence need saving).
|
||||
*/
|
||||
public boolean isDirty() {
|
||||
if (dirty) {
|
||||
return true;
|
||||
}
|
||||
if (mutableInfo != null) {
|
||||
for (int i = 0; i < mutableInfo.length; i++) {
|
||||
if (mutableInfo[i] != null && !mutableInfo[i].isEqualToObject(owner._ebean_getField(i))) {
|
||||
dirty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return dirty;
|
||||
}
|
||||
|
||||
@@ -386,8 +395,18 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
this.owner._ebean_setEmbeddedLoaded();
|
||||
this.lazyLoadProperty = -1;
|
||||
this.origValues = null;
|
||||
// after save, transfer the mutable next values back to mutable info
|
||||
if (mutableNext != null) {
|
||||
for (int i = 0; i < mutableNext.length; i++) {
|
||||
MutableValueNext next = mutableNext[i];
|
||||
if (next != null) {
|
||||
mutableInfo(i, next.info());
|
||||
}
|
||||
}
|
||||
}
|
||||
this.mutableNext = null;
|
||||
for (int i = 0; i < flags.length; i++) {
|
||||
flags[i] &= ~(FLAG_CHANGED_PROP + FLAG_ORIG_VALUE_SET);
|
||||
flags[i] &= ~(FLAG_CHANGED_PROP | FLAG_ORIG_VALUE_SET);
|
||||
}
|
||||
this.dirty = false;
|
||||
}
|
||||
@@ -460,6 +479,10 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* Return the original value that was changed via an update.
|
||||
*/
|
||||
public Object getOrigValue(int propertyIndex) {
|
||||
if ((flags[propertyIndex] & (FLAG_ORIG_VALUE_SET | FLAG_MUTABLE_HASH_SET)) == FLAG_MUTABLE_HASH_SET) {
|
||||
// mutable hash set, but not ORIG_VALUE
|
||||
setOriginalValue(propertyIndex, mutableInfo[propertyIndex].get());
|
||||
}
|
||||
if (origValues == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -494,7 +517,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* Return the number of properties.
|
||||
*/
|
||||
public int getPropertyLength() {
|
||||
return owner._ebean_getPropertyNames().length;
|
||||
return flags.length;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -569,6 +592,10 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
flags[propertyIndex] |= FLAG_CHANGED_PROP;
|
||||
}
|
||||
|
||||
private void setChangeLoaded(int propertyIndex) {
|
||||
flags[propertyIndex] |= FLAG_CHANGEDLOADED_PROP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set that an embedded bean has had one of its properties changed.
|
||||
*/
|
||||
@@ -578,7 +605,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
|
||||
private void setOriginalValue(int propertyIndex, Object value) {
|
||||
if (origValues == null) {
|
||||
origValues = new Object[owner._ebean_getPropertyNames().length];
|
||||
origValues = new Object[flags.length];
|
||||
}
|
||||
if ((flags[propertyIndex] & FLAG_ORIG_VALUE_SET) == 0) {
|
||||
flags[propertyIndex] |= FLAG_ORIG_VALUE_SET;
|
||||
@@ -591,7 +618,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
*/
|
||||
private void setOriginalValueForce(int propertyIndex, Object value) {
|
||||
if (origValues == null) {
|
||||
origValues = new Object[owner._ebean_getPropertyNames().length];
|
||||
origValues = new Object[flags.length];
|
||||
}
|
||||
origValues[propertyIndex] = value;
|
||||
}
|
||||
@@ -652,7 +679,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
public void addDirtyPropertyNames(Set<String> props, String prefix) {
|
||||
int len = getPropertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if ((flags[i] & FLAG_CHANGED_PROP) != 0) {
|
||||
if (isChangedProp(i)) {
|
||||
// the property has been changed on this bean
|
||||
props.add((prefix == null ? getProperty(i) : prefix + getProperty(i)));
|
||||
} else if ((flags[i] & FLAG_EMBEDDED_DIRTY) != 0) {
|
||||
@@ -670,7 +697,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
String[] names = owner._ebean_getPropertyNames();
|
||||
int len = getPropertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if ((flags[i] & FLAG_CHANGED_PROP) != 0) {
|
||||
if (isChangedProp(i)) {
|
||||
if (propertyNames.contains(names[i])) {
|
||||
return true;
|
||||
}
|
||||
@@ -698,7 +725,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
public void addDirtyPropertyValues(Map<String, ValuePair> dirtyValues, String prefix) {
|
||||
int len = getPropertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if ((flags[i] & FLAG_CHANGED_PROP) != 0) {
|
||||
if (isChangedProp(i)) {
|
||||
// the property has been changed on this bean
|
||||
String propName = (prefix == null ? getProperty(i) : prefix + getProperty(i));
|
||||
Object newVal = owner._ebean_getField(i);
|
||||
@@ -720,7 +747,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
public void addDirtyPropertyValues(BeanDiffVisitor visitor) {
|
||||
int len = getPropertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if ((flags[i] & FLAG_CHANGED_PROP) != 0) {
|
||||
if (isChangedProp(i)) {
|
||||
// the property has been changed on this bean
|
||||
Object newVal = owner._ebean_getField(i);
|
||||
Object oldVal = getOrigValue(i);
|
||||
@@ -755,7 +782,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
}
|
||||
int len = getPropertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if ((flags[i] & FLAG_CHANGED_PROP) != 0) {
|
||||
if ((flags[i] & FLAG_CHANGED_PROP) != 0) { // we do not check against mutablecontent here.
|
||||
sb.append(i).append(',');
|
||||
} else if ((flags[i] & FLAG_EMBEDDED_DIRTY) != 0) {
|
||||
// an embedded property has been changed - recurse
|
||||
@@ -816,7 +843,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
}
|
||||
// For stand alone reference bean or after deserialisation lazy load
|
||||
// using the ebeanServer. Synchronise only on the bean.
|
||||
loadBeanInternal(loadProperty, database.getPluginApi().beanLoader());
|
||||
loadBeanInternal(loadProperty, database.pluginApi().beanLoader());
|
||||
return;
|
||||
}
|
||||
} finally {
|
||||
@@ -931,10 +958,14 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* OneToMany and ManyToMany only set loaded state.
|
||||
*/
|
||||
public void preSetterMany(boolean interceptField, int propertyIndex, Object oldValue, Object newValue) {
|
||||
if (readOnly) {
|
||||
throw new IllegalStateException("This bean is readOnly");
|
||||
if (state == STATE_NEW) {
|
||||
setLoadedProperty(propertyIndex);
|
||||
} else {
|
||||
if (readOnly) {
|
||||
throw new IllegalStateException("This bean is readOnly");
|
||||
}
|
||||
setChangeLoaded(propertyIndex);
|
||||
}
|
||||
setLoadedProperty(propertyIndex);
|
||||
}
|
||||
|
||||
private void setChangedPropertyValue(int propertyIndex, boolean setDirtyState, Object origValue) {
|
||||
@@ -973,7 +1004,6 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check for primitive boolean.
|
||||
*/
|
||||
@@ -1123,7 +1153,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
*/
|
||||
public void setLoadError(int propertyIndex, Exception t) {
|
||||
if (loadErrors == null) {
|
||||
loadErrors = new Exception[owner._ebean_getPropertyNames().length];
|
||||
loadErrors = new Exception[flags.length];
|
||||
}
|
||||
loadErrors[propertyIndex] = t;
|
||||
flags[propertyIndex] |= FLAG_LOADED_PROP;
|
||||
@@ -1149,4 +1179,61 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private boolean isChangedProp(int i) {
|
||||
if ((flags[i] & FLAG_CHANGED_PROP) != 0) {
|
||||
return true;
|
||||
} else if (mutableInfo == null || mutableInfo[i] == null || mutableInfo[i].isEqualToObject(owner._ebean_getField(i))) {
|
||||
return false;
|
||||
} else {
|
||||
// mark for change
|
||||
flags[i] |= FLAG_CHANGED_PROP;
|
||||
dirty = true; // this makes the bean automatically dirty!
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the MutableValueInfo for the given property or null.
|
||||
*/
|
||||
public MutableValueInfo mutableInfo(int propertyIndex) {
|
||||
return mutableInfo == null ? null : mutableInfo[propertyIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the MutableValueInfo for the given property.
|
||||
*/
|
||||
public void mutableInfo(int propertyIndex, MutableValueInfo info) {
|
||||
if (mutableInfo == null) {
|
||||
mutableInfo = new MutableValueInfo[flags.length];
|
||||
}
|
||||
flags[propertyIndex] |= FLAG_MUTABLE_HASH_SET;
|
||||
mutableInfo[propertyIndex] = info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dirty detection set the next mutable property content and info .
|
||||
* <p>
|
||||
* Set here as the mutable property dirty detection is based on json content comparison.
|
||||
* We only want to perform the json serialisation once so storing it here as part of
|
||||
* dirty detection so that we can get it back to bind in insert or update etc.
|
||||
*/
|
||||
public void mutableNext(int propertyIndex, MutableValueNext next) {
|
||||
if (mutableNext == null) {
|
||||
mutableNext = new MutableValueNext[flags.length];
|
||||
}
|
||||
mutableNext[propertyIndex] = next;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the 'next' mutable info returning the content that was obtained via dirty detection.
|
||||
*/
|
||||
public String mutableNext(int propertyIndex) {
|
||||
if (mutableNext == null) {
|
||||
return null;
|
||||
}
|
||||
final MutableValueNext next = mutableNext[propertyIndex];
|
||||
return next != null ? next.content() : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package io.ebean.bean;
|
||||
|
||||
/**
|
||||
* Holds information on mutable values (like plain beans stored as json).
|
||||
* <p>
|
||||
* Used internally in EntityBeanIntercept for dirty detection on mutable values.
|
||||
* Typically, mutation detection is based on a hash/checksum of json content or the
|
||||
* original json content itself.
|
||||
* <p>
|
||||
* Refer to the mapping options {@code @DbJson(mutationDetection)}.
|
||||
*/
|
||||
public interface MutableValueInfo {
|
||||
|
||||
/**
|
||||
* Compares the given json returning null if deemed unchanged or returning
|
||||
* the MutableValueNext to use if deemed dirty/changed.
|
||||
* <p>
|
||||
* Returning MutableValueNext allows an implementation based on hash/checksum
|
||||
* to only perform that computation once.
|
||||
*
|
||||
* @return Null if deemed unchanged or the MutableValueNext if deemed changed.
|
||||
*/
|
||||
MutableValueNext nextDirty(String json);
|
||||
|
||||
/**
|
||||
* Compares the given object to an internal value.
|
||||
* <p>
|
||||
* This is used to support changelog/beanState. The implementation can serialize the
|
||||
* object into json form and compare it against the original json.
|
||||
*/
|
||||
boolean isEqualToObject(Object obj);
|
||||
|
||||
/**
|
||||
* Creates a new instance from the internal json string.
|
||||
* <p>
|
||||
* This is used to provide an original/old value for change logging / persist listeners.
|
||||
* This is only available for properties that have {@code @DbJson(keepSource=true)}.
|
||||
*/
|
||||
default Object get() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package io.ebean.bean;
|
||||
|
||||
/**
|
||||
* Represents a next value to use for mutable content properties (DbJson with jackson beans).
|
||||
*/
|
||||
public interface MutableValueNext {
|
||||
|
||||
/**
|
||||
* Return the next content to use. Provided such that we serialise to json once.
|
||||
*/
|
||||
String content();
|
||||
|
||||
/**
|
||||
* Return the next MutableValueInfo to use after an update.
|
||||
*/
|
||||
MutableValueInfo info();
|
||||
}
|
||||
@@ -5,7 +5,6 @@ package io.ebean.bean;
|
||||
* <p>
|
||||
* This is used to ensure only one instance for a given entity type and id is
|
||||
* used to build object graphs from queries and lazy loading.
|
||||
* </p>
|
||||
*/
|
||||
public interface PersistenceContext {
|
||||
|
||||
@@ -20,7 +19,6 @@ public interface PersistenceContext {
|
||||
* <p>
|
||||
* Returns an existing entity bean (if one is already there) and otherwise
|
||||
* returns null.
|
||||
* </p>
|
||||
*/
|
||||
Object putIfAbsent(Class<?> rootType, Object id, Object bean);
|
||||
|
||||
@@ -82,7 +80,6 @@ public interface PersistenceContext {
|
||||
* <p>
|
||||
* If a bean has been deleted then for the same persistence context is should
|
||||
* not be able to be fetched from persistence context or L2 cache.
|
||||
* </p>
|
||||
*/
|
||||
class WithOption {
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ public abstract class SingleBeanLoader implements BeanLoader {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return database.getName();
|
||||
return database.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -39,7 +39,7 @@ public abstract class SingleBeanLoader implements BeanLoader {
|
||||
|
||||
@Override
|
||||
public void loadBean(EntityBeanIntercept ebi) {
|
||||
database.getPluginApi().loadBeanL2(ebi);
|
||||
database.pluginApi().loadBeanL2(ebi);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ public abstract class SingleBeanLoader implements BeanLoader {
|
||||
|
||||
@Override
|
||||
public void loadBean(EntityBeanIntercept ebi) {
|
||||
database.getPluginApi().loadBeanRef(ebi);
|
||||
database.pluginApi().loadBeanRef(ebi);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ public abstract class SingleBeanLoader implements BeanLoader {
|
||||
|
||||
@Override
|
||||
public void loadBean(EntityBeanIntercept ebi) {
|
||||
database.getPluginApi().loadBean(ebi);
|
||||
database.pluginApi().loadBean(ebi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,7 @@ import java.util.Set;
|
||||
public class QueryCacheEntry {
|
||||
|
||||
private final Object value;
|
||||
|
||||
private final Set<String> dependentTables;
|
||||
|
||||
private final long timestamp;
|
||||
|
||||
/**
|
||||
|
||||
+19
-3
@@ -10,17 +10,17 @@ import java.util.Set;
|
||||
* Represents part of the "L2" server side cache.
|
||||
* <p>
|
||||
* This is used to cache beans or query results (bean collections).
|
||||
* </p>
|
||||
* <p>
|
||||
* There are 2 ServerCache's for each bean type. One is used as the 'bean cache'
|
||||
* which holds beans of a given type. The other is the 'query cache' holding
|
||||
* query results for a given type.
|
||||
* </p>
|
||||
*/
|
||||
public interface ServerCache {
|
||||
|
||||
/**
|
||||
* Get values for many keys.
|
||||
*/
|
||||
default Map<Object, Object> getAll(Set<Object> keys) {
|
||||
|
||||
Map<Object, Object> map = new LinkedHashMap<>();
|
||||
for (Object key : keys) {
|
||||
Object value = get(key);
|
||||
@@ -73,6 +73,14 @@ public interface ServerCache {
|
||||
/**
|
||||
* Return the hit ratio the cache is currently getting.
|
||||
*/
|
||||
default int hitRatio() {
|
||||
return getHitRatio();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated migrate to hitRatio().
|
||||
*/
|
||||
@Deprecated
|
||||
int getHitRatio();
|
||||
|
||||
/**
|
||||
@@ -80,6 +88,14 @@ public interface ServerCache {
|
||||
*
|
||||
* @param reset if true the statistics are reset.
|
||||
*/
|
||||
default ServerCacheStatistics statistics(boolean reset) {
|
||||
return getStatistics(reset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated migrate to statistics().
|
||||
*/
|
||||
@Deprecated
|
||||
ServerCacheStatistics getStatistics(boolean reset);
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,7 +21,15 @@ public interface ServerCacheManager {
|
||||
* rather than background processing.
|
||||
* </p>
|
||||
*/
|
||||
boolean isLocalL2Caching();
|
||||
boolean localL2Caching();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to localL2Caching().
|
||||
*/
|
||||
@Deprecated
|
||||
default boolean isLocalL2Caching() {
|
||||
return localL2Caching();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the cache regions.
|
||||
@@ -36,37 +44,78 @@ public interface ServerCacheManager {
|
||||
*
|
||||
* @param regions A region name or comma delimited list of region names.
|
||||
*/
|
||||
void setEnabledRegions(String regions);
|
||||
void enabledRegions(String regions);
|
||||
|
||||
/**
|
||||
* Deprecated migrate to enabledRegions().
|
||||
*/
|
||||
@Deprecated
|
||||
default void setEnabledRegions(String regions) {
|
||||
enabledRegions(regions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable all the cache regions.
|
||||
*/
|
||||
void setAllRegionsEnabled(boolean enabled);
|
||||
void allRegionsEnabled(boolean enabled);
|
||||
|
||||
/**
|
||||
* Return the cache region by name. Typically to enable or disable the region.
|
||||
* Deprecated migrate to allRegionsEnabled().
|
||||
*/
|
||||
ServerCacheRegion getRegion(String name);
|
||||
@Deprecated
|
||||
default void setAllRegionsEnabled(boolean enabled) {
|
||||
allRegionsEnabled(enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the cache region by name. Typically, to enable or disable the region.
|
||||
*/
|
||||
ServerCacheRegion region(String name);
|
||||
|
||||
@Deprecated
|
||||
default ServerCacheRegion getRegion(String name) {
|
||||
return region(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the cache for mapping natural keys to id values.
|
||||
*/
|
||||
ServerCache getNaturalKeyCache(Class<?> beanType);
|
||||
ServerCache naturalKeyCache(Class<?> beanType);
|
||||
|
||||
@Deprecated
|
||||
default ServerCache getNaturalKeyCache(Class<?> beanType) {
|
||||
return naturalKeyCache(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the cache for beans of a particular type.
|
||||
*/
|
||||
ServerCache getBeanCache(Class<?> beanType);
|
||||
ServerCache beanCache(Class<?> beanType);
|
||||
|
||||
@Deprecated
|
||||
default ServerCache getBeanCache(Class<?> beanType) {
|
||||
return beanCache(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the cache for associated many properties of a bean type.
|
||||
*/
|
||||
ServerCache getCollectionIdsCache(Class<?> beanType, String propertyName);
|
||||
ServerCache collectionIdsCache(Class<?> beanType, String propertyName);
|
||||
|
||||
@Deprecated
|
||||
default ServerCache getCollectionIdsCache(Class<?> beanType, String propertyName) {
|
||||
return collectionIdsCache(beanType, propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the cache for query results of a particular type of bean.
|
||||
*/
|
||||
ServerCache getQueryCache(Class<?> beanType);
|
||||
ServerCache queryCache(Class<?> beanType);
|
||||
|
||||
@Deprecated
|
||||
default ServerCache getQueryCache(Class<?> beanType) {
|
||||
return queryCache(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
* This clears both the bean and query cache for a given type.
|
||||
|
||||
@@ -18,7 +18,6 @@ public class ServerCacheOptions {
|
||||
* Construct with no set options.
|
||||
*/
|
||||
public ServerCacheOptions() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,7 +72,6 @@ public class ServerCacheOptions {
|
||||
* Return a copy of this object.
|
||||
*/
|
||||
public ServerCacheOptions copy() {
|
||||
|
||||
ServerCacheOptions copy = new ServerCacheOptions();
|
||||
copy.maxSize = maxSize;
|
||||
copy.maxIdleSecs = maxIdleSecs;
|
||||
|
||||
@@ -8,7 +8,15 @@ public interface ServerCacheRegion {
|
||||
/**
|
||||
* Return the region name.
|
||||
*/
|
||||
String getName();
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to name().
|
||||
*/
|
||||
@Deprecated
|
||||
default String getName() {
|
||||
return name();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the cache region is enabled.
|
||||
|
||||
@@ -63,7 +63,7 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
*/
|
||||
AbstractBeanCollection(BeanCollectionLoader loader, EntityBean ownerBean, String propertyName) {
|
||||
this.loader = loader;
|
||||
this.ebeanServerName = loader.getName();
|
||||
this.ebeanServerName = loader.name();
|
||||
this.ownerBean = ownerBean;
|
||||
this.propertyName = propertyName;
|
||||
this.readOnly = ownerBean != null && ownerBean._ebean_getIntercept().isReadOnly();
|
||||
@@ -111,7 +111,7 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
public void setLoader(BeanCollectionLoader loader) {
|
||||
this.registeredWithLoadContext = true;
|
||||
this.loader = loader;
|
||||
this.ebeanServerName = loader.getName();
|
||||
this.ebeanServerName = loader.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -135,6 +135,11 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
// Support for modify additions deletions etc - ManyToMany
|
||||
// ---------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public boolean hasModifications() {
|
||||
return modifyHolder != null && modifyHolder.hasModifications();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModifyListenMode getModifyListening() {
|
||||
return modifyListenMode;
|
||||
@@ -145,7 +150,6 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
*/
|
||||
@Override
|
||||
public void setModifyListening(ModifyListenMode mode) {
|
||||
|
||||
this.modifyListenMode = mode;
|
||||
this.modifyListening = mode != null && ModifyListenMode.NONE != mode;
|
||||
if (modifyListening) {
|
||||
|
||||
@@ -87,7 +87,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public void internalAddWithCheck(Object bean) {
|
||||
if (list == null || !containsInstance(bean)) {
|
||||
if (list == null || bean == null || !containsInstance(bean)) {
|
||||
internalAdd(bean);
|
||||
}
|
||||
}
|
||||
@@ -198,10 +198,9 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
}
|
||||
if (list == null) {
|
||||
sb.append("deferred ");
|
||||
|
||||
} else {
|
||||
sb.append("size[").append(list.size()).append("] ");
|
||||
sb.append("list").append(list).append("");
|
||||
sb.append("list").append(list);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
}
|
||||
|
||||
public void internalPutWithCheck(Object key, Object bean) {
|
||||
if (map == null || !map.containsKey(key)) {
|
||||
if (map == null || key == null || !map.containsKey(key)) {
|
||||
internalPut(key, bean);
|
||||
}
|
||||
}
|
||||
@@ -175,10 +175,6 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
|
||||
/**
|
||||
* Returns the map entrySet.
|
||||
* <p>
|
||||
* This is because the key values may need to be set against the details (so
|
||||
* they don't need to be set twice).
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
public Collection<?> getActualEntries() {
|
||||
@@ -194,7 +190,6 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
}
|
||||
if (map == null) {
|
||||
sb.append("deferred ");
|
||||
|
||||
} else {
|
||||
sb.append("size[").append(map.size()).append("]");
|
||||
sb.append(" map").append(map);
|
||||
@@ -243,17 +238,12 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public Set<Entry<K, E>> entrySet() {
|
||||
init();
|
||||
if (isReadOnly()) {
|
||||
return Collections.unmodifiableSet(map.entrySet());
|
||||
}
|
||||
if (modifyListening) {
|
||||
Set<Entry<K, E>> s = map.entrySet();
|
||||
return new ModifySet(this, s);
|
||||
}
|
||||
return map.entrySet();
|
||||
return modifyListening ? new ModifyEntrySet<>(this, map.entrySet()) : map.entrySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -274,8 +264,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
if (isReadOnly()) {
|
||||
return Collections.unmodifiableSet(map.keySet());
|
||||
}
|
||||
// we don't really care about modifications to the ketSet?
|
||||
return map.keySet();
|
||||
return modifyListening ? new ModifyKeySet<>(this, map.keySet()) : map.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -346,11 +335,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
if (isReadOnly()) {
|
||||
return Collections.unmodifiableCollection(map.values());
|
||||
}
|
||||
if (modifyListening) {
|
||||
Collection<E> c = map.values();
|
||||
return new ModifyCollection<>(this, c);
|
||||
}
|
||||
return map.values();
|
||||
return modifyListening ? new ModifyCollection<>(this, map.values()) : map.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -70,9 +70,8 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
|
||||
@Override
|
||||
public void internalAddWithCheck(Object bean) {
|
||||
if (set == null || !set.contains(bean)) {
|
||||
internalAdd(bean);
|
||||
}
|
||||
// set add() already de-dups so just add it
|
||||
internalAdd(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -177,7 +176,6 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
}
|
||||
if (set == null) {
|
||||
sb.append("deferred ");
|
||||
|
||||
} else {
|
||||
sb.append("size[").append(set.size()).append("]");
|
||||
sb.append(" set").append(set);
|
||||
|
||||
@@ -25,7 +25,7 @@ class ModifyCollection<E> implements Collection<E> {
|
||||
* The owner is notified of the additions and removals.
|
||||
* </p>
|
||||
*/
|
||||
public ModifyCollection(BeanCollection<E> owner, Collection<E> c) {
|
||||
ModifyCollection(BeanCollection<E> owner, Collection<E> c) {
|
||||
this.owner = owner;
|
||||
this.c = c;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
package io.ebean.common;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Handles the Entry Set for BeanMap.
|
||||
*/
|
||||
class ModifyEntrySet<K, E> implements Set<Map.Entry<K, E>> {
|
||||
|
||||
private final BeanMap<K, E> owner;
|
||||
private final Set<Map.Entry<K, E>> entrySet;
|
||||
|
||||
ModifyEntrySet(BeanMap<K, E> owner, Set<Map.Entry<K, E>> entrySet) {
|
||||
this.owner = owner;
|
||||
this.entrySet = entrySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return entrySet.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return entrySet.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return entrySet.contains(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return entrySet.toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T[] toArray(T[] a) {
|
||||
return entrySet.toArray(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> entries) {
|
||||
return entrySet.containsAll(entries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
owner.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(Map.Entry<K, E> entry) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends Map.Entry<K, E>> c) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
if (o instanceof Map.Entry) {
|
||||
Map.Entry entry = (Map.Entry) o;
|
||||
final E val = owner.get(entry.getKey());
|
||||
if (Objects.equals(val, entry.getValue())) {
|
||||
owner.remove(entry.getKey());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> entries) {
|
||||
boolean modified = false;
|
||||
final Iterator<Map.Entry<K, E>> it = iterator();
|
||||
while (it.hasNext()) {
|
||||
if (!entries.contains(it.next())) {
|
||||
it.remove();
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> entries) {
|
||||
boolean modified = false;
|
||||
for (Object entry : entries) {
|
||||
modified |= remove(entry);
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Map.Entry<K, E>> iterator() {
|
||||
return new EntrySetIterator(new ArrayList<>(entrySet).iterator());
|
||||
}
|
||||
|
||||
class EntrySetIterator implements Iterator<Map.Entry<K, E>> {
|
||||
|
||||
private final Iterator<Map.Entry<K, E>> iterator;
|
||||
private Map.Entry<K, E> entry;
|
||||
|
||||
EntrySetIterator(Iterator<Map.Entry<K, E>> iterator) {
|
||||
this.iterator = iterator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return iterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map.Entry<K, E> next() {
|
||||
entry = iterator.next();
|
||||
return entry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
owner.remove(entry.getKey());
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,9 +3,7 @@ package io.ebean.common;
|
||||
import io.ebean.bean.EntityBean;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Holds sets of additions and deletions from a 'owner' List Set or Map.
|
||||
@@ -23,19 +21,19 @@ class ModifyHolder<E> implements Serializable {
|
||||
/**
|
||||
* Deletions list for manyToMany persistence.
|
||||
*/
|
||||
private Set<E> modifyDeletions = new LinkedHashSet<>();
|
||||
private Map<E,Object> modifyDeletions = new IdentityHashMap<>();
|
||||
|
||||
/**
|
||||
* Additions list for manyToMany persistence.
|
||||
*/
|
||||
private Set<E> modifyAdditions = new LinkedHashSet<>();
|
||||
private Map<E,Object> modifyAdditions = new IdentityHashMap<>();
|
||||
|
||||
private boolean touched;
|
||||
|
||||
void reset() {
|
||||
touched = false;
|
||||
modifyDeletions = new LinkedHashSet<>();
|
||||
modifyAdditions = new LinkedHashSet<>();
|
||||
modifyDeletions = new IdentityHashMap<>();
|
||||
modifyAdditions = new IdentityHashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,51 +48,46 @@ class ModifyHolder<E> implements Serializable {
|
||||
}
|
||||
|
||||
private boolean undoDeletion(E bean) {
|
||||
return (bean != null) && modifyDeletions.remove(bean);
|
||||
return (bean != null) && modifyDeletions.remove(bean) != null;
|
||||
}
|
||||
|
||||
void modifyAddition(E bean) {
|
||||
if (bean != null) {
|
||||
touched = true;
|
||||
|
||||
if (bean instanceof EntityBean) {
|
||||
((EntityBean) bean)._ebean_getIntercept().setDeletedFromCollection(false);
|
||||
}
|
||||
|
||||
// If it is to delete then just remove the deletion
|
||||
if (!undoDeletion(bean)) {
|
||||
// Insert
|
||||
modifyAdditions.add(bean);
|
||||
modifyAdditions.put(bean, bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean undoAddition(Object bean) {
|
||||
return (bean != null) && modifyAdditions.remove(bean);
|
||||
return (bean != null) && modifyAdditions.remove(bean) != null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
void modifyRemoval(Object bean) {
|
||||
if (bean != null) {
|
||||
touched = true;
|
||||
|
||||
if (bean instanceof EntityBean) {
|
||||
((EntityBean) bean)._ebean_getIntercept().setDeletedFromCollection(true);
|
||||
}
|
||||
|
||||
// If it is to be added then just remove the addition
|
||||
if (!undoAddition(bean)) {
|
||||
modifyDeletions.add((E) bean);
|
||||
modifyDeletions.put((E) bean, bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Set<E> getModifyAdditions() {
|
||||
return modifyAdditions;
|
||||
return modifyAdditions.keySet();
|
||||
}
|
||||
|
||||
Set<E> getModifyRemovals() {
|
||||
return modifyDeletions;
|
||||
return modifyDeletions.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
package io.ebean.common;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Handle the Key Set for BeanMap.
|
||||
*/
|
||||
class ModifyKeySet<E> implements Set<E> {
|
||||
|
||||
private final Set<E> keySet;
|
||||
private final BeanMap<E, ?> owner;
|
||||
|
||||
ModifyKeySet(BeanMap<E, ?> owner, Set<E> keySet) {
|
||||
this.owner = owner;
|
||||
this.keySet = keySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return keySet.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return keySet.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return keySet.contains(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return keySet.toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T[] toArray(T[] a) {
|
||||
return keySet.toArray(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(E key) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends E> keys) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
return owner.remove(o) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> keys) {
|
||||
return keySet.containsAll(keys);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
owner.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return new KeySetIterator<>(new ArrayList<>(keySet).iterator());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> keys) {
|
||||
return keysMatch(keys, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> keys) {
|
||||
return keysMatch(keys, true);
|
||||
}
|
||||
|
||||
private boolean keysMatch(Collection<?> keys, boolean containsMatch) {
|
||||
boolean changed = false;
|
||||
final Iterator<E> iterator = iterator();
|
||||
while (iterator.hasNext()) {
|
||||
final E key = iterator.next();
|
||||
if (keys.contains(key) == containsMatch) {
|
||||
iterator.remove();
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
|
||||
class KeySetIterator<K> implements Iterator<K> {
|
||||
|
||||
private final Iterator<K> iterator;
|
||||
private K key;
|
||||
|
||||
KeySetIterator(Iterator<K> iterator) {
|
||||
this.iterator = iterator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return iterator.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public K next() {
|
||||
key = iterator.next();
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
owner.remove(key);
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package io.ebean.common;
|
||||
|
||||
import io.ebean.bean.BeanCollection;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Wraps a Set for the purposes of notifying removals and additions to the
|
||||
* BeanCollection owner.
|
||||
* <p>
|
||||
* This is required for persisting ManyToMany objects. Additions and removals
|
||||
* become inserts and deletes to the intersection table.
|
||||
* </p>
|
||||
*/
|
||||
class ModifySet<E> extends ModifyCollection<E> implements Set<E> {
|
||||
|
||||
/**
|
||||
* Create with an Owner that is notified of any additions or deletions.
|
||||
*/
|
||||
public ModifySet(BeanCollection<E> owner, Set<E> s) {
|
||||
super(owner, s);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,6 +7,8 @@ import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import static io.ebean.util.StringHelper.isNull;
|
||||
|
||||
/**
|
||||
* Provides some base implementation for NamingConventions.
|
||||
*
|
||||
@@ -78,10 +80,16 @@ public abstract class AbstractNamingConvention implements NamingConvention {
|
||||
|
||||
@Override
|
||||
public String getSequenceName(String rawTableName, String pkColumn) {
|
||||
final String tableNameUnquoted = databasePlatform.unQuote(rawTableName);
|
||||
TableName tableName = new TableName(rawTableName);
|
||||
String seqName = seqName(pkColumn, tableName.getName());
|
||||
return tableName.withCatalogAndSchema(seqName);
|
||||
}
|
||||
|
||||
private String seqName(String pkColumn, String tableName) {
|
||||
final String tableNameUnquoted = unQuote(tableName);
|
||||
String seqName = sequenceFormat.replace("{table}", tableNameUnquoted);
|
||||
pkColumn = (pkColumn == null) ? "" : databasePlatform.unQuote(pkColumn);
|
||||
return seqName.replace("{column}", pkColumn);
|
||||
pkColumn = (pkColumn == null) ? "" : unQuote(pkColumn);
|
||||
return quoteIdentifiers(seqName.replace("{column}", pkColumn));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -216,15 +224,13 @@ public abstract class AbstractNamingConvention implements NamingConvention {
|
||||
|| AnnotationUtil.has(supCls, DiscriminatorValue.class);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TableName getM2MJoinTableName(TableName lhsTable, TableName rhsTable) {
|
||||
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
buffer.append(lhsTable.getName());
|
||||
buffer.append(unQuote(lhsTable.getName()));
|
||||
buffer.append("_");
|
||||
|
||||
String rhsTableName = rhsTable.getName();
|
||||
String rhsTableName = unQuote(rhsTable.getName());
|
||||
if (rhsTableName.indexOf('_') < rhsPrefixLength) {
|
||||
// trim off a xx_ prefix if there is one
|
||||
rhsTableName = rhsTableName.substring(rhsTableName.indexOf('_') + 1);
|
||||
@@ -238,7 +244,13 @@ public abstract class AbstractNamingConvention implements NamingConvention {
|
||||
buffer.setLength(maxTableNameLength);
|
||||
}
|
||||
|
||||
return new TableName(lhsTable.getCatalog(), lhsTable.getSchema(), buffer.toString());
|
||||
String tableName = quoteIdentifiers(buffer.toString());
|
||||
return new TableName(lhsTable.getCatalog(), lhsTable.getSchema(), tableName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String deriveM2MColumn(String tableName, String dbColumn) {
|
||||
return quoteIdentifiers(unQuote(tableName) +"_" + unQuote(dbColumn));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -255,14 +267,29 @@ public abstract class AbstractNamingConvention implements NamingConvention {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableName(String catalog, String schema, String name) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (!isNull(catalog)) {
|
||||
sb.append(quoteIdentifiers(catalog)).append(".");
|
||||
}
|
||||
if (!isNull(schema)) {
|
||||
sb.append(quoteIdentifiers(schema)).append(".");
|
||||
}
|
||||
return sb.append(quoteIdentifiers(name)).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace back ticks (if they are used) with database platform specific
|
||||
* quoted identifiers.
|
||||
* Replace back ticks (if they are used) with database platform specific quoted identifiers.
|
||||
*/
|
||||
protected String quoteIdentifiers(String s) {
|
||||
return databasePlatform.convertQuotedIdentifiers(s);
|
||||
}
|
||||
|
||||
private String unQuote(String val) {
|
||||
return databasePlatform.unQuote(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks string is null or empty .
|
||||
*/
|
||||
|
||||
@@ -40,6 +40,13 @@ public class ClassLoadConfig {
|
||||
return isPresent("javax.validation.constraints.NotNull");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if jakarta validation annotations like Size and NotNull are present.
|
||||
*/
|
||||
public boolean isJakartaValidationAnnotationsPresent() {
|
||||
return isPresent("jakarta.validation.constraints.NotNull");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if javax PostConstruct annotation is present (maybe not in java9).
|
||||
* If not we don't support PostConstruct lifecycle events.
|
||||
|
||||
@@ -7,9 +7,7 @@ import io.ebean.EbeanVersion;
|
||||
import io.ebean.PersistenceContextScope;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.annotation.Encrypted;
|
||||
import io.ebean.annotation.PersistBatch;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.annotation.*;
|
||||
import io.ebean.cache.ServerCachePlugin;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.config.dbplatform.DbEncrypt;
|
||||
@@ -193,6 +191,11 @@ public class DatabaseConfig {
|
||||
*/
|
||||
private JsonConfig.Include jsonInclude = JsonConfig.Include.ALL;
|
||||
|
||||
/**
|
||||
* The default mode used for {@code @DbJson} with Jackson ObjectMapper.
|
||||
*/
|
||||
private MutationDetection jsonMutationDetection = MutationDetection.HASH;
|
||||
|
||||
/**
|
||||
* The database platform name. Used to imply a DatabasePlatform to use.
|
||||
*/
|
||||
@@ -232,6 +235,12 @@ public class DatabaseConfig {
|
||||
*/
|
||||
private String historyTableSuffix = "_history";
|
||||
|
||||
/**
|
||||
* When true explicit transactions beans that have been made dirty will be
|
||||
* automatically persisted via update on flush.
|
||||
*/
|
||||
private boolean autoPersistUpdates;
|
||||
|
||||
/**
|
||||
* Use for transaction scoped batch mode.
|
||||
*/
|
||||
@@ -310,6 +319,8 @@ public class DatabaseConfig {
|
||||
*/
|
||||
private ExternalTransactionManager externalTransactionManager;
|
||||
|
||||
private boolean skipDataSourceCheck;
|
||||
|
||||
/**
|
||||
* The data source (if programmatically provided).
|
||||
*/
|
||||
@@ -489,7 +500,7 @@ public class DatabaseConfig {
|
||||
* Should the javax.validation.constraints.NotNull enforce a notNull column in DB.
|
||||
* If set to false, use io.ebean.annotation.NotNull or Column(nullable=true).
|
||||
*/
|
||||
private boolean useJavaxValidationNotNull = true;
|
||||
private boolean useValidationNotNull = true;
|
||||
|
||||
/**
|
||||
* Generally we want to perform L2 cache notification in the background and not impact
|
||||
@@ -498,14 +509,23 @@ public class DatabaseConfig {
|
||||
private boolean notifyL2CacheInForeground;
|
||||
|
||||
/**
|
||||
* Set to true to support query plan capture.
|
||||
* Set to true to enable bind capture required for query plan capture.
|
||||
*/
|
||||
private boolean collectQueryPlans;
|
||||
private boolean queryPlanEnable;
|
||||
|
||||
/**
|
||||
* The default threshold in micros for collecting query plans.
|
||||
*/
|
||||
private long collectQueryPlanThresholdMicros = Long.MAX_VALUE;
|
||||
private long queryPlanThresholdMicros = Long.MAX_VALUE;
|
||||
|
||||
/**
|
||||
* Set to true to enable automatic periodic query plan capture.
|
||||
*/
|
||||
private boolean queryPlanCapture;
|
||||
private long queryPlanCapturePeriodSecs = 60 * 10; // 10 minutes
|
||||
private long queryPlanCaptureMaxTimeMillis = 10_000; // 10 seconds
|
||||
private int queryPlanCaptureMaxCount = 10;
|
||||
private QueryPlanListener queryPlanListener;
|
||||
|
||||
/**
|
||||
* The time in millis used to determine when a query is alerted for being slow.
|
||||
@@ -722,6 +742,24 @@ public class DatabaseConfig {
|
||||
this.jsonInclude = jsonInclude;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default MutableDetection to use with {@code @DbJson} using Jackson.
|
||||
*
|
||||
* @see DbJson#mutationDetection()
|
||||
*/
|
||||
public MutationDetection getJsonMutationDetection() {
|
||||
return jsonMutationDetection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default MutableDetection to use with {@code @DbJson} using Jackson.
|
||||
*
|
||||
* @see DbJson#mutationDetection()
|
||||
*/
|
||||
public void setJsonMutationDetection(MutationDetection jsonMutationDetection) {
|
||||
this.jsonMutationDetection = jsonMutationDetection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the Database.
|
||||
*/
|
||||
@@ -896,6 +934,20 @@ public class DatabaseConfig {
|
||||
this.tenantCatalogProvider = tenantCatalogProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if dirty beans are automatically persisted.
|
||||
*/
|
||||
public boolean isAutoPersistUpdates() {
|
||||
return autoPersistUpdates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if dirty beans are automatically persisted.
|
||||
*/
|
||||
public void setAutoPersistUpdates(boolean autoPersistUpdates) {
|
||||
this.autoPersistUpdates = autoPersistUpdates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the PersistBatch mode to use by default at the transaction level.
|
||||
* <p>
|
||||
@@ -1045,7 +1097,6 @@ public class DatabaseConfig {
|
||||
* This is a performance optimisation to reduce the number times Ebean
|
||||
* requests a sequence to be used as an Id for a bean (aka reduce network
|
||||
* chatter).
|
||||
|
||||
*/
|
||||
public void setDatabaseSequenceBatchSize(int databaseSequenceBatchSize) {
|
||||
platformConfig.setDatabaseSequenceBatchSize(databaseSequenceBatchSize);
|
||||
@@ -1602,6 +1653,20 @@ public class DatabaseConfig {
|
||||
this.autoTuneConfig = autoTuneConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the startup DataSource check should be skipped.
|
||||
*/
|
||||
public boolean skipDataSourceCheck() {
|
||||
return skipDataSourceCheck;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true to skip the startup DataSource check.
|
||||
*/
|
||||
public void setSkipDataSourceCheck(boolean skipDataSourceCheck) {
|
||||
this.skipDataSourceCheck = skipDataSourceCheck;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DataSource.
|
||||
*/
|
||||
@@ -2693,7 +2758,10 @@ public class DatabaseConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load settings from ebean.properties.
|
||||
* Load settings from application.properties, application.yaml and other sources.
|
||||
* <p>
|
||||
* Uses <code>avaje-config</code> to load configuration properties. Goto https://avaje.io/config
|
||||
* for detail on how and where properties are loaded from.
|
||||
*/
|
||||
public void loadFromProperties() {
|
||||
this.properties = Config.asProperties();
|
||||
@@ -2795,21 +2863,27 @@ public class DatabaseConfig {
|
||||
}
|
||||
loadDocStoreSettings(p);
|
||||
|
||||
defaultServer = p.getBoolean("defaultServer", defaultServer);
|
||||
autoPersistUpdates = p.getBoolean("autoPersistUpdates", autoPersistUpdates);
|
||||
loadModuleInfo = p.getBoolean("loadModuleInfo", loadModuleInfo);
|
||||
maxCallStack = p.getInt("maxCallStack", maxCallStack);
|
||||
dumpMetricsOnShutdown = p.getBoolean("dumpMetricsOnShutdown", dumpMetricsOnShutdown);
|
||||
dumpMetricsOptions = p.get("dumpMetricsOptions", dumpMetricsOptions);
|
||||
queryPlanTTLSeconds = p.getInt("queryPlanTTLSeconds", queryPlanTTLSeconds);
|
||||
slowQueryMillis = p.getLong("slowQueryMillis", slowQueryMillis);
|
||||
collectQueryPlans = p.getBoolean("collectQueryPlans", collectQueryPlans);
|
||||
collectQueryPlanThresholdMicros = p.getLong("collectQueryPlanThresholdMicros", collectQueryPlanThresholdMicros);
|
||||
queryPlanEnable = p.getBoolean("queryPlan.enable", queryPlanEnable);
|
||||
queryPlanThresholdMicros = p.getLong("queryPlan.thresholdMicros", queryPlanThresholdMicros);
|
||||
queryPlanCapture = p.getBoolean("queryPlan.capture", queryPlanCapture);
|
||||
queryPlanCapturePeriodSecs = p.getLong("queryPlan.capturePeriodSecs", queryPlanCapturePeriodSecs);
|
||||
queryPlanCaptureMaxTimeMillis = p.getLong("queryPlan.captureMaxTimeMillis", queryPlanCaptureMaxTimeMillis);
|
||||
queryPlanCaptureMaxCount = p.getInt("queryPlan.captureMaxCount", queryPlanCaptureMaxCount);
|
||||
docStoreOnly = p.getBoolean("docStoreOnly", docStoreOnly);
|
||||
disableL2Cache = p.getBoolean("disableL2Cache", disableL2Cache);
|
||||
localOnlyL2Cache = p.getBoolean("localOnlyL2Cache", localOnlyL2Cache);
|
||||
enabledL2Regions = p.get("enabledL2Regions", enabledL2Regions);
|
||||
notifyL2CacheInForeground = p.getBoolean("notifyL2CacheInForeground", notifyL2CacheInForeground);
|
||||
useJtaTransactionManager = p.getBoolean("useJtaTransactionManager", useJtaTransactionManager);
|
||||
useJavaxValidationNotNull = p.getBoolean("useJavaxValidationNotNull", useJavaxValidationNotNull);
|
||||
useValidationNotNull = p.getBoolean("useValidationNotNull", useValidationNotNull);
|
||||
autoReadOnlyDataSource = p.getBoolean("autoReadOnlyDataSource", autoReadOnlyDataSource);
|
||||
idGeneratorAutomatic = p.getBoolean("idGeneratorAutomatic", idGeneratorAutomatic);
|
||||
|
||||
@@ -2872,7 +2946,9 @@ public class DatabaseConfig {
|
||||
jsonInclude = p.getEnum(JsonConfig.Include.class, "jsonInclude", jsonInclude);
|
||||
jsonDateTime = p.getEnum(JsonConfig.DateTime.class, "jsonDateTime", jsonDateTime);
|
||||
jsonDate = p.getEnum(JsonConfig.Date.class, "jsonDate", jsonDate);
|
||||
jsonMutationDetection = p.getEnum(MutationDetection.class, "jsonMutationDetection", jsonMutationDetection);
|
||||
|
||||
skipDataSourceCheck = p.getBoolean("skipDataSourceCheck", skipDataSourceCheck);
|
||||
runMigration = p.getBoolean("migration.run", runMigration);
|
||||
ddlGenerate = p.getBoolean("ddl.generate", ddlGenerate);
|
||||
ddlRun = p.getBoolean("ddl.run", ddlRun);
|
||||
@@ -3056,20 +3132,21 @@ public class DatabaseConfig {
|
||||
/**
|
||||
* Returns if we use javax.validation.constraints.NotNull
|
||||
*/
|
||||
public boolean isUseJavaxValidationNotNull() {
|
||||
return useJavaxValidationNotNull;
|
||||
public boolean isUseValidationNotNull() {
|
||||
return useValidationNotNull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls if Ebean should ignore <code>&x64;javax.validation.contstraints.NotNull</code>
|
||||
* Controls if Ebean should ignore <code>&x64;javax.validation.contstraints.NotNull</code> or
|
||||
* <code>&x64;jakarta.validation.contstraints.NotNull</code>
|
||||
* with respect to generating a <code>NOT NULL</code> column.
|
||||
* <p>
|
||||
* Normally when Ebean sees javax NotNull annotation it means that column is defined as NOT NULL.
|
||||
* Set this to <code>false</code> and the javax NotNull annotation is effectively ignored (and
|
||||
* we instead use Ebean's own NotNull annotation or JPA Column(nullable=false) annotation.
|
||||
*/
|
||||
public void setUseJavaxValidationNotNull(boolean useJavaxValidationNotNull) {
|
||||
this.useJavaxValidationNotNull = useJavaxValidationNotNull;
|
||||
public void setUseValidationNotNull(boolean useValidationNotNull) {
|
||||
this.useValidationNotNull = useValidationNotNull;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3091,14 +3168,17 @@ public class DatabaseConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the query plan time to live.
|
||||
* Return the time to live for ebean's internal query plan.
|
||||
*/
|
||||
public int getQueryPlanTTLSeconds() {
|
||||
return queryPlanTTLSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the query plan time to live.
|
||||
* Set the time to live for ebean's internal query plan.
|
||||
* <p>
|
||||
* This is the plan that knows how to execute the query, read the result
|
||||
* and collects execution metrics. By default this is set to 5 mins.
|
||||
*/
|
||||
public void setQueryPlanTTLSeconds(int queryPlanTTLSeconds) {
|
||||
this.queryPlanTTLSeconds = queryPlanTTLSeconds;
|
||||
@@ -3171,29 +3251,110 @@ public class DatabaseConfig {
|
||||
/**
|
||||
* Return true if query plan capture is enabled.
|
||||
*/
|
||||
public boolean isCollectQueryPlans() {
|
||||
return collectQueryPlans;
|
||||
public boolean isQueryPlanEnable() {
|
||||
return queryPlanEnable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true to enable query plan capture.
|
||||
*/
|
||||
public void setCollectQueryPlans(boolean collectQueryPlans) {
|
||||
this.collectQueryPlans = collectQueryPlans;
|
||||
public void setQueryPlanEnable(boolean queryPlanEnable) {
|
||||
this.queryPlanEnable = queryPlanEnable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the query plan collection threshold in microseconds.
|
||||
*/
|
||||
public long getCollectQueryPlanThresholdMicros() {
|
||||
return collectQueryPlanThresholdMicros;
|
||||
public long getQueryPlanThresholdMicros() {
|
||||
return queryPlanThresholdMicros;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the query plan collection threshold in microseconds.
|
||||
* <p>
|
||||
* Queries executing slower than this will have bind values captured such that later
|
||||
* the query plan can be captured and reported.
|
||||
*/
|
||||
public void setCollectQueryPlanThresholdMicros(long collectQueryPlanThresholdMicros) {
|
||||
this.collectQueryPlanThresholdMicros = collectQueryPlanThresholdMicros;
|
||||
public void setQueryPlanThresholdMicros(long queryPlanThresholdMicros) {
|
||||
this.queryPlanThresholdMicros = queryPlanThresholdMicros;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if periodic capture of query plans is enabled.
|
||||
*/
|
||||
public boolean isQueryPlanCapture() {
|
||||
return queryPlanCapture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true to turn on periodic capture of query plans.
|
||||
*/
|
||||
public void setQueryPlanCapture(boolean queryPlanCapture) {
|
||||
this.queryPlanCapture = queryPlanCapture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the frequency to capture query plans.
|
||||
*/
|
||||
public long getQueryPlanCapturePeriodSecs() {
|
||||
return queryPlanCapturePeriodSecs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the frequency in seconds to capture query plans.
|
||||
*/
|
||||
public void setQueryPlanCapturePeriodSecs(long queryPlanCapturePeriodSecs) {
|
||||
this.queryPlanCapturePeriodSecs = queryPlanCapturePeriodSecs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the time after which a capture query plans request will
|
||||
* stop capturing more query plans.
|
||||
* <p>
|
||||
* Effectively this controls the amount of load/time we want to
|
||||
* allow for query plan capture.
|
||||
*/
|
||||
public long getQueryPlanCaptureMaxTimeMillis() {
|
||||
return queryPlanCaptureMaxTimeMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the time after which a capture query plans request will
|
||||
* stop capturing more query plans.
|
||||
* <p>
|
||||
* Effectively this controls the amount of load/time we want to
|
||||
* allow for query plan capture.
|
||||
*/
|
||||
public void setQueryPlanCaptureMaxTimeMillis(long queryPlanCaptureMaxTimeMillis) {
|
||||
this.queryPlanCaptureMaxTimeMillis = queryPlanCaptureMaxTimeMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the max number of query plans captured per request.
|
||||
*/
|
||||
public int getQueryPlanCaptureMaxCount() {
|
||||
return queryPlanCaptureMaxCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the max number of query plans captured per request.
|
||||
*/
|
||||
public void setQueryPlanCaptureMaxCount(int queryPlanCaptureMaxCount) {
|
||||
this.queryPlanCaptureMaxCount = queryPlanCaptureMaxCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the listener used to process captured query plans.
|
||||
*/
|
||||
public QueryPlanListener getQueryPlanListener() {
|
||||
return queryPlanListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the listener used to process captured query plans.
|
||||
*/
|
||||
public void setQueryPlanListener(QueryPlanListener queryPlanListener) {
|
||||
this.queryPlanListener = queryPlanListener;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,7 +15,7 @@ package io.ebean.config;
|
||||
*
|
||||
* public class EbeanConfigProvider implements DatabaseConfigProvider {
|
||||
*
|
||||
* @Override
|
||||
* @Override
|
||||
* public void apply(DatabaseConfig config) {
|
||||
*
|
||||
* // register the entity bean classes explicitly
|
||||
|
||||
@@ -39,11 +39,6 @@ public class MatchingNamingConvention extends AbstractNamingConvention {
|
||||
return new TableName(quoteIdentifiers(getCatalog()), quoteIdentifiers(getSchema()), quoteIdentifiers(beanClass.getSimpleName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPropertyFromColumn(Class<?> beanClass, String dbColumnName) {
|
||||
return dbColumnName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getForeignKey(String prefix, String fkProperty) {
|
||||
prefix = databasePlatform.unQuote(prefix);
|
||||
|
||||
@@ -7,13 +7,8 @@ import java.util.List;
|
||||
*/
|
||||
public interface ModuleInfoLoader {
|
||||
|
||||
/**
|
||||
* Return the entity classes to register with the default DB.
|
||||
*/
|
||||
List<Class<?>> entityClasses();
|
||||
|
||||
/**
|
||||
* Return entity classes to register for a named DB (not default DB).
|
||||
*/
|
||||
List<Class<?>> entityClassesFor(String dbName);
|
||||
List<Class<?>> classesFor(String dbName, boolean defaultServer);
|
||||
}
|
||||
|
||||
@@ -53,6 +53,16 @@ public interface NamingConvention {
|
||||
*/
|
||||
TableName getM2MJoinTableName(TableName lhsTable, TableName rhsTable);
|
||||
|
||||
/**
|
||||
* Derive a DB Column from a FK table and column.
|
||||
*/
|
||||
String deriveM2MColumn(String tableName, String dbColumn);
|
||||
|
||||
/**
|
||||
* Return the full table name taking into account quoted identifiers.
|
||||
*/
|
||||
String getTableName(String catalog, String schema, String name);
|
||||
|
||||
/**
|
||||
* Return the column name given the property name.
|
||||
*
|
||||
@@ -60,18 +70,6 @@ public interface NamingConvention {
|
||||
*/
|
||||
String getColumnFromProperty(Class<?> beanClass, String propertyName);
|
||||
|
||||
/**
|
||||
* Return the property name from the column name.
|
||||
* <p>
|
||||
* This is used to help mapping of raw SQL queries onto bean properties.
|
||||
* </p>
|
||||
*
|
||||
* @param beanClass the bean class
|
||||
* @param dbColumnName the db column name
|
||||
* @return the property name from the column name
|
||||
*/
|
||||
String getPropertyFromColumn(Class<?> beanClass, String dbColumnName);
|
||||
|
||||
/**
|
||||
* Return the sequence name given the table name (for DB's that use sequences).
|
||||
* <p>
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package io.ebean.config;
|
||||
|
||||
import io.ebean.Database;
|
||||
import io.ebean.meta.MetaQueryPlan;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The captured query plans.
|
||||
*/
|
||||
public class QueryPlanCapture {
|
||||
|
||||
private final Database database;
|
||||
private final List<MetaQueryPlan> plans;
|
||||
|
||||
public QueryPlanCapture(Database database, List<MetaQueryPlan> plans) {
|
||||
this.database = database;
|
||||
this.plans = plans;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the database the plans were captured for.
|
||||
*/
|
||||
public Database getDatabase() {
|
||||
return database;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the captured query plans.
|
||||
*/
|
||||
public List<MetaQueryPlan> getPlans() {
|
||||
return plans;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package io.ebean.config;
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL: Listener for captured query plans.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface QueryPlanListener {
|
||||
|
||||
/**
|
||||
* Process the captured query plans.
|
||||
*/
|
||||
void process(QueryPlanCapture capture);
|
||||
}
|
||||
@@ -16,7 +16,7 @@ package io.ebean.config;
|
||||
*
|
||||
* public class EbeanConfigProvider implements ServerConfigProvider {
|
||||
*
|
||||
* @Override
|
||||
* @Override
|
||||
* public void apply(ServerConfig config) {
|
||||
*
|
||||
* // register the entity bean classes explicitly
|
||||
|
||||
@@ -20,7 +20,7 @@ public final class TableName {
|
||||
/**
|
||||
* The name.
|
||||
*/
|
||||
private String name;
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* Construct with the given catalog schema and table name.
|
||||
@@ -29,7 +29,6 @@ public final class TableName {
|
||||
* </p>
|
||||
*/
|
||||
public TableName(String catalog, String schema, String name) {
|
||||
super();
|
||||
this.catalog = catalog != null ? catalog.trim() : null;
|
||||
this.schema = schema != null ? schema.trim() : null;
|
||||
this.name = name != null ? name.trim() : null;
|
||||
@@ -110,14 +109,11 @@ public final class TableName {
|
||||
* @return the qualified name
|
||||
*/
|
||||
public String getQualifiedName() {
|
||||
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
|
||||
// Add catalog
|
||||
if (catalog != null) {
|
||||
buffer.append(catalog);
|
||||
}
|
||||
|
||||
// Add schema
|
||||
if (schema != null) {
|
||||
if (buffer.length() > 0) {
|
||||
@@ -125,31 +121,27 @@ public final class TableName {
|
||||
}
|
||||
buffer.append(schema);
|
||||
}
|
||||
|
||||
if (buffer.length() > 0) {
|
||||
buffer.append(".");
|
||||
}
|
||||
buffer.append(name);
|
||||
|
||||
return buffer.toString();
|
||||
return buffer.append(name).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a catalog and schema prefix if they exist to the string builder.
|
||||
*/
|
||||
public void appendCatalogAndSchema(StringBuilder buffer) {
|
||||
if (catalog != null) {
|
||||
buffer.append(catalog).append(".");
|
||||
}
|
||||
public String withCatalogAndSchema(String name) {
|
||||
if (schema != null) {
|
||||
buffer.append(schema).append(".");
|
||||
name = schema + "." + name;
|
||||
}
|
||||
if (catalog != null) {
|
||||
name = catalog + "." + name;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if is table name is valid i.e. it has at least a name.
|
||||
*
|
||||
* @return true, if is valid
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return name != null && !name.isEmpty();
|
||||
|
||||
@@ -60,18 +60,6 @@ public class UnderscoreNamingConvention extends AbstractNamingConvention {
|
||||
return toUnderscoreFromCamel(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts underscore based column name to Camel case property name.
|
||||
*
|
||||
* @param beanClass the bean class
|
||||
* @param dbColumnName the db column name
|
||||
* @return the property from column
|
||||
*/
|
||||
@Override
|
||||
public String getPropertyFromColumn(Class<?> beanClass, String dbColumnName) {
|
||||
return toCamelFromUnderscore(dbColumnName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the result will be upper case.
|
||||
* <p>
|
||||
|
||||
@@ -9,9 +9,6 @@ import java.sql.Types;
|
||||
* functions for varchar, date and timestamp. If they are left null then that is
|
||||
* treated as though that data type can not be encrypted in the DB and will
|
||||
* instead use java client encryption.
|
||||
* </p>
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public abstract class AbstractDbEncrypt implements DbEncrypt {
|
||||
|
||||
@@ -47,13 +44,10 @@ public abstract class AbstractDbEncrypt implements DbEncrypt {
|
||||
case Types.CHAR:
|
||||
case Types.LONGVARCHAR:
|
||||
return varcharEncryptFunction;
|
||||
|
||||
case Types.DATE:
|
||||
return dateEncryptFunction;
|
||||
|
||||
case Types.TIMESTAMP:
|
||||
return timestampEncryptFunction;
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ public class DbDefaultValue {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method checks & convert the {@link DbDefault#value()} to a valid SQL literal.
|
||||
* This method checks and converts the {@link DbDefault#value()} to a valid SQL literal.
|
||||
*
|
||||
* This is mainly to quote string literals and verify integer/dates for correctness.
|
||||
* <p>
|
||||
|
||||
@@ -61,7 +61,7 @@ public class SimpleSequenceIdGenerator implements PlatformIdGenerator {
|
||||
PreparedStatement pstmt = null;
|
||||
ResultSet rset = null;
|
||||
try {
|
||||
c = useTxnConnection ? t.getConnection() : dataSource.getConnection();
|
||||
c = useTxnConnection ? t.connection() : dataSource.getConnection();
|
||||
pstmt = c.prepareStatement(sql);
|
||||
rset = pstmt.executeQuery();
|
||||
if (rset.next()) {
|
||||
|
||||
@@ -5,8 +5,6 @@ import io.ebean.config.dbplatform.DbEncryptFunction;
|
||||
|
||||
/**
|
||||
* H2 encryption support via encrypt decrypt function.
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public class H2DbEncrypt extends AbstractDbEncrypt {
|
||||
|
||||
|
||||
@@ -4,11 +4,7 @@ import org.h2.api.Trigger;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.sql.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
@@ -43,7 +39,6 @@ public class H2HistoryTrigger implements Trigger {
|
||||
|
||||
@Override
|
||||
public void init(Connection conn, String schemaName, String triggerName, String tableName, boolean before, int type) throws SQLException {
|
||||
|
||||
// get the columns for the table
|
||||
ResultSet rs = conn.getMetaData().getColumns(null, schemaName, tableName, null);
|
||||
|
||||
@@ -79,7 +74,6 @@ public class H2HistoryTrigger implements Trigger {
|
||||
|
||||
@Override
|
||||
public void fire(Connection connection, Object[] oldRow, Object[] newRow) throws SQLException {
|
||||
|
||||
if (oldRow != null) {
|
||||
// a delete or update event
|
||||
Timestamp now = new Timestamp(System.currentTimeMillis());
|
||||
@@ -99,7 +93,6 @@ public class H2HistoryTrigger implements Trigger {
|
||||
* Insert the data into the history table.
|
||||
*/
|
||||
private void insertIntoHistory(Connection connection, Object[] oldRow) throws SQLException {
|
||||
|
||||
try (PreparedStatement stmt = connection.prepareStatement(insertHistorySql)) {
|
||||
for (int i = 0; i < oldRow.length; i++) {
|
||||
stmt.setObject(i + 1, oldRow[i]);
|
||||
@@ -110,11 +103,11 @@ public class H2HistoryTrigger implements Trigger {
|
||||
|
||||
@Override
|
||||
public void close() throws SQLException {
|
||||
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() throws SQLException {
|
||||
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import io.ebean.config.dbplatform.DbEncryptFunction;
|
||||
|
||||
/**
|
||||
* MySql aes_encrypt aes_decrypt based encryption support.
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public class MySqlDbEncrypt extends AbstractDbEncrypt {
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ public class Oracle11Platform extends OraclePlatform {
|
||||
public Oracle11Platform() {
|
||||
super();
|
||||
this.platform = Platform.ORACLE11;
|
||||
this.columnAliasPrefix = "c";
|
||||
this.sqlLimiter = new OracleRownumSqlLimiter();
|
||||
this.basicSqlLimiter = new OracleRownumBasicLimiter();
|
||||
dbIdentity.setIdType(IdType.SEQUENCE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,6 @@ public class OracleDbEncrypt extends AbstractDbEncrypt {
|
||||
* @param decryptFunction the decrypt stored procedure
|
||||
*/
|
||||
public OracleDbEncrypt(String encryptFunction, String decryptFunction) {
|
||||
|
||||
this.varcharEncryptFunction = new OraVarcharFunction(encryptFunction, decryptFunction);
|
||||
this.dateEncryptFunction = new OraDateFunction(encryptFunction, decryptFunction);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ public class OraclePlatform extends DatabasePlatform {
|
||||
public OraclePlatform() {
|
||||
super();
|
||||
this.platform = Platform.ORACLE;
|
||||
this.columnAliasPrefix = "c";
|
||||
this.supportsDeleteTableAlias = true;
|
||||
this.maxTableNameLength = 30;
|
||||
this.maxConstraintNameLength = 30;
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package io.ebean.config.dbplatform.oracle;
|
||||
|
||||
import io.ebean.config.dbplatform.BasicSqlLimiter;
|
||||
|
||||
/**
|
||||
* Row limiter for Oracle 9,10,11 using rownum.
|
||||
*/
|
||||
public class OracleRownumBasicLimiter implements BasicSqlLimiter {
|
||||
|
||||
@Override
|
||||
public String limit(String dbSql, int firstRow, int maxRows) {
|
||||
if (firstRow < 1 && maxRows < 1) {
|
||||
return dbSql;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder(60 + dbSql.length());
|
||||
int lastRow = maxRows;
|
||||
if (lastRow > 0) {
|
||||
lastRow += firstRow;
|
||||
}
|
||||
sb.append("select * from (select ");
|
||||
if (maxRows > 0) {
|
||||
sb.append("/*+ FIRST_ROWS(").append(maxRows).append(") */ ");
|
||||
}
|
||||
sb.append("a.*, rownum rn_ from (");
|
||||
sb.append(dbSql).append(") a ");
|
||||
if (lastRow > 0) {
|
||||
sb.append(" where rownum <= ").append(lastRow);
|
||||
}
|
||||
sb.append(") ");
|
||||
if (firstRow > 0) {
|
||||
sb.append(" where rn_ > ").append(firstRow);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
+1
@@ -25,6 +25,7 @@ abstract class SqlServerBasePlatform extends DatabasePlatform {
|
||||
this.platform = Platform.SQLSERVER;
|
||||
// disable persistBatchOnCascade mode for
|
||||
// SQL Server unless we are using sequences
|
||||
this.dbEncrypt = new SqlServerDbEncrypt();
|
||||
this.persistBatchOnCascade = PersistBatch.NONE;
|
||||
this.idInExpandedForm = true;
|
||||
this.selectCountWithAlias = true;
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package io.ebean.config.dbplatform.sqlserver;
|
||||
|
||||
import io.ebean.config.dbplatform.AbstractDbEncrypt;
|
||||
import io.ebean.config.dbplatform.DbEncryptFunction;
|
||||
|
||||
/**
|
||||
* SQL Server EncryptByPassPhrase DecryptByPassPhrase based encryption support.
|
||||
*/
|
||||
public class SqlServerDbEncrypt extends AbstractDbEncrypt {
|
||||
|
||||
public SqlServerDbEncrypt() {
|
||||
this.varcharEncryptFunction = new VarcharFunction();
|
||||
this.dateEncryptFunction = new DateFunction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBindEncryptDataFirst() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static class VarcharFunction implements DbEncryptFunction {
|
||||
|
||||
@Override
|
||||
public String getDecryptSql(String columnWithTableAlias) {
|
||||
return "convert(nvarchar,DecryptByPassPhrase(?," + columnWithTableAlias + "))";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEncryptBindSql() {
|
||||
return "EncryptByPassPhrase(?,?)";
|
||||
}
|
||||
}
|
||||
|
||||
private static class DateFunction implements DbEncryptFunction {
|
||||
|
||||
@Override
|
||||
public String getDecryptSql(String columnWithTableAlias) {
|
||||
return "cast(convert(nvarchar,DecryptByPassPhrase(?," + columnWithTableAlias + ")) as date)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEncryptBindSql() {
|
||||
return "EncryptByPassPhrase(?,format(?,'yyyy-MM-dd'))";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.ebean.event;
|
||||
|
||||
import io.ebean.Database;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.Transaction;
|
||||
|
||||
@@ -9,18 +10,62 @@ import io.ebean.Transaction;
|
||||
public interface BeanDeleteIdRequest {
|
||||
|
||||
/**
|
||||
* Return the server processing the request.
|
||||
* Deprecated migrate to database().
|
||||
*/
|
||||
@Deprecated
|
||||
EbeanServer getEbeanServer();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to database().
|
||||
*/
|
||||
@Deprecated
|
||||
default Database getDatabase() {
|
||||
return getEbeanServer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DB processing the request.
|
||||
*/
|
||||
default Database database() {
|
||||
return getEbeanServer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Transaction associated with this request.
|
||||
*/
|
||||
Transaction getTransaction();
|
||||
Transaction transaction();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to transaction().
|
||||
*/
|
||||
@Deprecated
|
||||
default Transaction getTransaction() {
|
||||
return transaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the bean type of the bean being deleted.
|
||||
*/
|
||||
Class<?> beanType();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to beanType().
|
||||
*/
|
||||
@Deprecated
|
||||
default Class<?> getBeanType() {
|
||||
return beanType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Id value of the bean being deleted.
|
||||
*/
|
||||
Object getId();
|
||||
Object id();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to id().
|
||||
*/
|
||||
@Deprecated
|
||||
default Object getId() {
|
||||
return id();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.ebean.event;
|
||||
|
||||
import io.ebean.Database;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.ValuePair;
|
||||
@@ -17,20 +18,44 @@ import java.util.Set;
|
||||
public interface BeanPersistRequest<T> {
|
||||
|
||||
/**
|
||||
* Return the server processing the request.
|
||||
* Return the DB processing the request.
|
||||
*/
|
||||
default Database database() {
|
||||
return getEbeanServer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated migrate to database().
|
||||
*/
|
||||
@Deprecated
|
||||
EbeanServer getEbeanServer();
|
||||
|
||||
/**
|
||||
* Return the Transaction associated with this request.
|
||||
*/
|
||||
Transaction getTransaction();
|
||||
Transaction transaction();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to transaction().
|
||||
*/
|
||||
@Deprecated
|
||||
default Transaction getTransaction() {
|
||||
return transaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* For an update or delete of a partially populated bean this is the set of
|
||||
* loaded properties and otherwise returns null.
|
||||
*/
|
||||
Set<String> getLoadedProperties();
|
||||
Set<String> loadedProperties();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to loadedProperties().
|
||||
*/
|
||||
@Deprecated
|
||||
default Set<String> getLoadedProperties() {
|
||||
return loadedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* For an update this is the set of properties that where updated.
|
||||
@@ -39,12 +64,28 @@ public interface BeanPersistRequest<T> {
|
||||
* should be preferred if it satisfies the requirement.
|
||||
* </p>
|
||||
*/
|
||||
Set<String> getUpdatedProperties();
|
||||
Set<String> updatedProperties();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to updatedProperties().
|
||||
*/
|
||||
@Deprecated
|
||||
default Set<String> getUpdatedProperties() {
|
||||
return updatedProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Flags set for dirty properties (used by ElasticSearch integration).
|
||||
*/
|
||||
boolean[] getDirtyProperties();
|
||||
boolean[] dirtyProperties();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to updatedProperties().
|
||||
*/
|
||||
@Deprecated
|
||||
default boolean[] getDirtyProperties() {
|
||||
return dirtyProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true for an update request if at least one of dirty properties is contained
|
||||
@@ -66,11 +107,27 @@ public interface BeanPersistRequest<T> {
|
||||
/**
|
||||
* Returns the bean being inserted updated or deleted.
|
||||
*/
|
||||
T getBean();
|
||||
T bean();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to bean().
|
||||
*/
|
||||
@Deprecated
|
||||
default T getBean() {
|
||||
return bean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of the properties that have changed and their new and old values.
|
||||
*/
|
||||
Map<String, ValuePair> getUpdatedValues();
|
||||
Map<String, ValuePair> updatedValues();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to updatedValues().
|
||||
*/
|
||||
@Deprecated
|
||||
default Map<String, ValuePair> getUpdatedValues() {
|
||||
return updatedValues();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.ebean.event;
|
||||
|
||||
import io.ebean.Database;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.Transaction;
|
||||
@@ -10,19 +11,43 @@ import io.ebean.Transaction;
|
||||
public interface BeanQueryRequest<T> {
|
||||
|
||||
/**
|
||||
* Return the server processing the request.
|
||||
* Return the DB processing the request.
|
||||
*/
|
||||
default Database database() {
|
||||
return getEbeanServer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated migrate to database().
|
||||
*/
|
||||
@Deprecated
|
||||
EbeanServer getEbeanServer();
|
||||
|
||||
/**
|
||||
* Return the Transaction associated with this request.
|
||||
*/
|
||||
Transaction getTransaction();
|
||||
Transaction transaction();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to transaction().
|
||||
*/
|
||||
@Deprecated
|
||||
default Transaction getTransaction() {
|
||||
return transaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the query.
|
||||
*/
|
||||
Query<T> getQuery();
|
||||
Query<T> query();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to query().
|
||||
*/
|
||||
@Deprecated
|
||||
default Query<T> getQuery() {
|
||||
return query();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if an Id IN expression should have the bind parameters padded.
|
||||
|
||||
@@ -8,7 +8,15 @@ public interface BulkTableEvent {
|
||||
/**
|
||||
* Return the name of the table that was involved.
|
||||
*/
|
||||
String getTableName();
|
||||
String tableName();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to tableName().
|
||||
*/
|
||||
@Deprecated
|
||||
default String getTableName() {
|
||||
return tableName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if rows were inserted.
|
||||
|
||||
@@ -14,10 +14,9 @@ import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Manages the shutdown of the JVM Runtime.
|
||||
* Manages the shutdown of Ebean.
|
||||
* <p>
|
||||
* Makes sure all the resources are shutdown properly and in order.
|
||||
* </p>
|
||||
*/
|
||||
public final class ShutdownManager {
|
||||
|
||||
@@ -44,6 +43,9 @@ public final class ShutdownManager {
|
||||
private ShutdownManager() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the container (potentially with cluster management).
|
||||
*/
|
||||
public static void registerContainer(SpiContainer ebeanContainer) {
|
||||
container = ebeanContainer;
|
||||
}
|
||||
@@ -94,7 +96,7 @@ public final class ShutdownManager {
|
||||
/**
|
||||
* Register the shutdown hook with the Runtime.
|
||||
*/
|
||||
protected static void registerShutdownHook() {
|
||||
private static void registerShutdownHook() {
|
||||
lock.lock();
|
||||
try {
|
||||
String value = System.getProperty("ebean.registerShutdownHook");
|
||||
@@ -123,13 +125,10 @@ public final class ShutdownManager {
|
||||
// Already run shutdown...
|
||||
return;
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Shutting down");
|
||||
}
|
||||
|
||||
stopping = true;
|
||||
|
||||
deregisterShutdownHook();
|
||||
|
||||
String shutdownRunner = System.getProperty("ebean.shutdown.runnable");
|
||||
@@ -147,7 +146,6 @@ public final class ShutdownManager {
|
||||
// shutdown cluster networking if active
|
||||
container.shutdown();
|
||||
}
|
||||
|
||||
// shutdown any registered servers that have not
|
||||
// already been shutdown manually
|
||||
for (Database server : databases) {
|
||||
@@ -158,7 +156,6 @@ public final class ShutdownManager {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if ("true".equalsIgnoreCase(System.getProperty("ebean.datasource.deregisterAllDrivers", "false"))) {
|
||||
deregisterAllJdbcDrivers();
|
||||
}
|
||||
@@ -168,15 +165,15 @@ public final class ShutdownManager {
|
||||
}
|
||||
|
||||
private static void deregisterAllJdbcDrivers() {
|
||||
// This manually deregisters all JDBC drivers
|
||||
// This manually de-registers all JDBC drivers
|
||||
Enumeration<Driver> drivers = DriverManager.getDrivers();
|
||||
while (drivers.hasMoreElements()) {
|
||||
Driver driver = drivers.nextElement();
|
||||
try {
|
||||
logger.info("Deregistering jdbc driver: " + driver);
|
||||
logger.info("De-registering jdbc driver: " + driver);
|
||||
DriverManager.deregisterDriver(driver);
|
||||
} catch (SQLException e) {
|
||||
logger.error("Error deregistering driver " + driver, e);
|
||||
logger.error("Error de-registering driver " + driver, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -209,6 +206,9 @@ public final class ShutdownManager {
|
||||
}
|
||||
|
||||
private static class ShutdownHook extends Thread {
|
||||
private ShutdownHook() {
|
||||
super("EbeanHook");
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
ShutdownManager.shutdown();
|
||||
|
||||
@@ -18,22 +18,22 @@ public abstract class AbstractMetricVisitor implements MetricVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReset() {
|
||||
public boolean reset() {
|
||||
return reset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCollectTransactionMetrics() {
|
||||
public boolean collectTransactionMetrics() {
|
||||
return collectTransactionMetrics;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCollectQueryMetrics() {
|
||||
public boolean collectQueryMetrics() {
|
||||
return collectQueryMetrics;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCollectL2Metrics() {
|
||||
public boolean collectL2Metrics() {
|
||||
return collectL2Metrics;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,17 +27,17 @@ public class BasicMetricVisitor extends AbstractMetricVisitor implements ServerM
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MetaTimedMetric> getTimedMetrics() {
|
||||
public List<MetaTimedMetric> timedMetrics() {
|
||||
return timed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MetaQueryMetric> getQueryMetrics() {
|
||||
public List<MetaQueryMetric> queryMetrics() {
|
||||
return query;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MetaCountMetric> getCountMetrics() {
|
||||
public List<MetaCountMetric> countMetrics() {
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,13 @@ public interface MetaCountMetric extends MetaMetric {
|
||||
/**
|
||||
* Return the total count.
|
||||
*/
|
||||
long getCount();
|
||||
long count();
|
||||
|
||||
/**
|
||||
* Migrate to count()
|
||||
*/
|
||||
@Deprecated
|
||||
default long getCount() {
|
||||
return count();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,13 @@ public interface MetaMetric {
|
||||
/**
|
||||
* Return the metric name.
|
||||
*/
|
||||
String getName();
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Migrate to name().
|
||||
*/
|
||||
@Deprecated
|
||||
default String getName() {
|
||||
return name();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,21 +8,45 @@ public interface MetaQueryMetric extends MetaTimedMetric {
|
||||
/**
|
||||
* The type of entity or DTO bean.
|
||||
*/
|
||||
Class<?> getType();
|
||||
Class<?> type();
|
||||
|
||||
/**
|
||||
* Migrate to type().
|
||||
*/
|
||||
@Deprecated
|
||||
default Class<?> getType() {
|
||||
return type();
|
||||
}
|
||||
|
||||
/**
|
||||
* The label for the query (can be null).
|
||||
*/
|
||||
String getLabel();
|
||||
String label();
|
||||
|
||||
/**
|
||||
* Migrate to label().
|
||||
*/
|
||||
@Deprecated
|
||||
default String getLabel() {
|
||||
return label();
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual SQL of the query.
|
||||
*/
|
||||
String getSql();
|
||||
String sql();
|
||||
|
||||
/**
|
||||
* Migrate to sql().
|
||||
*/
|
||||
@Deprecated
|
||||
default String getSql() {
|
||||
return sql();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the hash of the plan.
|
||||
*/
|
||||
String getHash();
|
||||
String hash();
|
||||
|
||||
}
|
||||
|
||||
@@ -10,45 +10,45 @@ public interface MetaQueryPlan {
|
||||
/**
|
||||
* Return the bean type for the query.
|
||||
*/
|
||||
Class<?> getBeanType();
|
||||
Class<?> beanType();
|
||||
|
||||
/**
|
||||
* Return the label of the query.
|
||||
*/
|
||||
String getLabel();
|
||||
String label();
|
||||
|
||||
/**
|
||||
* Return the profile location for the query.
|
||||
*/
|
||||
ProfileLocation getProfileLocation();
|
||||
ProfileLocation profileLocation();
|
||||
|
||||
/**
|
||||
* Return the sql of the query.
|
||||
*/
|
||||
String getSql();
|
||||
String sql();
|
||||
|
||||
/**
|
||||
* Return the hash of the plan.
|
||||
*/
|
||||
String getHash();
|
||||
String hash();
|
||||
|
||||
/**
|
||||
* Return a description of the bind values.
|
||||
*/
|
||||
String getBind();
|
||||
String bind();
|
||||
|
||||
/**
|
||||
* Return the raw plan.
|
||||
*/
|
||||
String getPlan();
|
||||
String plan();
|
||||
|
||||
/**
|
||||
* Return the query execution time associated with the bind values capture.
|
||||
*/
|
||||
long getQueryTimeMicros();
|
||||
long queryTimeMicros();
|
||||
|
||||
/**
|
||||
* Return the total count of times bind capture has occurred.
|
||||
*/
|
||||
long getCaptureCount();
|
||||
long captureCount();
|
||||
}
|
||||
|
||||
@@ -9,27 +9,68 @@ public interface MetaTimedMetric extends MetaMetric {
|
||||
/**
|
||||
* Return the metric location if defined.
|
||||
*/
|
||||
String getLocation();
|
||||
String location();
|
||||
|
||||
/**
|
||||
* Migrate to location()
|
||||
*/
|
||||
@Deprecated
|
||||
default String getLocation() {
|
||||
return location();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the total count.
|
||||
*/
|
||||
long getCount();
|
||||
long count();
|
||||
|
||||
/**
|
||||
* Migrate to count()
|
||||
*/
|
||||
@Deprecated
|
||||
default long getCount() {
|
||||
return count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the total execution time in micros.
|
||||
*/
|
||||
long getTotal();
|
||||
long total();
|
||||
|
||||
/**
|
||||
* Migrate to total()
|
||||
*/
|
||||
@Deprecated
|
||||
default long getTotal() {
|
||||
return total();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the max execution time in micros.
|
||||
*/
|
||||
long getMax();
|
||||
long max();
|
||||
|
||||
/**
|
||||
* Migrate to max()
|
||||
*/
|
||||
@Deprecated
|
||||
default long getMax() {
|
||||
return max();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mean execution time in micros.
|
||||
*/
|
||||
long getMean();
|
||||
long mean();
|
||||
|
||||
|
||||
/**
|
||||
* Migrate to mean()
|
||||
*/
|
||||
@Deprecated
|
||||
default long getMean() {
|
||||
return mean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is the first metrics collection for this query.
|
||||
|
||||
@@ -8,22 +8,22 @@ public interface MetricVisitor {
|
||||
/**
|
||||
* Return true if the metrics should be reset.
|
||||
*/
|
||||
boolean isReset();
|
||||
boolean reset();
|
||||
|
||||
/**
|
||||
* Return true if we should visit the transaction metrics.
|
||||
*/
|
||||
boolean isCollectTransactionMetrics();
|
||||
boolean collectTransactionMetrics();
|
||||
|
||||
/**
|
||||
* Return true if we should visit the ORM and SQL query metrics.
|
||||
*/
|
||||
boolean isCollectQueryMetrics();
|
||||
boolean collectQueryMetrics();
|
||||
|
||||
/**
|
||||
* Return true if we should visit the L2 cache metrics.
|
||||
*/
|
||||
boolean isCollectL2Metrics();
|
||||
boolean collectL2Metrics();
|
||||
|
||||
/**
|
||||
* Visit has started.
|
||||
|
||||
@@ -32,7 +32,7 @@ public class QueryPlanInit {
|
||||
* Return the query execution time threshold which must be exceeded to initiate
|
||||
* query plan collection.
|
||||
*/
|
||||
public long getThresholdMicros() {
|
||||
public long thresholdMicros() {
|
||||
return thresholdMicros;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public class QueryPlanInit {
|
||||
* Set the query execution time threshold which must be exceeded to initiate
|
||||
* query plan collection.
|
||||
*/
|
||||
public void setThresholdMicros(long thresholdMicros) {
|
||||
public void thresholdMicros(long thresholdMicros) {
|
||||
this.thresholdMicros = thresholdMicros;
|
||||
}
|
||||
|
||||
@@ -54,14 +54,14 @@ public class QueryPlanInit {
|
||||
/**
|
||||
* Return the specific hashes that we want to collect query plans on.
|
||||
*/
|
||||
public Set<String> getHashes() {
|
||||
public Set<String> hashes() {
|
||||
return hashes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the specific hashes that we want to collect query plans on.
|
||||
*/
|
||||
public void setHashes(Set<String> hashes) {
|
||||
public void hashes(Set<String> hashes) {
|
||||
this.hashes = hashes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ public class QueryPlanRequest {
|
||||
* have been around for a while (e.g. 5 mins) and so reasonably represent
|
||||
* bind values that match the slowest execution for this query plan.
|
||||
*/
|
||||
public long getSince() {
|
||||
public long since() {
|
||||
return since;
|
||||
}
|
||||
|
||||
@@ -28,21 +28,24 @@ public class QueryPlanRequest {
|
||||
*
|
||||
* @param since The minimum age of the bind values capture.
|
||||
*/
|
||||
public void setSince(long since) {
|
||||
public void since(long since) {
|
||||
this.since = since;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the maximum number of plans to capture.
|
||||
*/
|
||||
public int getMaxCount() {
|
||||
public int maxCount() {
|
||||
return maxCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum number of plans to capture.
|
||||
* <p>
|
||||
* Use this to limit how much query plan capturing is done as query
|
||||
* plan capture is actual database load.
|
||||
*/
|
||||
public void setMaxCount(int maxCount) {
|
||||
public void maxCount(int maxCount) {
|
||||
this.maxCount = maxCount;
|
||||
}
|
||||
|
||||
@@ -51,16 +54,18 @@ public class QueryPlanRequest {
|
||||
* <p>
|
||||
* Query plan collection will stop once this time is exceeded.
|
||||
*/
|
||||
public long getMaxTimeMillis() {
|
||||
public long maxTimeMillis() {
|
||||
return maxTimeMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum amount of time we want to use to capture plans.
|
||||
* <p>
|
||||
* Query plan collection will stop once this time is exceeded.
|
||||
* Query plan collection will stop once this time is exceeded. We use
|
||||
* this to ensure the query plan capture does not use excessive amount
|
||||
* of time - put too much load on the database.
|
||||
*/
|
||||
public void setMaxTimeMillis(long maxTimeMillis) {
|
||||
public void maxTimeMillis(long maxTimeMillis) {
|
||||
this.maxTimeMillis = maxTimeMillis;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,16 +10,39 @@ public interface ServerMetrics {
|
||||
/**
|
||||
* Return timed metrics for Transactions, labelled SqlQuery, labelled SqlUpdate.
|
||||
*/
|
||||
List<MetaTimedMetric> getTimedMetrics();
|
||||
List<MetaTimedMetric> timedMetrics();
|
||||
|
||||
/**
|
||||
* Migrate to timedMetrics().
|
||||
*/
|
||||
@Deprecated
|
||||
default List<MetaTimedMetric> getTimedMetrics() {
|
||||
return timedMetrics();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the query metrics.
|
||||
*/
|
||||
List<MetaQueryMetric> getQueryMetrics();
|
||||
List<MetaQueryMetric> queryMetrics();
|
||||
|
||||
/**
|
||||
* Migrate to queryMetrics().
|
||||
*/
|
||||
@Deprecated
|
||||
default List<MetaQueryMetric> getQueryMetrics() {
|
||||
return queryMetrics();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Counter metrics.
|
||||
*/
|
||||
List<MetaCountMetric> getCountMetrics();
|
||||
List<MetaCountMetric> countMetrics();
|
||||
|
||||
/**
|
||||
* Migrate to countMetrics().
|
||||
*/
|
||||
@Deprecated
|
||||
default List<MetaCountMetric> getCountMetrics() {
|
||||
return countMetrics();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,12 +8,12 @@ import java.util.Comparator;
|
||||
public interface ServerMetricsAsJson {
|
||||
|
||||
/**
|
||||
* Set to false to exclude profile location and sql.
|
||||
* Set to false in order to exclude profile location and sql.
|
||||
*/
|
||||
ServerMetricsAsJson withExtraAttributes(boolean withLocation);
|
||||
|
||||
/**
|
||||
* Set to false to exclude SQL hash.
|
||||
* Set to false in order to exclude SQL hash.
|
||||
*/
|
||||
ServerMetricsAsJson withHash(boolean withHash);
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ public class SortMetric {
|
||||
|
||||
@Override
|
||||
public int compare(MetaCountMetric o1, MetaCountMetric o2) {
|
||||
return stringCompare(o1.getName(), o2.getName());
|
||||
return stringCompare(o1.name(), o2.name());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,8 +43,8 @@ public class SortMetric {
|
||||
|
||||
@Override
|
||||
public int compare(MetaTimedMetric o1, MetaTimedMetric o2) {
|
||||
int i = stringCompare(o1.getName(), o2.getName());
|
||||
return i != 0 ? i : Long.compare(o1.getCount(), o2.getCount());
|
||||
int i = stringCompare(o1.name(), o2.name());
|
||||
return i != 0 ? i : Long.compare(o1.count(), o2.count());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ public class SortMetric {
|
||||
|
||||
@Override
|
||||
public int compare(MetaTimedMetric o1, MetaTimedMetric o2) {
|
||||
return Long.compare(o2.getCount(), o1.getCount());
|
||||
return Long.compare(o2.count(), o1.count());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ public class SortMetric {
|
||||
|
||||
@Override
|
||||
public int compare(MetaTimedMetric o1, MetaTimedMetric o2) {
|
||||
return Long.compare(o2.getTotal(), o1.getTotal());
|
||||
return Long.compare(o2.total(), o1.total());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public class SortMetric {
|
||||
|
||||
@Override
|
||||
public int compare(MetaTimedMetric o1, MetaTimedMetric o2) {
|
||||
return Long.compare(o2.getMean(), o1.getMean());
|
||||
return Long.compare(o2.mean(), o1.mean());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ public class SortMetric {
|
||||
|
||||
@Override
|
||||
public int compare(MetaTimedMetric o1, MetaTimedMetric o2) {
|
||||
return Long.compare(o2.getMax(), o1.getMax());
|
||||
return Long.compare(o2.max(), o1.max());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,15 @@ public interface QueryPlanMetric {
|
||||
/**
|
||||
* Return the underlying timed metric.
|
||||
*/
|
||||
TimedMetric getMetric();
|
||||
TimedMetric metric();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to metric().
|
||||
*/
|
||||
@Deprecated
|
||||
default TimedMetric getMetric() {
|
||||
return metric();
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit the underlying metric.
|
||||
|
||||
@@ -16,11 +16,27 @@ public interface BeanDocType<T> {
|
||||
/**
|
||||
* Return the doc store index type for this bean type.
|
||||
*/
|
||||
default String indexType() {
|
||||
return getIndexType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated migrate to indexType().
|
||||
*/
|
||||
@Deprecated
|
||||
String getIndexType();
|
||||
|
||||
/**
|
||||
* Return the doc store index name for this bean type.
|
||||
*/
|
||||
default String indexName() {
|
||||
return getIndexName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated migrate to indexName().
|
||||
*/
|
||||
@Deprecated
|
||||
String getIndexName();
|
||||
|
||||
/**
|
||||
@@ -32,12 +48,28 @@ public interface BeanDocType<T> {
|
||||
/**
|
||||
* Return the FetchPath for the embedded document.
|
||||
*/
|
||||
default FetchPath embedded(String path) {
|
||||
return getEmbedded(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated migrate to embedded().
|
||||
*/
|
||||
@Deprecated
|
||||
FetchPath getEmbedded(String path);
|
||||
|
||||
/**
|
||||
* For embedded 'many' properties we need a FetchPath relative to the root which is used to
|
||||
* build and replace the embedded list.
|
||||
*/
|
||||
default FetchPath embeddedManyRoot(String path) {
|
||||
return getEmbeddedManyRoot(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated migrate to embeddedManyRoot().
|
||||
*/
|
||||
@Deprecated
|
||||
FetchPath getEmbeddedManyRoot(String path);
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,24 +22,56 @@ public interface BeanType<T> {
|
||||
* Return the short name of the bean type.
|
||||
*/
|
||||
@Nonnull
|
||||
String getName();
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to name().
|
||||
*/
|
||||
@Deprecated
|
||||
default String getName() {
|
||||
return name();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the full name of the bean type.
|
||||
*/
|
||||
@Nonnull
|
||||
String getFullName();
|
||||
String fullName();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to fullName().
|
||||
*/
|
||||
@Deprecated
|
||||
default String getFullName() {
|
||||
return fullName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the class type this BeanDescriptor describes.
|
||||
*/
|
||||
@Nonnull
|
||||
Class<T> getBeanType();
|
||||
Class<T> type();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to type().
|
||||
*/
|
||||
@Deprecated
|
||||
default Class<T> getBeanType() {
|
||||
return type();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type bean for an OneToMany or ManyToOne or ManyToMany property.
|
||||
*/
|
||||
BeanType<?> getBeanTypeAtPath(String propertyName);
|
||||
BeanType<?> beanTypeAtPath(String propertyName);
|
||||
|
||||
/**
|
||||
* Deprecated migrate to beanTypeAtPath().
|
||||
*/
|
||||
@Deprecated
|
||||
default BeanType<?> getBeanTypeAtPath(String propertyName) {
|
||||
return beanTypeAtPath(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the properties for this bean type.
|
||||
@@ -50,22 +82,54 @@ public interface BeanType<T> {
|
||||
/**
|
||||
* Return the Id property.
|
||||
*/
|
||||
Property getIdProperty();
|
||||
Property idProperty();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to idProperty().
|
||||
*/
|
||||
@Deprecated
|
||||
default Property getIdProperty() {
|
||||
return idProperty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the when modified property if there is one defined.
|
||||
*/
|
||||
Property getWhenModifiedProperty();
|
||||
Property whenModifiedProperty();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to idProperty().
|
||||
*/
|
||||
@Deprecated
|
||||
default Property getWhenModifiedProperty() {
|
||||
return whenModifiedProperty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the when created property if there is one defined.
|
||||
*/
|
||||
Property getWhenCreatedProperty();
|
||||
Property whenCreatedProperty();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to idProperty().
|
||||
*/
|
||||
@Deprecated
|
||||
default Property getWhenCreatedProperty() {
|
||||
return whenCreatedProperty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Property to read values from a bean.
|
||||
*/
|
||||
Property getProperty(String propertyName);
|
||||
Property property(String propertyName);
|
||||
|
||||
/**
|
||||
* Deprecated migrate to property().
|
||||
*/
|
||||
@Deprecated
|
||||
default Property getProperty(String propertyName) {
|
||||
return property(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ExpressionPath for a given property path.
|
||||
@@ -73,7 +137,15 @@ public interface BeanType<T> {
|
||||
* This can return a property or nested property path.
|
||||
* </p>
|
||||
*/
|
||||
ExpressionPath getExpressionPath(String path);
|
||||
ExpressionPath expressionPath(String path);
|
||||
|
||||
/**
|
||||
* Deprecated migrate to expressionPath().
|
||||
*/
|
||||
@Deprecated
|
||||
default ExpressionPath getExpressionPath(String path) {
|
||||
return expressionPath(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the property is a valid known property or path for the given bean type.
|
||||
@@ -108,7 +180,15 @@ public interface BeanType<T> {
|
||||
/**
|
||||
* Return the base table this bean type maps to.
|
||||
*/
|
||||
String getBaseTable();
|
||||
String baseTable();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to baseTable().
|
||||
*/
|
||||
@Deprecated
|
||||
default String getBaseTable() {
|
||||
return baseTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance of the bean.
|
||||
@@ -118,42 +198,99 @@ public interface BeanType<T> {
|
||||
/**
|
||||
* Return the bean id. This is the same as getBeanId() but without the generic type.
|
||||
*/
|
||||
Object beanId(Object bean);
|
||||
Object id(Object bean);
|
||||
|
||||
/**
|
||||
* Return the id value for the given bean.
|
||||
* Deprecated migrate to id()
|
||||
*/
|
||||
@Deprecated
|
||||
default Object beanId(Object bean) {
|
||||
return id(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated migrate to id()
|
||||
*/
|
||||
@Deprecated
|
||||
Object getBeanId(T bean);
|
||||
|
||||
/**
|
||||
* Set the id value to the bean.
|
||||
*/
|
||||
void setBeanId(T bean, Object idValue);
|
||||
void setId(T bean, Object idValue);
|
||||
|
||||
/**
|
||||
* Deprecated migrate to setId()
|
||||
*/
|
||||
@Deprecated
|
||||
default void setBeanId(T bean, Object idValue) {
|
||||
setId(bean, idValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bean persist controller.
|
||||
*/
|
||||
BeanPersistController getPersistController();
|
||||
BeanPersistController persistController();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to persistController()
|
||||
*/
|
||||
@Deprecated
|
||||
default BeanPersistController getPersistController() {
|
||||
return persistController();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bean persist listener.
|
||||
*/
|
||||
BeanPersistListener getPersistListener();
|
||||
BeanPersistListener persistListener();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to persistListener()
|
||||
*/
|
||||
@Deprecated
|
||||
default BeanPersistListener getPersistListener() {
|
||||
return persistListener();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the beanFinder. Usually null unless overriding the finder.
|
||||
*/
|
||||
BeanFindController getFindController();
|
||||
BeanFindController findController();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to findController()
|
||||
*/
|
||||
@Deprecated
|
||||
default BeanFindController getFindController() {
|
||||
return findController();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BeanQueryAdapter or null if none is defined.
|
||||
*/
|
||||
BeanQueryAdapter getQueryAdapter();
|
||||
BeanQueryAdapter queryAdapter();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to queryAdapter()
|
||||
*/
|
||||
@Deprecated
|
||||
default BeanQueryAdapter getQueryAdapter() {
|
||||
return queryAdapter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the identity generation type.
|
||||
*/
|
||||
IdType getIdType();
|
||||
IdType idType();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to idType()
|
||||
*/
|
||||
@Deprecated
|
||||
default IdType getIdType() {
|
||||
return idType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this bean type has doc store backing.
|
||||
@@ -167,12 +304,28 @@ public interface BeanType<T> {
|
||||
* for the document store.
|
||||
* </p>
|
||||
*/
|
||||
DocMapping getDocMapping();
|
||||
DocMapping docMapping();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to docMapping()
|
||||
*/
|
||||
@Deprecated
|
||||
default DocMapping getDocMapping() {
|
||||
return docMapping();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the doc store queueId for this bean type.
|
||||
*/
|
||||
String getDocStoreQueueId();
|
||||
String docStoreQueueId();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to docStoreQueueId()
|
||||
*/
|
||||
@Deprecated
|
||||
default String getDocStoreQueueId() {
|
||||
return docStoreQueueId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the doc store support for this bean type.\
|
||||
@@ -203,12 +356,28 @@ public interface BeanType<T> {
|
||||
/**
|
||||
* Returns all direct children of this beantype
|
||||
*/
|
||||
List<BeanType<?>> getInheritanceChildren();
|
||||
List<BeanType<?>> inheritanceChildren();
|
||||
|
||||
/**
|
||||
* Returns the parent in inheritance hiearchy
|
||||
* Deprecated migrate to inheritanceChildren()
|
||||
*/
|
||||
BeanType<?> getInheritanceParent();
|
||||
@Deprecated
|
||||
default List<BeanType<?>> getInheritanceChildren() {
|
||||
return inheritanceChildren();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent in inheritance hierarchy
|
||||
*/
|
||||
BeanType<?> inheritanceParent();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to inheritanceParent()
|
||||
*/
|
||||
@Deprecated
|
||||
default BeanType<?> getInheritanceParent() {
|
||||
return inheritanceParent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit all children recursively
|
||||
@@ -218,7 +387,15 @@ public interface BeanType<T> {
|
||||
/**
|
||||
* Return the discriminator column.
|
||||
*/
|
||||
String getDiscColumn();
|
||||
String discColumn();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to discColumn()
|
||||
*/
|
||||
@Deprecated
|
||||
default String getDiscColumn() {
|
||||
return discColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a bean given the discriminator value.
|
||||
|
||||
@@ -37,7 +37,15 @@ public interface ExpressionPath {
|
||||
/**
|
||||
* Return the default StringParser for the scalar property.
|
||||
*/
|
||||
StringParser getStringParser();
|
||||
StringParser stringParser();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to stringParser().
|
||||
*/
|
||||
@Deprecated
|
||||
default StringParser getStringParser() {
|
||||
return stringParser();
|
||||
}
|
||||
|
||||
/**
|
||||
* For DateTime capable scalar types convert the long systemTimeMillis into
|
||||
@@ -54,7 +62,15 @@ public interface ExpressionPath {
|
||||
/**
|
||||
* Return the underlying JDBC type or 0 if this is not a scalar type.
|
||||
*/
|
||||
int getJdbcType();
|
||||
int jdbcType();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to jdbcType().
|
||||
*/
|
||||
@Deprecated
|
||||
default int getJdbcType() {
|
||||
return jdbcType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is an ManyToOne or OneToOne associated bean property.
|
||||
@@ -67,20 +83,52 @@ public interface ExpressionPath {
|
||||
* Typically used to produce id = ? expression strings.
|
||||
* </p>
|
||||
*/
|
||||
String getAssocIdExpression(String propName, String bindOperator);
|
||||
String assocIdExpression(String propName, String bindOperator);
|
||||
|
||||
/**
|
||||
* Deprecated migrate to assocIdExpression().
|
||||
*/
|
||||
@Deprecated
|
||||
default String getAssocIdExpression(String propName, String bindOperator) {
|
||||
return assocIdExpression(propName, bindOperator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Id values for the given bean value.
|
||||
*/
|
||||
Object[] getAssocIdValues(EntityBean bean);
|
||||
Object[] assocIdValues(EntityBean bean);
|
||||
|
||||
/**
|
||||
* Deprecated migrate to assocIdValues().
|
||||
*/
|
||||
@Deprecated
|
||||
default Object[] getAssocIdValues(EntityBean bean) {
|
||||
return assocIdValues(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying bean property.
|
||||
*/
|
||||
Property getProperty();
|
||||
Property property();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to property().
|
||||
*/
|
||||
@Deprecated
|
||||
default Property getProperty() {
|
||||
return property();
|
||||
}
|
||||
|
||||
/**
|
||||
* The ElPrefix plus name.
|
||||
*/
|
||||
String getElName();
|
||||
String elName();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to elName().
|
||||
*/
|
||||
@Deprecated
|
||||
default String getElName() {
|
||||
return elName();
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user