mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
913
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
462d30bbb7 | ||
|
|
5466b889a7 | ||
|
|
d27d20dd1c | ||
|
|
b6edc54cd9 | ||
|
|
2929483b0d | ||
|
|
2ab7c3529a | ||
|
|
f409ea2431 | ||
|
|
e71be4e1b1 | ||
|
|
507aec20d9 | ||
|
|
6a2d0c233a | ||
|
|
a1db8794bb | ||
|
|
bac7cd1ee7 | ||
|
|
7ec0c72522 | ||
|
|
430926c5a9 | ||
|
|
a2389be4aa | ||
|
|
f21caa0755 | ||
|
|
e42d3dac18 | ||
|
|
4c47a84daf | ||
|
|
42aaceaafa | ||
|
|
e5f7a28d80 | ||
|
|
074a3bacc7 | ||
|
|
f52a18989c | ||
|
|
f415ee22b8 | ||
|
|
4878ca47b5 | ||
|
|
59a3766a53 | ||
|
|
15de44eef8 | ||
|
|
5ae9942dd5 | ||
|
|
bf375f1065 | ||
|
|
510e129ff6 | ||
|
|
1c32b9b0bc | ||
|
|
f25a20ff90 | ||
|
|
0ba6753c8c | ||
|
|
7efef027c0 | ||
|
|
3a84695130 | ||
|
|
3f6d6908e2 | ||
|
|
9f4bf6103f | ||
|
|
ad7bb7063d | ||
|
|
04b4fea559 | ||
|
|
eb824949fe | ||
|
|
34db4d0c1f | ||
|
|
54a3113dbc | ||
|
|
7635630808 | ||
|
|
e4018864ac | ||
|
|
75e69a0a23 | ||
|
|
6061f80dcc | ||
|
|
c60525a685 | ||
|
|
eef628531a | ||
|
|
33d9257a61 | ||
|
|
7b032351b1 | ||
|
|
265f865a7d | ||
|
|
73d30310fd | ||
|
|
e26fbbb11f | ||
|
|
a548c16789 | ||
|
|
ecf650c9bc | ||
|
|
b27b4e7038 | ||
|
|
58d190ef12 | ||
|
|
bffc9108f9 | ||
|
|
114a715432 | ||
|
|
67d98954b2 | ||
|
|
53e7aafb06 | ||
|
|
e207b4720b | ||
|
|
af6da23411 | ||
|
|
21f274fd34 | ||
|
|
1b8df12a01 | ||
|
|
b210d1a6a7 | ||
|
|
d53ca87d43 | ||
|
|
635820cab5 | ||
|
|
aedb0fdcac | ||
|
|
4db1925328 | ||
|
|
6f2a444954 | ||
|
|
59b6621077 | ||
|
|
15a39f62e6 | ||
|
|
40489706ce | ||
|
|
742f3b6dc4 | ||
|
|
753617a616 | ||
|
|
114da00d98 | ||
|
|
283ab7a1ac | ||
|
|
096988c19f | ||
|
|
baf727e8ea | ||
|
|
2eb6558145 | ||
|
|
d946504503 | ||
|
|
ed94edd96b | ||
|
|
6441030161 | ||
|
|
588527a5b9 | ||
|
|
06cad500c1 | ||
|
|
e29b57811b | ||
|
|
e6bf46e8c4 | ||
|
|
646f8cc66b | ||
|
|
4c9f0f23f0 | ||
|
|
ecfd831603 | ||
|
|
b8324905ae | ||
|
|
8cbcd1afad | ||
|
|
7970ea39f3 | ||
|
|
a399d4f2cd | ||
|
|
5b91e671dd | ||
|
|
547843fd52 | ||
|
|
21e9c5c3d4 | ||
|
|
05ab1ba25e | ||
|
|
82a6ec6957 | ||
|
|
cf1c08c4ac | ||
|
|
d32df16137 | ||
|
|
2bcbc6fa07 | ||
|
|
ba9158ec9c | ||
|
|
40a6693a4c | ||
|
|
e04f33aaf0 | ||
|
|
e4162a5b03 | ||
|
|
23e6b18262 | ||
|
|
c8852c521e | ||
|
|
7351258d99 | ||
|
|
af9f9585fb | ||
|
|
d7f9dd40a0 | ||
|
|
1ec389864d | ||
|
|
d353b98307 | ||
|
|
3ddd7b4b2b | ||
|
|
3960e1deb5 | ||
|
|
84af78e43c | ||
|
|
cbdbf6d2e0 | ||
|
|
548bf871a9 | ||
|
|
b5245544d2 | ||
|
|
a986d0c8cd | ||
|
|
0e02449f67 | ||
|
|
19389fb9d4 | ||
|
|
ab1a79281b | ||
|
|
073669d312 | ||
|
|
f66662fdfa | ||
|
|
04b0d23932 | ||
|
|
af613d3096 | ||
|
|
ecd27e145e | ||
|
|
5f6b4a7795 | ||
|
|
3d890f5383 | ||
|
|
31a0d9b6a6 | ||
|
|
95fbdf37c6 | ||
|
|
1d09c0864d | ||
|
|
02f7815e73 | ||
|
|
85b700757d | ||
|
|
d5838e3d64 | ||
|
|
01e9eb81cf | ||
|
|
1daad7af06 | ||
|
|
e51d6984fe | ||
|
|
c2777b0e27 | ||
|
|
505f87c524 | ||
|
|
4a372a5dc8 | ||
|
|
8e864897bd | ||
|
|
87b12cff93 | ||
|
|
14ea5521c4 | ||
|
|
e1522df8a5 | ||
|
|
b4f309c219 | ||
|
|
181c6a9d4b | ||
|
|
203aa52c2f | ||
|
|
ad3e88c562 | ||
|
|
adb302059b | ||
|
|
2d03421de4 | ||
|
|
9506e6456c | ||
|
|
4617ea2c1c | ||
|
|
55d7eb55d2 | ||
|
|
7feb193e95 | ||
|
|
ab8915b374 | ||
|
|
79fd689e9a | ||
|
|
a68665a37e | ||
|
|
9ff240dc10 | ||
|
|
9982fa3682 | ||
|
|
f7a11135a5 | ||
|
|
c29a81248a | ||
|
|
ef6d1dbca3 | ||
|
|
60a84b7a38 | ||
|
|
fa3e9e6fc6 | ||
|
|
8ca44edf9c | ||
|
|
fcefd94086 | ||
|
|
70e5d57b7e | ||
|
|
cc3b9c9508 | ||
|
|
be49be38d0 | ||
|
|
dca13db945 | ||
|
|
bd318a5d85 | ||
|
|
4c2be2986a | ||
|
|
3d7bebd244 | ||
|
|
e23bbf5f94 | ||
|
|
27b0c33a4b | ||
|
|
53ef159d06 | ||
|
|
a7d778d98b | ||
|
|
19580ff83d | ||
|
|
a79a44c513 | ||
|
|
184b82e1b2 | ||
|
|
04e935acd0 | ||
|
|
142ffe925c | ||
|
|
395505ec0d | ||
|
|
c21a76fa5b | ||
|
|
a2690fdccd | ||
|
|
4039c20462 | ||
|
|
6d43028fba | ||
|
|
efcee7e739 | ||
|
|
523fe6ae54 | ||
|
|
8ec031bfde | ||
|
|
cd938fd659 | ||
|
|
837e296451 | ||
|
|
52b0bd7b7d | ||
|
|
a8cad4f3d9 | ||
|
|
e4cb81cbba | ||
|
|
08cd0aa4b7 | ||
|
|
b565a5843e | ||
|
|
79c96c9ec1 | ||
|
|
b703b683d8 | ||
|
|
456eb3aca9 | ||
|
|
54c35300d4 | ||
|
|
dfc5963e35 | ||
|
|
36777d5a3d | ||
|
|
12b028fc43 | ||
|
|
72b2f30f2d | ||
|
|
1de74ac366 | ||
|
|
07cb243db3 | ||
|
|
9a02618b67 | ||
|
|
801cb6fa73 | ||
|
|
1c8a416de0 | ||
|
|
c30a8c79a2 | ||
|
|
35cb4356c5 | ||
|
|
a73c985315 | ||
|
|
b5fbfbf1b6 | ||
|
|
4471607b2d | ||
|
|
e4c4b0b43d | ||
|
|
d7ffc4bbb5 | ||
|
|
0bb2f104a4 | ||
|
|
ac3ca8113d | ||
|
|
4ec46e3008 | ||
|
|
e9ab0f34f3 | ||
|
|
2143ebc21c | ||
|
|
7dd25344ef | ||
|
|
c381464316 | ||
|
|
a5d5549f2c | ||
|
|
d7d144b908 | ||
|
|
25416a3cda | ||
|
|
e6b0306bde | ||
|
|
2d6ca4bb1e | ||
|
|
99d5f4f01c | ||
|
|
8ea0936da8 | ||
|
|
f8fc94c694 | ||
|
|
bac3fd6874 | ||
|
|
0659d7604c | ||
|
|
a825e50584 | ||
|
|
94f24f054e | ||
|
|
989d82813b | ||
|
|
2e0dba3741 | ||
|
|
56360f0fb3 | ||
|
|
d84f2eea58 | ||
|
|
34dc4375da | ||
|
|
9e186698fe | ||
|
|
0b615a79cc | ||
|
|
6e98486a03 | ||
|
|
b0364f3c42 | ||
|
|
8c47ba89d1 | ||
|
|
8ed871f116 | ||
|
|
f493c7e8cf | ||
|
|
0e596fd87f | ||
|
|
37154cf4d4 | ||
|
|
fe241d8cce | ||
|
|
efaa771bb4 | ||
|
|
4094b1e345 | ||
|
|
8bb9ec0cfe | ||
|
|
a9575048b4 | ||
|
|
86bcfa804b | ||
|
|
b6a3c54e99 | ||
|
|
6753e36327 | ||
|
|
e78ac677f6 | ||
|
|
19d2b04175 | ||
|
|
d1844c9b5a | ||
|
|
93803eade4 | ||
|
|
82fd6dc65f | ||
|
|
ca6171f697 | ||
|
|
5b4ff2627c | ||
|
|
2aa92d63fd | ||
|
|
658b5b7e06 | ||
|
|
4e3cd83e36 | ||
|
|
aa80bc0c10 | ||
|
|
638cfbca5e | ||
|
|
afa9d89cfe | ||
|
|
22a433997e | ||
|
|
b9d8a9c532 | ||
|
|
1f0191b9e4 | ||
|
|
2d78c5c5e8 | ||
|
|
7c54d21760 | ||
|
|
b9a502ca85 | ||
|
|
b622d85292 | ||
|
|
320ffb4a2d | ||
|
|
0292b4b558 | ||
|
|
2c8ae16179 | ||
|
|
381ac58eed | ||
|
|
af9459e41e | ||
|
|
5882169641 | ||
|
|
f694f2946a | ||
|
|
4c0144de61 | ||
|
|
5e70ea5095 | ||
|
|
acb28925f2 | ||
|
|
3d2a68782c | ||
|
|
8c97d4d0fe | ||
|
|
eb7de343a8 | ||
|
|
4ca1645f9f | ||
|
|
d1fe79005c | ||
|
|
015ee44de3 | ||
|
|
714bbadbc0 | ||
|
|
9e811e9aef | ||
|
|
f97dcb60c0 | ||
|
|
1af3d0bcf3 | ||
|
|
01a0cee3c2 | ||
|
|
f26feec3d9 | ||
|
|
65c76cb2c0 | ||
|
|
874427dac1 | ||
|
|
1176c2e97a | ||
|
|
44e0585fb7 | ||
|
|
889c0f12e0 | ||
|
|
0135263dbd | ||
|
|
564194042b | ||
|
|
244d45674a | ||
|
|
4722f10f5e | ||
|
|
3f5140e7f3 | ||
|
|
43dec17d08 | ||
|
|
f1ee45d7d1 | ||
|
|
3263e7bfc3 | ||
|
|
e01f19b3aa | ||
|
|
20f6a659fe | ||
|
|
09fe923770 | ||
|
|
e6f5e42c2d | ||
|
|
010f73fea2 | ||
|
|
5150ecba62 | ||
|
|
978b1dbe02 | ||
|
|
9813703ce5 | ||
|
|
09001e80b5 | ||
|
|
4aa3ca6d95 | ||
|
|
5ec8469ddc | ||
|
|
39099bbcc9 | ||
|
|
cb2ca0de11 | ||
|
|
b25233b0b9 | ||
|
|
743f1b10e3 | ||
|
|
6055a33dc8 | ||
|
|
230d18e48f | ||
|
|
371f50fb4d | ||
|
|
a3be2041c8 | ||
|
|
09a831f2d6 | ||
|
|
27d9e03691 | ||
|
|
5a3c6b9dad | ||
|
|
502eb78ffd | ||
|
|
61d6cccbcb | ||
|
|
761ec584b2 | ||
|
|
144b8c3077 | ||
|
|
79a1b3a024 | ||
|
|
519b75a778 | ||
|
|
1659c526d7 | ||
|
|
93fc7b07a0 | ||
|
|
d7e6feebc2 | ||
|
|
2a6c60c89b | ||
|
|
b569ec97ee | ||
|
|
a3540057b7 | ||
|
|
6b6cf48ae2 | ||
|
|
f09cba3ab5 | ||
|
|
724183f669 | ||
|
|
a40212d41e | ||
|
|
c9ce02c43d | ||
|
|
03c9782d63 | ||
|
|
130e9451f4 | ||
|
|
dce6a3e9e1 | ||
|
|
486044d29b | ||
|
|
934b0f0044 | ||
|
|
2633cd6bfe | ||
|
|
2c81d0df03 | ||
|
|
9ef59e359b | ||
|
|
6561f6f5e7 | ||
|
|
b2e8e628fa | ||
|
|
bbb8d85971 | ||
|
|
14b94ebe12 | ||
|
|
f5f59d90d4 | ||
|
|
ac3f4ca369 | ||
|
|
10133e6040 | ||
|
|
321fb26df3 | ||
|
|
28bd018d1f | ||
|
|
cceb29313b | ||
|
|
530bfa982e | ||
|
|
3cfa636e88 | ||
|
|
a2e8f098cf | ||
|
|
9e42cfd7d7 | ||
|
|
a3c54d4d20 | ||
|
|
1d48e2afb3 | ||
|
|
d84c9dc1a9 | ||
|
|
6165bf5a6c | ||
|
|
712d3ea78f | ||
|
|
96e3c95c29 | ||
|
|
e6e25b979f | ||
|
|
50fd0f6b1a | ||
|
|
0e9b83a1ce | ||
|
|
d2f629e7bb | ||
|
|
9720cd8189 | ||
|
|
bc4d9837c6 | ||
|
|
e290f68b29 | ||
|
|
a17e62b491 | ||
|
|
928db1f0f6 | ||
|
|
c317092dc5 | ||
|
|
95512d4851 | ||
|
|
62ed5a9f2b | ||
|
|
37ba0b63e4 | ||
|
|
22a5bd9b9d | ||
|
|
45529958ef | ||
|
|
7aa64f47c8 | ||
|
|
919adf331a | ||
|
|
9f229e3cc2 | ||
|
|
3277fe81a1 | ||
|
|
6c6ec3663a | ||
|
|
0461580d1c | ||
|
|
75dbb58c85 | ||
|
|
808f69cac1 | ||
|
|
974953a376 | ||
|
|
f85a367e98 | ||
|
|
87a3c58d93 | ||
|
|
1d1aea77d0 | ||
|
|
2a02935cee | ||
|
|
fd2e5c0fc7 | ||
|
|
6d6b07bf87 | ||
|
|
2cac3cd0bb | ||
|
|
d56098dbf0 | ||
|
|
07682c97a7 | ||
|
|
331a9152aa | ||
|
|
e87a06a713 | ||
|
|
3b5393dca6 | ||
|
|
101c5e52b1 | ||
|
|
5d3bcf4008 | ||
|
|
dd7605ac3a | ||
|
|
47dfbb6157 | ||
|
|
013123c1a7 | ||
|
|
cbc463cd10 | ||
|
|
6e9a8704b4 | ||
|
|
4a0f8931a0 | ||
|
|
3c8c52ca7f | ||
|
|
0fd2f34ed0 | ||
|
|
d29ef8934d | ||
|
|
a4c3949cfc | ||
|
|
97bbce321d | ||
|
|
72f1ab18cc | ||
|
|
b1bba9da5d | ||
|
|
8966faeb7e | ||
|
|
fed4413259 | ||
|
|
14dddb4866 | ||
|
|
0b9d199829 | ||
|
|
3da924b943 | ||
|
|
d7d6082038 | ||
|
|
c96357377b | ||
|
|
5ad313d290 | ||
|
|
8565f5f807 | ||
|
|
96e79248dc | ||
|
|
2789d0f97c | ||
|
|
79cd1da9a4 | ||
|
|
759cf18c41 | ||
|
|
0a61852711 | ||
|
|
6f5e144a93 | ||
|
|
391b33beae | ||
|
|
08e1a05bc9 | ||
|
|
f145aaa1e2 | ||
|
|
245ba9c6b3 | ||
|
|
66f4055b8f | ||
|
|
5170b9f329 | ||
|
|
3a2b20eb43 | ||
|
|
dd0ed8ea76 | ||
|
|
600aa10453 | ||
|
|
f6b87ed0b4 | ||
|
|
b300db77ff | ||
|
|
3f5800da3b | ||
|
|
c5612d50fe | ||
|
|
30bdfc4755 | ||
|
|
8fd24491da | ||
|
|
61deb2517c | ||
|
|
faa58f0fe4 | ||
|
|
d2bb985016 | ||
|
|
d190cd3a08 | ||
|
|
c8853cda58 | ||
|
|
e2d75f4c2e | ||
|
|
b56fa851e0 | ||
|
|
a82ba6d4aa | ||
|
|
359f8b41fe | ||
|
|
22e1403f43 | ||
|
|
9d60ebd19e | ||
|
|
87a27da2b9 | ||
|
|
f8c6a3c960 | ||
|
|
f4c747c6af | ||
|
|
7152cf656b | ||
|
|
c855df8b8d | ||
|
|
d710925cc7 | ||
|
|
f24f912693 | ||
|
|
8f9772e493 | ||
|
|
3c298a67ff | ||
|
|
27504a4dae | ||
|
|
9c64a69b8c | ||
|
|
6c354357ff | ||
|
|
19bbe6e860 | ||
|
|
62adaa7527 | ||
|
|
9a25fb584c | ||
|
|
475f937421 | ||
|
|
227968ef8e | ||
|
|
8e02dedf9f | ||
|
|
5a49041a3b | ||
|
|
ea341a556d | ||
|
|
7affd20092 | ||
|
|
9d9960ded2 | ||
|
|
62a055ef1f | ||
|
|
993607ef4b | ||
|
|
18765b3ac2 | ||
|
|
ea8e195183 | ||
|
|
f54c212b67 | ||
|
|
14d11b1c70 | ||
|
|
7f5f0f6b8e | ||
|
|
318b22448c | ||
|
|
610b3f7dc8 | ||
|
|
7a887d219f | ||
|
|
e74e4ba532 | ||
|
|
d5f753d110 | ||
|
|
c53ca6c16e | ||
|
|
5981d313ae | ||
|
|
cba3d24df1 | ||
|
|
27beab2980 | ||
|
|
aeb4b8ed25 | ||
|
|
edddc935df | ||
|
|
5c1b478085 | ||
|
|
39de9d56db | ||
|
|
e00e490e73 | ||
|
|
dd95081e63 | ||
|
|
03bd31677a | ||
|
|
4619c56b09 | ||
|
|
c3dc57f0fb | ||
|
|
50ba20289b | ||
|
|
6b73072982 | ||
|
|
6e340bd149 | ||
|
|
65f551650f | ||
|
|
3be3741db6 | ||
|
|
610afd3717 | ||
|
|
94dbd9d6ad | ||
|
|
7c23dd06f8 | ||
|
|
e813edae01 | ||
|
|
4218d5bd48 | ||
|
|
aaf7aa8386 | ||
|
|
fbe84a7c62 | ||
|
|
cbd213aad3 | ||
|
|
13622f6b62 | ||
|
|
8fe6de376d | ||
|
|
808ba719f4 | ||
|
|
117844b5ee | ||
|
|
fbb73d465c | ||
|
|
a5c3bbb97e | ||
|
|
674150dc75 | ||
|
|
ad938b2ce2 | ||
|
|
5b1ace8607 | ||
|
|
74321277ff | ||
|
|
c60362f6e1 | ||
|
|
c1320e4184 | ||
|
|
a7ea2cf3ef | ||
|
|
f86a0ac973 | ||
|
|
bcc21b1c04 | ||
|
|
d517dea27f | ||
|
|
7df168f232 | ||
|
|
563340edbd | ||
|
|
28d70cf9c4 | ||
|
|
25d0675532 | ||
|
|
c8ffad2831 | ||
|
|
8233058d2e | ||
|
|
f7e00aab78 | ||
|
|
a111f3ff10 | ||
|
|
29e2b81092 | ||
|
|
0dda3e0e93 | ||
|
|
f07c7411fa | ||
|
|
b4d037fa18 | ||
|
|
e46bbcf8cf | ||
|
|
0c2ab729bc | ||
|
|
81ef967d9f | ||
|
|
2d733795c7 | ||
|
|
7ce85fe5f2 | ||
|
|
e3e30cafdd | ||
|
|
e51ac7de36 | ||
|
|
ee71c79125 | ||
|
|
bce2dec1cd | ||
|
|
3f2d0ef520 | ||
|
|
bbb3ad9333 | ||
|
|
b7e62df371 | ||
|
|
7b3405ca25 | ||
|
|
9984b53070 | ||
|
|
5e1aef1953 | ||
|
|
4c13a3a779 | ||
|
|
100719ac1f | ||
|
|
a13f581a65 | ||
|
|
f319ee66ad | ||
|
|
6f249c7b72 | ||
|
|
09e20934d7 | ||
|
|
5b22506b9b | ||
|
|
13a913428e | ||
|
|
5667f1b118 | ||
|
|
fcb8e4ca64 | ||
|
|
c5e8b217e3 | ||
|
|
f98b6b0e2a | ||
|
|
f01d8174e8 | ||
|
|
ccf790a630 | ||
|
|
efe80a534c | ||
|
|
1aac01ead0 | ||
|
|
216c43eea6 | ||
|
|
5b2a8cdacb | ||
|
|
d2da4f7e52 | ||
|
|
186019da7f | ||
|
|
7d1772cb54 | ||
|
|
cd30c47951 | ||
|
|
4b11147b83 | ||
|
|
6d7a5f07f0 | ||
|
|
26f0605d72 | ||
|
|
4959053ce0 | ||
|
|
10c9b2addd | ||
|
|
3092b59622 | ||
|
|
8b086e0e49 | ||
|
|
981c3595a8 | ||
|
|
5414fa17cf | ||
|
|
807b017463 | ||
|
|
96b674114c | ||
|
|
456086fb3c | ||
|
|
341b9a7449 | ||
|
|
6c7cedc1f1 | ||
|
|
01155c3466 | ||
|
|
c297ebda5a | ||
|
|
cec7492c10 | ||
|
|
4252445eb4 | ||
|
|
a23f241fff | ||
|
|
d145e6494d | ||
|
|
2563d52ecf | ||
|
|
8632aef268 | ||
|
|
f827a292ff | ||
|
|
a027c630b1 | ||
|
|
ab1a49abee | ||
|
|
bc5cf0e326 | ||
|
|
348535ec6c | ||
|
|
273f994cdf | ||
|
|
c0a3f7e05d | ||
|
|
1bc9bab988 | ||
|
|
dc730fd97b | ||
|
|
6c15115530 | ||
|
|
841b268fc7 | ||
|
|
6c8db9dec7 | ||
|
|
51d2f52d19 | ||
|
|
ff45f9ab63 | ||
|
|
507027df0a | ||
|
|
50d45c6da9 | ||
|
|
f5e9356451 | ||
|
|
dfe46cc011 | ||
|
|
34cdbc5620 | ||
|
|
595c057964 | ||
|
|
73bc9e516e | ||
|
|
6a4cfb231d | ||
|
|
4523db85c3 | ||
|
|
d703709f14 | ||
|
|
e8afba7ed2 | ||
|
|
dd5bb3edff | ||
|
|
475b05052e | ||
|
|
4cc012b974 | ||
|
|
c214fe52f0 | ||
|
|
4f57bd3511 | ||
|
|
82dc2d031a | ||
|
|
a831ee9ac9 | ||
|
|
e01b20aecb | ||
|
|
58713c7083 | ||
|
|
2df6f2e5fb | ||
|
|
19724e71db | ||
|
|
1a74c7ca85 | ||
|
|
0356f595c8 | ||
|
|
b12a9adf46 | ||
|
|
2b874189a2 | ||
|
|
f2d95cf012 | ||
|
|
d4825cd72c | ||
|
|
c7bd6c8bde | ||
|
|
c9b3a91539 | ||
|
|
565f6c5ac6 | ||
|
|
356b5e58d9 | ||
|
|
094fc3f4b8 | ||
|
|
cfb9d860f9 | ||
|
|
2f7b553d7c | ||
|
|
ec9481420c | ||
|
|
797e1f4bd2 | ||
|
|
a14507e563 | ||
|
|
732f0e13e2 | ||
|
|
a6304ebe8b | ||
|
|
4050d5e900 | ||
|
|
87cc95f60d | ||
|
|
e8d663c94e | ||
|
|
effcb86174 | ||
|
|
7e50e6e427 | ||
|
|
47b940f672 | ||
|
|
01d5aa8199 | ||
|
|
7474430a63 | ||
|
|
ed830aeb0c | ||
|
|
54cbdae22d | ||
|
|
bb77d6588a | ||
|
|
f930471beb | ||
|
|
3a84e4183d | ||
|
|
d12dc9bfed | ||
|
|
5f689dee1b | ||
|
|
08d3a3b2f5 | ||
|
|
4ed5f91963 | ||
|
|
f36e4543ee | ||
|
|
37f92bf967 | ||
|
|
eb14531b66 | ||
|
|
6c1a3647f9 | ||
|
|
fa9e9be003 | ||
|
|
02ead0bcdb | ||
|
|
892e7bc84a | ||
|
|
4bdcd49eab | ||
|
|
7a0de51721 | ||
|
|
0ea44b36dc | ||
|
|
35e1aa2737 | ||
|
|
dab428ead5 | ||
|
|
dbcc779731 | ||
|
|
3c2b5f253f | ||
|
|
31c20ca9a2 | ||
|
|
0100d024d9 | ||
|
|
7a6d91c2f4 | ||
|
|
31ac0f794f | ||
|
|
648bdf4553 | ||
|
|
bda0786924 | ||
|
|
64311b2b9d | ||
|
|
743acf1f30 | ||
|
|
74fef50b67 | ||
|
|
185404a537 | ||
|
|
ced5bb1089 | ||
|
|
52759e0510 | ||
|
|
7db2210ba4 | ||
|
|
9b80dd97c9 | ||
|
|
23ca0e716c | ||
|
|
eac03a0721 | ||
|
|
cf8f099447 | ||
|
|
6698dda8ae | ||
|
|
1cb011df5b | ||
|
|
ac1e1757e8 | ||
|
|
48404fc85d | ||
|
|
9252e72581 | ||
|
|
64f99f5205 | ||
|
|
a5e3b9e68a | ||
|
|
4b43751512 | ||
|
|
1d9db88050 | ||
|
|
5f6efd29ef | ||
|
|
110bc614e4 | ||
|
|
ec89d31a32 | ||
|
|
fbae9cad8a | ||
|
|
fdfe2533c9 | ||
|
|
7e3d39ac1a | ||
|
|
ce19837649 | ||
|
|
11e20edb59 | ||
|
|
88b6a60feb | ||
|
|
43dac07d5b | ||
|
|
04434215d0 | ||
|
|
52e6c0c625 | ||
|
|
745fbe883e | ||
|
|
283e0b66fa | ||
|
|
523deb20f4 | ||
|
|
23d52ca192 | ||
|
|
d20d276d56 | ||
|
|
5b92ac6e02 | ||
|
|
6392f90f32 | ||
|
|
bb8f3831b8 | ||
|
|
4bb43814b7 | ||
|
|
95c1554642 | ||
|
|
2cd59c5166 | ||
|
|
2d65a3f1c9 | ||
|
|
afdb1df7ce | ||
|
|
fa6fdf124d | ||
|
|
1e044f03ed | ||
|
|
7989fcd6ce | ||
|
|
a5256df6f2 | ||
|
|
fa11dac2b2 | ||
|
|
c40ca2fad7 | ||
|
|
5b9359f509 | ||
|
|
403556d8b2 | ||
|
|
06ad2edfc1 | ||
|
|
16e2489ba0 | ||
|
|
162b3449e8 | ||
|
|
8c3ed6996e | ||
|
|
583c5f74eb | ||
|
|
ab047996d2 | ||
|
|
239f87bb5d | ||
|
|
5be3b7717c | ||
|
|
e29d83a379 | ||
|
|
8301fd5e74 | ||
|
|
3e3647816d | ||
|
|
9aa7ae79e2 | ||
|
|
168c940b79 | ||
|
|
1ee18a1823 | ||
|
|
c02ab7340c | ||
|
|
c67773505d | ||
|
|
9c354919e5 | ||
|
|
c8be59fd95 | ||
|
|
d1a40b4739 | ||
|
|
bb9cfe9d0f | ||
|
|
ede2ad4d54 | ||
|
|
1060503fe1 | ||
|
|
2edfc33d00 | ||
|
|
37902c75eb | ||
|
|
14abb34739 | ||
|
|
68680ffd34 | ||
|
|
8106ffd73d | ||
|
|
d00cb854fc | ||
|
|
ca445b5226 | ||
|
|
74b4994221 | ||
|
|
62106935f4 | ||
|
|
bf034eb2a1 | ||
|
|
c5e980991e | ||
|
|
1004675a0b | ||
|
|
12e508ab48 | ||
|
|
be0e1116a7 | ||
|
|
4b03c8a00a | ||
|
|
0db93bc82d | ||
|
|
e04a1baabe | ||
|
|
506e2f5625 | ||
|
|
7fbc1f8111 | ||
|
|
4084822d2c | ||
|
|
a2c82263ee | ||
|
|
30f3d542b3 | ||
|
|
56cb2c69aa | ||
|
|
bd1dd43cbf | ||
|
|
5caae29df9 | ||
|
|
9713b607b5 | ||
|
|
0e46558cae | ||
|
|
2386f1034b | ||
|
|
ddf9f5c508 | ||
|
|
559867294f | ||
|
|
bf0c8d8dab | ||
|
|
7077e92cb0 | ||
|
|
035c5570c3 | ||
|
|
0be0fd1e05 | ||
|
|
bdfd380687 | ||
|
|
d1a4c73cd6 | ||
|
|
7133c81fc5 | ||
|
|
c6b4de39e8 | ||
|
|
94f367af70 | ||
|
|
dc6c393300 | ||
|
|
239f3a0a54 | ||
|
|
d3e78ab54e | ||
|
|
c6483535bd | ||
|
|
95bb2a5d56 | ||
|
|
23649ed840 | ||
|
|
3ee4034a76 | ||
|
|
21d377546e | ||
|
|
8c9dccc6a3 | ||
|
|
6fdf681993 | ||
|
|
7e8f413578 | ||
|
|
6705e5a962 | ||
|
|
d9126a936d | ||
|
|
4ee024b1ce | ||
|
|
19491d5ae6 | ||
|
|
db816594c5 | ||
|
|
fa73b7791f | ||
|
|
c61da5b0e5 | ||
|
|
49d724ad65 | ||
|
|
3ee2410a79 | ||
|
|
c2ddc70565 | ||
|
|
2f66e07c25 | ||
|
|
0807569ee2 | ||
|
|
206dec1bf8 | ||
|
|
0e852f5bb5 | ||
|
|
a272fb4e02 | ||
|
|
cbdc6e09aa | ||
|
|
211087f636 | ||
|
|
dca824b431 | ||
|
|
6bcc8eb0f2 | ||
|
|
844df4d5c9 | ||
|
|
6360d5fe1c | ||
|
|
e57a074b68 | ||
|
|
052632239e | ||
|
|
16aa4caceb | ||
|
|
83d84f6079 | ||
|
|
23c278d878 | ||
|
|
7074b0de71 | ||
|
|
2a9b025e88 | ||
|
|
16b3a0b1c1 | ||
|
|
e0c4f73600 | ||
|
|
6eb1947a6e | ||
|
|
2f793c29dc | ||
|
|
326fc221bf | ||
|
|
d49018363c | ||
|
|
2a2a0ad1f4 | ||
|
|
463b03ef7c | ||
|
|
80d39775ba | ||
|
|
92cdd25ca9 | ||
|
|
53680ba53b | ||
|
|
aa85c5fa3b | ||
|
|
a1ce6f8a81 | ||
|
|
7480904792 | ||
|
|
b12cfafc21 | ||
|
|
f07727651e | ||
|
|
6090eaa167 | ||
|
|
40eada4e80 | ||
|
|
2d375b3596 | ||
|
|
d864e2c723 | ||
|
|
e50c372562 | ||
|
|
e2cb033119 | ||
|
|
9620c57f19 | ||
|
|
07cc0fcbb6 | ||
|
|
6d1beb5c03 | ||
|
|
1667107422 | ||
|
|
de5cf1df2c | ||
|
|
a83114ced2 | ||
|
|
d6983422bf | ||
|
|
6d4b3ad84e | ||
|
|
a3df7919b5 | ||
|
|
6f1aa39cc9 | ||
|
|
f18c24c1d1 | ||
|
|
068401c29c | ||
|
|
6fbbd8b107 | ||
|
|
6379bd9e5d | ||
|
|
94d58dfa7c | ||
|
|
035fb80959 | ||
|
|
3b97f77083 | ||
|
|
a7d47202e6 | ||
|
|
199a9d3118 | ||
|
|
5df3ac4b04 | ||
|
|
782f77b688 | ||
|
|
1d570a233e | ||
|
|
4a6b58bd9b | ||
|
|
d64073bef0 | ||
|
|
6d8a9236f8 | ||
|
|
1665b4f2fa |
@@ -17,14 +17,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'zulu'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
@@ -36,5 +36,5 @@ jobs:
|
||||
# - name: Maven single test
|
||||
# run: mvn --batch-mode clean verify -Dtest="io.ebeaninternal.server.core.DefaultServer_getReferenceTest" -DfailIfNoTests=false
|
||||
- name: Build with Maven
|
||||
run: mvn clean package
|
||||
run: mvn -T 8 clean test
|
||||
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
@@ -35,4 +35,4 @@ jobs:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: db2
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-db2.properties
|
||||
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-db2.properties
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'zulu'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
@@ -37,5 +37,5 @@ jobs:
|
||||
- name: Maven version
|
||||
run: mvn --version
|
||||
- name: H2Database
|
||||
run: mvn clean package
|
||||
run: mvn -T 8 clean package
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
|
||||
name: JDK 18-ea
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '30 6 * * 1,3,5'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
java_version: [18-ea]
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'zulu'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
path:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: Build with Maven
|
||||
run: mvn package
|
||||
|
||||
@@ -16,20 +16,18 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
## valhalla - failing on javadoc with:
|
||||
## javadoc: error - The code being documented uses packages in the unnamed module, but the packages defined in https://ebean.io/platforms/ebean-platform-h2/apidocs/ are in named modules.
|
||||
java_version: [GA,EA,loom,metropolis,panama]
|
||||
java_version: [GA,EA]
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: oracle-actions/setup-java@v1
|
||||
with:
|
||||
website: jdk.java.net
|
||||
release: ${{ matrix.java_version }}
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
@@ -39,5 +37,5 @@ jobs:
|
||||
- name: Maven version
|
||||
run: mvn --version
|
||||
- name: Build with Maven
|
||||
run: mvn package
|
||||
run: mvn -T 8 test
|
||||
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
@@ -35,4 +35,4 @@ jobs:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: mariadb 10.6
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-mariadb.properties
|
||||
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-mariadb.properties
|
||||
|
||||
@@ -17,14 +17,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'zulu'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
@@ -35,4 +35,4 @@ jobs:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: mysql
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-mysql.properties
|
||||
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-mysql.properties
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
name: Oracle18
|
||||
name: Oracle
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'zulu'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
@@ -35,4 +35,4 @@ jobs:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: oracle
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-oracle.properties
|
||||
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-oracle.properties
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
@@ -35,4 +35,4 @@ jobs:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: postgres
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-postgres.properties
|
||||
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-postgres.properties
|
||||
|
||||
@@ -17,14 +17,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
@@ -35,4 +35,4 @@ jobs:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: sqlserver 2017
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-sqlserver17.properties
|
||||
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-sqlserver17.properties
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -1,26 +1,55 @@
|
||||
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/build.yml)
|
||||
[](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean)
|
||||
[](https://github.com/ebean-orm/ebean/blob/master/LICENSE)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/multi-jdk-build.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/jdk-18-ea.yml)
|
||||
|
||||
##### Build with database platforms
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/h2database.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/postgres.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/mysql.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/mariadb.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/oracle.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/sqlserver.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/db2luw.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/yugabyte.yml)
|
||||
|
||||
|
||||
#### Builds against EA (Early Access) versions of Java (19, Loom, panama etc)
|
||||
|
||||
##### Build with Java Early Access versions
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/jdk-ea.yml)
|
||||
[](https://github.com/ebean-orm/ebean-datasource/actions/workflows/jdk-ea.yml)
|
||||
[](https://github.com/ebean-orm/ebean-migration/actions/workflows/jdk-ea.yml)
|
||||
[](https://github.com/ebean-orm/ebean-test-docker/actions/workflows/jdk-ea.yml)
|
||||
[](https://github.com/ebean-orm/ebean-agent/actions/workflows/jdk-ea.yml)
|
||||
|
||||
----------------------
|
||||
|
||||
# Ebean ORM for Java & Kotlin
|
||||
|
||||
**Multiple abstraction levels**: Ebean provides multiple levels of query abstraction [ORM Queries, mixed with SQL](https://ebean.io/docs/intro/queries/orm-query), [DTO Queries](https://ebean.io/docs/intro/queries/dto-query), [SqlQuery and JDBC](https://ebean.io/docs/intro/queries/sql-query).
|
||||
Work at the highest level of abstraction and drop down levels as needed.
|
||||
|
||||
**Database migrations**: Built in [DB migration](https://ebean.io/docs/db-migrations/) generation and running. Support for "rebase" migrations as well as repeatable, init and 'normal' migrations.
|
||||
|
||||
**Awesome SQL**: Ebean produces SQL that you would hand craft yourself. Use great SQL, never generate SQL cartesian product, always honor relational limit/offset.
|
||||
|
||||
**Automated query tuning**: For ORM queries Ebean can profile the object graph being used and either [automatically tune the query](https://ebean.io/docs/query/background/autotune).
|
||||
|
||||
**Docker test containers**: [Docker test containers](https://ebean.io/docs/testing/) for all the supported databases. Get 100% test coverage on all the features of the database we use.
|
||||
|
||||
**Type safe queries**: We can build queries using type safe [query beans](https://ebean.io/docs/query/query-beans). IDE auto-complete when writing queries, compile time checking and it's FUN.
|
||||
|
||||
**Performance isn't optional**: Optimise queries to only fetch what we need (partial objects). Automatically avoid N+1 via a smart load context.
|
||||
|
||||
#### Benefits of ORM
|
||||
|
||||
* Automatically avoid N+1
|
||||
* L2 caching to reduce database load
|
||||
* Queries mixing database and L2 cache
|
||||
* Automatically tune ORM queries
|
||||
* Elasticsearch for search or L3 cache
|
||||
|
||||
|
||||
----------------------
|
||||
# Sponsors
|
||||
<table>
|
||||
<tbody>
|
||||
@@ -50,13 +79,14 @@
|
||||
</table>
|
||||
|
||||
## Need help?
|
||||
Post questions or issues to the Ebean google group - https://groups.google.com/forum/#!forum/ebean
|
||||
Post questions or issues to the [Ebean google group](https://groups.google.com/forum/#!forum/ebean)
|
||||
or [github discussions](https://github.com/ebean-orm/ebean/discussions)
|
||||
|
||||
## Documentation
|
||||
Goto [https://ebean.io/docs/](https://ebean.io/docs/)
|
||||
|
||||
## Maven central
|
||||
[Maven central - io.ebean](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22io.ebean%22%20)
|
||||
[Maven central - g:io.ebean](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22io.ebean%22%20)
|
||||
|
||||
## Building Ebean from source
|
||||
|
||||
@@ -90,3 +120,4 @@ To set this option as the global default for IntelliJ use:
|
||||
`Run - Edit Configurations -> Edit configuration templates -> JUnit -> modify options - Do not use module-path option`
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-clickhouse</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -31,17 +31,23 @@
|
||||
<version>${ebean-datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>${ebean-migration.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Technically optional but most expected to use query beans -->
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-clickhouse</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-cockroach</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -31,17 +31,23 @@
|
||||
<version>${ebean-datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>${ebean-migration.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Technically optional but most expected to use query beans -->
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-db2</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -31,17 +31,23 @@
|
||||
<version>${ebean-datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>${ebean-migration.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Technically optional but most expected to use query beans -->
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-db2</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-h2</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -31,17 +31,23 @@
|
||||
<version>${ebean-datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>${ebean-migration.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Technically optional but most expected to use query beans -->
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-hana</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -31,17 +31,23 @@
|
||||
<version>${ebean-datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>${ebean-migration.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Technically optional but most expected to use query beans -->
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-hana</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-mariadb</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -31,17 +31,23 @@
|
||||
<version>${ebean-datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>${ebean-migration.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Technically optional but most expected to use query beans -->
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-mariadb</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-mysql</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -31,17 +31,23 @@
|
||||
<version>${ebean-datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>${ebean-migration.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Technically optional but most expected to use query beans -->
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-mysql</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-nuodb</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -31,17 +31,23 @@
|
||||
<version>${ebean-datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>${ebean-migration.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Technically optional but most expected to use query beans -->
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-nuodb</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-oracle</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -31,17 +31,23 @@
|
||||
<version>${ebean-datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>${ebean-migration.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Technically optional but most expected to use query beans -->
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-oracle</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-postgres</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -31,17 +31,23 @@
|
||||
<version>${ebean-datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>${ebean-migration.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Technically optional but most expected to use query beans -->
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-sqlite</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -31,17 +31,23 @@
|
||||
<version>${ebean-datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>${ebean-migration.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Technically optional but most expected to use query beans -->
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlite</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-sqlserver</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -31,17 +31,23 @@
|
||||
<version>${ebean-datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>${ebean-migration.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Technically optional but most expected to use query beans -->
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlserver</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-yugabyte</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -31,17 +31,23 @@
|
||||
<version>${ebean-datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>${ebean-migration.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Technically optional but most expected to use query beans -->
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean (all platforms)</name>
|
||||
@@ -16,13 +16,31 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-joda-time</artifactId>
|
||||
<version>13.18.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-jsonnode</artifactId>
|
||||
<version>13.18.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-mapper</artifactId>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -31,17 +49,23 @@
|
||||
<version>${ebean-datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>${ebean-migration.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Technically optional but most expected to use query beans -->
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-all</artifactId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>composites</artifactId>
|
||||
|
||||
+57
-25
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.6.2-SNAPSHOT</version>
|
||||
<version>13.19.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean api</name>
|
||||
@@ -13,21 +13,17 @@
|
||||
|
||||
<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.36</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>avaje-config</artifactId>
|
||||
<version>2.0</version>
|
||||
<artifactId>avaje-applog</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- exclude avaje-applog-slf4j to direct logging to something else -->
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>avaje-applog-slf4j</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
@@ -37,25 +33,31 @@
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>avaje-lang</artifactId>
|
||||
<version>1.0</version>
|
||||
<version>1.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>avaje-config</artifactId>
|
||||
<version>3.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>persistence-api</artifactId>
|
||||
<version>2.2.5</version>
|
||||
<version>${ebean-persistence-api.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-annotation</artifactId>
|
||||
<version>8.0</version>
|
||||
<version>${ebean-annotation.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-types</artifactId>
|
||||
<version>2.2</version>
|
||||
<version>${ebean-types.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -64,6 +66,14 @@
|
||||
<version>${ebean-datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Support MdcBackgroundExecutorWrapper -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.36</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Jackson core used internally by Ebean -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
@@ -80,19 +90,22 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.transaction</groupId>
|
||||
<artifactId>jta</artifactId>
|
||||
<version>1.1</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- JAVAX-DEPENDENCY-START -->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!-- JAVAX-DEPENDENCY-END -->
|
||||
<!-- JAKARTA-DEPENDENCY-START ___
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<version>6.0.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
____ JAKARTA-DEPENDENCY-END -->
|
||||
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
@@ -103,4 +116,23 @@
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
<includes>
|
||||
<include>**/ebean-maven-version.txt</include>
|
||||
</includes>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>false</filtering>
|
||||
<excludes>
|
||||
<exclude>**/ebean-maven-version.txt</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.util.Optional;
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* @Component
|
||||
* public class CustomerFinder extends BeanFinder<Long,Customer> {
|
||||
*
|
||||
* @Inject
|
||||
@@ -26,29 +27,31 @@ import java.util.Optional;
|
||||
*
|
||||
* @param <I> The ID type
|
||||
* @param <T> The Bean type
|
||||
*
|
||||
* @see BeanRepository
|
||||
*/
|
||||
@NonNullApi
|
||||
public abstract class BeanFinder<I,T> {
|
||||
|
||||
protected final Database server;
|
||||
protected final Database database;
|
||||
protected final Class<T> type;
|
||||
|
||||
/**
|
||||
* Create with the given bean type and Database instance.
|
||||
*
|
||||
* @param type The bean type
|
||||
* @param server The Database instance typically created via Spring factory or equivalent.
|
||||
* @param database The Database instance typically created via Spring factory or equivalent.
|
||||
*/
|
||||
protected BeanFinder(Class<T> type, Database server) {
|
||||
protected BeanFinder(Class<T> type, Database database) {
|
||||
this.type = type;
|
||||
this.server = server;
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Database to use.
|
||||
*/
|
||||
public Database db() {
|
||||
return server;
|
||||
return database;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -70,10 +73,10 @@ public abstract class BeanFinder<I,T> {
|
||||
* <p>
|
||||
* This is equivalent to {@link DB#byName(String)}
|
||||
*
|
||||
* @param server The name of the Database. If this is null then the default Database is returned.
|
||||
* @param name The name of the Database. If this is null then the default Database is returned.
|
||||
*/
|
||||
public Database db(String server) {
|
||||
return DB.byName(server);
|
||||
public Database db(String name) {
|
||||
return DB.byName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,11 +6,15 @@ import io.ebean.bean.EntityBean;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Provides finder functionality for use with "Dependency Injection style" use of Ebean.
|
||||
* Provides find and persist functionality for use with "Dependency Injection style" use of Ebean.
|
||||
* <p>
|
||||
* Extend the BeanRepository with additional finder and persisting methods as needed by the
|
||||
* application. The intention is to keep all the related logic together, for example, all the
|
||||
* persisting and finding logic for Customer would be in CustomerRepository.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* @Repository
|
||||
* @Component
|
||||
* public class CustomerRepository extends BeanRepository<Long,Customer> {
|
||||
*
|
||||
* @Inject
|
||||
@@ -50,10 +54,10 @@ public abstract class BeanRepository<I, T> extends BeanFinder<I, T> {
|
||||
* }</pre>
|
||||
*
|
||||
* @param type The bean type
|
||||
* @param server The Database instance typically created via Spring factory or equivalent
|
||||
* @param database The Database instance typically created via Spring factory or equivalent
|
||||
*/
|
||||
protected BeanRepository(Class<T> type, Database server) {
|
||||
super(type, server);
|
||||
protected BeanRepository(Class<T> type, Database database) {
|
||||
super(type, database);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,8 +126,8 @@ public abstract class BeanRepository<I, T> extends BeanFinder<I, T> {
|
||||
/**
|
||||
* Save all the beans in the collection.
|
||||
*/
|
||||
public int saveAll(Collection<T> bean) {
|
||||
return db().saveAll(bean);
|
||||
public int saveAll(Collection<T> beans) {
|
||||
return db().saveAll(beans);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,6 @@ import io.avaje.lang.Nullable;
|
||||
import io.ebean.annotation.TxIsolation;
|
||||
import io.ebean.cache.ServerCacheManager;
|
||||
import io.ebean.plugin.Property;
|
||||
import io.ebean.text.csv.CsvReader;
|
||||
import io.ebean.text.json.JsonContext;
|
||||
|
||||
import javax.persistence.OptimisticLockException;
|
||||
@@ -238,7 +237,7 @@ public final class DB {
|
||||
}
|
||||
|
||||
/**
|
||||
* The batch will be flushing automatically but you can use this to explicitly
|
||||
* The batch will be flushing automatically but, you can use this to explicitly
|
||||
* flush the batch if you like.
|
||||
* <p>
|
||||
* Flushing occurs automatically when:
|
||||
@@ -785,12 +784,6 @@ public final class DB {
|
||||
return getDefault().createUpdate(beanType, ormUpdate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a CsvReader for a given beanType.
|
||||
*/
|
||||
public static <T> CsvReader<T> createCsvReader(Class<T> beanType) {
|
||||
return getDefault().createCsvReader(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a named query.
|
||||
@@ -961,7 +954,7 @@ public final class DB {
|
||||
*
|
||||
* DB.execute(scope, new TxRunnable() {
|
||||
* public void run() {
|
||||
* User u1 = DB.find(User.class, 1);
|
||||
* User u1 = DB.find(User.class, 1);
|
||||
* ...
|
||||
* }
|
||||
* });
|
||||
@@ -1010,9 +1003,9 @@ public final class DB {
|
||||
*
|
||||
* DB.executeCall(scope, new Callable<String>() {
|
||||
* public String call() {
|
||||
* User u1 = DB.find(User.class, 1);
|
||||
* ...
|
||||
* return u1.getEmail();
|
||||
* User u1 = DB.find(User.class, 1);
|
||||
* ...
|
||||
* return u1.getEmail();
|
||||
* }
|
||||
* });
|
||||
* }</pre>
|
||||
|
||||
@@ -9,7 +9,6 @@ import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.meta.MetaInfoManager;
|
||||
import io.ebean.plugin.Property;
|
||||
import io.ebean.plugin.SpiServer;
|
||||
import io.ebean.text.csv.CsvReader;
|
||||
import io.ebean.text.json.JsonContext;
|
||||
|
||||
import javax.persistence.OptimisticLockException;
|
||||
@@ -30,29 +29,24 @@ import java.util.concurrent.Callable;
|
||||
* singleton (see {@link DatabaseConfig#setRegister(boolean)}). The DB
|
||||
* singleton is essentially a map of Database's that have been registered
|
||||
* with it.
|
||||
* </p>
|
||||
* <p>
|
||||
* The Database can then be retrieved later via {@link DB#byName(String)}.
|
||||
* </p>
|
||||
*
|
||||
* <h5>The 'default' Database</h5>
|
||||
* <p>
|
||||
* One Database can be designated as the 'default' or 'primary' Database
|
||||
* (see {@link DatabaseConfig#setDefaultServer(boolean)}. Many methods on DB
|
||||
* (see {@link DatabaseConfig#setDefaultServer(boolean)}). Many methods on DB
|
||||
* such as {@link DB#find(Class)} etc are actually just a convenient way to
|
||||
* call methods on the 'default/primary' Database.
|
||||
* </p>
|
||||
*
|
||||
* <h5>Constructing a Database</h5>
|
||||
* <p>
|
||||
* Database's are constructed by the DatabaseFactory. They can be created
|
||||
* Databases are constructed by the DatabaseFactory. They can be created
|
||||
* programmatically via {@link DatabaseFactory#create(DatabaseConfig)} or they
|
||||
* can be automatically constructed on demand using configuration information in
|
||||
* the application.properties file.
|
||||
* </p>
|
||||
*
|
||||
* <h5>Example: Get a Database</h5>
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // Get access to the Human Resources Database
|
||||
@@ -71,22 +65,19 @@ import java.util.concurrent.Callable;
|
||||
*
|
||||
* <h5>Database vs DB API</h5>
|
||||
* <p>
|
||||
* Database provides additional API compared with DB. For example it
|
||||
* Database provides additional API compared with DB. For example, it
|
||||
* provides more control over the use of Transactions that is not available in
|
||||
* the DB API.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* <em>External Transactions:</em> If you wanted to use transactions created
|
||||
* externally to Ebean then Database provides additional methods where you
|
||||
* can explicitly pass a transaction (that can be created externally).
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* <em>Bypass ThreadLocal Mechanism:</em> If you want to bypass the built in
|
||||
* <em>Bypass ThreadLocal Mechanism:</em> If you want to bypass the built-in
|
||||
* ThreadLocal transaction management you can use the createTransaction()
|
||||
* method. Example: a single thread requires more than one transaction.
|
||||
* </p>
|
||||
*
|
||||
* @see DB
|
||||
* @see DatabaseFactory
|
||||
@@ -104,12 +95,10 @@ public interface Database {
|
||||
* Shutdown the Database instance programmatically.
|
||||
* <p>
|
||||
* This method is not normally required. Ebean registers a shutdown hook and shuts down cleanly.
|
||||
* </p>
|
||||
* <p>
|
||||
* If the under underlying DataSource is the Ebean implementation then you
|
||||
* also have the option of shutting down the DataSource and deregistering the
|
||||
* also have the option of shutting down the DataSource and de-registering the
|
||||
* JDBC driver.
|
||||
* </p>
|
||||
*
|
||||
* @param shutdownDataSource if true then shutdown the underlying DataSource if it is the Ebean
|
||||
* DataSource implementation.
|
||||
@@ -155,10 +144,10 @@ public interface Database {
|
||||
* <p>
|
||||
* Note many platforms have multiple specific platform types so often we want to
|
||||
* get the base platform via {@link Platform#base()}.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* Platform platform = database.getPlatform().base();
|
||||
* Platform platform = database.platform().base();
|
||||
* if (platform == Platform.MYSQL) {
|
||||
* // do MySql specific function
|
||||
* }
|
||||
@@ -177,8 +166,7 @@ public interface Database {
|
||||
/**
|
||||
* Return the BeanState for a given entity bean.
|
||||
* <p>
|
||||
* This will return null if the bean is not an enhanced entity bean.
|
||||
* </p>
|
||||
* This will throw an IllegalArgumentException if the bean is not an enhanced entity bean.
|
||||
*/
|
||||
BeanState beanState(Object bean);
|
||||
|
||||
@@ -192,7 +180,6 @@ public interface Database {
|
||||
* <p>
|
||||
* For example, if the id value passed in is a String but ought to be a Long or UUID etc
|
||||
* then it will automatically be converted.
|
||||
* </p>
|
||||
*
|
||||
* @param bean The entity bean to set the id value on.
|
||||
* @param id The id value to set.
|
||||
@@ -204,7 +191,6 @@ public interface Database {
|
||||
* <p>
|
||||
* When null is passed in for b, then the 'OldValues' of a is used for the
|
||||
* difference comparison.
|
||||
* </p>
|
||||
*/
|
||||
Map<String, ValuePair> diff(Object newBean, Object oldBean);
|
||||
|
||||
@@ -214,14 +200,9 @@ public interface Database {
|
||||
* Useful if you use BeanPostConstructListeners or @PostConstruct Annotations.
|
||||
* In this case you should not use "new Bean...()". Making all bean constructors protected
|
||||
* could be a good idea here.
|
||||
* </p>
|
||||
*/
|
||||
<T> T createEntityBean(Class<T> type);
|
||||
|
||||
/**
|
||||
* Create a CsvReader for a given beanType.
|
||||
*/
|
||||
<T> CsvReader<T> createCsvReader(Class<T> beanType);
|
||||
|
||||
/**
|
||||
* Create an Update query to perform a bulk update.
|
||||
@@ -248,7 +229,6 @@ public interface Database {
|
||||
* Create a named query.
|
||||
* <p>
|
||||
* For RawSql the named query is expected to be in ebean.xml.
|
||||
* </p>
|
||||
*
|
||||
* @param beanType The type of entity bean
|
||||
* @param namedQuery The name of the query
|
||||
@@ -304,17 +284,14 @@ public interface Database {
|
||||
* <p>
|
||||
* You can use the methods on the Query object to specify fetch paths,
|
||||
* predicates, order by, limits etc.
|
||||
* </p>
|
||||
* <p>
|
||||
* You then use findList(), findSet(), findMap() and findOne() to execute
|
||||
* the query and return the collection or bean.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that a query executed by {@link Query#findList()}
|
||||
* {@link Query#findSet()} etc will execute against the same Database from
|
||||
* which is was created.
|
||||
* </p>
|
||||
* <p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // Find order 2 specifying explicitly the parts of the object graph to
|
||||
@@ -344,7 +321,7 @@ public interface Database {
|
||||
* Create a query using native SQL.
|
||||
* <p>
|
||||
* The native SQL can contain named parameters or positioned parameters.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* String sql = "select c.id, c.name from customer c where c.name like ? order by c.name";
|
||||
@@ -367,12 +344,10 @@ public interface Database {
|
||||
* <p>
|
||||
* This will only work when a IdGenerator is on the bean such as for beans
|
||||
* that use a DB sequence or UUID.
|
||||
* </p>
|
||||
* <p>
|
||||
* For DB's supporting getGeneratedKeys and sequences such as Oracle10 you do
|
||||
* not need to use this method generally. It is made available for more
|
||||
* complex cases where it is useful to get an ID prior to some processing.
|
||||
* </p>
|
||||
*/
|
||||
Object nextId(Class<?> beanType);
|
||||
|
||||
@@ -381,10 +356,8 @@ public interface Database {
|
||||
* going back to the database.
|
||||
* <p>
|
||||
* This produces and returns a new list with the sort and filters applied.
|
||||
* </p>
|
||||
* <p>
|
||||
* Refer to {@link Filter} for an example of its use.
|
||||
* </p>
|
||||
*/
|
||||
<T> Filter<T> filter(Class<T> beanType);
|
||||
|
||||
@@ -401,12 +374,10 @@ public interface Database {
|
||||
* <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.
|
||||
* </p>
|
||||
* <p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // find orders and their customers
|
||||
@@ -431,17 +402,15 @@ public interface Database {
|
||||
<T> void sort(List<T> list, String sortByClause);
|
||||
|
||||
/**
|
||||
* Create a orm update where you will supply the insert/update or delete
|
||||
* Create an orm update where you will supply the insert/update or delete
|
||||
* statement (rather than using a named one that is already defined using the
|
||||
* @NamedUpdates annotation).
|
||||
* <p>
|
||||
* The orm update differs from the sql update in that it you can use the bean
|
||||
* name and bean property names rather than table and column names.
|
||||
* </p>
|
||||
* <p>
|
||||
* An example:
|
||||
* </p>
|
||||
* <p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // The bean name and properties - "topic","postCount" and "id"
|
||||
@@ -466,7 +435,6 @@ public interface Database {
|
||||
* <p>
|
||||
* DTO beans are just normal bean like classes with public constructor(s) and setters.
|
||||
* They do not need to be registered with DB before use.
|
||||
* </p>
|
||||
*
|
||||
* @param dtoType The type of the DTO bean the rows will be mapped into.
|
||||
* @param sql The SQL query to execute.
|
||||
@@ -479,7 +447,6 @@ public interface Database {
|
||||
* <p>
|
||||
* DTO beans are just normal bean like classes with public constructor(s) and setters.
|
||||
* They do not need to be registered with DB before use.
|
||||
* </p>
|
||||
*
|
||||
* @param dtoType The type of the DTO bean the rows will be mapped into.
|
||||
* @param namedQuery The name of the query
|
||||
@@ -493,10 +460,8 @@ public interface Database {
|
||||
*
|
||||
* <p>
|
||||
* Refer to {@link DtoQuery} for native sql queries returning DTO beans.
|
||||
* </p>
|
||||
* <p>
|
||||
* Refer to {@link #findNative(Class, String)} for native sql queries returning entity beans.
|
||||
* </p>
|
||||
*/
|
||||
SqlQuery sqlQuery(String sql);
|
||||
|
||||
@@ -505,11 +470,9 @@ public interface Database {
|
||||
* <p>
|
||||
* Use this to execute a Insert Update or Delete statement. The statement will
|
||||
* be native to the database and contain database table and column names.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* See {@link SqlUpdate} for example usage.
|
||||
* </p>
|
||||
*
|
||||
* @return The SqlUpdate instance to set parameters and execute
|
||||
*/
|
||||
@@ -522,7 +485,7 @@ public interface Database {
|
||||
|
||||
/**
|
||||
* Register a TransactionCallback on the currently active transaction.
|
||||
* <p/>
|
||||
* <p>
|
||||
* If there is no currently active transaction then a PersistenceException is thrown.
|
||||
*
|
||||
* @param transactionCallback The transaction callback to be registered with the current transaction.
|
||||
@@ -536,7 +499,6 @@ public interface Database {
|
||||
* You will want to do this if you want multiple Transactions in a single
|
||||
* thread or generally use transactions outside of the TransactionThreadLocal
|
||||
* management.
|
||||
* </p>
|
||||
*/
|
||||
Transaction createTransaction();
|
||||
|
||||
@@ -544,7 +506,6 @@ public interface Database {
|
||||
* Create a new transaction additionally specifying the isolation level.
|
||||
* <p>
|
||||
* Note that this transaction is NOT stored in a thread local.
|
||||
* </p>
|
||||
*/
|
||||
Transaction createTransaction(TxIsolation isolation);
|
||||
|
||||
@@ -552,86 +513,77 @@ public interface Database {
|
||||
* Start a transaction with 'REQUIRED' semantics.
|
||||
* <p>
|
||||
* With REQUIRED semantics if an active transaction already exists that transaction will be used.
|
||||
* </p>
|
||||
* <p>
|
||||
* The transaction is stored in a ThreadLocal variable and typically you only
|
||||
* need to use the returned Transaction <em>IF</em> you wish to do things like
|
||||
* use batch mode, change the transaction isolation level, use savepoints or
|
||||
* log comments to the transaction log.
|
||||
* </p>
|
||||
* <p>
|
||||
* Example of using a transaction to span multiple calls to find(), save()
|
||||
* etc.
|
||||
* </p>
|
||||
* <p>
|
||||
* Example of using a transaction to span multiple calls to find(), save() etc.
|
||||
*
|
||||
* <h3>Using try with resources</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // start a transaction (stored in a ThreadLocal)
|
||||
* // start a transaction (stored in a ThreadLocal)
|
||||
* try (Transaction txn = database.beginTransaction()) {
|
||||
*
|
||||
* try (Transaction txn = database.beginTransaction()) {
|
||||
* Order order = database.find(Order.class, 10);
|
||||
* ...
|
||||
* database.save(order);
|
||||
*
|
||||
* Order order = database.find(Order.class, 10);
|
||||
* ...
|
||||
* database.save(order);
|
||||
*
|
||||
* txn.commit();
|
||||
* }
|
||||
* txn.commit();
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
*
|
||||
* <h3>Using try finally block</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // start a transaction (stored in a ThreadLocal)
|
||||
* Transaction txn = database.beginTransaction();
|
||||
* try {
|
||||
* Order order = database.find(Order.class,10);
|
||||
* // start a transaction (stored in a ThreadLocal)
|
||||
* Transaction txn = database.beginTransaction();
|
||||
* try {
|
||||
* Order order = database.find(Order.class,10);
|
||||
*
|
||||
* database.save(order);
|
||||
*
|
||||
* txn.commit();
|
||||
*
|
||||
* } finally {
|
||||
* txn.end();
|
||||
* }
|
||||
* database.save(order);
|
||||
* txn.commit();
|
||||
*
|
||||
* } finally {
|
||||
* txn.end();
|
||||
* }
|
||||
* }</pre>
|
||||
* <p>
|
||||
*
|
||||
* <h3>Transaction options</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* try (Transaction txn = database.beginTransaction()) {
|
||||
* try (Transaction txn = database.beginTransaction()) {
|
||||
*
|
||||
* // explicitly turn on/off JDBC batch use
|
||||
* txn.setBatchMode(true);
|
||||
* txn.setBatchSize(50);
|
||||
* // explicitly turn on/off JDBC batch use
|
||||
* txn.setBatchMode(true);
|
||||
* txn.setBatchSize(50);
|
||||
*
|
||||
* // control flushing when mixing save and queries
|
||||
* txn.setBatchFlushOnQuery(false);
|
||||
* // control flushing when mixing save and queries
|
||||
* txn.setBatchFlushOnQuery(false);
|
||||
*
|
||||
* // turn off persist cascade if needed
|
||||
* txn.setPersistCascade(false);
|
||||
* // turn off persist cascade if needed
|
||||
* txn.setPersistCascade(false);
|
||||
*
|
||||
* // for large batch insert processing when we do not
|
||||
* // ... need the generatedKeys, don't get them
|
||||
* txn.setBatchGetGeneratedKeys(false);
|
||||
* // for large batch insert processing when we do not
|
||||
* // ... need the generatedKeys, don't get them
|
||||
* txn.setBatchGetGeneratedKeys(false);
|
||||
*
|
||||
* // explicitly flush the JDBC batch buffer
|
||||
* txn.flush();
|
||||
* // explicitly flush the JDBC batch buffer
|
||||
* txn.flush();
|
||||
*
|
||||
* ...
|
||||
* ...
|
||||
*
|
||||
* txn.commit();
|
||||
* }
|
||||
* txn.commit();
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* <p>
|
||||
* If you want to externalise the transaction management then you use
|
||||
* createTransaction() and pass the transaction around to the various methods on
|
||||
* Database yourself.
|
||||
* </p>
|
||||
*/
|
||||
Transaction beginTransaction();
|
||||
|
||||
@@ -643,11 +595,9 @@ public interface Database {
|
||||
/**
|
||||
* Start a transaction typically specifying REQUIRES_NEW or REQUIRED semantics.
|
||||
* <p>
|
||||
* <p>
|
||||
* Note that this provides an try finally alternative to using {@link #executeCall(TxScope, Callable)} or
|
||||
* {@link #execute(TxScope, Runnable)}.
|
||||
* </p>
|
||||
* <p>
|
||||
*
|
||||
* <h3>REQUIRES_NEW example:</h3>
|
||||
* <pre>{@code
|
||||
* // Start a new transaction. If there is a current transaction
|
||||
@@ -694,10 +644,8 @@ public interface Database {
|
||||
* This only is useful when JDBC batch is used. Flush occurs automatically when the
|
||||
* transaction commits or batch size is reached. This manually flushes the JDBC batch
|
||||
* buffer.
|
||||
* </p>
|
||||
* <p>
|
||||
* This is the same as <code>currentTransaction().flush()</code>.
|
||||
* </p>
|
||||
*/
|
||||
void flush();
|
||||
|
||||
@@ -717,7 +665,6 @@ public interface Database {
|
||||
* <p>
|
||||
* Useful to put in a finally block to ensure the transaction is ended, rather
|
||||
* than a rollbackTransaction() in each catch block.
|
||||
* </p>
|
||||
* <p>
|
||||
* Code example:
|
||||
* <p>
|
||||
@@ -744,7 +691,6 @@ public interface Database {
|
||||
* <p>
|
||||
* Note that this resets OneToMany and ManyToMany properties so that if they
|
||||
* are accessed a lazy load will refresh the many property.
|
||||
* </p>
|
||||
*/
|
||||
void refresh(Object bean);
|
||||
|
||||
@@ -763,12 +709,11 @@ public interface Database {
|
||||
* // Fetch order 1
|
||||
* Order order = database.find(Order.class, 1);
|
||||
* }</pre>
|
||||
* <p>
|
||||
*
|
||||
* <p>
|
||||
* If you want more control over the query then you can use createQuery() and
|
||||
* Query.findOne();
|
||||
* </p>
|
||||
* <p>
|
||||
*
|
||||
* <pre>{@code
|
||||
* // ... additionally fetching customer, customer shipping address,
|
||||
* // order details, and the product associated with each order detail.
|
||||
@@ -810,10 +755,9 @@ public interface Database {
|
||||
* <p>
|
||||
* This will not perform a query against the database unless some property other
|
||||
* that the id property is accessed.
|
||||
* </p>
|
||||
* <p>
|
||||
* It is most commonly used to set a 'foreign key' on another bean like:
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* Product product = database.getReference(Product.class, 1);
|
||||
@@ -853,12 +797,10 @@ public interface Database {
|
||||
* <p>
|
||||
* The extended API has the options for executing queries that take an explicit
|
||||
* transaction as an argument.
|
||||
* </p>
|
||||
* <p>
|
||||
* Typically we only need to use the extended API when we do NOT want to use the
|
||||
* Typically, we only need to use the extended API when we do NOT want to use the
|
||||
* usual ThreadLocal based mechanism to obtain the current transaction but instead
|
||||
* supply the transaction explicitly.
|
||||
* </p>
|
||||
*/
|
||||
ExtendedServer extended();
|
||||
|
||||
@@ -867,32 +809,27 @@ public interface Database {
|
||||
* <p>
|
||||
* If there is no current transaction one will be created and committed for
|
||||
* you automatically.
|
||||
* </p>
|
||||
* <p>
|
||||
* Save can cascade along relationships. For this to happen you need to
|
||||
* specify a cascade of CascadeType.ALL or CascadeType.PERSIST on the
|
||||
* OneToMany, OneToOne or ManyToMany annotation.
|
||||
* </p>
|
||||
* <p>
|
||||
* In this example below the details property has a CascadeType.ALL set so
|
||||
* saving an order will also save all its details.
|
||||
* </p>
|
||||
* <p>
|
||||
*
|
||||
* <pre>{@code
|
||||
* public class Order { ...
|
||||
*
|
||||
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
|
||||
* List<OrderDetail> details;
|
||||
* ...
|
||||
* List<OrderDetail> details;
|
||||
* ...
|
||||
* }
|
||||
* }</pre>
|
||||
* <p>
|
||||
* <p>
|
||||
* When a save cascades via a OneToMany or ManyToMany Ebean will automatically
|
||||
* set the 'parent' object to the 'detail' object. In the example below in
|
||||
* saving the order and cascade saving the order details the 'parent' order
|
||||
* will be set against each order detail when it is saved.
|
||||
* </p>
|
||||
*/
|
||||
void save(Object bean) throws OptimisticLockException;
|
||||
|
||||
@@ -910,16 +847,13 @@ public interface Database {
|
||||
* Delete the bean.
|
||||
* <p>
|
||||
* This will return true if the bean was deleted successfully or JDBC batch is being used.
|
||||
* </p>
|
||||
* <p>
|
||||
* If there is no current transaction one will be created and committed for
|
||||
* you automatically.
|
||||
* </p>
|
||||
* <p>
|
||||
* If the Bean does not have a version property (or loaded version property) and
|
||||
* the bean does not exist then this returns false indicating that nothing was
|
||||
* deleted. Note that, if JDBC batch mode is used then this always returns true.
|
||||
* </p>
|
||||
*/
|
||||
boolean delete(Object bean) throws OptimisticLockException;
|
||||
|
||||
@@ -927,12 +861,10 @@ public interface Database {
|
||||
* Delete the bean with an explicit transaction.
|
||||
* <p>
|
||||
* This will return true if the bean was deleted successfully or JDBC batch is being used.
|
||||
* </p>
|
||||
* <p>
|
||||
* If the Bean does not have a version property (or loaded version property) and
|
||||
* the bean does not exist then this returns false indicating that nothing was
|
||||
* deleted. However, if JDBC batch mode is used then this always returns true.
|
||||
* </p>
|
||||
*/
|
||||
boolean delete(Object bean, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
@@ -1014,16 +946,13 @@ public interface Database {
|
||||
* <p>
|
||||
* If you wish to execute a Sql Select natively then you should use the
|
||||
* SqlQuery object or DtoQuery.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that the table modification information is automatically deduced and
|
||||
* you do not need to call the DB.externalModification() method when you
|
||||
* use this method.
|
||||
* </p>
|
||||
* <p>
|
||||
* Example:
|
||||
* </p>
|
||||
* <p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // example that uses 'named' parameters
|
||||
@@ -1051,7 +980,6 @@ public interface Database {
|
||||
* transaction.
|
||||
* <p>
|
||||
* This returns the number of rows that where inserted, updated or deleted.
|
||||
* </p>
|
||||
*/
|
||||
int execute(Update<?> update);
|
||||
|
||||
@@ -1065,8 +993,7 @@ public interface Database {
|
||||
* For making calls to stored procedures.
|
||||
* <p>
|
||||
* Example:
|
||||
* </p>
|
||||
* <p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* String sql = "{call sp_order_modify(?,?,?)}";
|
||||
@@ -1091,23 +1018,19 @@ public interface Database {
|
||||
* <p>
|
||||
* If you use database.execute(UpdateSql) then the table modification information
|
||||
* is automatically deduced and you do not need to call this method yourself.
|
||||
* </p>
|
||||
* <p>
|
||||
* This information is used to invalidate objects out of the cache and
|
||||
* potentially text indexes. This information is also automatically broadcast
|
||||
* across the cluster.
|
||||
* </p>
|
||||
* <p>
|
||||
* If there is a transaction then this information is placed into the current
|
||||
* transactions event information. When the transaction is committed this
|
||||
* information is registered (with the transaction manager). If this
|
||||
* transaction is rolled back then none of the transaction event information
|
||||
* registers including the information you put in via this method.
|
||||
* </p>
|
||||
* <p>
|
||||
* If there is NO current transaction when you call this method then this
|
||||
* information is registered immediately (with the transaction manager).
|
||||
* </p>
|
||||
*
|
||||
* @param tableName the name of the table that was modified
|
||||
* @param inserted true if rows where inserted into the table
|
||||
@@ -1147,7 +1070,6 @@ public interface Database {
|
||||
* Note: This checks only the root bean!
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // there is a unique constraint on title
|
||||
*
|
||||
* Document doc = new Document();
|
||||
@@ -1176,7 +1098,7 @@ public interface Database {
|
||||
* // uniqueProperties > [title]
|
||||
* // custom msg > property[title] value[One flew over the cuckoo's nest]
|
||||
*
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
@@ -1200,13 +1122,12 @@ public interface Database {
|
||||
* dirty so that it is not skipped.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
* Customer customer = database.find(Customer, id);
|
||||
*
|
||||
* Customer customer = database.find(Customer, id);
|
||||
*
|
||||
* // mark the bean as dirty so that a save() or update() will
|
||||
* // increment the version property
|
||||
* database.markAsDirty(customer);
|
||||
* database.save(customer);
|
||||
* // mark the bean as dirty so that a save() or update() will
|
||||
* // increment the version property
|
||||
* database.markAsDirty(customer);
|
||||
* database.save(customer);
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@@ -1219,18 +1140,17 @@ public interface Database {
|
||||
* <b>Stateless updates:</b> Note that the bean does not have to be previously fetched to call
|
||||
* update().You can create a new instance and set some of its properties programmatically for via
|
||||
* JSON/XML marshalling etc. This is described as a 'stateless update'.
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>Optimistic Locking: </b> Note that if the version property is not set when update() is
|
||||
* called then no optimistic locking is performed (internally ConcurrencyMode.NONE is used).
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // A 'stateless update' example
|
||||
* Customer customer = new Customer();
|
||||
* customer.setId(7);
|
||||
* customer.setName("ModifiedNameNoOCC");
|
||||
* database.update(customer);
|
||||
* // A 'stateless update' example
|
||||
* Customer customer = new Customer();
|
||||
* customer.setId(7);
|
||||
* customer.setName("ModifiedNameNoOCC");
|
||||
* database.update(customer);
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@@ -1281,7 +1201,6 @@ public interface Database {
|
||||
* Compared to save() this forces bean to perform an insert rather than trying to decide
|
||||
* based on the bean state. As such this is useful when you fetch beans from one database
|
||||
* and want to insert them into another database (and you want to explicitly insert them).
|
||||
* </p>
|
||||
*/
|
||||
void insert(Object bean);
|
||||
|
||||
@@ -1314,21 +1233,18 @@ public interface Database {
|
||||
/**
|
||||
* Execute a Runnable in a Transaction with an explicit scope.
|
||||
* <p>
|
||||
* The scope can control the transaction type, isolation and rollback
|
||||
* semantics.
|
||||
* </p>
|
||||
* <p>
|
||||
* The scope can control the transaction type, isolation and rollback semantics.
|
||||
*
|
||||
* <pre>{@code
|
||||
* // set specific transactional scope settings
|
||||
* TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE);
|
||||
*
|
||||
* // set specific transactional scope settings
|
||||
* TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE);
|
||||
*
|
||||
* database.execute(scope, new Runnable() {
|
||||
* public void run() {
|
||||
* User u1 = database.find(User.class, 1);
|
||||
* ...
|
||||
* }
|
||||
* });
|
||||
* database.execute(scope, new Runnable() {
|
||||
* public void run() {
|
||||
* User u1 = database.find(User.class, 1);
|
||||
* ...
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@@ -1339,21 +1255,19 @@ public interface Database {
|
||||
* <p>
|
||||
* The default scope runs with REQUIRED and by default will rollback on any
|
||||
* exception (checked or runtime).
|
||||
* </p>
|
||||
* <p>
|
||||
*
|
||||
* <pre>{@code
|
||||
* database.execute(() -> {
|
||||
*
|
||||
* database.execute(() -> {
|
||||
* User u1 = database.find(User.class, 1);
|
||||
* User u2 = database.find(User.class, 2);
|
||||
*
|
||||
* User u1 = database.find(User.class, 1);
|
||||
* User u2 = database.find(User.class, 2);
|
||||
* u1.setName("u1 mod");
|
||||
* u2.setName("u2 mod");
|
||||
*
|
||||
* u1.setName("u1 mod");
|
||||
* u2.setName("u2 mod");
|
||||
*
|
||||
* u1.save();
|
||||
* u2.save();
|
||||
* });
|
||||
* u1.save();
|
||||
* u2.save();
|
||||
* });
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@@ -1364,18 +1278,16 @@ public interface Database {
|
||||
* <p>
|
||||
* The scope can control the transaction type, isolation and rollback
|
||||
* semantics.
|
||||
* </p>
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* <pre>{@code
|
||||
* // set specific transactional scope settings
|
||||
* TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE);
|
||||
*
|
||||
* database.executeCall(scope, new Callable<String>() {
|
||||
* public String call() {
|
||||
* User u1 = database.find(User.class, 1);
|
||||
* ...
|
||||
* return u1.getEmail();
|
||||
* public String call() {
|
||||
* User u1 = database.find(User.class, 1);
|
||||
* ...
|
||||
* return u1.getEmail();
|
||||
* }
|
||||
* });
|
||||
*
|
||||
@@ -1388,10 +1300,8 @@ public interface Database {
|
||||
* <p>
|
||||
* The default scope runs with REQUIRED and by default will rollback on any
|
||||
* exception (checked or runtime).
|
||||
* </p>
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* <pre>{@code
|
||||
* database.executeCall(new Callable<String>() {
|
||||
* public String call() {
|
||||
* User u1 = database.find(User.class, 1);
|
||||
@@ -1406,7 +1316,6 @@ public interface Database {
|
||||
* return u1.getEmail();
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
<T> T executeCall(Callable<T> callable);
|
||||
@@ -1417,8 +1326,7 @@ public interface Database {
|
||||
ServerCacheManager cacheManager();
|
||||
|
||||
/**
|
||||
* Return the BackgroundExecutor service for asynchronous processing of
|
||||
* queries.
|
||||
* Return the BackgroundExecutor service for asynchronous processing of queries.
|
||||
*/
|
||||
BackgroundExecutor backgroundExecutor();
|
||||
|
||||
@@ -1427,33 +1335,30 @@ public interface Database {
|
||||
* <p>
|
||||
* This instance is safe to be used concurrently by multiple threads and this
|
||||
* method is cheap to call.
|
||||
* </p>
|
||||
* <p>
|
||||
*
|
||||
* <h3>Simple example:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* JsonContext json = database.json();
|
||||
* String jsonOutput = json.toJson(list);
|
||||
* System.out.println(jsonOutput);
|
||||
*
|
||||
* JsonContext json = database.json();
|
||||
* String jsonOutput = json.toJson(list);
|
||||
* System.out.println(jsonOutput);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* <h3>Using PathProperties:</h3>
|
||||
* <pre>{@code
|
||||
* // specify just the properties we want
|
||||
* PathProperties paths = PathProperties.parse("name, status, anniversary");
|
||||
*
|
||||
* // specify just the properties we want
|
||||
* PathProperties paths = PathProperties.parse("name, status, anniversary");
|
||||
* List<Customer> customers =
|
||||
* database.find(Customer.class)
|
||||
* // apply those paths to the query (only fetch what we need)
|
||||
* .apply(paths)
|
||||
* .where().ilike("name", "rob%")
|
||||
* .findList();
|
||||
*
|
||||
* List<Customer> customers =
|
||||
* database.find(Customer.class)
|
||||
* // apply those paths to the query (only fetch what we need)
|
||||
* .apply(paths)
|
||||
* .where().ilike("name", "rob%")
|
||||
* .findList();
|
||||
*
|
||||
* // ... get the json
|
||||
* JsonContext jsonContext = database.json();
|
||||
* String json = jsonContext.toJson(customers, paths);
|
||||
* // ... get the json
|
||||
* JsonContext jsonContext = database.json();
|
||||
* String json = jsonContext.toJson(customers, paths);
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
@@ -1478,7 +1383,6 @@ public interface Database {
|
||||
* Publish a single bean given its type and id returning the resulting live bean.
|
||||
* <p>
|
||||
* The values are published from the draft to the live bean.
|
||||
* </p>
|
||||
*
|
||||
* @param <T> the type of the entity bean
|
||||
* @param beanType the type of the entity bean
|
||||
@@ -1493,7 +1397,6 @@ public interface Database {
|
||||
* This will use the current transaction or create one if required.
|
||||
* <p>
|
||||
* The values are published from the draft to the live bean.
|
||||
* </p>
|
||||
*
|
||||
* @param <T> the type of the entity bean
|
||||
* @param beanType the type of the entity bean
|
||||
@@ -1506,7 +1409,6 @@ public interface Database {
|
||||
* Publish the beans that match the query returning the resulting published beans.
|
||||
* <p>
|
||||
* The values are published from the draft beans to the live beans.
|
||||
* </p>
|
||||
*
|
||||
* @param <T> the type of the entity bean
|
||||
* @param query the query used to select the draft beans to publish
|
||||
@@ -1519,7 +1421,6 @@ public interface Database {
|
||||
* This will use the current transaction or create one if required.
|
||||
* <p>
|
||||
* The values are published from the draft beans to the live beans.
|
||||
* </p>
|
||||
*
|
||||
* @param <T> the type of the entity bean
|
||||
* @param query the query used to select the draft beans to publish
|
||||
@@ -1531,7 +1432,6 @@ public interface Database {
|
||||
* <p>
|
||||
* The values from the live beans are set back to the draft bean and the
|
||||
* <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset.
|
||||
* </p>
|
||||
*
|
||||
* @param <T> the type of the entity bean
|
||||
* @param beanType the type of the entity bean
|
||||
@@ -1546,7 +1446,6 @@ public interface Database {
|
||||
* <p>
|
||||
* The values from the live beans are set back to the draft bean and the
|
||||
* <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset.
|
||||
* </p>
|
||||
*
|
||||
* @param <T> the type of the entity bean
|
||||
* @param beanType the type of the entity bean
|
||||
@@ -1560,7 +1459,6 @@ public interface Database {
|
||||
* <p>
|
||||
* The values from the live beans are set back to the draft bean and the
|
||||
* <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset.
|
||||
* </p>
|
||||
*
|
||||
* @param <T> the type of the entity bean
|
||||
* @param query the query used to select the draft beans to restore
|
||||
@@ -1573,7 +1471,6 @@ public interface Database {
|
||||
* <p>
|
||||
* The values from the live beans are set back to the draft bean and the
|
||||
* <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset.
|
||||
* </p>
|
||||
*
|
||||
* @param <T> the type of the entity bean
|
||||
* @param query the query used to select the draft beans to restore
|
||||
@@ -1585,7 +1482,6 @@ public interface Database {
|
||||
* <p>
|
||||
* Validate the query checking the where and orderBy expression paths to confirm if
|
||||
* they represent valid properties/path for the given bean type.
|
||||
* </p>
|
||||
*/
|
||||
<T> Set<String> validateQuery(Query<T> query);
|
||||
|
||||
@@ -1611,6 +1507,6 @@ public interface Database {
|
||||
/**
|
||||
* Truncate the base tables for the given bean types.
|
||||
*/
|
||||
void truncate(Class<?>... tables);
|
||||
void truncate(Class<?>... beanTypes);
|
||||
|
||||
}
|
||||
|
||||
@@ -2,20 +2,20 @@ package io.ebean;
|
||||
|
||||
import io.ebean.config.BeanNotEnhancedException;
|
||||
import io.ebean.datasource.DataSourceConfigurationException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import static java.lang.System.Logger.Level.ERROR;
|
||||
|
||||
/**
|
||||
* Holds Database instances.
|
||||
*/
|
||||
final class DbContext {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger("io.ebean");
|
||||
private static final System.Logger log = EbeanVersion.log;
|
||||
static {
|
||||
EbeanVersion.getVersion();
|
||||
}
|
||||
@@ -23,14 +23,9 @@ final class DbContext {
|
||||
private static final DbContext INSTANCE = new DbContext();
|
||||
|
||||
private final ConcurrentHashMap<String, Database> concMap = new ConcurrentHashMap<>();
|
||||
|
||||
private final HashMap<String, Database> syncMap = new HashMap<>();
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
/**
|
||||
* The 'default' Database.
|
||||
*/
|
||||
private Database defaultDatabase;
|
||||
|
||||
private DbContext() {
|
||||
@@ -52,7 +47,7 @@ final class DbContext {
|
||||
throw new DataSourceConfigurationException(msg, e);
|
||||
|
||||
} catch (Throwable e) {
|
||||
log.error("Error trying to create the default Database", e);
|
||||
log.log(ERROR, "Error trying to create the default Database", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
@@ -69,9 +64,9 @@ final class DbContext {
|
||||
*/
|
||||
Database getDefault() {
|
||||
if (defaultDatabase == null) {
|
||||
String msg = "The default Database has not been defined?";
|
||||
msg += " This is normally set via the ebean.datasource.default property.";
|
||||
msg += " Otherwise it should be registered programmatically via registerServer()";
|
||||
String msg = "The default Database has not been defined?"
|
||||
+ " This is normally set via the ebean.datasource.default property."
|
||||
+ " Otherwise it should be registered programmatically via registerServer()";
|
||||
throw new PersistenceException(msg);
|
||||
}
|
||||
return defaultDatabase;
|
||||
|
||||
@@ -76,9 +76,9 @@ final class DbPrimary {
|
||||
defaultServerName = System.getProperty("db", defaultServerName);
|
||||
defaultServerName = System.getProperty("ebean_db", defaultServerName);
|
||||
if (isEmpty(defaultServerName)) {
|
||||
defaultServerName = Config.get("datasource.default", null);
|
||||
defaultServerName = Config.getOptional("datasource.default").orElse(null);
|
||||
if (isEmpty(defaultServerName)) {
|
||||
defaultServerName = Config.get("ebean.default.datasource", null);
|
||||
defaultServerName = Config.getOptional("ebean.default.datasource").orElse(null);
|
||||
}
|
||||
}
|
||||
if (defaultServerName == null) {
|
||||
|
||||
@@ -129,6 +129,11 @@ public interface DtoQuery<T> extends CancelableQuery {
|
||||
*/
|
||||
DtoQuery<T> setParameter(String name, Object value);
|
||||
|
||||
/**
|
||||
* Bind the named parameter to SQL NULL.
|
||||
*/
|
||||
DtoQuery<T> setNullParameter(String name, int jdbcType);
|
||||
|
||||
/**
|
||||
* Bind the named multi-value array parameter which we would use with Postgres ANY.
|
||||
* <p>
|
||||
@@ -141,6 +146,11 @@ public interface DtoQuery<T> extends CancelableQuery {
|
||||
*/
|
||||
DtoQuery<T> setParameter(int position, Object value);
|
||||
|
||||
/**
|
||||
* Set a positioned parameter to SQL NULL.
|
||||
*/
|
||||
DtoQuery<T> setNullParameter(int position, int jdbcType);
|
||||
|
||||
/**
|
||||
* Set the index of the first row of the results to return.
|
||||
*/
|
||||
|
||||
@@ -2,6 +2,28 @@ package io.ebean;
|
||||
|
||||
/**
|
||||
* Thrown when a duplicate is attempted on a unique constraint.
|
||||
* <p>
|
||||
* In terms of catching this exception with the view of continuing processing
|
||||
* using the same transaction look to use {@link Transaction#rollbackAndContinue()}.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* try (Transaction txn = database.beginTransaction()) {
|
||||
*
|
||||
* try {
|
||||
* ...
|
||||
* database.save(bean);
|
||||
* database.flush();
|
||||
* } catch (DuplicateKeyException e) {
|
||||
* // carry on processing using the transaction
|
||||
* txn.rollbackAndContinue();
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* txn.commit();
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
public class DuplicateKeyException extends DataIntegrityException {
|
||||
private static final long serialVersionUID = -4771932723285724817L;
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package io.ebean;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import io.avaje.applog.AppLog;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.LineNumberReader;
|
||||
import java.util.Properties;
|
||||
|
||||
import static java.lang.System.Logger.Level.*;
|
||||
|
||||
/**
|
||||
* Class to determine the ebean version.
|
||||
*
|
||||
@@ -14,7 +17,7 @@ import java.util.Properties;
|
||||
*/
|
||||
public final class EbeanVersion {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger("io.ebean");
|
||||
public static final System.Logger log = AppLog.getLogger("io.ebean");
|
||||
|
||||
/**
|
||||
* Maintain the minimum ebean-agent version manually based on required ebean-agent bug fixes.
|
||||
@@ -22,6 +25,7 @@ public final class EbeanVersion {
|
||||
private static final int MIN_AGENT_MAJOR_VERSION = 12;
|
||||
private static final int MIN_AGENT_MINOR_VERSION = 12;
|
||||
private static String version = "unknown";
|
||||
|
||||
static {
|
||||
readVersion();
|
||||
checkAgentVersion();
|
||||
@@ -29,14 +33,16 @@ public final class EbeanVersion {
|
||||
|
||||
private static void readVersion() {
|
||||
try {
|
||||
try (InputStream in = ClassLoader.getSystemResourceAsStream("META-INF/maven/io.ebean/ebean-api/pom.properties")) {
|
||||
try (InputStream in = ClassLoader.getSystemResourceAsStream("META-INF/ebean-maven-version.txt")) {
|
||||
if (in != null) {
|
||||
version = readVersion(in);
|
||||
try (LineNumberReader reader = new LineNumberReader(new InputStreamReader(in))) {
|
||||
version = reader.readLine();
|
||||
log.log(INFO, "ebean version: {0}", version);
|
||||
}
|
||||
}
|
||||
}
|
||||
log.info("ebean version: {}", version);
|
||||
} catch (IOException e) {
|
||||
log.warn("Could not determine ebean version: {}", e.getMessage());
|
||||
log.log(WARNING, "Could not determine ebean version: {0}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,13 +54,13 @@ public final class EbeanVersion {
|
||||
String agentVersion = readVersion(in);
|
||||
if (agentVersion != null) {
|
||||
if (checkMinAgentVersion(agentVersion)) {
|
||||
log.error("Expected minimum ebean-agent version {}.{}.0 but we have {}, please update the ebean-agent", MIN_AGENT_MAJOR_VERSION, MIN_AGENT_MINOR_VERSION, agentVersion);
|
||||
log.log(ERROR, "Expected minimum ebean-agent version {0}.{1}.0 but we have {2}, please update the ebean-agent", MIN_AGENT_MAJOR_VERSION, MIN_AGENT_MINOR_VERSION, agentVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.warn("Could not check minimum ebean-agent version {}.{}.0 required due to - {}", MIN_AGENT_MAJOR_VERSION, MIN_AGENT_MINOR_VERSION, e.getMessage());
|
||||
log.log(WARNING, "Could not check minimum ebean-agent version {0}.{1}.0 required due to - {2}", MIN_AGENT_MAJOR_VERSION, MIN_AGENT_MINOR_VERSION, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +94,7 @@ public final class EbeanVersion {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ebean version (read from /META-INF/maven/io.ebean/ebean/pom.properties)
|
||||
* Returns the ebean version (read from META-INF/ebean-maven-version.txt)
|
||||
*/
|
||||
public static String getVersion() {
|
||||
return version;
|
||||
|
||||
@@ -30,18 +30,25 @@ public final class Expr {
|
||||
private Expr() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying expression factory.
|
||||
*/
|
||||
public static ExpressionFactory factory() {
|
||||
return DB.expressionFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Equal To - property equal to the given value.
|
||||
*/
|
||||
public static Expression eq(String propertyName, Object value) {
|
||||
return DB.expressionFactory().eq(propertyName, value);
|
||||
return factory().eq(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not Equal To - property not equal to the given value.
|
||||
*/
|
||||
public static Expression ne(String propertyName, Object value) {
|
||||
return DB.expressionFactory().ne(propertyName, value);
|
||||
return factory().ne(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -49,7 +56,7 @@ public final class Expr {
|
||||
* using a lower() function to make it case insensitive).
|
||||
*/
|
||||
public static Expression ieq(String propertyName, String value) {
|
||||
return DB.expressionFactory().ieq(propertyName, value);
|
||||
return factory().ieq(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,28 +66,28 @@ public final class Expr {
|
||||
* </p>
|
||||
*/
|
||||
public static Expression inRange(String propertyName, Object value1, Object value2) {
|
||||
return DB.expressionFactory().inRange(propertyName, value1, value2);
|
||||
return factory().inRange(propertyName, value1, value2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Between - property between the two given values.
|
||||
*/
|
||||
public static Expression between(String propertyName, Object value1, Object value2) {
|
||||
return DB.expressionFactory().between(propertyName, value1, value2);
|
||||
return factory().between(propertyName, value1, value2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Between - value between two given properties.
|
||||
*/
|
||||
public static Expression between(String lowProperty, String highProperty, Object value) {
|
||||
return DB.expressionFactory().betweenProperties(lowProperty, highProperty, value);
|
||||
return factory().betweenProperties(lowProperty, highProperty, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater Than - property greater than the given value.
|
||||
*/
|
||||
public static Expression gt(String propertyName, Object value) {
|
||||
return DB.expressionFactory().gt(propertyName, value);
|
||||
return factory().gt(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -88,42 +95,42 @@ public final class Expr {
|
||||
* value.
|
||||
*/
|
||||
public static Expression ge(String propertyName, Object value) {
|
||||
return DB.expressionFactory().ge(propertyName, value);
|
||||
return factory().ge(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Less Than - property less than the given value.
|
||||
*/
|
||||
public static Expression lt(String propertyName, Object value) {
|
||||
return DB.expressionFactory().lt(propertyName, value);
|
||||
return factory().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.expressionFactory().le(propertyName, value);
|
||||
return factory().le(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is Null - property is null.
|
||||
*/
|
||||
public static Expression isNull(String propertyName) {
|
||||
return DB.expressionFactory().isNull(propertyName);
|
||||
return factory().isNull(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is Not Null - property is not null.
|
||||
*/
|
||||
public static Expression isNotNull(String propertyName) {
|
||||
return DB.expressionFactory().isNotNull(propertyName);
|
||||
return factory().isNotNull(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Case insensitive {@link #exampleLike(Object)}
|
||||
*/
|
||||
public static ExampleExpression iexampleLike(Object example) {
|
||||
return DB.expressionFactory().iexampleLike(example);
|
||||
return factory().iexampleLike(example);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,14 +138,14 @@ public final class Expr {
|
||||
* LikeType.RAW (you need to add you own wildcards % and _).
|
||||
*/
|
||||
public static ExampleExpression exampleLike(Object example) {
|
||||
return DB.expressionFactory().exampleLike(example);
|
||||
return factory().exampleLike(example);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the query by Example expression specifying more options.
|
||||
*/
|
||||
public static ExampleExpression exampleLike(Object example, boolean caseInsensitive, LikeType likeType) {
|
||||
return DB.expressionFactory().exampleLike(example, caseInsensitive, likeType);
|
||||
return factory().exampleLike(example, caseInsensitive, likeType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,7 +153,7 @@ public final class Expr {
|
||||
* characters % (percentage) and _ (underscore).
|
||||
*/
|
||||
public static Expression like(String propertyName, String value) {
|
||||
return DB.expressionFactory().like(propertyName, value);
|
||||
return factory().like(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,14 +162,14 @@ public final class Expr {
|
||||
* a lower() function to make the expression case insensitive.
|
||||
*/
|
||||
public static Expression ilike(String propertyName, String value) {
|
||||
return DB.expressionFactory().ilike(propertyName, value);
|
||||
return factory().ilike(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts With - property like value%.
|
||||
*/
|
||||
public static Expression startsWith(String propertyName, String value) {
|
||||
return DB.expressionFactory().startsWith(propertyName, value);
|
||||
return factory().startsWith(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,14 +177,14 @@ public final class Expr {
|
||||
* lower() function to make the expression case insensitive.
|
||||
*/
|
||||
public static Expression istartsWith(String propertyName, String value) {
|
||||
return DB.expressionFactory().istartsWith(propertyName, value);
|
||||
return factory().istartsWith(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends With - property like %value.
|
||||
*/
|
||||
public static Expression endsWith(String propertyName, String value) {
|
||||
return DB.expressionFactory().endsWith(propertyName, value);
|
||||
return factory().endsWith(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,14 +192,14 @@ public final class Expr {
|
||||
* function to make the expression case insensitive.
|
||||
*/
|
||||
public static Expression iendsWith(String propertyName, String value) {
|
||||
return DB.expressionFactory().iendsWith(propertyName, value);
|
||||
return factory().iendsWith(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains - property like %value%.
|
||||
*/
|
||||
public static Expression contains(String propertyName, String value) {
|
||||
return DB.expressionFactory().contains(propertyName, value);
|
||||
return factory().contains(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -200,42 +207,42 @@ public final class Expr {
|
||||
* function to make the expression case insensitive.
|
||||
*/
|
||||
public static Expression icontains(String propertyName, String value) {
|
||||
return DB.expressionFactory().icontains(propertyName, value);
|
||||
return factory().icontains(propertyName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* For collection properties that are empty (have not existing elements).
|
||||
*/
|
||||
public static Expression isEmpty(String propertyName) {
|
||||
return DB.expressionFactory().isEmpty(propertyName);
|
||||
return factory().isEmpty(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* For collection properties that are not empty (have existing elements).
|
||||
*/
|
||||
public static Expression isNotEmpty(String propertyName) {
|
||||
return DB.expressionFactory().isNotEmpty(propertyName);
|
||||
return factory().isNotEmpty(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* In - property has a value in the array of values.
|
||||
*/
|
||||
public static Expression in(String propertyName, Object[] values) {
|
||||
return DB.expressionFactory().in(propertyName, values);
|
||||
return factory().in(propertyName, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* In - using a subQuery.
|
||||
*/
|
||||
public static Expression in(String propertyName, Query<?> subQuery) {
|
||||
return DB.expressionFactory().in(propertyName, subQuery);
|
||||
return factory().in(propertyName, subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* In - property has a value in the collection of values.
|
||||
*/
|
||||
public static Expression in(String propertyName, Collection<?> values) {
|
||||
return DB.expressionFactory().in(propertyName, values);
|
||||
return factory().in(propertyName, values);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,14 +279,14 @@ public final class Expr {
|
||||
* }</pre>
|
||||
*/
|
||||
public static Expression inOrEmpty(String propertyName, Collection<?> values) {
|
||||
return DB.expressionFactory().inOrEmpty(propertyName, values);
|
||||
return factory().inOrEmpty(propertyName, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Id Equal to - ID property is equal to the value.
|
||||
*/
|
||||
public static Expression idEq(Object value) {
|
||||
return DB.expressionFactory().idEq(value);
|
||||
return factory().idEq(value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -292,7 +299,7 @@ public final class Expr {
|
||||
* @param propertyMap a map keyed by property names.
|
||||
*/
|
||||
public static Expression allEq(Map<String, Object> propertyMap) {
|
||||
return DB.expressionFactory().allEq(propertyMap);
|
||||
return factory().allEq(propertyMap);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -303,7 +310,7 @@ public final class Expr {
|
||||
* </p>
|
||||
*/
|
||||
public static Expression raw(String raw, Object value) {
|
||||
return DB.expressionFactory().raw(raw, value);
|
||||
return factory().raw(raw, value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,48 +321,48 @@ public final class Expr {
|
||||
* </p>
|
||||
*/
|
||||
public static Expression raw(String raw, Object[] values) {
|
||||
return DB.expressionFactory().raw(raw, values);
|
||||
return factory().raw(raw, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add raw expression with no parameters.
|
||||
*/
|
||||
public static Expression raw(String raw) {
|
||||
return DB.expressionFactory().raw(raw);
|
||||
return factory().raw(raw);
|
||||
}
|
||||
|
||||
/**
|
||||
* And - join two expressions with a logical and.
|
||||
*/
|
||||
public static Expression and(Expression expOne, Expression expTwo) {
|
||||
return DB.expressionFactory().and(expOne, expTwo);
|
||||
return factory().and(expOne, expTwo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Or - join two expressions with a logical or.
|
||||
*/
|
||||
public static Expression or(Expression expOne, Expression expTwo) {
|
||||
return DB.expressionFactory().or(expOne, expTwo);
|
||||
return factory().or(expOne, expTwo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Negate the expression (prefix it with NOT).
|
||||
*/
|
||||
public static Expression not(Expression exp) {
|
||||
return DB.expressionFactory().not(exp);
|
||||
return factory().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.expressionFactory().conjunction(query);
|
||||
return factory().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.expressionFactory().disjunction(query);
|
||||
return factory().disjunction(query);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.search.Match;
|
||||
import io.ebean.search.MultiMatch;
|
||||
import io.ebean.search.TextCommonTerms;
|
||||
import io.ebean.search.TextQueryString;
|
||||
import io.ebean.search.TextSimple;
|
||||
import io.ebean.search.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
@@ -117,6 +113,11 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
Expression arrayIsNotEmpty(String propertyName);
|
||||
|
||||
/**
|
||||
* Equal To the result of a sub-query.
|
||||
*/
|
||||
Expression eq(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Equal To - property equal to the given value.
|
||||
*/
|
||||
@@ -127,6 +128,11 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
Expression eqOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Not Equal To the result of a sub-query.
|
||||
*/
|
||||
Expression ne(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Not Equal To - property not equal to the given value.
|
||||
*/
|
||||
@@ -181,6 +187,23 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
Expression inRangeWith(String lowProperty, String highProperty, Object value);
|
||||
|
||||
/**
|
||||
* A Property is in Range between 2 properties.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* .orderDate.inRangeWith(QOrder.Alias.product.startDate, QOrder.Alias.product.endDate)
|
||||
*
|
||||
* // which equates to
|
||||
* product.startDate <= orderDate and (orderDate < product.endDate or product.endDate is null)
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* This is a convenience expression combining a number of simple expressions.
|
||||
*/
|
||||
Expression inRangeWithProperties(String propertyName, String lowProperty, String highProperty);
|
||||
|
||||
/**
|
||||
* Between - property between the two given values.
|
||||
*/
|
||||
@@ -207,11 +230,21 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
Expression geOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Greater Than the result of a sub-query.
|
||||
*/
|
||||
Expression gt(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Greater Than - property greater than the given value.
|
||||
*/
|
||||
Expression gt(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Greater Than or Equal to the result of a sub-query.
|
||||
*/
|
||||
Expression ge(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Greater Than or Equal to - property greater than or equal to the given
|
||||
* value.
|
||||
@@ -234,11 +267,21 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
Expression leOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Less Than the result of a sub-query.
|
||||
*/
|
||||
Expression lt(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Less Than - property less than the given value.
|
||||
*/
|
||||
Expression lt(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Less Than or Equal to the result of a sub-query.
|
||||
*/
|
||||
Expression le(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Less Than or Equal to - property less than or equal to the given value.
|
||||
*/
|
||||
@@ -376,6 +419,94 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
Expression inOrEmpty(String propertyName, Collection<?> values);
|
||||
|
||||
/**
|
||||
* EXISTS a raw SQL SubQuery.
|
||||
*
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
Expression exists(String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Not EXISTS a raw SQL SubQuery.
|
||||
*
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
Expression notExists(String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* IN a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
Expression inSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Not IN a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
Expression notInSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Equal To a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
Expression eqSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Not Equal To a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
Expression neSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Greater Than or Equal To a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
Expression geSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Greater Than a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
Expression gtSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Less Than or Equal To a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
Expression leSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Less Than a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
Expression ltSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Not In - property has a value in the array of values.
|
||||
*/
|
||||
|
||||
@@ -54,14 +54,12 @@ public interface ExpressionList<T> {
|
||||
Query<T> orderById(boolean orderById);
|
||||
|
||||
/**
|
||||
* Set the order by clause replacing the existing order by clause if there is
|
||||
* one.
|
||||
* <p>
|
||||
* This follows SQL syntax using commas between each property with the
|
||||
* optional asc and desc keywords representing ascending and descending order
|
||||
* respectively.
|
||||
* Deprecated migrate to {@link #orderBy(String)}
|
||||
*/
|
||||
ExpressionList<T> order(String orderByClause);
|
||||
@Deprecated(since = "13.19")
|
||||
default ExpressionList<T> order(String orderByClause) {
|
||||
return orderBy(orderByClause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the order by clause replacing the existing order by clause if there is
|
||||
@@ -74,15 +72,12 @@ public interface ExpressionList<T> {
|
||||
ExpressionList<T> orderBy(String orderBy);
|
||||
|
||||
/**
|
||||
* Return the OrderBy so that you can append an ascending or descending
|
||||
* property to the order by clause.
|
||||
* <p>
|
||||
* This will never return a null. If no order by clause exists then an 'empty'
|
||||
* OrderBy object is returned.
|
||||
* <p>
|
||||
* This is the same as <code>orderBy()</code>
|
||||
* Deprecated migrate to orderBy().
|
||||
*/
|
||||
OrderBy<T> order();
|
||||
@Deprecated
|
||||
default OrderBy<T> order() {
|
||||
return orderBy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the OrderBy so that you can append an ascending or descending
|
||||
@@ -95,12 +90,6 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
OrderBy<T> orderBy();
|
||||
|
||||
/**
|
||||
* Deprecated migrate to {@link #orderBy(String)}
|
||||
*/
|
||||
@Deprecated
|
||||
Query<T> setOrderBy(String orderBy);
|
||||
|
||||
/**
|
||||
* Apply the path properties to the query replacing the select and fetch clauses.
|
||||
*/
|
||||
@@ -383,6 +372,15 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
<A> List<A> findSingleAttributeList();
|
||||
|
||||
/**
|
||||
* Executes the query returning a set of values for a single property.
|
||||
* <p>
|
||||
* This can be used to cache sets.
|
||||
*
|
||||
* @return a HashSet of values for the selegted property
|
||||
*/
|
||||
<A> Set<A> findSingleAttributeSet();
|
||||
|
||||
/**
|
||||
* Execute a query returning a single value of a single property/column.
|
||||
* <pre>{@code
|
||||
@@ -395,6 +393,7 @@ public interface ExpressionList<T> {
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@Nullable
|
||||
default <A> A findSingleAttribute() {
|
||||
List<A> list = findSingleAttributeList();
|
||||
return !list.isEmpty() ? list.get(0) : null;
|
||||
@@ -821,16 +820,40 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> addAll(ExpressionList<T> exprList);
|
||||
|
||||
/**
|
||||
* Equal To the result of a sub-query.
|
||||
*/
|
||||
ExpressionList<T> eq(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Equal To - property is equal to a given value.
|
||||
*/
|
||||
ExpressionList<T> eq(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Is EQUAL TO if value is non-null and otherwise no expression is added to the query.
|
||||
* <p>
|
||||
* This is the EQUAL TO equivalent to {@link #inOrEmpty(String, Collection)} where the expression/predicate
|
||||
* is only added when the value is non-null.
|
||||
* <p>
|
||||
* This is effectively a helper method that allows a query to be built in fluid style where some predicates are
|
||||
* effectively optional. We can use <code>eqIfPresent()</code> rather than having a separate if block.
|
||||
* <p>
|
||||
* Another option is to instead globally use {@link io.ebean.config.DatabaseConfig#setExpressionEqualsWithNullAsNoop(boolean)}
|
||||
* but that is not always desirable.
|
||||
*/
|
||||
ExpressionList<T> eqIfPresent(String propertyName, @Nullable Object value);
|
||||
|
||||
/**
|
||||
* Equal To or Null - property is equal to a given value or null.
|
||||
*/
|
||||
ExpressionList<T> eqOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Not Equal To the result of a sub-query.
|
||||
*/
|
||||
ExpressionList<T> ne(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Not Equal To - property not equal to the given value.
|
||||
*/
|
||||
@@ -867,6 +890,23 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> inRangeWith(String lowProperty, String highProperty, Object value);
|
||||
|
||||
/**
|
||||
* A Property is in Range between 2 properties.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* .orderDate.inRangeWith(QOrder.Alias.product.startDate, QOrder.Alias.product.endDate)
|
||||
*
|
||||
* // which equates to
|
||||
* product.startDate <= orderDate and (orderDate < product.endDate or product.endDate is null)
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* This is a convenience expression combining a number of simple expressions.
|
||||
*/
|
||||
ExpressionList<T> inRangeWithProperties(String propertyName, String lowProperty, String highProperty);
|
||||
|
||||
/**
|
||||
* In Range - {@code property >= value1 and property < value2}.
|
||||
* <p>
|
||||
@@ -885,6 +925,11 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> betweenProperties(String lowProperty, String highProperty, Object value);
|
||||
|
||||
/**
|
||||
* Greater Than the result of a sub-query.
|
||||
*/
|
||||
ExpressionList<T> gt(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Greater Than - property greater than the given value.
|
||||
*/
|
||||
@@ -896,9 +941,17 @@ public interface ExpressionList<T> {
|
||||
ExpressionList<T> gtOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Greater Than or Equal to OR Null - ({@code >= or null }).
|
||||
* Is GREATER THAN if value is non-null and otherwise no expression is added to the query.
|
||||
* <p>
|
||||
* This is effectively a helper method that allows a query to be built in fluid style where some predicates are
|
||||
* effectively optional. We can use <code>gtIfPresent()</code> rather than having a separate if block.
|
||||
*/
|
||||
ExpressionList<T> geOrNull(String propertyName, Object value);
|
||||
ExpressionList<T> gtIfPresent(String propertyName, @Nullable Object value);
|
||||
|
||||
/**
|
||||
* Greater Than or Equal to the result of a sub-query.
|
||||
*/
|
||||
ExpressionList<T> ge(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Greater Than or Equal to - property greater than or equal to the given
|
||||
@@ -906,6 +959,25 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> ge(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Greater Than or Equal to OR Null - ({@code >= or null }).
|
||||
*/
|
||||
ExpressionList<T> geOrNull(String propertyName, Object value);
|
||||
|
||||
|
||||
/**
|
||||
* Is GREATER THAN OR EQUAL TO if value is non-null and otherwise no expression is added to the query.
|
||||
* <p>
|
||||
* This is effectively a helper method that allows a query to be built in fluid style where some predicates are
|
||||
* effectively optional. We can use <code>geIfPresent()</code> rather than having a separate if block.
|
||||
*/
|
||||
ExpressionList<T> geIfPresent(String propertyName, @Nullable Object value);
|
||||
|
||||
/**
|
||||
* Less Than the result of a sub-query.
|
||||
*/
|
||||
ExpressionList<T> lt(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Less Than - property less than the given value.
|
||||
*/
|
||||
@@ -917,15 +989,36 @@ public interface ExpressionList<T> {
|
||||
ExpressionList<T> ltOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Less Than or Equal to OR Null - ({@code <= or null }).
|
||||
* Is LESS THAN if value is non-null and otherwise no expression is added to the query.
|
||||
* <p>
|
||||
* This is effectively a helper method that allows a query to be built in fluid style where some predicates are
|
||||
* effectively optional. We can use <code>ltIfPresent()</code> rather than having a separate if block.
|
||||
*/
|
||||
ExpressionList<T> leOrNull(String propertyName, Object value);
|
||||
ExpressionList<T> ltIfPresent(String propertyName, @Nullable Object value);
|
||||
|
||||
/**
|
||||
* Less Than or Equal to the result of a sub-query.
|
||||
*/
|
||||
ExpressionList<T> le(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Less Than or Equal to - property less than or equal to the given value.
|
||||
*/
|
||||
ExpressionList<T> le(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Less Than or Equal to OR Null - ({@code <= or null }).
|
||||
*/
|
||||
ExpressionList<T> leOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Is LESS THAN OR EQUAL TO if value is non-null and otherwise no expression is added to the query.
|
||||
* <p>
|
||||
* This is effectively a helper method that allows a query to be built in fluid style where some predicates are
|
||||
* effectively optional. We can use <code>leIfPresent()</code> rather than having a separate if block.
|
||||
*/
|
||||
ExpressionList<T> leIfPresent(String propertyName, @Nullable Object value);
|
||||
|
||||
/**
|
||||
* Is Null - property is null.
|
||||
*/
|
||||
@@ -1038,6 +1131,94 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> inPairs(Pairs pairs);
|
||||
|
||||
/**
|
||||
* EXISTS a raw SQL SubQuery.
|
||||
*
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
ExpressionList<T> exists(String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Not EXISTS a raw SQL SubQuery.
|
||||
*
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
ExpressionList<T> notExists(String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* IN a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
ExpressionList<T> inSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Not IN a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
ExpressionList<T> notInSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Equal To a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
ExpressionList<T> eqSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Not Equal To a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
ExpressionList<T> neSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Greater Than a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
ExpressionList<T> gtSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Greater Than or Equal To a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
ExpressionList<T> geSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Less Than a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
ExpressionList<T> ltSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Less Than or Equal To a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
ExpressionList<T> leSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* In - using a subQuery.
|
||||
*/
|
||||
@@ -1660,4 +1841,8 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> endNot();
|
||||
|
||||
/**
|
||||
* Clears the current expression list.
|
||||
*/
|
||||
ExpressionList<T> clear();
|
||||
}
|
||||
|
||||
@@ -1,480 +1,21 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.avaje.lang.Nullable;
|
||||
|
||||
import javax.persistence.NonUniqueResultException;
|
||||
import java.time.Clock;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* The extended API for Database.
|
||||
* <p>
|
||||
* This provides the finder methods that take an explicit transaction rather than obtaining
|
||||
* the transaction from the usual mechanism (which is ThreadLocal based).
|
||||
* </p>
|
||||
* <p>
|
||||
* In general we only want to use this ExtendedServer API when we want to avoid / bypass
|
||||
* the use of the mechanism to get the current transaction and instead explicitly supply
|
||||
* the transaction to use.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that in all cases the transaction supplied can be null and in this case the Database
|
||||
* will use the normal mechanism to obtain the transaction to use.
|
||||
* </p>
|
||||
*/
|
||||
public interface ExtendedServer {
|
||||
|
||||
/**
|
||||
* Return the NOW time from the Clock.
|
||||
*/
|
||||
long clockNow();
|
||||
|
||||
/**
|
||||
* Deprecated but no yet determined suitable replacement (to support testing only change of clock).
|
||||
* <p>
|
||||
* Set the Clock to use for <code>@WhenCreated</code> and <code>@WhenModified</code>.
|
||||
* <p>
|
||||
* Note that we only expect to change the Clock for testing purposes.
|
||||
* </p>
|
||||
*/
|
||||
@Deprecated
|
||||
void setClock(Clock clock);
|
||||
|
||||
/**
|
||||
* Execute the query returning true if a row is found.
|
||||
* <p>
|
||||
* The query is executed using max rows of 1 and will only select the id property.
|
||||
* This method is really just a convenient way to optimise a query to perform a
|
||||
* 'does a row exist in the db' check.
|
||||
* </p>
|
||||
*
|
||||
* <h2>Example:</h2>
|
||||
* <pre>{@code
|
||||
*
|
||||
* boolean userExists = query().where().eq("email", "rob@foo.com").exists();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h2>Example using a query bean:</h2>
|
||||
* <pre>{@code
|
||||
*
|
||||
* boolean userExists = new QContact().email.equalTo("rob@foo.com").exists();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @return True if the query finds a matching row in the database
|
||||
*/
|
||||
<T> boolean exists(Query<T> ormQuery, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Return the number of 'top level' or 'root' entities this query should return.
|
||||
*
|
||||
* @see Query#findCount()
|
||||
* @see Query#findFutureCount()
|
||||
*/
|
||||
<T> int findCount(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Return the Id values of the query as a List.
|
||||
*
|
||||
* @see Query#findIds()
|
||||
*/
|
||||
<A, T> List<A> findIds(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Return a QueryIterator for the query.
|
||||
* <p>
|
||||
* Generally using {@link #findEach(Query, Consumer, Transaction)} or
|
||||
* {@link #findEachWhile(Query, Predicate, Transaction)} is preferred
|
||||
* to findIterate(). The reason is that those methods automatically take care of
|
||||
* closing the queryIterator (and the underlying jdbc statement and resultSet).
|
||||
* <p>
|
||||
* This is similar to findEach in that not all the result beans need to be held
|
||||
* in memory at the same time and as such is good for processing large queries.
|
||||
*
|
||||
* @see Query#findIterate()
|
||||
* @see Query#findEach(Consumer)
|
||||
* @see Query#findEachWhile(Predicate)
|
||||
*/
|
||||
<T> QueryIterator<T> findIterate(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the query returning the result as a Stream.
|
||||
* <p>
|
||||
* Note that this can support very large queries iterating any number of results.
|
||||
* To do so internally it can use multiple persistence contexts.
|
||||
* <p>
|
||||
* Note that the stream needs to be closed so use with try with resources.
|
||||
* </p>
|
||||
*/
|
||||
<T> Stream<T> findStream(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the query visiting the each bean one at a time.
|
||||
* <p>
|
||||
* Unlike findList() this is suitable for processing a query that will return
|
||||
* a very large resultSet. The reason is that not all the result beans need to be
|
||||
* held in memory at the same time and instead processed one at a time.
|
||||
* </p>
|
||||
* <p>
|
||||
* Internally this query using a PersistenceContext scoped to each bean (and the
|
||||
* beans associated object graph).
|
||||
* </p>
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* DB.find(Order.class)
|
||||
* .where().eq("status", Order.Status.NEW)
|
||||
* .order().asc("id")
|
||||
* .findEach((Order order) -> {
|
||||
*
|
||||
* // do something with the order bean
|
||||
* System.out.println(" -- processing order ... " + order);
|
||||
* });
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @see Query#findEach(Consumer)
|
||||
* @see Query#findEachWhile(Predicate)
|
||||
*/
|
||||
<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>
|
||||
* Compared to findEach() this provides the ability to stop processing the query
|
||||
* results early by returning false for the Predicate.
|
||||
* </p>
|
||||
* <p>
|
||||
* Unlike findList() this is suitable for processing a query that will return
|
||||
* a very large resultSet. The reason is that not all the result beans need to be
|
||||
* held in memory at the same time and instead processed one at a time.
|
||||
* </p>
|
||||
* <p>
|
||||
* Internally this query using a PersistenceContext scoped to each bean (and the
|
||||
* beans associated object graph).
|
||||
* </p>
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* DB.find(Order.class)
|
||||
* .where().eq("status", Order.Status.NEW)
|
||||
* .order().asc("id")
|
||||
* .findEachWhile((Order order) -> {
|
||||
*
|
||||
* // do something with the order bean
|
||||
* System.out.println(" -- processing order ... " + order);
|
||||
*
|
||||
* boolean carryOnProcessing = ...
|
||||
* return carryOnProcessing;
|
||||
* });
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @see Query#findEach(Consumer)
|
||||
* @see Query#findEachWhile(Predicate)
|
||||
*/
|
||||
<T> void findEachWhile(Query<T> query, Predicate<T> consumer, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Return versions of a @History entity bean.
|
||||
* <p>
|
||||
* Generally this query is expected to be a find by id or unique predicates query.
|
||||
* It will execute the query against the history returning the versions of the bean.
|
||||
* </p>
|
||||
*/
|
||||
<T> List<Version<T>> findVersions(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute a query returning a list of beans.
|
||||
* <p>
|
||||
* Generally you are able to use {@link Query#findList()} rather than
|
||||
* explicitly calling this method. You could use this method if you wish to
|
||||
* explicitly control the transaction used for the query.
|
||||
* </p>
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<Customer> customers = DB.find(Customer.class)
|
||||
* .where().ilike("name", "rob%")
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param <T> the type of entity bean to fetch.
|
||||
* @param query the query to execute.
|
||||
* @param transaction the transaction to use (can be null).
|
||||
* @return the list of fetched beans.
|
||||
* @see Query#findList()
|
||||
*/
|
||||
<T> List<T> findList(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute find row count query in a background thread.
|
||||
* <p>
|
||||
* This returns a Future object which can be used to cancel, check the
|
||||
* execution status (isDone etc) and get the value (with or without a
|
||||
* timeout).
|
||||
* </p>
|
||||
*
|
||||
* @param query the query to execute the row count on
|
||||
* @param transaction the transaction (can be null).
|
||||
* @return a Future object for the row count query
|
||||
* @see Query#findFutureCount()
|
||||
*/
|
||||
<T> FutureRowCount<T> findFutureCount(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute find Id's query in a background thread.
|
||||
* <p>
|
||||
* This returns a Future object which can be used to cancel, check the
|
||||
* execution status (isDone etc) and get the value (with or without a
|
||||
* timeout).
|
||||
* </p>
|
||||
*
|
||||
* @param query the query to execute the fetch Id's on
|
||||
* @param transaction the transaction (can be null).
|
||||
* @return a Future object for the list of Id's
|
||||
* @see Query#findFutureIds()
|
||||
*/
|
||||
<T> FutureIds<T> findFutureIds(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute find list query in a background thread returning a FutureList object.
|
||||
* <p>
|
||||
* This returns a Future object which can be used to cancel, check the
|
||||
* execution status (isDone etc) and get the value (with or without a timeout).
|
||||
* <p>
|
||||
* This query will execute in it's own PersistenceContext and using its own transaction.
|
||||
* What that means is that it will not share any bean instances with other queries.
|
||||
*
|
||||
* @param query the query to execute in the background
|
||||
* @param transaction the transaction (can be null).
|
||||
* @return a Future object for the list result of the query
|
||||
* @see Query#findFutureList()
|
||||
*/
|
||||
<T> FutureList<T> findFutureList(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Return a PagedList for this query using firstRow and maxRows.
|
||||
* <p>
|
||||
* The benefit of using this over findList() is that it provides functionality to get the
|
||||
* total row count etc.
|
||||
* </p>
|
||||
* <p>
|
||||
* If maxRows is not set on the query prior to calling findPagedList() then a
|
||||
* PersistenceException is thrown.
|
||||
* </p>
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* PagedList<Order> pagedList = DB.find(Order.class)
|
||||
* .setFirstRow(50)
|
||||
* .setMaxRows(20)
|
||||
* .findPagedList();
|
||||
*
|
||||
* // fetch the total row count in the background
|
||||
* pagedList.loadRowCount();
|
||||
*
|
||||
* List<Order> orders = pagedList.getList();
|
||||
* int totalRowCount = pagedList.getTotalRowCount();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @return The PagedList
|
||||
* @see Query#findPagedList()
|
||||
*/
|
||||
<T> PagedList<T> findPagedList(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the query returning a set of entity beans.
|
||||
* <p>
|
||||
* Generally you are able to use {@link Query#findSet()} rather than
|
||||
* explicitly calling this method. You could use this method if you wish to
|
||||
* explicitly control the transaction used for the query.
|
||||
* </p>
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* Set<Customer> customers = DB.find(Customer.class)
|
||||
* .where().ilike("name", "rob%")
|
||||
* .findSet();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param <T> the type of entity bean to fetch.
|
||||
* @param query the query to execute
|
||||
* @param transaction the transaction to use (can be null).
|
||||
* @return the set of fetched beans.
|
||||
* @see Query#findSet()
|
||||
*/
|
||||
<T> Set<T> findSet(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the query returning the entity beans in a Map.
|
||||
* <p>
|
||||
* Generally you are able to use {@link Query#findMap()} rather than
|
||||
* explicitly calling this method. You could use this method if you wish to
|
||||
* explicitly control the transaction used for the query.
|
||||
* </p>
|
||||
*
|
||||
* @param <T> the type of entity bean to fetch.
|
||||
* @param query the query to execute.
|
||||
* @param transaction the transaction to use (can be null).
|
||||
* @return the map of fetched beans.
|
||||
* @see Query#findMap()
|
||||
*/
|
||||
<K, T> Map<K, T> findMap(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the query returning a list of values for a single property.
|
||||
* <p>
|
||||
* <h3>Example 1:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<String> names =
|
||||
* DB.find(Customer.class)
|
||||
* .select("name")
|
||||
* .order().asc("name")
|
||||
* .findSingleAttributeList();
|
||||
*
|
||||
* }</pre>
|
||||
* <h3>Example 2:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<String> names =
|
||||
* DB.find(Customer.class)
|
||||
* .setDistinct(true)
|
||||
* .select("name")
|
||||
* .where().eq("status", Customer.Status.NEW)
|
||||
* .order().asc("name")
|
||||
* .setMaxRows(100)
|
||||
* .findSingleAttributeList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @return the list of values for the selected property
|
||||
* @see Query#findSingleAttributeList()
|
||||
*/
|
||||
<A, T> List<A> findSingleAttributeList(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the query returning at most one entity bean or null (if no matching
|
||||
* bean is found).
|
||||
* <p>
|
||||
* This will throw a NonUniqueResultException if the query finds more than one result.
|
||||
* </p>
|
||||
* <p>
|
||||
* Generally you are able to use {@link Query#findOne()} rather than
|
||||
* explicitly calling this method. You could use this method if you wish to
|
||||
* explicitly control the transaction used for the query.
|
||||
* </p>
|
||||
*
|
||||
* @param <T> the type of entity bean to fetch.
|
||||
* @param query the query to execute.
|
||||
* @param transaction the transaction to use (can be null).
|
||||
* @return the list of fetched beans.
|
||||
* @throws NonUniqueResultException if more than one result was found
|
||||
* @see Query#findOne()
|
||||
*/
|
||||
@Nullable
|
||||
<T> T findOne(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Similar to findOne() but returns an Optional (rather than nullable).
|
||||
*/
|
||||
<T> Optional<T> findOneOrEmpty(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute as a delete query deleting the 'root level' beans that match the predicates
|
||||
* in the query.
|
||||
* <p>
|
||||
* Note that if the query includes joins then the generated delete statement may not be
|
||||
* optimal depending on the database platform.
|
||||
* </p>
|
||||
*
|
||||
* @param query the query used for the delete
|
||||
* @param transaction the transaction to use (can be null)
|
||||
* @param <T> the type of entity bean to fetch.
|
||||
* @return the number of beans/rows that were deleted
|
||||
*/
|
||||
<T> int delete(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the update query returning the number of rows updated.
|
||||
* <p>
|
||||
* The update query must be created using {@link Database#update(Class)}.
|
||||
* </p>
|
||||
*
|
||||
* @param query the update query to execute
|
||||
* @param transaction the optional transaction to use for the update (can be null)
|
||||
* @param <T> the type of entity bean
|
||||
* @return The number of rows updated
|
||||
*/
|
||||
<T> int update(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the sql query returning a list of MapBean.
|
||||
* <p>
|
||||
* Generally you are able to use {@link SqlQuery#findList()} rather than
|
||||
* explicitly calling this method. You could use this method if you wish to
|
||||
* explicitly control the transaction used for the query.
|
||||
* </p>
|
||||
*
|
||||
* @param query the query to execute.
|
||||
* @param transaction the transaction to use (can be null).
|
||||
* @return the list of fetched MapBean.
|
||||
* @see SqlQuery#findList()
|
||||
*/
|
||||
List<SqlRow> findList(SqlQuery query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the SqlQuery iterating a row at a time.
|
||||
* <p>
|
||||
* This streaming type query is useful for large query execution as only 1 row needs to be held in memory.
|
||||
* </p>
|
||||
*/
|
||||
void findEach(SqlQuery query, Consumer<SqlRow> consumer, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the SqlQuery iterating a row at a time with the ability to stop consuming part way through.
|
||||
* <p>
|
||||
* Returning false after processing a row stops the iteration through the query results.
|
||||
* </p>
|
||||
* <p>
|
||||
* This streaming type query is useful for large query execution as only 1 row needs to be held in memory.
|
||||
* </p>
|
||||
*/
|
||||
void findEachWhile(SqlQuery query, Predicate<SqlRow> consumer, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the sql query returning a single MapBean or null.
|
||||
* <p>
|
||||
* This will throw a PersistenceException if the query found more than one
|
||||
* result.
|
||||
* </p>
|
||||
* <p>
|
||||
* Generally you are able to use {@link SqlQuery#findOne()} rather than
|
||||
* explicitly calling this method. You could use this method if you wish to
|
||||
* explicitly control the transaction used for the query.
|
||||
* </p>
|
||||
*
|
||||
* @param query the query to execute.
|
||||
* @param transaction the transaction to use (can be null).
|
||||
* @return the fetched MapBean or null if none was found.
|
||||
* @see SqlQuery#findOne()
|
||||
*/
|
||||
@Nullable
|
||||
SqlRow findOne(SqlQuery query, Transaction transaction);
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ import java.util.List;
|
||||
* Intended to be used as a base class for 'Finder' implementations that can then
|
||||
* be injected or used as public static fields on the associated entity bean.
|
||||
* <p>
|
||||
* When using dependency injection {@link BeanRepository} and {@link BeanFinder}
|
||||
* are expected to be used rather than this Finder.
|
||||
* <p>
|
||||
* These 'finders' are a place to organise all the finder methods for that bean type
|
||||
* and specific finder methods are expected to be added (find by unique properties etc).
|
||||
* </p>
|
||||
@@ -54,6 +57,8 @@ import java.util.List;
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @see BeanRepository
|
||||
* @see BeanFinder
|
||||
*/
|
||||
@NonNullApi
|
||||
public class Finder<I, T> {
|
||||
|
||||
@@ -231,18 +231,6 @@ public class OrderBy<T> implements Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this order by can be used in select clause.
|
||||
*/
|
||||
public boolean supportsSelect() {
|
||||
for (Property property : list) {
|
||||
if (!property.supportsSelect()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A property and its ascending descending order.
|
||||
*/
|
||||
@@ -403,12 +391,6 @@ public class OrderBy<T> implements Serializable {
|
||||
this.ascending = ascending;
|
||||
}
|
||||
|
||||
/**
|
||||
* Support use in select clause if no collation or nulls ordering.
|
||||
*/
|
||||
boolean supportsSelect() {
|
||||
return nulls == null;
|
||||
}
|
||||
}
|
||||
|
||||
private void parse(String orderByClause) {
|
||||
|
||||
@@ -17,17 +17,17 @@ public interface ProfileLocation {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a new ProfileLocation with a given lineNumber and label.
|
||||
* Create and return a new ProfileLocation with line number.
|
||||
*/
|
||||
static ProfileLocation create(int lineNumber, String label) {
|
||||
return XServiceProvider.profileLocationFactory().create(lineNumber, label);
|
||||
static ProfileLocation createWithLine() {
|
||||
return XServiceProvider.profileLocationFactory().createWithLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a new ProfileLocation with a given location.
|
||||
* Create and return a new ProfileLocation with a given lineNumber and label.
|
||||
*/
|
||||
static ProfileLocation createAt(String location) {
|
||||
return XServiceProvider.profileLocationFactory().createAt(location);
|
||||
static ProfileLocation create(String label) {
|
||||
return XServiceProvider.profileLocationFactory().create(label);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -926,7 +926,12 @@ public interface Query<T> extends CancelableQuery {
|
||||
<A> List<A> findSingleAttributeList();
|
||||
|
||||
/**
|
||||
* Execute a query returning a single value of a single property/column.
|
||||
* Execute the query returning a hashset of values for a single property.
|
||||
*/
|
||||
<A> Set<A> findSingleAttributeSet();
|
||||
|
||||
/**
|
||||
* Execute a query returning a single value or null for a single property/column.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -938,6 +943,7 @@ public interface Query<T> extends CancelableQuery {
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@Nullable
|
||||
<A> A findSingleAttribute();
|
||||
|
||||
/**
|
||||
@@ -1366,13 +1372,9 @@ public interface Query<T> extends CancelableQuery {
|
||||
Query<T> orderBy(String orderByClause);
|
||||
|
||||
/**
|
||||
* Set the order by clause replacing the existing order by clause if there is
|
||||
* one.
|
||||
* <p>
|
||||
* This follows SQL syntax using commas between each property with the
|
||||
* optional asc and desc keywords representing ascending and descending order
|
||||
* respectively.
|
||||
* Deprecated migrate to orderBy().
|
||||
*/
|
||||
@Deprecated(since = "13.19")
|
||||
default Query<T> order(String orderByClause) {
|
||||
return orderBy(orderByClause);
|
||||
}
|
||||
@@ -1389,14 +1391,9 @@ public interface Query<T> extends CancelableQuery {
|
||||
OrderBy<T> orderBy();
|
||||
|
||||
/**
|
||||
* Return the OrderBy so that you can append an ascending or descending
|
||||
* property to the order by clause.
|
||||
* <p>
|
||||
* This will never return a null. If no order by clause exists then an 'empty'
|
||||
* OrderBy object is returned.
|
||||
* <p>
|
||||
* This is the same as <code>orderBy()</code>
|
||||
* Deprecated migrate to orderBy().
|
||||
*/
|
||||
@Deprecated(since = "13.19")
|
||||
default OrderBy<T> order() {
|
||||
return orderBy();
|
||||
}
|
||||
@@ -1407,8 +1404,9 @@ public interface Query<T> extends CancelableQuery {
|
||||
Query<T> setOrderBy(OrderBy<T> orderBy);
|
||||
|
||||
/**
|
||||
* Set an OrderBy object to replace any existing OrderBy clause.
|
||||
* Deprecated migrate to setOrderBy().
|
||||
*/
|
||||
@Deprecated(since = "13.19")
|
||||
default Query<T> setOrder(OrderBy<T> orderBy) {
|
||||
return setOrderBy(orderBy);
|
||||
}
|
||||
@@ -1573,13 +1571,6 @@ public interface Query<T> extends CancelableQuery {
|
||||
*/
|
||||
Query<T> setReadOnly(boolean readOnly);
|
||||
|
||||
/**
|
||||
* Will be deprecated - migrate to use setBeanCacheMode(CacheMode.RECACHE).
|
||||
* <p>
|
||||
* When set to true all the beans from this query are loaded into the bean cache.
|
||||
*/
|
||||
Query<T> setLoadBeanCache(boolean loadBeanCache);
|
||||
|
||||
/**
|
||||
* Set a timeout on this query.
|
||||
* <p>
|
||||
@@ -1761,4 +1752,31 @@ public interface Query<T> extends CancelableQuery {
|
||||
*/
|
||||
Query<T> orderById(boolean orderById);
|
||||
|
||||
/**
|
||||
* Type safe query bean properties and expressions (marker interface).
|
||||
* <p>
|
||||
* Implemented by query bean properties and expressions based on those properties.
|
||||
* <p>
|
||||
* The base type determines which {@link StdOperators} can be used on the property.
|
||||
*
|
||||
* @param <T> The property type.
|
||||
*/
|
||||
interface Property<T> {
|
||||
|
||||
/**
|
||||
* Return a property given the expression.
|
||||
*/
|
||||
static <T> Property<T> of(String expression) {
|
||||
return new SimpleProperty<>(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the property in string expression form.
|
||||
* <p>
|
||||
* This is a path to a database column (like "name" or "billingAddress.city") or a function
|
||||
* wrapping a path (like <em>lower(name)</em>, <em>concat(name, '-', billingAddress.city)</em>
|
||||
*/
|
||||
@Override
|
||||
String toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package io.ebean;
|
||||
|
||||
final class SimpleProperty<T> implements Query.Property<T> {
|
||||
|
||||
private final String expression;
|
||||
|
||||
SimpleProperty(String expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return expression;
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,8 @@ package io.ebean;
|
||||
|
||||
import io.avaje.lang.NonNullApi;
|
||||
import io.avaje.lang.Nullable;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
@@ -40,6 +40,11 @@ import java.util.function.Predicate;
|
||||
@NonNullApi
|
||||
public interface SqlQuery extends Serializable, CancelableQuery {
|
||||
|
||||
/**
|
||||
* Execute the query using the given transaction.
|
||||
*/
|
||||
SqlQuery usingTransaction(Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the query returning a list.
|
||||
*/
|
||||
@@ -298,6 +303,11 @@ public interface SqlQuery extends Serializable, CancelableQuery {
|
||||
*/
|
||||
interface TypeQuery<T> {
|
||||
|
||||
/**
|
||||
* Execute the query using the given transaction.
|
||||
*/
|
||||
TypeQuery<T> usingTransaction(Transaction transaction);
|
||||
|
||||
/**
|
||||
* Return the single value.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,332 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.Query.Property;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Standard Operators for use with strongly typed query construction.
|
||||
* <p>
|
||||
* This is currently deemed to be experimental and subject to change.
|
||||
*/
|
||||
@Deprecated(since = "experimental")
|
||||
public final class StdOperators {
|
||||
|
||||
// ---- Functions ---- //
|
||||
|
||||
/**
|
||||
* Sum of the given property.
|
||||
*/
|
||||
public static Property<Number> sum(Property<? extends Number> property) {
|
||||
return Property.of("sum(" + property + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Count of the given property.
|
||||
*/
|
||||
public static Property<Number> count(Property<?> property) {
|
||||
return Property.of("count(" + property + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Average of the given property.
|
||||
*/
|
||||
public static <T> Property<T> avg(Property<T> property) {
|
||||
return Property.of("avg(" + property + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Max of the given property.
|
||||
*/
|
||||
public static <T> Property<T> max(Property<T> property) {
|
||||
return Property.of("max(" + property + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Min of the given property.
|
||||
*/
|
||||
public static <T> Property<T> min(Property<T> property) {
|
||||
return Property.of("min(" + property + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Coalesce of the property and value.
|
||||
*/
|
||||
public static <T> Property<T> coalesce(Property<T> property, Object value) {
|
||||
return Property.of("coalesce(" + property.toString() + "," + sqlValue(value) + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Lower of the given property.
|
||||
*/
|
||||
public static Property<String> lower(Property<String> property) {
|
||||
return Property.of("lower(" + property + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Upper of the given property.
|
||||
*/
|
||||
public static Property<String> upper(Property<String> property) {
|
||||
return Property.of("upper(" + property + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Concat of the given property and values or other properties.
|
||||
*/
|
||||
public static Property<String> concat(Property<?> property, Object... values) {
|
||||
StringBuilder expression = new StringBuilder(50);
|
||||
expression.append("concat(").append(property.toString());
|
||||
for (Object value : values) {
|
||||
expression.append(",").append(sqlConcatString(value));
|
||||
}
|
||||
expression.append(")");
|
||||
return Property.of(expression.toString());
|
||||
}
|
||||
|
||||
private static String sqlConcatString(Object value) {
|
||||
if (value instanceof Property) {
|
||||
return value.toString();
|
||||
} else {
|
||||
return sqlQuote(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows numbers to be unquoted.
|
||||
*/
|
||||
private static String sqlValue(Object value) {
|
||||
if (value instanceof Property || value instanceof Number) {
|
||||
return value.toString();
|
||||
} else {
|
||||
return sqlQuote(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SQL quoted escaping single quotes.
|
||||
*/
|
||||
private static String sqlQuote(Object value) {
|
||||
return "'" + String.valueOf(value).replace("'", "''") + "'";
|
||||
}
|
||||
|
||||
// ---- Operators ---- //
|
||||
|
||||
/**
|
||||
* Equal to - for a property and value.
|
||||
*/
|
||||
public static <T> Expression eq(Property<T> property, T value) {
|
||||
return Expr.eq(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Equal to - for a property and sub-query.
|
||||
*/
|
||||
public static <T> Expression eq(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.in(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Equal to or null - for a property and value.
|
||||
*/
|
||||
public static <T> Expression eqOrNull(Property<T> property, T value) {
|
||||
return Expr.factory().eqOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not equal to - for a property and value.
|
||||
*/
|
||||
public static <T> Expression ne(Property<T> property, T value) {
|
||||
return Expr.ne(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not equal to - for a property and sub-query.
|
||||
*/
|
||||
public static <T> Expression ne(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.ne(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater than - for a property and value.
|
||||
*/
|
||||
public static <T> Expression gt(Property<T> property, T value) {
|
||||
return Expr.gt(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater than - for a property and sub-query.
|
||||
*/
|
||||
public static <T> Expression gt(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.gt(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater than or null - for a property and value.
|
||||
*/
|
||||
public static <T> Expression gtOrNull(Property<T> property, T value) {
|
||||
return Expr.factory().gtOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater than or equal to - for a property and value.
|
||||
*/
|
||||
public static <T> Expression ge(Property<T> property, T value) {
|
||||
return Expr.ge(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater than or equal to - for a property and sub-query.
|
||||
*/
|
||||
public static <T> Expression ge(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.ge(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater than or null - for a property and value.
|
||||
*/
|
||||
public static <T> Expression geOrNull(Property<T> property, T value) {
|
||||
return Expr.factory().geOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Less than - for a property and value.
|
||||
*/
|
||||
public static <T> Expression lt(Property<T> property, T value) {
|
||||
return Expr.lt(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Less than - for a property and sub-query.
|
||||
*/
|
||||
public static <T> Expression lt(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.lt(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Less than or null - for a property and value.
|
||||
*/
|
||||
public static <T> Expression ltOrNull(Property<T> property, T value) {
|
||||
return Expr.factory().ltOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater than or equal to - for a property and value.
|
||||
*/
|
||||
public static <T> Expression le(Property<T> property, T value) {
|
||||
return Expr.le(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater than or equal to - for a property and sub-query.
|
||||
*/
|
||||
public static <T> Expression le(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.le(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater than or equal to or null - for a property and value.
|
||||
*/
|
||||
public static <T> Expression leOrNull(Property<T> property, T value) {
|
||||
return Expr.factory().leOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* In range - for a property and values.
|
||||
*/
|
||||
public static <T> Expression inRange(Property<T> property, T lowValue, T highValue) {
|
||||
return Expr.factory().inRange(property.toString(), lowValue, highValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* In range - for properties and a value.
|
||||
*/
|
||||
public static <T> Expression inRange(Property<T> lowProperty, Property<T> highProperty, T value) {
|
||||
return Expr.factory().inRangeWith(lowProperty.toString(), highProperty.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* In range - for properties.
|
||||
*/
|
||||
public static <T> Expression inRange(Property<T> lowProperty, Property<T> property, Property<T> highProperty) {
|
||||
return Expr.factory().inRangeWithProperties(lowProperty.toString(), property.toString(), highProperty.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* In - for a given property and collection of values.
|
||||
*/
|
||||
public static <T> Expression in(Property<T> property, Collection<T> value) {
|
||||
return Expr.in(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* In - for a given property and sub-query.
|
||||
*/
|
||||
public static <T> Expression in(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.in(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* In or empty - for a given property and collection of values.
|
||||
*/
|
||||
public static <T> Expression inOrEmpty(Property<T> property, Collection<T> value) {
|
||||
return Expr.inOrEmpty(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not In - for a given property and collection of values.
|
||||
*/
|
||||
public static <T> Expression notIn(Property<T> property, Collection<T> value) {
|
||||
return Expr.factory().notIn(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not In - for a given property and sub-query.
|
||||
*/
|
||||
public static <T> Expression notIn(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.factory().notIn(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
// ---- String operators ---- //
|
||||
|
||||
/**
|
||||
* Like - for a given property and value.
|
||||
*/
|
||||
public static Expression like(Property<String> property, String value) {
|
||||
return Expr.like(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Case-insensitive Like - for a given property and value.
|
||||
*/
|
||||
public static Expression ilike(Property<String> property, String value) {
|
||||
return Expr.ilike(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts with - for a given property and value.
|
||||
*/
|
||||
public static Expression startsWith(Property<String> property, String value) {
|
||||
return Expr.startsWith(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Case-insensitive starts with - for a given property and value.
|
||||
*/
|
||||
public static Expression istartsWith(Property<String> property, String value) {
|
||||
return Expr.istartsWith(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains - for a given property and value.
|
||||
*/
|
||||
public static Expression contains(Property<String> property, String value) {
|
||||
return Expr.contains(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Case-insensitive contains - for a given property and value.
|
||||
*/
|
||||
public static Expression icontains(Property<String> property, String value) {
|
||||
return Expr.icontains(property.toString(), value);
|
||||
}
|
||||
}
|
||||
@@ -144,6 +144,35 @@ public interface Transaction extends AutoCloseable {
|
||||
*/
|
||||
void rollback(Throwable e) throws PersistenceException;
|
||||
|
||||
/**
|
||||
* Performs a rollback on the underlying JDBC connection with the intention of
|
||||
* continuing to use this same transaction and performing a commit or rollback
|
||||
* later to complete the transaction.
|
||||
* <p>
|
||||
* Typically used when catching {@link DuplicateKeyException} where we wish to
|
||||
* rollback work done at that point but carry on processing using the transaction.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* try (Transaction txn = database.beginTransaction()) {
|
||||
*
|
||||
* try {
|
||||
* ...
|
||||
* database.save(bean);
|
||||
* database.flush();
|
||||
* } catch (DuplicateKeyException e) {
|
||||
* // carry on processing using the transaction
|
||||
* txn.rollbackAndContinue();
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* txn.commit();
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
void rollbackAndContinue();
|
||||
|
||||
/**
|
||||
* Set when we want nested transactions to use Savepoint's.
|
||||
* <p>
|
||||
|
||||
@@ -14,7 +14,7 @@ package io.ebean;
|
||||
*
|
||||
* int rows = DB.update(Customer.class)
|
||||
* .set("status", Customer.Status.ACTIVE)
|
||||
* .set("updtime", new Timestamp(System.currentTimeMillis()))
|
||||
* .set("whenUpdated", Instant.now())
|
||||
* .where()
|
||||
* .gt("id", 1000)
|
||||
* .update();
|
||||
@@ -25,6 +25,20 @@ package io.ebean;
|
||||
* update o_customer set status=?, updtime=? where id > ?
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h4>Example: Using query bean</h4>
|
||||
* <pre>{@code
|
||||
*
|
||||
* var cust = QCustomer.alias();
|
||||
*
|
||||
* int rows = new QCustomer()
|
||||
* .id.gt(1000)
|
||||
* .asUpdate()
|
||||
* .set(cust.status, Customer.Status.COMPLETE)
|
||||
* .set(cust.whenUpdated, Instant.now())
|
||||
* .update();
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* Note that if the where() clause contains a join then the SQL update changes to use a
|
||||
* <code> WHERE ID IN () </code> form.
|
||||
@@ -40,7 +54,7 @@ package io.ebean;
|
||||
*
|
||||
* int rows = DB.update(Customer.class)
|
||||
* .set("status", Customer.Status.ACTIVE)
|
||||
* .set("updtime", new Timestamp(System.currentTimeMillis()))
|
||||
* .set("whenUpdated", Instant.now())
|
||||
* .where()
|
||||
* .eq("status", Customer.Status.NEW)
|
||||
* .eq("billingAddress.country", nz)
|
||||
@@ -73,7 +87,7 @@ public interface UpdateQuery<T> {
|
||||
*
|
||||
* int rows = DB.update(Customer.class)
|
||||
* .set("status", Customer.Status.ACTIVE)
|
||||
* .set("updtime", new Timestamp(System.currentTimeMillis()))
|
||||
* .set("whenUpdated", Instant.now())
|
||||
* .where()
|
||||
* .gt("id", 1000)
|
||||
* .update();
|
||||
@@ -85,6 +99,27 @@ public interface UpdateQuery<T> {
|
||||
*/
|
||||
UpdateQuery<T> set(String property, Object value);
|
||||
|
||||
/**
|
||||
* Set the value of a property.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* var cust = QCustomer.alias();
|
||||
*
|
||||
* int rows = new QCustomer()
|
||||
* .id.gt(1000)
|
||||
* .asUpdate()
|
||||
* .set(cust.status, Customer.Status.COMPLETE)
|
||||
* .set(cust.whenUpdated, Instant.now())
|
||||
* .update();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param property The bean property to be set
|
||||
* @param value The value to set the property to
|
||||
*/
|
||||
<P> UpdateQuery<T> set(Query.Property<P> property, P value);
|
||||
|
||||
/**
|
||||
* Set the property to be null.
|
||||
* <p>
|
||||
@@ -102,6 +137,13 @@ public interface UpdateQuery<T> {
|
||||
*/
|
||||
UpdateQuery<T> setNull(String property);
|
||||
|
||||
/**
|
||||
* Set the property to be null.
|
||||
*
|
||||
* @param property The bean property to be set
|
||||
*/
|
||||
UpdateQuery<T> setNull(Query.Property<?> property);
|
||||
|
||||
/**
|
||||
* Set using a property expression that does not need any bind values.
|
||||
* <p>
|
||||
|
||||
@@ -77,12 +77,12 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
|
||||
/**
|
||||
* Return the bean that owns this collection.
|
||||
*/
|
||||
EntityBean getOwnerBean();
|
||||
EntityBean owner();
|
||||
|
||||
/**
|
||||
* Return the bean property name this collection represents.
|
||||
*/
|
||||
String getPropertyName();
|
||||
String propertyName();
|
||||
|
||||
/**
|
||||
* Check after the lazy load that the underlying collection is not null
|
||||
@@ -99,7 +99,7 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
|
||||
* This is so that the filter can be applied on refresh.
|
||||
* </p>
|
||||
*/
|
||||
ExpressionList<?> getFilterMany();
|
||||
ExpressionList<?> filterMany();
|
||||
|
||||
/**
|
||||
* Set the filter that was used in building this collection.
|
||||
@@ -154,7 +154,7 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
|
||||
/**
|
||||
* Returns the underlying collection of beans from the Set, Map or List.
|
||||
*/
|
||||
Collection<E> getActualDetails();
|
||||
Collection<E> actualDetails();
|
||||
|
||||
/**
|
||||
* Returns the underlying entries so for Maps this is a collection of
|
||||
@@ -162,7 +162,7 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
|
||||
* <p>
|
||||
* For maps this returns the entrySet as we need the keys of the map.
|
||||
*/
|
||||
Collection<?> getActualEntries();
|
||||
Collection<?> actualEntries();
|
||||
|
||||
/**
|
||||
* return true if there are real rows held. Return false is this is using
|
||||
@@ -195,7 +195,7 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
|
||||
/**
|
||||
* Return the current modify listening mode. Can be null for on newly created beans.
|
||||
*/
|
||||
ModifyListenMode getModifyListening();
|
||||
ModifyListenMode modifyListening();
|
||||
|
||||
/**
|
||||
* Add an object to the additions list.
|
||||
@@ -217,13 +217,13 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
|
||||
* Return the list of objects added to the list set or map. These will used to
|
||||
* insert rows into the intersection table of a ManyToMany.
|
||||
*/
|
||||
Set<E> getModifyAdditions();
|
||||
Set<E> modifyAdditions();
|
||||
|
||||
/**
|
||||
* Return the list of objects removed from the list set or map. These will
|
||||
* used to delete rows from the intersection table of a ManyToMany.
|
||||
*/
|
||||
Set<E> getModifyRemovals();
|
||||
Set<E> modifyRemovals();
|
||||
|
||||
/**
|
||||
* Reset the set of additions and deletions. This is called after the
|
||||
@@ -239,5 +239,5 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
|
||||
/**
|
||||
* Return a shallow copy of this collection that is modifiable.
|
||||
*/
|
||||
BeanCollection<E> getShallowCopy();
|
||||
BeanCollection<E> shallowCopy();
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ public interface BeanLoader {
|
||||
/**
|
||||
* Return the name of the associated Database.
|
||||
*/
|
||||
String getName();
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Invoke the lazy loading for this bean.
|
||||
|
||||
@@ -8,15 +8,15 @@ public interface CallOrigin {
|
||||
/**
|
||||
* Return the top element. Typically the top stack element with class and line.
|
||||
*/
|
||||
String getTopElement();
|
||||
String top();
|
||||
|
||||
/**
|
||||
* Return the full description of the call origin.
|
||||
*/
|
||||
String getFullDescription();
|
||||
String description();
|
||||
|
||||
/**
|
||||
* Compute and return an origin key based on the query hash.
|
||||
*/
|
||||
String getOriginKey(int queryHash);
|
||||
String key(int queryHash);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebean.bean;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static io.ebean.util.EncodeB64.enc;
|
||||
|
||||
@@ -27,20 +28,27 @@ public final class CallStack implements Serializable, CallOrigin {
|
||||
|
||||
private final String zeroHash;
|
||||
private final String pathHash;
|
||||
private final StackTraceElement[] callStack;
|
||||
private final Object[] callStack;
|
||||
private final int hc;
|
||||
|
||||
public CallStack(StackTraceElement[] callStack, int zeroHash, int pathHash) {
|
||||
public CallStack(Object[] callStack, int zeroHash, int pathHash) {
|
||||
this.callStack = callStack;
|
||||
this.hc = computeHashCode();
|
||||
this.zeroHash = enc(zeroHash);
|
||||
this.pathHash = enc(pathHash);
|
||||
}
|
||||
|
||||
public CallStack(List<StackWalker.StackFrame> frames) {
|
||||
this.callStack = frames.toArray(new Object[0]);
|
||||
this.hc = computeHashCode();
|
||||
this.zeroHash = enc(callStack[0].toString().hashCode());
|
||||
this.pathHash = enc(hc);
|
||||
}
|
||||
|
||||
private int computeHashCode() {
|
||||
int hc = 0;
|
||||
for (StackTraceElement element : callStack) {
|
||||
hc = 92821 * hc + element.hashCode();
|
||||
for (Object element : callStack) {
|
||||
hc = 92821 * hc + element.toString().hashCode();
|
||||
}
|
||||
return hc;
|
||||
}
|
||||
@@ -71,7 +79,7 @@ public final class CallStack implements Serializable, CallOrigin {
|
||||
* Return the first element of the call stack.
|
||||
*/
|
||||
@Override
|
||||
public String getTopElement() {
|
||||
public String top() {
|
||||
return callStack[0].toString();
|
||||
}
|
||||
|
||||
@@ -79,7 +87,7 @@ public final class CallStack implements Serializable, CallOrigin {
|
||||
* Return the call stack lines appended with the given newLine string.
|
||||
*/
|
||||
@Override
|
||||
public String getFullDescription() {
|
||||
public String description() {
|
||||
StringBuilder sb = new StringBuilder(400);
|
||||
for (int i = 0; i < callStack.length; i++) {
|
||||
if (i > 0) {
|
||||
@@ -91,7 +99,7 @@ public final class CallStack implements Serializable, CallOrigin {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginKey(int queryHash) {
|
||||
public String key(int queryHash) {
|
||||
return enc(queryHash) + "." + zeroHash + "." + pathHash;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,17 +6,23 @@ import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This is the object associated to every entity bean using byte code enhancement.
|
||||
* <p>
|
||||
* This provides per property state such as loaded state, changed state, original values
|
||||
* as well as bean level dirty state etc.
|
||||
*/
|
||||
public interface EntityBeanIntercept extends Serializable {
|
||||
|
||||
/**
|
||||
* Return the 'owning' entity bean.
|
||||
*/
|
||||
EntityBean getOwner();
|
||||
EntityBean owner();
|
||||
|
||||
/**
|
||||
* Return the persistenceContext.
|
||||
*/
|
||||
PersistenceContext getPersistenceContext();
|
||||
PersistenceContext persistenceContext();
|
||||
|
||||
/**
|
||||
* Set the persistenceContext.
|
||||
@@ -31,7 +37,7 @@ public interface EntityBeanIntercept extends Serializable {
|
||||
/**
|
||||
* Return the ownerId (IdClass).
|
||||
*/
|
||||
Object getOwnerId();
|
||||
Object ownerId();
|
||||
|
||||
/**
|
||||
* Set the ownerId (IdClass).
|
||||
@@ -41,12 +47,12 @@ public interface EntityBeanIntercept extends Serializable {
|
||||
/**
|
||||
* Return the owning bean for an embedded bean.
|
||||
*/
|
||||
Object getEmbeddedOwner();
|
||||
Object embeddedOwner();
|
||||
|
||||
/**
|
||||
* Return the property index (for the parent) of this embedded bean.
|
||||
*/
|
||||
int getEmbeddedOwnerIndex();
|
||||
int embeddedOwnerIndex();
|
||||
|
||||
/**
|
||||
* Clear the getter callback.
|
||||
@@ -223,7 +229,7 @@ public interface EntityBeanIntercept extends Serializable {
|
||||
/**
|
||||
* Return the original value that was changed via an update.
|
||||
*/
|
||||
Object getOrigValue(int propertyIndex);
|
||||
Object origValue(int propertyIndex);
|
||||
|
||||
/**
|
||||
* Finds the index position of a given property. Returns -1 if the
|
||||
@@ -234,12 +240,12 @@ public interface EntityBeanIntercept extends Serializable {
|
||||
/**
|
||||
* Return the property name for the given property.
|
||||
*/
|
||||
String getProperty(int propertyIndex);
|
||||
String property(int propertyIndex);
|
||||
|
||||
/**
|
||||
* Return the number of properties.
|
||||
*/
|
||||
int getPropertyLength();
|
||||
int propertyLength();
|
||||
|
||||
/**
|
||||
* Set the loaded state of the property given it's name.
|
||||
@@ -282,8 +288,14 @@ public interface EntityBeanIntercept extends Serializable {
|
||||
*/
|
||||
void markPropertyAsChanged(int propertyIndex);
|
||||
|
||||
/**
|
||||
* Set the changed state for the given property.
|
||||
*/
|
||||
void setChangedProperty(int propertyIndex);
|
||||
|
||||
/**
|
||||
* Set the changed and loaded state for the given property.
|
||||
*/
|
||||
void setChangeLoaded(int propertyIndex);
|
||||
|
||||
/**
|
||||
@@ -291,6 +303,9 @@ public interface EntityBeanIntercept extends Serializable {
|
||||
*/
|
||||
void setEmbeddedPropertyDirty(int propertyIndex);
|
||||
|
||||
/**
|
||||
* Set the original value for the property.
|
||||
*/
|
||||
void setOriginalValue(int propertyIndex, Object value);
|
||||
|
||||
/**
|
||||
@@ -306,17 +321,17 @@ public interface EntityBeanIntercept extends Serializable {
|
||||
/**
|
||||
* Return the set of property names for a partially loaded bean.
|
||||
*/
|
||||
Set<String> getLoadedPropertyNames();
|
||||
Set<String> loadedPropertyNames();
|
||||
|
||||
/**
|
||||
* Return the array of flags indicating the dirty properties.
|
||||
*/
|
||||
boolean[] getDirtyProperties();
|
||||
boolean[] dirtyProperties();
|
||||
|
||||
/**
|
||||
* Return the set of dirty properties.
|
||||
*/
|
||||
Set<String> getDirtyPropertyNames();
|
||||
Set<String> dirtyPropertyNames();
|
||||
|
||||
/**
|
||||
* Recursively add dirty properties.
|
||||
@@ -331,7 +346,7 @@ public interface EntityBeanIntercept extends Serializable {
|
||||
/**
|
||||
* Return a map of dirty properties with their new and old values.
|
||||
*/
|
||||
Map<String, ValuePair> getDirtyValues();
|
||||
Map<String, ValuePair> dirtyValues();
|
||||
|
||||
/**
|
||||
* Recursively add dirty properties.
|
||||
@@ -346,7 +361,7 @@ public interface EntityBeanIntercept extends Serializable {
|
||||
/**
|
||||
* Return a dirty property hash taking into account embedded beans.
|
||||
*/
|
||||
StringBuilder getDirtyPropertyKey();
|
||||
StringBuilder dirtyPropertyKey();
|
||||
|
||||
/**
|
||||
* Add and return a dirty property hash.
|
||||
@@ -356,19 +371,22 @@ public interface EntityBeanIntercept extends Serializable {
|
||||
/**
|
||||
* Return a loaded property hash.
|
||||
*/
|
||||
StringBuilder getLoadedPropertyKey();
|
||||
StringBuilder loadedPropertyKey();
|
||||
|
||||
boolean[] getLoaded();
|
||||
/**
|
||||
* Return the loaded state for all the properties.
|
||||
*/
|
||||
boolean[] loaded();
|
||||
|
||||
/**
|
||||
* Return the index of the property that triggered the lazy load.
|
||||
*/
|
||||
int getLazyLoadPropertyIndex();
|
||||
int lazyLoadPropertyIndex();
|
||||
|
||||
/**
|
||||
* Return the property that triggered the lazy load.
|
||||
*/
|
||||
String getLazyLoadProperty();
|
||||
String lazyLoadProperty();
|
||||
|
||||
/**
|
||||
* Load the bean when it is a reference.
|
||||
@@ -385,6 +403,9 @@ public interface EntityBeanIntercept extends Serializable {
|
||||
*/
|
||||
void initialisedMany(int propertyIndex);
|
||||
|
||||
/**
|
||||
* Invoke the PreGetterCallback if it has been set due to getter for the given property.
|
||||
*/
|
||||
void preGetterCallback(int propertyIndex);
|
||||
|
||||
/**
|
||||
@@ -402,8 +423,14 @@ public interface EntityBeanIntercept extends Serializable {
|
||||
*/
|
||||
void preSetterMany(boolean interceptField, int propertyIndex, Object oldValue, Object newValue);
|
||||
|
||||
/**
|
||||
* Set the property changed state, bean dirtyState and property original value.
|
||||
*/
|
||||
void setChangedPropertyValue(int propertyIndex, boolean setDirtyState, Object origValue);
|
||||
|
||||
/**
|
||||
* Set the dirty state on the bean.
|
||||
*/
|
||||
void setDirtyStatus();
|
||||
|
||||
/**
|
||||
@@ -470,7 +497,7 @@ public interface EntityBeanIntercept extends Serializable {
|
||||
/**
|
||||
* Return the sort order value for an order column.
|
||||
*/
|
||||
int getSortOrder();
|
||||
int sortOrder();
|
||||
|
||||
/**
|
||||
* Set the sort order value for an order column.
|
||||
@@ -482,6 +509,9 @@ public interface EntityBeanIntercept extends Serializable {
|
||||
*/
|
||||
void setDeletedFromCollection(boolean deletedFromCollection);
|
||||
|
||||
/**
|
||||
* Return true if the bean was orphan deleted from a collection.
|
||||
*/
|
||||
boolean isOrphanDelete();
|
||||
|
||||
/**
|
||||
@@ -492,9 +522,12 @@ public interface EntityBeanIntercept extends Serializable {
|
||||
/**
|
||||
* Returns the loadErrors.
|
||||
*/
|
||||
Map<String, Exception> getLoadErrors();
|
||||
Map<String, Exception> loadErrors();
|
||||
|
||||
boolean isChangedProp(int i);
|
||||
/**
|
||||
* Return true if the property has its changed state set.
|
||||
*/
|
||||
boolean isChangedProp(int propertyIndex);
|
||||
|
||||
/**
|
||||
* Return the MutableValueInfo for the given property or null.
|
||||
|
||||
@@ -6,21 +6,36 @@ import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* EntityBeanIntercept optimised for read only use.
|
||||
* <p>
|
||||
* For the read only use this intercept doesn't need to hold any state that is normally
|
||||
* required for updates such as per property changed, loaded, dirty state, original values
|
||||
* bean state etc.
|
||||
*/
|
||||
public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
|
||||
private final EntityBean owner;
|
||||
|
||||
/**
|
||||
* Create with a given entity.
|
||||
*/
|
||||
public InterceptReadOnly(Object ownerBean) {
|
||||
this.owner = (EntityBean) ownerBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityBean getOwner() {
|
||||
public String toString() {
|
||||
return "InterceptReadOnly{" + owner + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityBean owner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceContext getPersistenceContext() {
|
||||
public PersistenceContext persistenceContext() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -35,7 +50,7 @@ public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOwnerId() {
|
||||
public Object ownerId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -45,12 +60,12 @@ public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getEmbeddedOwner() {
|
||||
public Object embeddedOwner() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEmbeddedOwnerIndex() {
|
||||
public int embeddedOwnerIndex() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -215,7 +230,7 @@ public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOrigValue(int propertyIndex) {
|
||||
public Object origValue(int propertyIndex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -225,12 +240,12 @@ public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProperty(int propertyIndex) {
|
||||
public String property(int propertyIndex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPropertyLength() {
|
||||
public int propertyLength() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -305,17 +320,17 @@ public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getLoadedPropertyNames() {
|
||||
public Set<String> loadedPropertyNames() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] getDirtyProperties() {
|
||||
public boolean[] dirtyProperties() {
|
||||
return new boolean[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getDirtyPropertyNames() {
|
||||
public Set<String> dirtyPropertyNames() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@@ -330,7 +345,7 @@ public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ValuePair> getDirtyValues() {
|
||||
public Map<String, ValuePair> dirtyValues() {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
@@ -345,7 +360,7 @@ public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuilder getDirtyPropertyKey() {
|
||||
public StringBuilder dirtyPropertyKey() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -355,22 +370,22 @@ public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuilder getLoadedPropertyKey() {
|
||||
public StringBuilder loadedPropertyKey() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] getLoaded() {
|
||||
public boolean[] loaded() {
|
||||
return new boolean[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLazyLoadPropertyIndex() {
|
||||
public int lazyLoadPropertyIndex() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLazyLoadProperty() {
|
||||
public String lazyLoadProperty() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -480,7 +495,7 @@ public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSortOrder() {
|
||||
public int sortOrder() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -505,7 +520,7 @@ public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Exception> getLoadErrors() {
|
||||
public Map<String, Exception> loadErrors() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
* <p>
|
||||
* This provides the mechanisms to support deferred fetching of reference beans
|
||||
* and oldValues generation for concurrency checking.
|
||||
* </p>
|
||||
*/
|
||||
public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
|
||||
@@ -32,30 +31,23 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
private static final int STATE_LOADED = 2;
|
||||
|
||||
/**
|
||||
* Used when a bean is partially filled.
|
||||
* Used when a bean is partially loaded.
|
||||
*/
|
||||
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.
|
||||
* Flags indicating if a property is a dirty embedded bean. Used to distinguish between an
|
||||
* embedded bean being completely overwritten vs one with embedded properties that are 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 final ReentrantLock lock = new ReentrantLock();
|
||||
private transient NodeUsageCollector nodeUsageCollector;
|
||||
private transient PersistenceContext persistenceContext;
|
||||
private transient BeanLoader beanLoader;
|
||||
@@ -78,10 +70,9 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
private boolean readOnly;
|
||||
private boolean dirty;
|
||||
/**
|
||||
* Flag set to disable lazy loading - typically for SQL "report" type entity beans.
|
||||
* Flag set to disable lazy loading.
|
||||
*/
|
||||
private boolean disableLazyLoad;
|
||||
|
||||
/**
|
||||
* Flag set when lazy loading failed due to the underlying bean being deleted in the DB.
|
||||
*/
|
||||
@@ -107,7 +98,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
private MutableValueNext[] mutableNext;
|
||||
|
||||
/**
|
||||
* Create a intercept with a given entity.
|
||||
* Create with a given entity.
|
||||
*/
|
||||
public InterceptReadWrite(Object ownerBean) {
|
||||
this.owner = (EntityBean) ownerBean;
|
||||
@@ -123,12 +114,30 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityBean getOwner() {
|
||||
public String toString() {
|
||||
return "InterceptReadWrite@" + hashCode() + "{state=" + state +
|
||||
(dirty ? " dirty;" : "") +
|
||||
(forceUpdate ? " forceUpdate;" : "") +
|
||||
(readOnly ? " readOnly;" : "") +
|
||||
(disableLazyLoad ? " disableLazyLoad;" : "") +
|
||||
(lazyLoadFailure ? " lazyLoadFailure;" : "") +
|
||||
(fullyLoadedBean ? " fullyLoadedBean;" : "") +
|
||||
(loadedFromCache ? " loadedFromCache;" : "") +
|
||||
", pc=" + System.identityHashCode(persistenceContext) +
|
||||
", flags=" + Arrays.toString(flags) +
|
||||
(lazyLoadProperty > -1 ? (", lazyLoadProperty=" + lazyLoadProperty) : "") +
|
||||
", loader=" + beanLoader +
|
||||
(ownerId != null ? (", ownerId=" + ownerId) : "") +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityBean owner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceContext getPersistenceContext() {
|
||||
public PersistenceContext persistenceContext() {
|
||||
return persistenceContext;
|
||||
}
|
||||
|
||||
@@ -143,7 +152,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOwnerId() {
|
||||
public Object ownerId() {
|
||||
return ownerId;
|
||||
}
|
||||
|
||||
@@ -153,12 +162,12 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getEmbeddedOwner() {
|
||||
public Object embeddedOwner() {
|
||||
return embeddedOwner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEmbeddedOwnerIndex() {
|
||||
public int embeddedOwnerIndex() {
|
||||
return embeddedOwnerIndex;
|
||||
}
|
||||
|
||||
@@ -182,13 +191,13 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
public void setBeanLoader(BeanLoader beanLoader, PersistenceContext ctx) {
|
||||
this.beanLoader = beanLoader;
|
||||
this.persistenceContext = ctx;
|
||||
this.ebeanServerName = beanLoader.getName();
|
||||
this.ebeanServerName = beanLoader.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanLoader(BeanLoader beanLoader) {
|
||||
this.beanLoader = beanLoader;
|
||||
this.ebeanServerName = beanLoader.getName();
|
||||
this.ebeanServerName = beanLoader.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -371,8 +380,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
@Override
|
||||
public void setEmbeddedLoaded(Object embeddedBean) {
|
||||
if (embeddedBean instanceof EntityBean) {
|
||||
EntityBean eb = (EntityBean) embeddedBean;
|
||||
eb._ebean_getIntercept().setLoaded();
|
||||
((EntityBean) embeddedBean)._ebean_getIntercept().setLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -392,7 +400,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getOrigValue(int propertyIndex) {
|
||||
public Object origValue(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());
|
||||
@@ -405,7 +413,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
|
||||
@Override
|
||||
public int findProperty(String propertyName) {
|
||||
String[] names = owner._ebean_getPropertyNames();
|
||||
final String[] names = owner._ebean_getPropertyNames();
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
if (names[i].equals(propertyName)) {
|
||||
return i;
|
||||
@@ -415,7 +423,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProperty(int propertyIndex) {
|
||||
public String property(int propertyIndex) {
|
||||
if (propertyIndex == -1) {
|
||||
return null;
|
||||
}
|
||||
@@ -423,13 +431,13 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPropertyLength() {
|
||||
public int propertyLength() {
|
||||
return flags.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPropertyLoaded(String propertyName, boolean loaded) {
|
||||
int position = findProperty(propertyName);
|
||||
final int position = findProperty(propertyName);
|
||||
if (position == -1) {
|
||||
throw new IllegalArgumentException("Property " + propertyName + " not found");
|
||||
}
|
||||
@@ -523,23 +531,23 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getLoadedPropertyNames() {
|
||||
public Set<String> loadedPropertyNames() {
|
||||
if (fullyLoadedBean) {
|
||||
return null;
|
||||
}
|
||||
Set<String> props = new LinkedHashSet<>();
|
||||
final Set<String> props = new LinkedHashSet<>();
|
||||
for (int i = 0; i < flags.length; i++) {
|
||||
if ((flags[i] & FLAG_LOADED_PROP) != 0) {
|
||||
props.add(getProperty(i));
|
||||
props.add(property(i));
|
||||
}
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] getDirtyProperties() {
|
||||
int len = getPropertyLength();
|
||||
boolean[] dirties = new boolean[len];
|
||||
public boolean[] dirtyProperties() {
|
||||
final int len = propertyLength();
|
||||
final boolean[] dirties = new boolean[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
// this, or an embedded property has been changed - recurse
|
||||
dirties[i] = (flags[i] & (FLAG_CHANGED_PROP + FLAG_EMBEDDED_DIRTY)) != 0;
|
||||
@@ -548,31 +556,31 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getDirtyPropertyNames() {
|
||||
Set<String> props = new LinkedHashSet<>();
|
||||
public Set<String> dirtyPropertyNames() {
|
||||
final Set<String> props = new LinkedHashSet<>();
|
||||
addDirtyPropertyNames(props, null);
|
||||
return props;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDirtyPropertyNames(Set<String> props, String prefix) {
|
||||
int len = getPropertyLength();
|
||||
final int len = propertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (isChangedProp(i)) {
|
||||
// the property has been changed on this bean
|
||||
props.add((prefix == null ? getProperty(i) : prefix + getProperty(i)));
|
||||
props.add((prefix == null ? property(i) : prefix + property(i)));
|
||||
} else if ((flags[i] & FLAG_EMBEDDED_DIRTY) != 0) {
|
||||
// an embedded property has been changed - recurse
|
||||
EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
|
||||
embeddedBean._ebean_getIntercept().addDirtyPropertyNames(props, getProperty(i) + ".");
|
||||
final EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
|
||||
embeddedBean._ebean_getIntercept().addDirtyPropertyNames(props, property(i) + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDirtyProperty(Set<String> propertyNames) {
|
||||
String[] names = owner._ebean_getPropertyNames();
|
||||
int len = getPropertyLength();
|
||||
final String[] names = owner._ebean_getPropertyNames();
|
||||
final int len = propertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (isChangedProp(i)) {
|
||||
if (propertyNames.contains(names[i])) {
|
||||
@@ -588,46 +596,46 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ValuePair> getDirtyValues() {
|
||||
Map<String, ValuePair> dirtyValues = new LinkedHashMap<>();
|
||||
public Map<String, ValuePair> dirtyValues() {
|
||||
final Map<String, ValuePair> dirtyValues = new LinkedHashMap<>();
|
||||
addDirtyPropertyValues(dirtyValues, null);
|
||||
return dirtyValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDirtyPropertyValues(Map<String, ValuePair> dirtyValues, String prefix) {
|
||||
int len = getPropertyLength();
|
||||
final int len = propertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
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);
|
||||
Object oldVal = getOrigValue(i);
|
||||
final String propName = (prefix == null ? property(i) : prefix + property(i));
|
||||
final Object newVal = owner._ebean_getField(i);
|
||||
final Object oldVal = origValue(i);
|
||||
if (notEqual(oldVal, newVal)) {
|
||||
dirtyValues.put(propName, new ValuePair(newVal, oldVal));
|
||||
}
|
||||
} else if ((flags[i] & FLAG_EMBEDDED_DIRTY) != 0) {
|
||||
// an embedded property has been changed - recurse
|
||||
EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
|
||||
embeddedBean._ebean_getIntercept().addDirtyPropertyValues(dirtyValues, getProperty(i) + ".");
|
||||
final EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
|
||||
embeddedBean._ebean_getIntercept().addDirtyPropertyValues(dirtyValues, property(i) + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDirtyPropertyValues(BeanDiffVisitor visitor) {
|
||||
int len = getPropertyLength();
|
||||
final int len = propertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (isChangedProp(i)) {
|
||||
// the property has been changed on this bean
|
||||
Object newVal = owner._ebean_getField(i);
|
||||
Object oldVal = getOrigValue(i);
|
||||
final Object newVal = owner._ebean_getField(i);
|
||||
final Object oldVal = origValue(i);
|
||||
if (notEqual(oldVal, newVal)) {
|
||||
visitor.visit(i, newVal, oldVal);
|
||||
}
|
||||
} else if ((flags[i] & FLAG_EMBEDDED_DIRTY) != 0) {
|
||||
// an embedded property has been changed - recurse
|
||||
EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
|
||||
final EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
|
||||
visitor.visitPush(i);
|
||||
embeddedBean._ebean_getIntercept().addDirtyPropertyValues(visitor);
|
||||
visitor.visitPop();
|
||||
@@ -636,8 +644,8 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuilder getDirtyPropertyKey() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
public StringBuilder dirtyPropertyKey() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
addDirtyPropertyKey(sb);
|
||||
return sb;
|
||||
}
|
||||
@@ -647,24 +655,23 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
if (sortOrder > 0) {
|
||||
sb.append("s,");
|
||||
}
|
||||
int len = getPropertyLength();
|
||||
final int len = propertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
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
|
||||
EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
|
||||
sb.append(i).append('[');
|
||||
embeddedBean._ebean_getIntercept().addDirtyPropertyKey(sb);
|
||||
((EntityBean) owner._ebean_getField(i))._ebean_getIntercept().addDirtyPropertyKey(sb);
|
||||
sb.append(']');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuilder getLoadedPropertyKey() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int len = getPropertyLength();
|
||||
public StringBuilder loadedPropertyKey() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final int len = propertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (isLoadedProperty(i)) {
|
||||
sb.append(i).append(',');
|
||||
@@ -674,8 +681,8 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] getLoaded() {
|
||||
boolean[] ret = new boolean[flags.length];
|
||||
public boolean[] loaded() {
|
||||
final boolean[] ret = new boolean[flags.length];
|
||||
for (int i = 0; i < ret.length; i++) {
|
||||
ret[i] = (flags[i] & FLAG_LOADED_PROP) != 0;
|
||||
}
|
||||
@@ -683,13 +690,13 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLazyLoadPropertyIndex() {
|
||||
public int lazyLoadPropertyIndex() {
|
||||
return lazyLoadProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLazyLoadProperty() {
|
||||
return getProperty(lazyLoadProperty);
|
||||
public String lazyLoadProperty() {
|
||||
return property(lazyLoadProperty);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -699,7 +706,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
if (beanLoader == null) {
|
||||
final Database database = DB.byName(ebeanServerName);
|
||||
if (database == null) {
|
||||
throw new PersistenceException("Database [" + ebeanServerName + "] was not found?");
|
||||
throw new PersistenceException(ebeanServerName == null ? "No registered default server" : "Database [" + ebeanServerName + "] is not registered");
|
||||
}
|
||||
// For stand alone reference bean or after deserialisation lazy load
|
||||
// using the ebeanServer. Synchronise only on the bean.
|
||||
@@ -727,14 +734,14 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
}
|
||||
if (lazyLoadFailure) {
|
||||
// failed when batch lazy loaded by another bean in the batch
|
||||
throw new EntityNotFoundException("(Lazy) loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted");
|
||||
throw new EntityNotFoundException("(Lazy) loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted. BeanLoader: " + beanLoader);
|
||||
}
|
||||
if (lazyLoadProperty == -1) {
|
||||
lazyLoadProperty = loadProperty;
|
||||
loader.loadBean(this);
|
||||
if (lazyLoadFailure) {
|
||||
// failed when lazy loading this bean
|
||||
throw new EntityNotFoundException("Lazy loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted.");
|
||||
throw new EntityNotFoundException("Lazy loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted. BeanLoader: " + beanLoader);
|
||||
}
|
||||
// bean should be loaded and intercepting now. setLoaded() has
|
||||
// been called by the lazy loading mechanism
|
||||
@@ -829,7 +836,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
loadBean(propertyIndex);
|
||||
}
|
||||
if (nodeUsageCollector != null) {
|
||||
nodeUsageCollector.addUsed(getProperty(propertyIndex));
|
||||
nodeUsageCollector.addUsed(property(propertyIndex));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -978,7 +985,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSortOrder() {
|
||||
public int sortOrder() {
|
||||
return sortOrder;
|
||||
}
|
||||
|
||||
@@ -1007,19 +1014,19 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Exception> getLoadErrors() {
|
||||
public Map<String, Exception> loadErrors() {
|
||||
if (loadErrors == null) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
Map<String, Exception> ret = null;
|
||||
int len = getPropertyLength();
|
||||
int len = propertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
Exception loadError = loadErrors[i];
|
||||
final Exception loadError = loadErrors[i];
|
||||
if (loadError != null) {
|
||||
if (ret == null) {
|
||||
ret = new LinkedHashMap<>();
|
||||
}
|
||||
ret.put(getProperty(i), loadError);
|
||||
ret.put(property(i), loadError);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
||||
@@ -8,7 +8,6 @@ import java.util.Objects;
|
||||
* <p>
|
||||
* It represents a location relative to the root of an object graph and specific
|
||||
* to a query and call stack hash.
|
||||
* </p>
|
||||
*/
|
||||
public final class ObjectGraphNode implements Serializable {
|
||||
|
||||
@@ -17,7 +16,7 @@ public final class ObjectGraphNode implements Serializable {
|
||||
/**
|
||||
* Identifies the origin.
|
||||
*/
|
||||
private final ObjectGraphOrigin originQueryPoint;
|
||||
private final ObjectGraphOrigin origin;
|
||||
|
||||
/**
|
||||
* The path relative to the root.
|
||||
@@ -28,26 +27,26 @@ public final class ObjectGraphNode implements Serializable {
|
||||
* Create at a sub level.
|
||||
*/
|
||||
public ObjectGraphNode(ObjectGraphNode parent, String path) {
|
||||
this.originQueryPoint = parent.getOriginQueryPoint();
|
||||
this.path = parent.getChildPath(path);
|
||||
this.origin = parent.origin();
|
||||
this.path = parent.childPath(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an the root level.
|
||||
*/
|
||||
public ObjectGraphNode(ObjectGraphOrigin originQueryPoint, String path) {
|
||||
this.originQueryPoint = originQueryPoint;
|
||||
public ObjectGraphNode(ObjectGraphOrigin origin, String path) {
|
||||
this.origin = origin;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the origin query point.
|
||||
*/
|
||||
public ObjectGraphOrigin getOriginQueryPoint() {
|
||||
return originQueryPoint;
|
||||
public ObjectGraphOrigin origin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
private String getChildPath(String childPath) {
|
||||
private String childPath(String childPath) {
|
||||
if (path == null) {
|
||||
return childPath;
|
||||
} else if (childPath == null) {
|
||||
@@ -60,18 +59,18 @@ public final class ObjectGraphNode implements Serializable {
|
||||
/**
|
||||
* Return the path relative to the root.
|
||||
*/
|
||||
public String getPath() {
|
||||
public String path() {
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "origin:" + originQueryPoint + " path[" + path + "]";
|
||||
return "origin:" + origin + " path[" + path + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hc = 92821 * originQueryPoint.hashCode();
|
||||
int hc = 92821 * origin.hashCode();
|
||||
hc = 92821 * hc + (path == null ? 0 : path.hashCode());
|
||||
return hc;
|
||||
}
|
||||
@@ -87,6 +86,6 @@ public final class ObjectGraphNode implements Serializable {
|
||||
|
||||
ObjectGraphNode e = (ObjectGraphNode) obj;
|
||||
return (Objects.equals(e.path, path))
|
||||
&& e.originQueryPoint.equals(originQueryPoint);
|
||||
&& e.origin.equals(origin);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,38 +28,38 @@ public final class ObjectGraphOrigin implements Serializable {
|
||||
this.callOrigin = callOrigin;
|
||||
this.beanType = beanType;
|
||||
this.queryHash = queryHash;
|
||||
this.key = callOrigin.getOriginKey(queryHash);
|
||||
this.key = callOrigin.key(queryHash);
|
||||
}
|
||||
|
||||
/**
|
||||
* The key includes the queryPlan hash and the callStack hash. This becomes
|
||||
* the unique identifier for a query point.
|
||||
*/
|
||||
public String getKey() {
|
||||
public String key() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of bean the query is fetching.
|
||||
*/
|
||||
public String getBeanType() {
|
||||
public String beanType() {
|
||||
return beanType;
|
||||
}
|
||||
|
||||
/**
|
||||
* The call stack involved.
|
||||
*/
|
||||
public CallOrigin getCallOrigin() {
|
||||
public CallOrigin callOrigin() {
|
||||
return callOrigin;
|
||||
}
|
||||
|
||||
public String getTopElement() {
|
||||
return callOrigin.getTopElement();
|
||||
public String top() {
|
||||
return callOrigin.top();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "key[" + key + "] type[" + beanType + "] " + callOrigin.getTopElement();
|
||||
return "key[" + key + "] type[" + beanType + "] " + callOrigin.top();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,7 +19,7 @@ public abstract class SingleBeanLoader implements BeanLoader {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
public String name() {
|
||||
return database.name();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package io.ebean.bean;
|
||||
|
||||
import io.ebean.common.BeanMap;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
@@ -112,7 +110,7 @@ public final class ToStringBuilder {
|
||||
} else {
|
||||
String content = String.valueOf(value);
|
||||
if (content.length() > TRIM_LENGTH) {
|
||||
content = content.substring(0, TRIM_LENGTH) + " <trimmed>";
|
||||
content = content.substring(0, TRIM_LENGTH) + " (trimmed)";
|
||||
}
|
||||
sb.append(content);
|
||||
if (sb.length() >= MAX_TOTAL_CONTENT) {
|
||||
|
||||
@@ -6,7 +6,6 @@ import java.util.Set;
|
||||
* Notification event that dependent tables have been modified.
|
||||
* <p>
|
||||
* This is sent to other interested servers (in the cluster).
|
||||
* </p>
|
||||
*/
|
||||
public class ServerCacheNotification {
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import io.ebean.config.DatabaseConfig;
|
||||
* Plugin that provides a ServerCacheNotify implementation.
|
||||
* <p>
|
||||
* Is supplied this will be used to send the ServerCacheNotification event to other cluster members.
|
||||
* </p>
|
||||
*/
|
||||
public interface ServerCacheNotifyPlugin {
|
||||
|
||||
|
||||
@@ -29,6 +29,11 @@ public class ServerCacheStatistics {
|
||||
|
||||
protected long evictCount;
|
||||
|
||||
protected long gcCount;
|
||||
protected long idleCount;
|
||||
protected long ttlCount;
|
||||
protected long lruCount;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
//noinspection StringBufferReplaceableByString
|
||||
@@ -43,6 +48,10 @@ public class ServerCacheStatistics {
|
||||
sb.append(" remove:").append(removeCount);
|
||||
sb.append(" clear:").append(clearCount);
|
||||
sb.append(" evict:").append(evictCount);
|
||||
sb.append(" gc:").append(gcCount);
|
||||
sb.append(" idle:").append(idleCount);
|
||||
sb.append(" ttl:").append(ttlCount);
|
||||
sb.append(" lru:").append(lruCount);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@@ -191,4 +200,37 @@ public class ServerCacheStatistics {
|
||||
return evictCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the count of entries removed by the garbage collection.
|
||||
*/
|
||||
public void setGcCount(long gcCount) {
|
||||
this.gcCount = gcCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of entries removed by the garbage collection.
|
||||
*/
|
||||
public long getGcCount() {
|
||||
return gcCount;
|
||||
}
|
||||
|
||||
public void setIdleCount(long idleCount) {
|
||||
this.idleCount = idleCount;
|
||||
}
|
||||
|
||||
public long getIdleCount() {
|
||||
return idleCount;
|
||||
}
|
||||
|
||||
public void setTtlCount(long ttlCount) {
|
||||
this.ttlCount = ttlCount;
|
||||
}
|
||||
|
||||
public long getTtlCount() {
|
||||
return ttlCount;
|
||||
}
|
||||
|
||||
public void setLruCount(long lruCount) {
|
||||
this.lruCount = lruCount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,39 +17,28 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
private static final long serialVersionUID = 3365725236140187588L;
|
||||
|
||||
protected final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
protected boolean readOnly;
|
||||
|
||||
protected boolean disableLazyLoad;
|
||||
|
||||
/**
|
||||
* The Database this is associated with. (used for lazy fetch).
|
||||
*/
|
||||
protected transient BeanCollectionLoader loader;
|
||||
|
||||
protected transient ExpressionList<?> filterMany;
|
||||
|
||||
/**
|
||||
* Flag set when registered with the batch loading context.
|
||||
*/
|
||||
protected boolean registeredWithLoadContext;
|
||||
|
||||
protected String ebeanServerName;
|
||||
|
||||
/**
|
||||
* The owning bean (used for lazy fetch).
|
||||
*/
|
||||
protected EntityBean ownerBean;
|
||||
|
||||
/**
|
||||
* The name of this property in the owning bean (used for lazy fetch).
|
||||
*/
|
||||
protected String propertyName;
|
||||
|
||||
protected ModifyHolder<E> modifyHolder;
|
||||
|
||||
protected ModifyListenMode modifyListenMode;
|
||||
|
||||
protected boolean modifyListening;
|
||||
|
||||
/**
|
||||
@@ -70,17 +59,17 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityBean getOwnerBean() {
|
||||
public EntityBean owner() {
|
||||
return ownerBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPropertyName() {
|
||||
public String propertyName() {
|
||||
return propertyName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<?> getFilterMany() {
|
||||
public ExpressionList<?> filterMany() {
|
||||
return filterMany;
|
||||
}
|
||||
|
||||
@@ -126,8 +115,7 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
|
||||
void checkReadOnly() {
|
||||
if (readOnly) {
|
||||
String msg = "This collection is in ReadOnly mode";
|
||||
throw new IllegalStateException(msg);
|
||||
throw new IllegalStateException("This collection is in ReadOnly mode");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +129,7 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModifyListenMode getModifyListening() {
|
||||
public ModifyListenMode modifyListening() {
|
||||
return modifyListenMode;
|
||||
}
|
||||
|
||||
@@ -194,7 +182,7 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<E> getModifyAdditions() {
|
||||
public Set<E> modifyAdditions() {
|
||||
if (modifyHolder == null) {
|
||||
return null;
|
||||
} else {
|
||||
@@ -203,7 +191,7 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<E> getModifyRemovals() {
|
||||
public Set<E> modifyRemovals() {
|
||||
if (modifyHolder == null) {
|
||||
return null;
|
||||
} else {
|
||||
@@ -225,7 +213,7 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all relevant properties for a clone. See {@link #getShallowCopy()}
|
||||
* Copies all relevant properties for a clone. See {@link #shallowCopy()}
|
||||
*/
|
||||
protected void setFromOriginal(AbstractBeanCollection<E> other) {
|
||||
this.disableLazyLoad = other.disableLazyLoad;
|
||||
|
||||
@@ -3,15 +3,10 @@ package io.ebean.common;
|
||||
import io.ebean.bean.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* List capable of lazy loading.
|
||||
* List capable of lazy loading and modification awareness.
|
||||
*/
|
||||
public final class BeanList<E> extends AbstractBeanCollection<E> implements List<E>, BeanCollectionAdd {
|
||||
|
||||
@@ -73,7 +68,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
}
|
||||
list.addAll((Collection<? extends E>) other.getActualDetails());
|
||||
list.addAll((Collection<? extends E>) other.actualDetails());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -150,7 +145,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
* Set the actual underlying list.
|
||||
* <p>
|
||||
* This is primarily for the deferred fetching function.
|
||||
* </p>
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setActualList(List<?> list) {
|
||||
@@ -160,17 +154,17 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
/**
|
||||
* Return the actual underlying list.
|
||||
*/
|
||||
public List<E> getActualList() {
|
||||
public List<E> actualList() {
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<E> getActualDetails() {
|
||||
public Collection<E> actualDetails() {
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<?> getActualEntries() {
|
||||
public Collection<?> actualEntries() {
|
||||
return list;
|
||||
}
|
||||
|
||||
@@ -206,12 +200,11 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
* Specifically obj does not need to be a BeanList but any list. This does not
|
||||
* use the FindMany, fetchedMaxRows or finishedFetch properties in the equals
|
||||
* test.
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
public boolean equals(Object other) {
|
||||
init();
|
||||
return list.equals(obj);
|
||||
return list.equals(other);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -244,40 +237,40 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(E o) {
|
||||
public boolean add(E bean) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
if (list.add(o)) {
|
||||
modifyAddition(o);
|
||||
if (list.add(bean)) {
|
||||
modifyAddition(bean);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return list.add(o);
|
||||
return list.add(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends E> c) {
|
||||
public boolean addAll(Collection<? extends E> beans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
// all elements in c are added (no contains checking)
|
||||
getModifyHolder().modifyAdditionAll(c);
|
||||
getModifyHolder().modifyAdditionAll(beans);
|
||||
}
|
||||
return list.addAll(c);
|
||||
return list.addAll(beans);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, Collection<? extends E> c) {
|
||||
public boolean addAll(int index, Collection<? extends E> beans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
// all elements in c are added (no contains checking)
|
||||
getModifyHolder().modifyAdditionAll(c);
|
||||
getModifyHolder().modifyAdditionAll(beans);
|
||||
}
|
||||
return list.addAll(index, c);
|
||||
return list.addAll(index, beans);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -287,23 +280,23 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
// and fetch just the Id's
|
||||
initClear();
|
||||
if (modifyListening) {
|
||||
for (E aList : list) {
|
||||
getModifyHolder().modifyRemoval(aList);
|
||||
for (E element : list) {
|
||||
getModifyHolder().modifyRemoval(element);
|
||||
}
|
||||
}
|
||||
list.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
public boolean contains(Object bean) {
|
||||
init();
|
||||
return list.contains(o);
|
||||
return list.contains(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
public boolean containsAll(Collection<?> beans) {
|
||||
init();
|
||||
return list.containsAll(c);
|
||||
return list.containsAll(beans);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -313,9 +306,9 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(Object o) {
|
||||
public int indexOf(Object bean) {
|
||||
init();
|
||||
return list.indexOf(o);
|
||||
return list.indexOf(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -327,31 +320,29 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
init();
|
||||
if (isReadOnly()) {
|
||||
if (readOnly) {
|
||||
return new ReadOnlyListIterator<>(list.listIterator());
|
||||
}
|
||||
if (modifyListening) {
|
||||
Iterator<E> it = list.iterator();
|
||||
return new ModifyIterator<>(this, it);
|
||||
return new ModifyIterator<>(this, list.iterator());
|
||||
}
|
||||
return list.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lastIndexOf(Object o) {
|
||||
public int lastIndexOf(Object bean) {
|
||||
init();
|
||||
return list.lastIndexOf(o);
|
||||
return list.lastIndexOf(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator<E> listIterator() {
|
||||
init();
|
||||
if (isReadOnly()) {
|
||||
if (readOnly) {
|
||||
return new ReadOnlyListIterator<>(list.listIterator());
|
||||
}
|
||||
if (modifyListening) {
|
||||
ListIterator<E> it = list.listIterator();
|
||||
return new ModifyListIterator<>(this, it);
|
||||
return new ModifyListIterator<>(this, list.listIterator());
|
||||
}
|
||||
return list.listIterator();
|
||||
}
|
||||
@@ -359,12 +350,11 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
@Override
|
||||
public ListIterator<E> listIterator(int index) {
|
||||
init();
|
||||
if (isReadOnly()) {
|
||||
if (readOnly) {
|
||||
return new ReadOnlyListIterator<>(list.listIterator(index));
|
||||
}
|
||||
if (modifyListening) {
|
||||
ListIterator<E> it = list.listIterator(index);
|
||||
return new ModifyListIterator<>(this, it);
|
||||
return new ModifyListIterator<>(this, list.listIterator(index));
|
||||
}
|
||||
return list.listIterator(index);
|
||||
}
|
||||
@@ -389,17 +379,17 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
public boolean remove(Object bean) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
boolean isRemove = list.remove(o);
|
||||
boolean isRemove = list.remove(bean);
|
||||
if (isRemove) {
|
||||
modifyRemoval(o);
|
||||
modifyRemoval(bean);
|
||||
}
|
||||
return isRemove;
|
||||
}
|
||||
return list.remove(o);
|
||||
return list.remove(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -463,7 +453,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
@Override
|
||||
public List<E> subList(int fromIndex, int toIndex) {
|
||||
init();
|
||||
if (isReadOnly()) {
|
||||
if (readOnly) {
|
||||
return Collections.unmodifiableList(list.subList(fromIndex, toIndex));
|
||||
}
|
||||
if (modifyListening) {
|
||||
@@ -479,13 +469,13 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T[] toArray(T[] a) {
|
||||
public <T> T[] toArray(T[] array) {
|
||||
init();
|
||||
//noinspection SuspiciousToArrayCall
|
||||
return list.toArray(a);
|
||||
return list.toArray(array);
|
||||
}
|
||||
|
||||
private static class ReadOnlyListIterator<E> implements ListIterator<E>, Serializable {
|
||||
private static final class ReadOnlyListIterator<E> implements ListIterator<E>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 3097271091406323699L;
|
||||
|
||||
@@ -543,7 +533,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollection<E> getShallowCopy() {
|
||||
public BeanCollection<E> shallowCopy() {
|
||||
BeanList<E> copy = new BeanList<>(new CopyOnFirstWriteList<>(list));
|
||||
copy.setFromOriginal(this);
|
||||
return copy;
|
||||
|
||||
@@ -5,14 +5,10 @@ import io.ebean.bean.BeanCollectionLoader;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.ToStringBuilder;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Map capable of lazy loading.
|
||||
* Map capable of lazy loading and modification aware.
|
||||
*/
|
||||
public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Map<K, E> {
|
||||
|
||||
@@ -71,7 +67,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
public void loadFrom(BeanCollection<?> other) {
|
||||
BeanMap<K, E> otherMap = (BeanMap<K, E>) other;
|
||||
internalPutNull();
|
||||
map.putAll(otherMap.getActualMap());
|
||||
map.putAll(otherMap.actualMap());
|
||||
}
|
||||
|
||||
public void internalPutNull() {
|
||||
@@ -175,7 +171,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
/**
|
||||
* Return the actual underlying map.
|
||||
*/
|
||||
public Map<K, E> getActualMap() {
|
||||
public Map<K, E> actualMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -183,7 +179,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
* Returns the collection of beans (map values).
|
||||
*/
|
||||
@Override
|
||||
public Collection<E> getActualDetails() {
|
||||
public Collection<E> actualDetails() {
|
||||
return map.values();
|
||||
}
|
||||
|
||||
@@ -191,7 +187,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
* Returns the map entrySet.
|
||||
*/
|
||||
@Override
|
||||
public Collection<?> getActualEntries() {
|
||||
public Collection<?> actualEntries() {
|
||||
return map.entrySet();
|
||||
}
|
||||
|
||||
@@ -247,7 +243,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
@Override
|
||||
public Set<Entry<K, E>> entrySet() {
|
||||
init();
|
||||
if (isReadOnly()) {
|
||||
if (readOnly) {
|
||||
return Collections.unmodifiableSet(map.entrySet());
|
||||
}
|
||||
return modifyListening ? new ModifyEntrySet<>(this, map.entrySet()) : map.entrySet();
|
||||
@@ -268,7 +264,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
init();
|
||||
if (isReadOnly()) {
|
||||
if (readOnly) {
|
||||
return Collections.unmodifiableSet(map.keySet());
|
||||
}
|
||||
return modifyListening ? new ModifyKeySet<>(this, map.keySet()) : map.keySet();
|
||||
@@ -339,14 +335,14 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
@Override
|
||||
public Collection<E> values() {
|
||||
init();
|
||||
if (isReadOnly()) {
|
||||
if (readOnly) {
|
||||
return Collections.unmodifiableCollection(map.values());
|
||||
}
|
||||
return modifyListening ? new ModifyCollection<>(this, map.values()) : map.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollection<E> getShallowCopy() {
|
||||
public BeanCollection<E> shallowCopy() {
|
||||
BeanMap<K, E> copy = new BeanMap<>(new LinkedHashMap<>(map));
|
||||
copy.setFromOriginal(this);
|
||||
return copy;
|
||||
|
||||
@@ -9,7 +9,7 @@ import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Set capable of lazy loading.
|
||||
* Set capable of lazy loading and modification aware.
|
||||
*/
|
||||
public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E>, BeanCollectionAdd {
|
||||
|
||||
@@ -67,7 +67,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
if (set == null) {
|
||||
set = new LinkedHashSet<>();
|
||||
}
|
||||
set.addAll((Collection<? extends E>) other.getActualDetails());
|
||||
set.addAll((Collection<? extends E>) other.actualDetails());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -155,17 +155,17 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
/**
|
||||
* Return the actual underlying set.
|
||||
*/
|
||||
public Set<E> getActualSet() {
|
||||
public Set<E> actualSet() {
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<E> getActualDetails() {
|
||||
public Collection<E> actualDetails() {
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<?> getActualEntries() {
|
||||
public Collection<?> actualEntries() {
|
||||
return set;
|
||||
}
|
||||
|
||||
@@ -210,27 +210,27 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
// -----------------------------------------------------//
|
||||
|
||||
@Override
|
||||
public boolean add(E o) {
|
||||
public boolean add(E bean) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
if (set.add(o)) {
|
||||
modifyAddition(o);
|
||||
if (set.add(bean)) {
|
||||
modifyAddition(bean);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return set.add(o);
|
||||
return set.add(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends E> addCollection) {
|
||||
public boolean addAll(Collection<? extends E> beans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
boolean changed = false;
|
||||
for (E bean : addCollection) {
|
||||
for (E bean : beans) {
|
||||
if (set.add(bean)) {
|
||||
// register the addition of the bean
|
||||
modifyAddition(bean);
|
||||
@@ -239,7 +239,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
return set.addAll(addCollection);
|
||||
return set.addAll(beans);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -255,15 +255,15 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
public boolean contains(Object bean) {
|
||||
init();
|
||||
return set.contains(o);
|
||||
return set.contains(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
public boolean containsAll(Collection<?> beans) {
|
||||
init();
|
||||
return set.containsAll(c);
|
||||
return set.containsAll(beans);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -275,7 +275,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
init();
|
||||
if (isReadOnly()) {
|
||||
if (readOnly) {
|
||||
return new ReadOnlyIterator<>(set.iterator());
|
||||
}
|
||||
if (modifyListening) {
|
||||
@@ -285,17 +285,17 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
public boolean remove(Object bean) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
if (set.remove(o)) {
|
||||
modifyRemoval(o);
|
||||
if (set.remove(bean)) {
|
||||
modifyRemoval(bean);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return set.remove(o);
|
||||
return set.remove(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -349,13 +349,13 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T[] toArray(T[] a) {
|
||||
public <T> T[] toArray(T[] array) {
|
||||
init();
|
||||
//noinspection SuspiciousToArrayCall
|
||||
return set.toArray(a);
|
||||
return set.toArray(array);
|
||||
}
|
||||
|
||||
private static class ReadOnlyIterator<E> implements Iterator<E>, Serializable {
|
||||
private static final class ReadOnlyIterator<E> implements Iterator<E>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 2577697326745352605L;
|
||||
|
||||
@@ -382,7 +382,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollection<E> getShallowCopy() {
|
||||
public BeanCollection<E> shallowCopy() {
|
||||
BeanSet<E> copy = new BeanSet<>(new LinkedHashSet<>(set));
|
||||
copy.setFromOriginal(this);
|
||||
return copy;
|
||||
|
||||
@@ -237,7 +237,7 @@ public abstract class AbstractNamingConvention implements NamingConvention {
|
||||
}
|
||||
buffer.append(rhsTableName);
|
||||
|
||||
int maxTableNameLength = databasePlatform.getMaxTableNameLength();
|
||||
int maxTableNameLength = databasePlatform.maxTableNameLength();
|
||||
|
||||
// maxConstraintNameLength is used as the max table name length.
|
||||
if (buffer.length() > maxTableNameLength) {
|
||||
|
||||
@@ -6,6 +6,10 @@ import java.util.concurrent.Callable;
|
||||
* BackgroundExecutorWrapper that can be used to wrap tasks that are sent to background (i.e. another thread).
|
||||
* It should copy all necessary thread-local variables. See {@link MdcBackgroundExecutorWrapper} for implementation details.
|
||||
*
|
||||
* Note: only tasks that are executed immediately (submit, execute) are wrapped. Periodic or scheduled tasks are not wrapped,
|
||||
* as these may keep copied variables in memory either forever or until the scheduled task is finished.
|
||||
* The caller is responsible to handle these cases.
|
||||
*
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*/
|
||||
public interface BackgroundExecutorWrapper {
|
||||
|
||||
@@ -16,6 +16,7 @@ import io.ebean.event.changelog.ChangeLogPrepare;
|
||||
import io.ebean.event.changelog.ChangeLogRegister;
|
||||
import io.ebean.event.readaudit.ReadAuditLogger;
|
||||
import io.ebean.event.readaudit.ReadAuditPrepare;
|
||||
import io.ebean.meta.MetricNamingMatch;
|
||||
import io.ebean.util.StringHelper;
|
||||
|
||||
import javax.persistence.EnumType;
|
||||
@@ -24,19 +25,18 @@ import java.time.Clock;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* The configuration used for creating a Database.
|
||||
* <p>
|
||||
* Used to programmatically construct an Database and optionally register it
|
||||
* with the DB singleton.
|
||||
* </p>
|
||||
* <p>
|
||||
* If you just use DB thout this programmatic configuration Ebean will read
|
||||
* the application.properties file and take the configuration from there. This usually
|
||||
* includes searching the class path and automatically registering any entity
|
||||
* classes and listeners etc.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* DatabaseConfig config = new DatabaseConfig();
|
||||
@@ -56,7 +56,6 @@ import java.util.*;
|
||||
* <p>
|
||||
* Note that DatabaseConfigProvider provides a standard Java ServiceLoader mechanism that can
|
||||
* be used to apply configuration to the DatabaseConfig.
|
||||
* </p>
|
||||
*
|
||||
* @author emcgreal
|
||||
* @author rbygrave
|
||||
@@ -115,19 +114,19 @@ public class DatabaseConfig {
|
||||
private TenantCatalogProvider tenantCatalogProvider;
|
||||
|
||||
/**
|
||||
* When true will load entity classes via ModuleInfoLoader.
|
||||
* When true will load entity classes via EntityClassRegister.
|
||||
* <p>
|
||||
* NB: ModuleInfoLoader implementations are generated by querybean generator.
|
||||
* NB: EntityClassRegister implementations are generated by querybean generator.
|
||||
* Having this on and registering entity classes means we don't need to manually
|
||||
* write that code or use classpath scanning to find entity classes.
|
||||
*/
|
||||
private boolean loadModuleInfo = true;
|
||||
|
||||
/**
|
||||
* List of interesting classes such as entities, embedded, ScalarTypes,
|
||||
* Listeners, Finders, Controllers etc.
|
||||
* Interesting classes such as entities, embedded, ScalarTypes,
|
||||
* Listeners, Finders, Controllers, AttributeConverters etc.
|
||||
*/
|
||||
private List<Class<?>> classes = new ArrayList<>();
|
||||
private Set<Class<?>> classes = new HashSet<>();
|
||||
|
||||
/**
|
||||
* The packages that are searched for interesting classes. Only used when
|
||||
@@ -527,11 +526,6 @@ public class DatabaseConfig {
|
||||
|
||||
private ProfilingConfig profilingConfig = new ProfilingConfig();
|
||||
|
||||
/**
|
||||
* Controls the default order by id setting of queries. See {@link Query#orderById(boolean)}
|
||||
*/
|
||||
private boolean defaultOrderById;
|
||||
|
||||
/**
|
||||
* The mappingLocations for searching xml mapping.
|
||||
*/
|
||||
@@ -546,6 +540,8 @@ public class DatabaseConfig {
|
||||
|
||||
private String dumpMetricsOptions;
|
||||
|
||||
private Function<String, String> metricNaming = MetricNamingMatch.INSTANCE;
|
||||
|
||||
/**
|
||||
* Construct a Database Configuration for programmatically creating an Database.
|
||||
*/
|
||||
@@ -594,24 +590,8 @@ public class DatabaseConfig {
|
||||
this.slowQueryListener = slowQueryListener;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deprecated - look to have explicit order by. Sets the default orderById setting for queries.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setDefaultOrderById(boolean defaultOrderById) {
|
||||
this.defaultOrderById = defaultOrderById;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default orderById setting for queries.
|
||||
*/
|
||||
public boolean isDefaultOrderById() {
|
||||
return defaultOrderById;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a service object into configuration such that it can be passed to a plugin.
|
||||
* Put a service object into configuration such that it can be used by ebean or a plugin.
|
||||
* <p>
|
||||
* For example, put IgniteConfiguration in to be passed to the Ignite plugin.
|
||||
*/
|
||||
@@ -619,6 +599,23 @@ public class DatabaseConfig {
|
||||
serviceObject.put(key, configObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a service object into configuration such that it can be used by ebean or a plugin.
|
||||
* <p>
|
||||
* For example, put IgniteConfiguration in to be passed to the Ignite plugin.
|
||||
* You can also override some SPI objects that should be used for that Database. Currently, the following
|
||||
* objects are possible.
|
||||
* <ul>
|
||||
* <li>DataSourceAlertFactory (e.g. add different alert factories for different ebean instances)</li>
|
||||
* <li>DocStoreFactory</li>
|
||||
* <li>SlowQueryListener (e.g. add custom query listener for a certain ebean instance)</li>
|
||||
* <li>ServerCacheNotifyPlugin</li>
|
||||
* </ul>
|
||||
*/
|
||||
public <T> void putServiceObject(Class<T> iface, T configObject) {
|
||||
serviceObject.put(serviceObjectKey(iface), configObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the service object given the key.
|
||||
*/
|
||||
@@ -627,7 +624,7 @@ public class DatabaseConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* Put a service object into configuration such that it can be passed to a plugin.
|
||||
* Put a service object into configuration such that it can be used by ebean or a plugin.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -652,7 +649,7 @@ public class DatabaseConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by plugins to obtain service objects.
|
||||
* Used by ebean or plugins to obtain service objects.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -2302,19 +2299,15 @@ public class DatabaseConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* Programmatically add classes (typically entities) that this server should
|
||||
* use.
|
||||
* Programmatically add classes (typically entities) that this server should use.
|
||||
* <p>
|
||||
* The class can be an Entity, Embedded type, ScalarType, BeanPersistListener,
|
||||
* BeanFinder or BeanPersistController.
|
||||
* <p>
|
||||
* If no classes are specified then the classes are found automatically via
|
||||
* searching the class path.
|
||||
* <p>
|
||||
* Alternatively the classes can be added via {@link #setClasses(List)}.
|
||||
*
|
||||
* @param cls the entity type (or other type) that should be registered by this
|
||||
* database.
|
||||
* @param cls the entity type (or other type) that should be registered by this database.
|
||||
*/
|
||||
public void addClass(Class<?> cls) {
|
||||
classes.add(cls);
|
||||
@@ -2323,7 +2316,7 @@ public class DatabaseConfig {
|
||||
/**
|
||||
* Register all the classes (typically entity classes).
|
||||
*/
|
||||
public void addAll(List<Class<?>> classList) {
|
||||
public void addAll(Collection<Class<?>> classList) {
|
||||
if (classList != null && !classList.isEmpty()) {
|
||||
classes.addAll(classList);
|
||||
}
|
||||
@@ -2365,15 +2358,26 @@ public class DatabaseConfig {
|
||||
* <p>
|
||||
* Alternatively the classes can contain added via {@link #addClass(Class)}.
|
||||
*/
|
||||
public void setClasses(List<Class<?>> classes) {
|
||||
this.classes = classes;
|
||||
public void setClasses(Collection<Class<?>> classes) {
|
||||
this.classes = new HashSet<>(classes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the classes registered for this database. Typically this includes
|
||||
* Return the classes registered for this database. Typically, this includes
|
||||
* entities and perhaps listeners.
|
||||
*/
|
||||
public List<Class<?>> getClasses() {
|
||||
public Set<Class<?>> classes() {
|
||||
return classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to classes().
|
||||
* <p>
|
||||
* Sorry if returning Set rather than List breaks code but it feels safer to
|
||||
* do that than a subtle change to return a shallow copy which you will not detect.
|
||||
*/
|
||||
@Deprecated
|
||||
public Set<Class<?>> getClasses() {
|
||||
return classes;
|
||||
}
|
||||
|
||||
@@ -2742,8 +2746,6 @@ public class DatabaseConfig {
|
||||
this.classLoadConfig = classLoadConfig;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Load settings from application.properties, application.yaml and other sources.
|
||||
* <p>
|
||||
@@ -2888,7 +2890,7 @@ public class DatabaseConfig {
|
||||
serverCachePlugin = p.createInstance(ServerCachePlugin.class, "serverCachePlugin", serverCachePlugin);
|
||||
|
||||
String packagesProp = p.get("search.packages", p.get("packages", null));
|
||||
packages = getSearchList(packagesProp, packages);
|
||||
packages = searchList(packagesProp, packages);
|
||||
|
||||
skipCacheAfterWrite = p.getBoolean("skipCacheAfterWrite", skipCacheAfterWrite);
|
||||
updateAllPropertiesInBatch = p.getBoolean("updateAllPropertiesInBatch", updateAllPropertiesInBatch);
|
||||
@@ -2917,7 +2919,6 @@ public class DatabaseConfig {
|
||||
jdbcFetchSizeFindEach = p.getInt("jdbcFetchSizeFindEach", jdbcFetchSizeFindEach);
|
||||
jdbcFetchSizeFindList = p.getInt("jdbcFetchSizeFindList", jdbcFetchSizeFindList);
|
||||
databasePlatformName = p.get("databasePlatformName", databasePlatformName);
|
||||
defaultOrderById = p.getBoolean("defaultOrderById", defaultOrderById);
|
||||
|
||||
uuidVersion = p.getEnum(UuidVersion.class, "uuidVersion", uuidVersion);
|
||||
uuidStateFile = p.get("uuidStateFile", uuidStateFile);
|
||||
@@ -2964,10 +2965,10 @@ public class DatabaseConfig {
|
||||
tenantCatalogProvider = p.createInstance(TenantCatalogProvider.class, "tenant.catalogProvider", tenantCatalogProvider);
|
||||
tenantSchemaProvider = p.createInstance(TenantSchemaProvider.class, "tenant.schemaProvider", tenantSchemaProvider);
|
||||
tenantPartitionColumn = p.get("tenant.partitionColumn", tenantPartitionColumn);
|
||||
classes = getClasses(p);
|
||||
classes = readClasses(p);
|
||||
|
||||
String mappingsProp = p.get("mappingLocations", null);
|
||||
mappingLocations = getSearchList(mappingsProp, mappingLocations);
|
||||
mappingLocations = searchList(mappingsProp, mappingLocations);
|
||||
}
|
||||
|
||||
private NamingConvention createNamingConvention(PropertiesWrapper properties, NamingConvention namingConvention) {
|
||||
@@ -2981,13 +2982,13 @@ public class DatabaseConfig {
|
||||
* @param properties the properties
|
||||
* @return the classes
|
||||
*/
|
||||
private List<Class<?>> getClasses(PropertiesWrapper properties) {
|
||||
private Set<Class<?>> readClasses(PropertiesWrapper properties) {
|
||||
String classNames = properties.get("classes", null);
|
||||
if (classNames == null) {
|
||||
return classes;
|
||||
}
|
||||
|
||||
List<Class<?>> classList = new ArrayList<>();
|
||||
Set<Class<?>> classList = new HashSet<>();
|
||||
String[] split = StringHelper.splitNames(classNames);
|
||||
for (String cn : split) {
|
||||
if (!"class".equalsIgnoreCase(cn)) {
|
||||
@@ -3002,7 +3003,7 @@ public class DatabaseConfig {
|
||||
return classList;
|
||||
}
|
||||
|
||||
private List<String> getSearchList(String searchNames, List<String> defaultValue) {
|
||||
private List<String> searchList(String searchNames, List<String> defaultValue) {
|
||||
if (searchNames != null) {
|
||||
String[] entries = StringHelper.splitNames(searchNames);
|
||||
List<String> hitList = new ArrayList<>(entries.length);
|
||||
@@ -3020,7 +3021,7 @@ public class DatabaseConfig {
|
||||
public PersistBatch appliedPersistBatchOnCascade() {
|
||||
if (persistBatchOnCascade == PersistBatch.INHERIT) {
|
||||
// use the platform default (ALL except SQL Server which has NONE)
|
||||
return databasePlatform.getPersistBatchOnCascade();
|
||||
return databasePlatform.persistBatchOnCascade();
|
||||
}
|
||||
return persistBatchOnCascade;
|
||||
}
|
||||
@@ -3376,13 +3377,21 @@ public class DatabaseConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if entity classes should be loaded and registered via ModuleInfoLoader.
|
||||
* Return true if entity classes should be loaded and registered via EntityClassRegister.
|
||||
* <p>
|
||||
* When false we either register entity classes via application code or use classpath
|
||||
* scanning to find and register entity classes.
|
||||
*/
|
||||
public boolean isLoadModuleInfo() {
|
||||
return loadModuleInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to isLoadModuleInfo().
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isAutoLoadModuleInfo() {
|
||||
return loadModuleInfo && classes.isEmpty();
|
||||
return loadModuleInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3396,6 +3405,20 @@ public class DatabaseConfig {
|
||||
this.loadModuleInfo = loadModuleInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the naming convention to apply to metrics names.
|
||||
*/
|
||||
public Function<String, String> getMetricNaming() {
|
||||
return metricNaming;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the naming convention to apply to metrics names.
|
||||
*/
|
||||
public void setMetricNaming(Function<String, String> metricNaming) {
|
||||
this.metricNaming = metricNaming;
|
||||
}
|
||||
|
||||
public enum UuidVersion {
|
||||
VERSION4,
|
||||
VERSION1,
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ import java.util.List;
|
||||
/**
|
||||
* Loads and returns entity classes to register with Ebean databases.
|
||||
*/
|
||||
public interface ModuleInfoLoader {
|
||||
public interface EntityClassRegister {
|
||||
|
||||
/**
|
||||
* Return entity classes to register for a named DB (not default DB).
|
||||
+5
-10
@@ -1,20 +1,16 @@
|
||||
package io.ebean.platform.db2;
|
||||
package io.ebean.config.dbplatform;
|
||||
|
||||
import io.ebean.config.dbplatform.SqlLimitRequest;
|
||||
import io.ebean.config.dbplatform.SqlLimitResponse;
|
||||
import io.ebean.config.dbplatform.SqlLimiter;
|
||||
|
||||
public class Db2SqlLimiter implements SqlLimiter {
|
||||
public final class AnsiSqlRowsLimiter implements SqlLimiter {
|
||||
|
||||
@Override
|
||||
public SqlLimitResponse limit(SqlLimitRequest request) {
|
||||
|
||||
StringBuilder sb = new StringBuilder(512);
|
||||
String dbSql = request.getDbSql();
|
||||
StringBuilder sb = new StringBuilder(50 + dbSql.length());
|
||||
sb.append("select ");
|
||||
if (request.isDistinct()) {
|
||||
sb.append("distinct ");
|
||||
}
|
||||
sb.append(request.getDbSql());
|
||||
sb.append(dbSql);
|
||||
int firstRow = request.getFirstRow();
|
||||
if (firstRow > 0) {
|
||||
sb.append(" offset ").append(firstRow).append(" rows");
|
||||
@@ -23,7 +19,6 @@ public class Db2SqlLimiter implements SqlLimiter {
|
||||
if (maxRows > 0) {
|
||||
sb.append(" fetch next ").append(maxRows).append(" rows only");
|
||||
}
|
||||
|
||||
String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
|
||||
return new SqlLimitResponse(sql);
|
||||
}
|
||||
@@ -1,49 +1,26 @@
|
||||
package io.ebean.config.dbplatform;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.EbeanVersion;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.annotation.PartitionMode;
|
||||
import io.ebean.annotation.PersistBatch;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.CustomDbTypeMapping;
|
||||
import io.ebean.config.PlatformConfig;
|
||||
import io.ebean.util.JdbcClose;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.sql.Types;
|
||||
import java.sql.*;
|
||||
|
||||
import static java.lang.System.Logger.Level.*;
|
||||
|
||||
/**
|
||||
* Database platform specific settings.
|
||||
*/
|
||||
public class DatabasePlatform {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger("io.ebean");
|
||||
|
||||
/**
|
||||
* Behavior used when ending a query only transaction (at read committed isolation level).
|
||||
*/
|
||||
public enum OnQueryOnly {
|
||||
|
||||
/**
|
||||
* Rollback the transaction.
|
||||
*/
|
||||
ROLLBACK,
|
||||
|
||||
/**
|
||||
* Commit the transaction
|
||||
*/
|
||||
COMMIT
|
||||
}
|
||||
|
||||
private static final System.Logger log = EbeanVersion.log;
|
||||
|
||||
/**
|
||||
* Set to true for MySql, no other jdbc drivers need this workaround.
|
||||
@@ -60,16 +37,11 @@ public class DatabasePlatform {
|
||||
* Can we use native java time API objects in
|
||||
* {@link ResultSet#getObject(int, Class)} and
|
||||
* {@link PreparedStatement#setObject(int, Object)}.
|
||||
*
|
||||
* <p>
|
||||
* Not all drivers (DB2 e.g.) will support this.
|
||||
*/
|
||||
protected boolean supportsNativeJavaTime = true;
|
||||
|
||||
/**
|
||||
* The behaviour used when ending a read only transaction at read committed isolation level.
|
||||
*/
|
||||
protected OnQueryOnly onQueryOnly = OnQueryOnly.COMMIT;
|
||||
|
||||
/**
|
||||
* The open quote used by quoted identifiers.
|
||||
*/
|
||||
@@ -146,11 +118,6 @@ public class DatabasePlatform {
|
||||
*/
|
||||
protected int clobDbType = Types.CLOB;
|
||||
|
||||
/**
|
||||
* For Oracle treat empty strings as null.
|
||||
*/
|
||||
protected boolean treatEmptyStringsAsNull;
|
||||
|
||||
/**
|
||||
* The database platform name.
|
||||
*/
|
||||
@@ -165,7 +132,7 @@ public class DatabasePlatform {
|
||||
* want to use quoted identifiers for. The backticks get converted to the
|
||||
* appropriate characters in convertQuotedIdentifiers
|
||||
*/
|
||||
private static final char[] QUOTED_IDENTIFIERS = new char[] { '"', '\'', '[', ']', '`' };
|
||||
private static final char[] QUOTED_IDENTIFIERS = new char[]{'"', '\'', '[', ']', '`'};
|
||||
|
||||
/**
|
||||
* The non-escaped like clause (to stop slash being escaped on some platforms).
|
||||
@@ -299,7 +266,7 @@ public class DatabasePlatform {
|
||||
/**
|
||||
* Return the platform key.
|
||||
*/
|
||||
public Platform getPlatform() {
|
||||
public Platform platform() {
|
||||
return platform;
|
||||
}
|
||||
|
||||
@@ -309,14 +276,14 @@ public class DatabasePlatform {
|
||||
* "generic" is returned when no specific database platform has been set or found.
|
||||
* </p>
|
||||
*/
|
||||
public String getName() {
|
||||
public String name() {
|
||||
return platform.name().toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if we are using Sequence batch mode rather than STEP.
|
||||
*/
|
||||
public boolean isSequenceBatchMode() {
|
||||
public boolean sequenceBatchMode() {
|
||||
return sequenceBatchMode;
|
||||
}
|
||||
|
||||
@@ -330,52 +297,52 @@ public class DatabasePlatform {
|
||||
/**
|
||||
* Return true if this database platform supports native ILIKE expression.
|
||||
*/
|
||||
public boolean isSupportsNativeIlike() {
|
||||
public boolean supportsNativeIlike() {
|
||||
return supportsNativeIlike;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the platform supports delete statements with table alias.
|
||||
*/
|
||||
public boolean isSupportsDeleteTableAlias() {
|
||||
public boolean supportsDeleteTableAlias() {
|
||||
return supportsDeleteTableAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the collation is case sensitive.
|
||||
* Return true if the collation is case-sensitive.
|
||||
* <p>
|
||||
* This is expected to be used for testing only.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isCaseSensitiveCollation() {
|
||||
public boolean caseSensitiveCollation() {
|
||||
return caseSensitiveCollation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the platform supports SavepointId values.
|
||||
*/
|
||||
public boolean isSupportsSavepointId() {
|
||||
public boolean supportsSavepointId() {
|
||||
return supportsSavepointId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if migrations should use stored procedures.
|
||||
*/
|
||||
public boolean isUseMigrationStoredProcedures() {
|
||||
public boolean useMigrationStoredProcedures() {
|
||||
return useMigrationStoredProcedures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the platform supports LIMIT with sql update.
|
||||
*/
|
||||
public boolean isInlineSqlUpdateLimit() {
|
||||
public boolean inlineSqlUpdateLimit() {
|
||||
return inlineSqlUpdateLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the maximum number of bind values this database platform allows or zero for no limit.
|
||||
*/
|
||||
public int getMaxInBinding() {
|
||||
public int maxInBinding() {
|
||||
return maxInBinding;
|
||||
}
|
||||
|
||||
@@ -385,14 +352,14 @@ public class DatabasePlatform {
|
||||
* This is used when deriving names of intersection tables.
|
||||
* </p>
|
||||
*/
|
||||
public int getMaxTableNameLength() {
|
||||
public int maxTableNameLength() {
|
||||
return maxTableNameLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the maximum constraint name allowed for the platform.
|
||||
*/
|
||||
public int getMaxConstraintNameLength() {
|
||||
public int maxConstraintNameLength() {
|
||||
return maxConstraintNameLength;
|
||||
}
|
||||
|
||||
@@ -420,24 +387,10 @@ public class DatabasePlatform {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the behaviour to use when ending a read only transaction.
|
||||
*/
|
||||
public OnQueryOnly getOnQueryOnly() {
|
||||
return onQueryOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the behaviour to use when ending a read only transaction.
|
||||
*/
|
||||
public void setOnQueryOnly(OnQueryOnly onQueryOnly) {
|
||||
this.onQueryOnly = onQueryOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DbEncrypt handler for this DB platform.
|
||||
*/
|
||||
public DbEncrypt getDbEncrypt() {
|
||||
public DbEncrypt dbEncrypt() {
|
||||
return dbEncrypt;
|
||||
}
|
||||
|
||||
@@ -451,7 +404,7 @@ public class DatabasePlatform {
|
||||
/**
|
||||
* Return the history support for this database platform.
|
||||
*/
|
||||
public DbHistorySupport getHistorySupport() {
|
||||
public DbHistorySupport historySupport() {
|
||||
return historySupport;
|
||||
}
|
||||
|
||||
@@ -465,14 +418,14 @@ public class DatabasePlatform {
|
||||
/**
|
||||
* So no except for Postgres and CockroachDB.
|
||||
*/
|
||||
public boolean isNativeArrayType() {
|
||||
public boolean nativeArrayType() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the DB supports native UUID.
|
||||
*/
|
||||
public boolean isNativeUuidType() {
|
||||
public boolean nativeUuidType() {
|
||||
return nativeUuidType;
|
||||
}
|
||||
|
||||
@@ -481,21 +434,21 @@ public class DatabasePlatform {
|
||||
*
|
||||
* @return the db type map
|
||||
*/
|
||||
public DbPlatformTypeMapping getDbTypeMap() {
|
||||
public DbPlatformTypeMapping dbTypeMap() {
|
||||
return dbTypeMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mapping for DB column default values.
|
||||
*/
|
||||
public DbDefaultValue getDbDefaultValue() {
|
||||
public DbDefaultValue dbDefaultValue() {
|
||||
return dbDefaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the column alias prefix.
|
||||
*/
|
||||
public String getColumnAliasPrefix() {
|
||||
public String columnAliasPrefix() {
|
||||
return columnAliasPrefix;
|
||||
}
|
||||
|
||||
@@ -509,21 +462,21 @@ public class DatabasePlatform {
|
||||
/**
|
||||
* Return the close quote for quoted identifiers.
|
||||
*/
|
||||
public String getCloseQuote() {
|
||||
public String closeQuote() {
|
||||
return closeQuote;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the open quote for quoted identifiers.
|
||||
*/
|
||||
public String getOpenQuote() {
|
||||
public String openQuote() {
|
||||
return openQuote;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JDBC type used to store booleans.
|
||||
*/
|
||||
public int getBooleanDbType() {
|
||||
public int booleanDbType() {
|
||||
return booleanDbType;
|
||||
}
|
||||
|
||||
@@ -534,7 +487,7 @@ public class DatabasePlatform {
|
||||
* example.
|
||||
* </p>
|
||||
*/
|
||||
public int getBlobDbType() {
|
||||
public int blobDbType() {
|
||||
return blobDbType;
|
||||
}
|
||||
|
||||
@@ -544,25 +497,16 @@ public class DatabasePlatform {
|
||||
* This is typically Types.CLOB but for Postgres is Types.VARCHAR.
|
||||
* </p>
|
||||
*/
|
||||
public int getClobDbType() {
|
||||
public int clobDbType() {
|
||||
return clobDbType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if empty strings should be treated as null.
|
||||
*
|
||||
* @return true, if checks if is treat empty strings as null
|
||||
*/
|
||||
public boolean isTreatEmptyStringsAsNull() {
|
||||
return treatEmptyStringsAsNull;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if a compound ID in (...) type expression needs to be in
|
||||
* expanded form of (a=? and b=?) or (a=? and b=?) or ... rather than (a,b) in
|
||||
* ((?,?),(?,?),...);
|
||||
*/
|
||||
public boolean isIdInExpandedForm() {
|
||||
public boolean idInExpandedForm() {
|
||||
return idInExpandedForm;
|
||||
}
|
||||
|
||||
@@ -573,7 +517,7 @@ public class DatabasePlatform {
|
||||
* This specifically is required for MySql when processing large results.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isForwardOnlyHintOnFindIterate() {
|
||||
public boolean forwardOnlyHintOnFindIterate() {
|
||||
return forwardOnlyHintOnFindIterate;
|
||||
}
|
||||
|
||||
@@ -591,7 +535,7 @@ public class DatabasePlatform {
|
||||
* This specifically is required for Hana which doesn't support CONCUR_UPDATABLE
|
||||
* </p>
|
||||
*/
|
||||
public boolean isSupportsResultSetConcurrencyModeUpdatable() {
|
||||
public boolean supportsResultSetConcurrencyModeUpdatable() {
|
||||
return supportsResultSetConcurrencyModeUpdatable;
|
||||
}
|
||||
|
||||
@@ -611,7 +555,7 @@ public class DatabasePlatform {
|
||||
*
|
||||
* @return the db identity
|
||||
*/
|
||||
public DbIdentity getDbIdentity() {
|
||||
public DbIdentity dbIdentity() {
|
||||
return dbIdentity;
|
||||
}
|
||||
|
||||
@@ -624,14 +568,14 @@ public class DatabasePlatform {
|
||||
*
|
||||
* @return the sql limiter
|
||||
*/
|
||||
public SqlLimiter getSqlLimiter() {
|
||||
public SqlLimiter sqlLimiter() {
|
||||
return sqlLimiter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BasicSqlLimiter for limit/offset of SqlQuery queries.
|
||||
*/
|
||||
public BasicSqlLimiter getBasicSqlLimiter() {
|
||||
public BasicSqlLimiter basicSqlLimiter() {
|
||||
return basicSqlLimiter;
|
||||
}
|
||||
|
||||
@@ -666,7 +610,7 @@ public class DatabasePlatform {
|
||||
if (isQuote(dbName.charAt(dbName.length() - 1))) {
|
||||
return openQuote + dbName.substring(1, dbName.length() - 1) + closeQuote;
|
||||
} else {
|
||||
log.error("Missing backquote on [" + dbName + "]");
|
||||
log.log(ERROR, "Missing backquote on [" + dbName + "]");
|
||||
}
|
||||
} else if (allQuotedIdentifiers) {
|
||||
return openQuote + dbName + closeQuote;
|
||||
@@ -676,8 +620,8 @@ public class DatabasePlatform {
|
||||
}
|
||||
|
||||
private boolean isQuote(char ch) {
|
||||
for (char identifer : QUOTED_IDENTIFIERS) {
|
||||
if (identifer == ch) {
|
||||
for (char identifier : QUOTED_IDENTIFIERS) {
|
||||
if (identifier == ch) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -700,14 +644,14 @@ public class DatabasePlatform {
|
||||
/**
|
||||
* Set to true if select count against anonymous view requires an alias.
|
||||
*/
|
||||
public boolean isSelectCountWithAlias() {
|
||||
public boolean selectCountWithAlias() {
|
||||
return selectCountWithAlias;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if select count with subquery needs column alias (SQL Server).
|
||||
*/
|
||||
public boolean isSelectCountWithColumnAlias() {
|
||||
public boolean selectCountWithColumnAlias() {
|
||||
return selectCountWithColumnAlias;
|
||||
}
|
||||
|
||||
@@ -729,7 +673,7 @@ public class DatabasePlatform {
|
||||
|
||||
protected String withForUpdate(String sql, Query.LockWait lockWait, Query.LockType lockType) {
|
||||
// silently assume the database does not support the "for update" clause.
|
||||
log.info("it seems your database does not support the 'for update' clause");
|
||||
log.log(INFO, "it seems your database does not support the ''for update'' clause");
|
||||
return sql;
|
||||
}
|
||||
|
||||
@@ -738,14 +682,14 @@ public class DatabasePlatform {
|
||||
* <p>
|
||||
* This may include an escape clause to disable a default escape character.
|
||||
*/
|
||||
public String getLikeClause(boolean rawLikeExpression) {
|
||||
public String likeClause(boolean rawLikeExpression) {
|
||||
return rawLikeExpression ? likeClauseRaw : likeClauseEscaped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the platform default JDBC batch mode for persist cascade.
|
||||
*/
|
||||
public PersistBatch getPersistBatchOnCascade() {
|
||||
public PersistBatch persistBatchOnCascade() {
|
||||
return persistBatchOnCascade;
|
||||
}
|
||||
|
||||
@@ -763,7 +707,7 @@ public class DatabasePlatform {
|
||||
if (!schemaExists(dbSchema, connection)) {
|
||||
Statement query = connection.createStatement();
|
||||
try {
|
||||
log.debug("create schema:{}", dbSchema);
|
||||
log.log(DEBUG, "create schema:{0}", dbSchema);
|
||||
query.executeUpdate("create schema " + dbSchema);
|
||||
} finally {
|
||||
JdbcClose.close(query);
|
||||
@@ -789,33 +733,6 @@ public class DatabasePlatform {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the table exists.
|
||||
*/
|
||||
public boolean tableExists(Connection connection, String catalog, String schema, String table) throws SQLException {
|
||||
DatabaseMetaData metaData = connection.getMetaData();
|
||||
ResultSet tables = metaData.getTables(catalog, schema, table, null);
|
||||
try {
|
||||
return tables.next();
|
||||
} finally {
|
||||
JdbcClose.close(tables);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if partitions exist for the given table.
|
||||
*/
|
||||
public boolean tablePartitionsExist(Connection connection, String table) throws SQLException {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the SQL to create an initial partition for the given table.
|
||||
*/
|
||||
public String tablePartitionInit(String tableName, PartitionMode mode, String property, String singlePrimaryKey) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes the like string for this DB-Platform
|
||||
*/
|
||||
|
||||
@@ -3,42 +3,25 @@ package io.ebean.config.dbplatform;
|
||||
/**
|
||||
* Adds LIMIT OFFSET clauses to a SQL query.
|
||||
*/
|
||||
public class LimitOffsetSqlLimiter implements SqlLimiter {
|
||||
|
||||
/**
|
||||
* LIMIT keyword.
|
||||
*/
|
||||
private static final String LIMIT = "limit";
|
||||
|
||||
/**
|
||||
* OFFSET keyword.
|
||||
*/
|
||||
private static final String OFFSET = "offset";
|
||||
public final class LimitOffsetSqlLimiter implements SqlLimiter {
|
||||
|
||||
@Override
|
||||
public SqlLimitResponse limit(SqlLimitRequest request) {
|
||||
|
||||
String dbSql = request.getDbSql();
|
||||
|
||||
StringBuilder sb = new StringBuilder(50 + dbSql.length());
|
||||
sb.append("select ");
|
||||
if (request.isDistinct()) {
|
||||
sb.append("distinct ");
|
||||
}
|
||||
|
||||
sb.append(dbSql);
|
||||
|
||||
int firstRow = request.getFirstRow();
|
||||
int maxRows = request.getMaxRows();
|
||||
|
||||
if (maxRows > 0 || firstRow > 0) {
|
||||
sb.append(" ").append(LIMIT).append(" ").append(maxRows);
|
||||
if (firstRow > 0) {
|
||||
sb.append(" ").append(OFFSET).append(" ");
|
||||
sb.append(firstRow);
|
||||
}
|
||||
if (maxRows > 0) {
|
||||
sb.append(" limit ").append(maxRows);
|
||||
}
|
||||
int firstRow = request.getFirstRow();
|
||||
if (firstRow > 0) {
|
||||
sb.append(" offset ").append(firstRow);
|
||||
}
|
||||
|
||||
String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
|
||||
return new SqlLimitResponse(sql);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package io.ebean.config.dbplatform;
|
||||
|
||||
import io.avaje.applog.AppLog;
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.util.JdbcClose;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.sql.DataSource;
|
||||
@@ -19,12 +18,15 @@ import java.util.TreeSet;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import static java.lang.System.Logger.Level.DEBUG;
|
||||
import static java.lang.System.Logger.Level.ERROR;
|
||||
|
||||
/**
|
||||
* Database sequence based IdGenerator.
|
||||
*/
|
||||
public abstract class SequenceIdGenerator implements PlatformIdGenerator {
|
||||
|
||||
protected static final Logger log = LoggerFactory.getLogger("io.ebean.SEQ");
|
||||
protected static final System.Logger log = AppLog.getLogger("io.ebean.SEQ");
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
protected final String seqName;
|
||||
@@ -120,7 +122,7 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
|
||||
protected void loadInBackground(final int requestSize) {
|
||||
if (currentlyBackgroundLoading.get()) {
|
||||
// skip as already background loading
|
||||
log.debug("... skip background sequence load (another load in progress)");
|
||||
log.log(DEBUG, "... skip background sequence load (another load in progress)");
|
||||
return;
|
||||
}
|
||||
currentlyBackgroundLoading.set(true);
|
||||
@@ -152,9 +154,6 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
|
||||
resultSet = statement.executeQuery();
|
||||
|
||||
List<Long> newIds = readIds(resultSet, requestSize);
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("seq:{} loaded:{} sql:{}", seqName, newIds.size(), sql);
|
||||
}
|
||||
if (newIds.isEmpty()) {
|
||||
throw new PersistenceException("Always expecting more than 1 row from " + sql);
|
||||
}
|
||||
@@ -164,7 +163,7 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
|
||||
} catch (SQLException e) {
|
||||
if (e.getMessage().contains("Database is already closed")) {
|
||||
String msg = "Error getting SEQ when DB shutting down " + e.getMessage();
|
||||
log.error(msg);
|
||||
log.log(ERROR, msg);
|
||||
System.out.println(msg);
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
|
||||
@@ -32,7 +32,12 @@ public class SqlCodeTranslator implements SqlExceptionTranslator {
|
||||
}
|
||||
|
||||
private DataErrorType getErrorType(SQLException e) {
|
||||
DataErrorType errorType = map.get(e.getSQLState());
|
||||
String sqlState = e.getSQLState();
|
||||
while (sqlState == null && e.getCause() instanceof SQLException) {
|
||||
e = (SQLException)e.getCause();
|
||||
sqlState = e.getSQLState();
|
||||
}
|
||||
DataErrorType errorType = map.get(sqlState);
|
||||
if (errorType == null) {
|
||||
// fall back to error code
|
||||
errorType = map.get(String.valueOf(e.getErrorCode()));
|
||||
|
||||
@@ -5,14 +5,6 @@ package io.ebean.config.dbplatform;
|
||||
*/
|
||||
public interface SqlLimiter {
|
||||
|
||||
/**
|
||||
* the new line character used.
|
||||
* <p>
|
||||
* Note that this is removed for logging sql to the transaction log.
|
||||
* </p>
|
||||
*/
|
||||
char NEW_LINE = '\n';
|
||||
|
||||
/**
|
||||
* Add the SQL limiting statements around the query.
|
||||
*/
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package io.ebean.event;
|
||||
|
||||
import io.ebean.Database;
|
||||
import io.ebean.EbeanVersion;
|
||||
import io.ebean.service.SpiContainer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.Driver;
|
||||
import java.sql.DriverManager;
|
||||
@@ -13,6 +12,8 @@ import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import static java.lang.System.Logger.Level.*;
|
||||
|
||||
/**
|
||||
* Manages the shutdown of Ebean.
|
||||
* <p>
|
||||
@@ -20,13 +21,14 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
*/
|
||||
public final class ShutdownManager {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger("io.ebean");
|
||||
private static final System.Logger log = EbeanVersion.log;
|
||||
private static final ReentrantLock lock = new ReentrantLock();
|
||||
private static final List<Database> databases = new ArrayList<>();
|
||||
private static final ShutdownHook shutdownHook = new ShutdownHook();
|
||||
|
||||
private static boolean stopping;
|
||||
private static SpiContainer container;
|
||||
|
||||
static {
|
||||
// Register the Shutdown hook
|
||||
registerShutdownHook();
|
||||
@@ -120,9 +122,7 @@ public final class ShutdownManager {
|
||||
// Already run shutdown...
|
||||
return;
|
||||
}
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Ebean shutting down");
|
||||
}
|
||||
log.log(DEBUG, "Ebean shutting down");
|
||||
stopping = true;
|
||||
deregisterShutdownHook();
|
||||
|
||||
@@ -133,7 +133,7 @@ public final class ShutdownManager {
|
||||
Runnable r = (Runnable) ClassUtil.newInstance(shutdownRunner);
|
||||
r.run();
|
||||
} catch (Exception e) {
|
||||
log.error("Error running custom shutdown runnable", e);
|
||||
log.log(ERROR, "Error running custom shutdown runnable", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,11 +143,11 @@ public final class ShutdownManager {
|
||||
}
|
||||
// shutdown any registered servers that have not
|
||||
// already been shutdown manually
|
||||
for (Database server : databases) {
|
||||
for (Database server : new ArrayList<>(databases)) {
|
||||
try {
|
||||
server.shutdown();
|
||||
} catch (Exception ex) {
|
||||
log.error("Error executing shutdown runnable", ex);
|
||||
log.log(ERROR, "Error executing shutdown runnable", ex);
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -165,10 +165,10 @@ public final class ShutdownManager {
|
||||
while (drivers.hasMoreElements()) {
|
||||
Driver driver = drivers.nextElement();
|
||||
try {
|
||||
log.info("De-registering jdbc driver: " + driver);
|
||||
log.log(INFO, "De-registering jdbc driver: " + driver);
|
||||
DriverManager.deregisterDriver(driver);
|
||||
} catch (SQLException e) {
|
||||
log.error("Error de-registering driver " + driver, e);
|
||||
log.log(ERROR, "Error de-registering driver " + driver, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -204,6 +204,7 @@ public final class ShutdownManager {
|
||||
private ShutdownHook() {
|
||||
super("EbeanHook");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
ShutdownManager.shutdown();
|
||||
|
||||
@@ -2,28 +2,57 @@ package io.ebean.meta;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A simple MetricVisitor that can collect the desired metrics into lists.
|
||||
*/
|
||||
public class BasicMetricVisitor extends AbstractMetricVisitor implements ServerMetrics {
|
||||
|
||||
private final String name;
|
||||
private final Function<String,String> naming;
|
||||
private final List<MetaTimedMetric> timed = new ArrayList<>();
|
||||
private final List<MetaQueryMetric> query = new ArrayList<>();
|
||||
private final List<MetaCountMetric> count = new ArrayList<>();
|
||||
|
||||
public BasicMetricVisitor() {
|
||||
this("db", MetricNamingMatch.INSTANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct to reset and collect everything.
|
||||
*/
|
||||
public BasicMetricVisitor() {
|
||||
super(true, true, true, true);
|
||||
public BasicMetricVisitor(String name, Function<String,String> naming) {
|
||||
this(name, naming, true, true, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct specifying reset and what to collect.
|
||||
*/
|
||||
public BasicMetricVisitor(boolean reset, boolean collectTransactionMetrics, boolean collectQueryMetrics, boolean collectL2Metrics) {
|
||||
public BasicMetricVisitor(String name, Function<String,String> naming, boolean reset, boolean collectTransactionMetrics, boolean collectQueryMetrics, boolean collectL2Metrics) {
|
||||
super(reset, collectTransactionMetrics, collectQueryMetrics, collectL2Metrics);
|
||||
this.name = name;
|
||||
this.naming = naming;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function<String, String> namingConvention() {
|
||||
return naming;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServerMetricsAsJson asJson() {
|
||||
return new MetricsAsJson(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MetricData> asData() {
|
||||
return new MetricsAsData(this).data();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,23 +16,6 @@ public interface MetaInfoManager {
|
||||
*/
|
||||
ServerMetrics collectMetrics();
|
||||
|
||||
/**
|
||||
* Collect the metrics in raw JSON form.
|
||||
* <pre>{@code
|
||||
*
|
||||
* String metricsJson = database.getMetaInfoManager()
|
||||
* .collectMetricsAsJson()
|
||||
* .json();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
ServerMetricsAsJson collectMetricsAsJson();
|
||||
|
||||
/**
|
||||
* Return the metrics as a list of MetricData.
|
||||
*/
|
||||
List<MetricData> collectMetricsAsData();
|
||||
|
||||
/**
|
||||
* Visit the metrics resetting and collecting/reporting as desired.
|
||||
*/
|
||||
|
||||
@@ -2,6 +2,8 @@ package io.ebean.meta;
|
||||
|
||||
import io.ebean.ProfileLocation;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
/**
|
||||
* Meta data for captured query plan.
|
||||
*/
|
||||
@@ -51,4 +53,14 @@ public interface MetaQueryPlan {
|
||||
* Return the total count of times bind capture has occurred.
|
||||
*/
|
||||
long captureCount();
|
||||
|
||||
/**
|
||||
* Return the time taken to capture this plan in microseconds.
|
||||
*/
|
||||
long captureMicros();
|
||||
|
||||
/**
|
||||
* Return the instant when the bind values were captured.
|
||||
*/
|
||||
Instant whenCaptured();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package io.ebean.meta;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Metric naming convention that is exact match.
|
||||
*/
|
||||
public final class MetricNamingMatch implements Function<String, String> {
|
||||
|
||||
public static final Function<String, String> INSTANCE = new MetricNamingMatch();
|
||||
|
||||
@Override
|
||||
public String apply(String name) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,17 @@
|
||||
package io.ebean.meta;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Defines visitor to read and report the transaction and query metrics.
|
||||
*/
|
||||
public interface MetricVisitor {
|
||||
|
||||
/**
|
||||
* Return the naming convention that should be applied to the reported metric names.
|
||||
*/
|
||||
Function<String, String> namingConvention();
|
||||
|
||||
/**
|
||||
* Return true if the metrics should be reset.
|
||||
*/
|
||||
|
||||
+9
-25
@@ -1,12 +1,4 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebean.Database;
|
||||
import io.ebean.meta.MetaCountMetric;
|
||||
import io.ebean.meta.MetaMetric;
|
||||
import io.ebean.meta.MetaQueryMetric;
|
||||
import io.ebean.meta.MetaTimedMetric;
|
||||
import io.ebean.meta.MetricData;
|
||||
import io.ebean.meta.ServerMetrics;
|
||||
package io.ebean.meta;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -14,34 +6,26 @@ import java.util.List;
|
||||
/**
|
||||
* Dump the metrics into a list of MetricData.
|
||||
*/
|
||||
final class DumpMetricsData {
|
||||
final class MetricsAsData {
|
||||
|
||||
private final Database database;
|
||||
private final ServerMetrics metrics;
|
||||
private final List<MetricData> list = new ArrayList<>();
|
||||
|
||||
DumpMetricsData(Database database) {
|
||||
this.database = database;
|
||||
MetricsAsData(ServerMetrics metrics) {
|
||||
this.metrics = metrics;
|
||||
}
|
||||
|
||||
List<MetricData> data() {
|
||||
collect(database.metaInfo().collectMetrics());
|
||||
return list;
|
||||
}
|
||||
|
||||
private void collect(ServerMetrics serverMetrics) {
|
||||
final List<MetaTimedMetric> timedMetrics = serverMetrics.timedMetrics();
|
||||
final List<MetaCountMetric> countMetrics = serverMetrics.countMetrics();
|
||||
final List<MetaQueryMetric> queryMetrics = serverMetrics.queryMetrics();
|
||||
|
||||
for (MetaTimedMetric metric : timedMetrics) {
|
||||
for (MetaTimedMetric metric : metrics.timedMetrics()) {
|
||||
add(metric);
|
||||
}
|
||||
for (MetaCountMetric metric : countMetrics) {
|
||||
for (MetaCountMetric metric : metrics.countMetrics()) {
|
||||
addCount(metric);
|
||||
}
|
||||
for (MetaQueryMetric metric : queryMetrics) {
|
||||
for (MetaQueryMetric metric : metrics.queryMetrics()) {
|
||||
addQuery(metric);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private MetricData create(MetaMetric metric) {
|
||||
+13
-22
@@ -1,25 +1,16 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebean.Database;
|
||||
import io.ebean.meta.MetaCountMetric;
|
||||
import io.ebean.meta.MetaMetric;
|
||||
import io.ebean.meta.MetaQueryMetric;
|
||||
import io.ebean.meta.MetaTimedMetric;
|
||||
import io.ebean.meta.ServerMetrics;
|
||||
import io.ebean.meta.ServerMetricsAsJson;
|
||||
import io.ebean.meta.SortMetric;
|
||||
package io.ebean.meta;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
final class DumpMetricsJson implements ServerMetricsAsJson {
|
||||
final class MetricsAsJson implements ServerMetricsAsJson {
|
||||
|
||||
private final Database database;
|
||||
private final ServerMetrics metrics;
|
||||
private Appendable writer;
|
||||
/**
|
||||
* By default include sql and location attributes for the initial collection only.
|
||||
* By default, include sql and location attributes for the initial collection only.
|
||||
*/
|
||||
private int includeExtraAttributes = 1;
|
||||
private boolean withHeader = true;
|
||||
@@ -29,8 +20,8 @@ final class DumpMetricsJson implements ServerMetricsAsJson {
|
||||
private int listCounter;
|
||||
private int objKeyCounter;
|
||||
|
||||
DumpMetricsJson(Database database) {
|
||||
this.database = database;
|
||||
MetricsAsJson(ServerMetrics metrics) {
|
||||
this.metrics = metrics;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,24 +57,24 @@ final class DumpMetricsJson implements ServerMetricsAsJson {
|
||||
@Override
|
||||
public String json() {
|
||||
writer = new StringWriter();
|
||||
collect(database.metaInfo().collectMetrics());
|
||||
collect();
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Appendable buffer) {
|
||||
writer = buffer;
|
||||
collect(database.metaInfo().collectMetrics());
|
||||
collect();
|
||||
}
|
||||
|
||||
private void collect(ServerMetrics serverMetrics) {
|
||||
private void collect() {
|
||||
try {
|
||||
start();
|
||||
for (MetaTimedMetric metric : serverMetrics.timedMetrics()) {
|
||||
for (MetaTimedMetric metric : metrics.timedMetrics()) {
|
||||
logTimed(metric);
|
||||
}
|
||||
|
||||
List<MetaCountMetric> countMetrics = serverMetrics.countMetrics();
|
||||
List<MetaCountMetric> countMetrics = metrics.countMetrics();
|
||||
if (!countMetrics.isEmpty()) {
|
||||
if (sortBy != null) {
|
||||
countMetrics.sort(SortMetric.COUNT_NAME);
|
||||
@@ -93,7 +84,7 @@ final class DumpMetricsJson implements ServerMetricsAsJson {
|
||||
}
|
||||
}
|
||||
|
||||
List<MetaQueryMetric> queryMetrics = serverMetrics.queryMetrics();
|
||||
List<MetaQueryMetric> queryMetrics = metrics.queryMetrics();
|
||||
if (!queryMetrics.isEmpty()) {
|
||||
if (sortBy != null) {
|
||||
queryMetrics.sort(sortBy);
|
||||
@@ -112,7 +103,7 @@ final class DumpMetricsJson implements ServerMetricsAsJson {
|
||||
if (withHeader) {
|
||||
objStart();
|
||||
key("db");
|
||||
val(database.name());
|
||||
val(metrics.name());
|
||||
key("metrics");
|
||||
listStart();
|
||||
}
|
||||
@@ -7,6 +7,21 @@ import java.util.List;
|
||||
*/
|
||||
public interface ServerMetrics {
|
||||
|
||||
/**
|
||||
* Return the name of the database these metrics were obtained for.
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Return ServerMetricsAsJson to build the metrics as JSON content.
|
||||
*/
|
||||
ServerMetricsAsJson asJson();
|
||||
|
||||
/**
|
||||
* Return the metrics as a list of MetricData.
|
||||
*/
|
||||
List<MetricData> asData();
|
||||
|
||||
/**
|
||||
* Return timed metrics for Transactions, labelled SqlQuery, labelled SqlUpdate.
|
||||
*/
|
||||
|
||||
@@ -39,18 +39,6 @@ public interface ExpressionPath {
|
||||
*/
|
||||
StringParser stringParser();
|
||||
|
||||
/**
|
||||
* For DateTime capable scalar types convert the long systemTimeMillis into
|
||||
* an appropriate java time (Date,Timestamp,Time,Calendar, JODA type etc).
|
||||
*/
|
||||
Object parseDateTime(long systemTimeMillis);
|
||||
|
||||
/**
|
||||
* Return true if the last type is "DateTime capable" - can support
|
||||
* {@link #parseDateTime(long)}.
|
||||
*/
|
||||
boolean isDateTimeCapable();
|
||||
|
||||
/**
|
||||
* Return the underlying JDBC type or 0 if this is not a scalar type.
|
||||
*/
|
||||
|
||||
@@ -13,9 +13,16 @@ public interface SpiProfileLocationFactory {
|
||||
ProfileLocation create();
|
||||
|
||||
/**
|
||||
* Create a profile location with a line number.
|
||||
* Create a profile location with line numbering.
|
||||
*/
|
||||
ProfileLocation create(int lineNumber, String label);
|
||||
ProfileLocation createWithLine();
|
||||
|
||||
/**
|
||||
* Create with a given label - used only with {@code @Transaction}.
|
||||
*
|
||||
* @param label the label for the transaction
|
||||
*/
|
||||
ProfileLocation create(String label);
|
||||
|
||||
/**
|
||||
* Create a known location.
|
||||
|
||||
@@ -6,6 +6,7 @@ package io.ebean.text;
|
||||
* Basic interface to support CSV, JSON and XML processing.
|
||||
* </p>
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface StringFormatter {
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,6 +5,7 @@ package io.ebean.text;
|
||||
* <p>
|
||||
* Basic interface to support CSV, JSON and XML processing.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface StringParser {
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
package io.ebean.text;
|
||||
|
||||
import java.sql.Time;
|
||||
|
||||
/**
|
||||
* Parser for TIME types that supports both HH:mm:ss and HH:mm.
|
||||
*/
|
||||
public final class TimeStringParser implements StringParser {
|
||||
|
||||
private static final TimeStringParser SHARED = new TimeStringParser();
|
||||
|
||||
/**
|
||||
* Return a shared instance as this is thread safe.
|
||||
*/
|
||||
public static TimeStringParser get() {
|
||||
return SHARED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the String supporting both HH:mm:ss and HH:mm formats.
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public Object parse(String value) {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String s = value.trim();
|
||||
int firstColon = s.indexOf(':');
|
||||
|
||||
if (firstColon == -1) {
|
||||
throw new java.lang.IllegalArgumentException("No ':' in value [" + s + "]");
|
||||
}
|
||||
try {
|
||||
int second;
|
||||
int minute;
|
||||
int hour = Integer.parseInt(s.substring(0, firstColon));
|
||||
int secondColon = s.indexOf(':', firstColon + 1);
|
||||
|
||||
if (secondColon == -1) {
|
||||
minute = Integer.parseInt(s.substring(firstColon + 1, s.length()));
|
||||
second = 0;
|
||||
} else {
|
||||
minute = Integer.parseInt(s.substring(firstColon + 1, secondColon));
|
||||
second = Integer.parseInt(s.substring(secondColon + 1));
|
||||
}
|
||||
|
||||
return new Time(hour, minute, second);
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
throw new java.lang.IllegalArgumentException("Number format Error parsing time [" + s + "] " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
package io.ebean.text.csv;
|
||||
|
||||
import io.ebean.Database;
|
||||
|
||||
/**
|
||||
* Provides callback methods for customisation of CSV processing.
|
||||
* <p>
|
||||
* You can provide your own CsvCallback implementation to customise the CSV
|
||||
* processing. It is expected that the DefaultCsvCallback provides a good base
|
||||
* class that you can extend.
|
||||
*/
|
||||
public interface CsvCallback<T> {
|
||||
|
||||
/**
|
||||
* The processing is about to begin.
|
||||
* <p>
|
||||
* Typically the callback will create a transaction, set batch mode, batch
|
||||
* size etc.
|
||||
* </p>
|
||||
*/
|
||||
void begin(Database database);
|
||||
|
||||
/**
|
||||
* Read the header row.
|
||||
* <p>
|
||||
* This is only called if {@link CsvReader#setHasHeader(boolean, boolean)} has
|
||||
* been set to true.
|
||||
* </p>
|
||||
*
|
||||
* @param line the header line content.
|
||||
*/
|
||||
void readHeader(String[] line);
|
||||
|
||||
/**
|
||||
* Check that the row should be processed - return true to process the row or
|
||||
* false to ignore the row. Gives ability to handle bad data... empty rows etc
|
||||
* and ignore it rather than fail.
|
||||
*/
|
||||
boolean processLine(int row, String[] line);
|
||||
|
||||
/**
|
||||
* Called for each bean after it has been loaded from the CSV content.
|
||||
* <p>
|
||||
* This allows you to process the bean however you like.
|
||||
* </p>
|
||||
* <p>
|
||||
* When you use a CsvCallback the CsvReader *WILL NOT* create a transaction
|
||||
* and will not save the bean for you. You have complete control and must do
|
||||
* these things yourself (if that is want you want).
|
||||
* </p>
|
||||
*
|
||||
* @param row the index of the content being processed
|
||||
* @param line the content that has been used to load the bean
|
||||
* @param bean the entity bean after it has been loaded from the csv content
|
||||
*/
|
||||
void processBean(int row, String[] line, T bean);
|
||||
|
||||
/**
|
||||
* The processing has ended successfully.
|
||||
* <p>
|
||||
* Typically the callback will commit the transaction.
|
||||
* </p>
|
||||
*/
|
||||
void end(int row);
|
||||
|
||||
/**
|
||||
* The processing has ended due to an error.
|
||||
* <p>
|
||||
* This gives the callback the opportunity to rollback the transaction if one
|
||||
* was created.
|
||||
* </p>
|
||||
*
|
||||
* @param row the row that the error has occurred on
|
||||
* @param e the error that occurred
|
||||
*/
|
||||
void endWithError(int row, Exception e);
|
||||
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
package io.ebean.text.csv;
|
||||
|
||||
import io.ebean.text.StringParser;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Reads CSV data turning it into object graphs that you can be saved (inserted)
|
||||
* or processed yourself.
|
||||
* <p>
|
||||
* This first example doesn't use a {@link CsvCallback} and this means it will
|
||||
* automatically create a transaction, save the customers and commit the
|
||||
* transaction when successful.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
* try {
|
||||
* File f = new File("src/test/resources/test1.csv");
|
||||
*
|
||||
* FileReader reader = new FileReader(f, encoding);
|
||||
*
|
||||
* CsvReader<Customer> csvReader = DB.createCsvReader(Customer.class);
|
||||
*
|
||||
* csvReader.setPersistBatchSize(20);
|
||||
*
|
||||
* csvReader.addProperty("status");
|
||||
* // ignore the next property
|
||||
* csvReader.addIgnore();
|
||||
* csvReader.addProperty("name");
|
||||
* csvReader.addDateTime("anniversary", "dd-MMM-yyyy");
|
||||
* csvReader.addProperty("billingAddress.line1");
|
||||
* csvReader.addProperty("billingAddress.city");
|
||||
*
|
||||
* csvReader.process(reader);
|
||||
*
|
||||
* } catch (Exception e) {
|
||||
* throw new RuntimeException(e);
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @param <T> the entity bean type
|
||||
*/
|
||||
public interface CsvReader<T> {
|
||||
|
||||
/**
|
||||
* Explicitly set the default Locale.
|
||||
*/
|
||||
void setDefaultLocale(Locale defaultLocale);
|
||||
|
||||
/**
|
||||
* Set the default format to use for Time types.
|
||||
*/
|
||||
void setDefaultTimeFormat(String defaultTimeFormat);
|
||||
|
||||
/**
|
||||
* Set the default format to use for Date types.
|
||||
*/
|
||||
void setDefaultDateFormat(String defaultDateFormat);
|
||||
|
||||
/**
|
||||
* Set the default format to use for Timestamp types.
|
||||
*/
|
||||
void setDefaultTimestampFormat(String defaultTimestampFormat);
|
||||
|
||||
/**
|
||||
* Set the batch size for using JDBC statement batching.
|
||||
* <p>
|
||||
* By default this is set to 20 and setting this to 1 will disable the use of
|
||||
* JDBC statement batching.
|
||||
* </p>
|
||||
*/
|
||||
void setPersistBatchSize(int persistBatchSize);
|
||||
|
||||
/**
|
||||
* Set to true if there is a header row that should be ignored.
|
||||
* <p>
|
||||
* If addPropertiesFromHeader is true then all the properties are added using
|
||||
* the default time,date and timestamp formats.
|
||||
* <p>
|
||||
* If you have a mix of dateTime formats you can not use this method and must
|
||||
* add the properties yourself.
|
||||
* </p>
|
||||
*/
|
||||
void setHasHeader(boolean hasHeader, boolean addPropertiesFromHeader);
|
||||
|
||||
/**
|
||||
* Same as setHasHeader(true,true);
|
||||
* <p>
|
||||
* This will use a header to define all the properties to load using the
|
||||
* default formats for time, date and datetime types.
|
||||
* </p>
|
||||
*/
|
||||
void setAddPropertiesFromHeader();
|
||||
|
||||
/**
|
||||
* Same as setHasHeader(true, false);
|
||||
* <p>
|
||||
* This indicates that there is a header but that it should be ignored.
|
||||
* </p>
|
||||
*/
|
||||
void setIgnoreHeader();
|
||||
|
||||
/**
|
||||
* Set the frequency with which a INFO message will be logged showing the
|
||||
* progress of the processing. You might set this to 1000 or 10000 etc.
|
||||
* <p>
|
||||
* If this is not set then no INFO messages will be logged.
|
||||
* </p>
|
||||
*/
|
||||
void setLogInfoFrequency(int logInfoFrequency);
|
||||
|
||||
/**
|
||||
* Ignore the next column of data.
|
||||
*/
|
||||
void addIgnore();
|
||||
|
||||
/**
|
||||
* Define the property which will be loaded from the next column of data.
|
||||
* <p>
|
||||
* This takes into account the data type of the property and handles the
|
||||
* String to object conversion automatically.
|
||||
* </p>
|
||||
*/
|
||||
void addProperty(String propertyName);
|
||||
|
||||
/**
|
||||
* Define the next property and use a custom StringParser to convert the
|
||||
* string content into the appropriate type for the property.
|
||||
*/
|
||||
void addProperty(String propertyName, StringParser parser);
|
||||
|
||||
/**
|
||||
* Add a property with a custom Date/Time/Timestamp format using the default
|
||||
* Locale. This will convert the string into the appropriate java type for the
|
||||
* given property (Date, Calendar, SQL Date, Time, Timestamp, JODA etc).
|
||||
*/
|
||||
void addDateTime(String propertyName, String dateTimeFormat);
|
||||
|
||||
/**
|
||||
* Add a property with a custom Date/Time/Timestamp format. This will convert
|
||||
* the string into the appropriate java type for the given property (Date,
|
||||
* Calendar, SQL Date, Time, Timestamp, JODA etc).
|
||||
*/
|
||||
void addDateTime(String propertyName, String dateTimeFormat, Locale locale);
|
||||
|
||||
/**
|
||||
* Automatically create a transaction if required to process all the CSV
|
||||
* content from the reader.
|
||||
* <p>
|
||||
* This will check for a current transaction. If there is no current
|
||||
* transaction then one is started and will commit (or rollback) at the end of
|
||||
* processing. This will also set the persistBatchSize on the transaction.
|
||||
* </p>
|
||||
*/
|
||||
void process(Reader reader) throws Exception;
|
||||
|
||||
/**
|
||||
* Process the CSV content passing the bean to the CsvCallback after each row.
|
||||
* <p>
|
||||
* This provides you with the ability to modify and process the bean.
|
||||
* </p>
|
||||
* <p>
|
||||
* When using a CsvCallback the reader WILL NOT create a transaction or save
|
||||
* the bean(s) for you. If you want to insert the processed beans you must
|
||||
* create your own transaction and save the bean(s) yourself.
|
||||
* </p>
|
||||
*/
|
||||
void process(Reader reader, CsvCallback<T> callback) throws Exception;
|
||||
|
||||
}
|
||||
@@ -1,198 +0,0 @@
|
||||
package io.ebean.text.csv;
|
||||
|
||||
import io.ebean.Database;
|
||||
import io.ebean.Transaction;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Provides the default implementation of CsvCallback.
|
||||
* <p>
|
||||
* This handles transaction creation (if no current transaction existed) and
|
||||
* transaction commit or rollback on error.
|
||||
* </p>
|
||||
* <p>
|
||||
* For customising the processing you can extend this object and override the
|
||||
* appropriate methods.
|
||||
* </p>
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public class DefaultCsvCallback<T> implements CsvCallback<T> {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(DefaultCsvCallback.class);
|
||||
|
||||
/**
|
||||
* The transaction to use (if not using CsvCallback).
|
||||
*/
|
||||
protected Transaction transaction;
|
||||
|
||||
/**
|
||||
* Flag set when we created the transaction.
|
||||
*/
|
||||
protected boolean createdTransaction;
|
||||
|
||||
/**
|
||||
* The EbeanServer used to save the beans.
|
||||
*/
|
||||
protected Database server;
|
||||
|
||||
/**
|
||||
* Used to log a message to indicate progress through large files.
|
||||
*/
|
||||
protected final int logInfoFrequency;
|
||||
|
||||
/**
|
||||
* The batch size used when saving the beans.
|
||||
*/
|
||||
protected final int persistBatchSize;
|
||||
|
||||
/**
|
||||
* The time the process started.
|
||||
*/
|
||||
protected long startTime;
|
||||
|
||||
/**
|
||||
* The execution time of the process.
|
||||
*/
|
||||
protected long exeTime;
|
||||
|
||||
/**
|
||||
* Construct with a default batch size of 30 and logging info messages every
|
||||
* 1000 rows.
|
||||
*/
|
||||
public DefaultCsvCallback() {
|
||||
this(30, 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct with explicit batch size and logging info frequency.
|
||||
*/
|
||||
public DefaultCsvCallback(int persistBatchSize, int logInfoFrequency) {
|
||||
this.persistBatchSize = persistBatchSize;
|
||||
this.logInfoFrequency = logInfoFrequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a transaction if required.
|
||||
*/
|
||||
@Override
|
||||
public void begin(Database server) {
|
||||
this.server = server;
|
||||
this.startTime = System.currentTimeMillis();
|
||||
initTransactionIfRequired();
|
||||
}
|
||||
|
||||
/**
|
||||
* Override to read the heading line.
|
||||
* <p>
|
||||
* This is only called if {@link CsvReader#setHasHeader(boolean, boolean)} is
|
||||
* set to true.
|
||||
* <p>
|
||||
* By default this does nothing (effectively ignoring the heading).
|
||||
*/
|
||||
@Override
|
||||
public void readHeader(String[] line) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the content is valid and return false if the row should be
|
||||
* ignored.
|
||||
* <p>
|
||||
* By default this just returns true.
|
||||
* </p>
|
||||
* <p>
|
||||
* Override this to add custom validation logic returning false if you want
|
||||
* the row to be ignored. For example, if all the content is empty return
|
||||
* false to ignore the row (rather than having the processing fail with some
|
||||
* error).
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
public boolean processLine(int row, String[] line) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will save the bean.
|
||||
* <p>
|
||||
* Override this method to customise the bean (set additional properties etc)
|
||||
* or to control the saving of other related beans (when you can't/don't want
|
||||
* to use Cascade.PERSIST etc).
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
public void processBean(int row, String[] line, T bean) {
|
||||
// assumes single bean or Cascade.PERSIST will save any
|
||||
// related beans (e.g. customer -> customer.billingAddress
|
||||
server.save(bean, transaction);
|
||||
if (logInfoFrequency > 0 && (row % logInfoFrequency == 0)) {
|
||||
log.debug("processed {} rows", row);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit the transaction if one was created.
|
||||
*/
|
||||
@Override
|
||||
public void end(int row) {
|
||||
commitTransactionIfCreated();
|
||||
exeTime = System.currentTimeMillis() - startTime;
|
||||
log.info("Csv finished, rows[{}] exeMillis[{}]", row, exeTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback the transaction if one was created.
|
||||
*/
|
||||
@Override
|
||||
public void endWithError(int row, Exception e) {
|
||||
rollbackTransactionIfCreated(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a transaction if one is not already active and set its batch mode
|
||||
* and batch size.
|
||||
*/
|
||||
protected void initTransactionIfRequired() {
|
||||
transaction = server.currentTransaction();
|
||||
if (transaction == null || !transaction.isActive()) {
|
||||
transaction = server.beginTransaction();
|
||||
createdTransaction = true;
|
||||
if (persistBatchSize > 1) {
|
||||
log.debug("Creating transaction, batchSize[{}]", persistBatchSize);
|
||||
transaction.setBatchMode(true);
|
||||
transaction.setBatchSize(persistBatchSize);
|
||||
transaction.setGetGeneratedKeys(false);
|
||||
} else {
|
||||
// explicitly turn off JDBC batching in case
|
||||
// is has been turned on globally
|
||||
transaction.setBatchMode(false);
|
||||
log.debug("Creating transaction with no JDBC batching");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If we created a transaction commit it. We have successfully processed all
|
||||
* the rows.
|
||||
*/
|
||||
protected void commitTransactionIfCreated() {
|
||||
if (createdTransaction) {
|
||||
transaction.commit();
|
||||
log.debug("Committed transaction");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback the transaction if we where not successful in processing all the
|
||||
* rows.
|
||||
*/
|
||||
protected void rollbackTransactionIfCreated(Throwable e) {
|
||||
if (createdTransaction) {
|
||||
transaction.rollback(e);
|
||||
log.debug("Rolled back transaction");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
/**
|
||||
* CSV processing objects.
|
||||
*/
|
||||
package io.ebean.text.csv;
|
||||
@@ -1,19 +1,20 @@
|
||||
package io.ebean.util;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import io.ebean.EbeanVersion;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
import static java.lang.System.Logger.Level.WARNING;
|
||||
|
||||
/**
|
||||
* Utility for closing raw Jdbc resources.
|
||||
*/
|
||||
public final class JdbcClose {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger("io.ebean");
|
||||
private static final System.Logger log = EbeanVersion.log;
|
||||
|
||||
/**
|
||||
* Close the resultSet logging if an error occurs.
|
||||
@@ -24,7 +25,7 @@ public final class JdbcClose {
|
||||
statement.close();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.warn("Error closing statement", e);
|
||||
log.log(WARNING, "Error closing statement", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +38,7 @@ public final class JdbcClose {
|
||||
resultSet.close();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.warn("Error closing resultSet", e);
|
||||
log.log(WARNING, "Error closing resultSet", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +51,7 @@ public final class JdbcClose {
|
||||
connection.close();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.warn("Error closing connection", e);
|
||||
log.log(WARNING, "Error closing connection", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +64,7 @@ public final class JdbcClose {
|
||||
connection.rollback();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.warn("Error on connection rollback", e);
|
||||
log.log(WARNING, "Error on connection rollback", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +77,7 @@ public final class JdbcClose {
|
||||
stmt.cancel();
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
log.warn("Error on cancelling statement", e);
|
||||
log.log(WARNING, "Error on cancelling statement", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user