mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
638
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a70e289b00 | ||
|
|
4ad0e06aab | ||
|
|
86de7e845e | ||
|
|
38501ca372 | ||
|
|
4790c83fa1 | ||
|
|
b410c83492 | ||
|
|
b19145f16f | ||
|
|
c28cff2f40 | ||
|
|
0c8cf78ecc | ||
|
|
df112815ff | ||
|
|
85522ed8bc | ||
|
|
cf88f2375b | ||
|
|
24151f11fd | ||
|
|
424a83fa0a | ||
|
|
53dd91416c | ||
|
|
5a463c5071 | ||
|
|
bc3cf1348a | ||
|
|
f3b1024283 | ||
|
|
7ba35d7a62 | ||
|
|
990ca2980b | ||
|
|
38dd3d82fc | ||
|
|
6be26aaff2 | ||
|
|
d1462b032a | ||
|
|
6ab974a330 | ||
|
|
64618da6a7 | ||
|
|
d242ff7351 | ||
|
|
7d54aaa9a7 | ||
|
|
0e46184656 | ||
|
|
c9e1a6edbd | ||
|
|
3c0cffd146 | ||
|
|
d31547fb69 | ||
|
|
93adaa12bc | ||
|
|
d1cdbe94de | ||
|
|
e7c6223799 | ||
|
|
d33afd85de | ||
|
|
77bcb4aef9 | ||
|
|
a70fe184c2 | ||
|
|
7238f39be5 | ||
|
|
ae44b59c5f | ||
|
|
ced4e71307 | ||
|
|
9cb43bd5dd | ||
|
|
9665de2dbe | ||
|
|
e2666f0c4c | ||
|
|
89c83c90d1 | ||
|
|
cdd25351a6 | ||
|
|
17e0413837 | ||
|
|
b04419d9c7 | ||
|
|
0453892ebd | ||
|
|
55493c5b7d | ||
|
|
eb2f7cd852 | ||
|
|
f44eb234c8 | ||
|
|
404b57ab21 | ||
|
|
a54f09ca4b | ||
|
|
a3bb909308 | ||
|
|
7eb443859e | ||
|
|
8b39788ae3 | ||
|
|
1ec132b7dd | ||
|
|
343a975073 | ||
|
|
944f7bd086 | ||
|
|
3639c2a540 | ||
|
|
a9cc8ed702 | ||
|
|
0351a15067 | ||
|
|
c7300a1707 | ||
|
|
c48008c4b2 | ||
|
|
e5d8804591 | ||
|
|
f6dc294bc2 | ||
|
|
692baf8bb6 | ||
|
|
e1c00f3856 | ||
|
|
cf173d0695 | ||
|
|
a3798c6ca3 | ||
|
|
7bcf1da823 | ||
|
|
2ccd8dabeb | ||
|
|
f9800dd59e | ||
|
|
fb3e8b9fc4 | ||
|
|
18be5989c7 | ||
|
|
be91e3f3f7 | ||
|
|
03a9aa3dec | ||
|
|
a2a301beda | ||
|
|
695e4f653b | ||
|
|
e84c75929c | ||
|
|
7592178b6b | ||
|
|
70d65b734f | ||
|
|
f9a3dfeda0 | ||
|
|
eb85931fe2 | ||
|
|
1745334737 | ||
|
|
ea92ddfd89 | ||
|
|
3400928798 | ||
|
|
4e665fd66f | ||
|
|
09cd2c12e2 | ||
|
|
e3e45929f0 | ||
|
|
2caeafaaa2 | ||
|
|
5cd21de174 | ||
|
|
78df595861 | ||
|
|
3c89a0537f | ||
|
|
282463c2e8 | ||
|
|
03bb7a4aaf | ||
|
|
e4fa031cd3 | ||
|
|
00d227c598 | ||
|
|
fb86cb91bc | ||
|
|
f11ee20b73 | ||
|
|
3665c5bfaf | ||
|
|
638446680c | ||
|
|
bd9bfa25be | ||
|
|
753d17a8d2 | ||
|
|
f5cfce3f44 | ||
|
|
1c6363e85c | ||
|
|
b8bcbd8af9 | ||
|
|
d70768277b | ||
|
|
b39b4a2e8c | ||
|
|
93b2f4035c | ||
|
|
31ee0c4582 | ||
|
|
6c2dad4851 | ||
|
|
ed190ede03 | ||
|
|
f252b80c2d | ||
|
|
2859ea657e | ||
|
|
664b1cbd75 | ||
|
|
8bc283fef4 | ||
|
|
7d85398139 | ||
|
|
f42be3d65a | ||
|
|
ff8e5af4e5 | ||
|
|
526d67eeb4 | ||
|
|
374fc8d702 | ||
|
|
9c6c59afab | ||
|
|
c3eae0d3a5 | ||
|
|
25ec73364e | ||
|
|
c7818e7f23 | ||
|
|
8318bbc4ca | ||
|
|
337646a6ce | ||
|
|
fa6ee93e5b | ||
|
|
0fe691112f | ||
|
|
6946ff07e0 | ||
|
|
7c3d052da0 | ||
|
|
aea7a7fd65 | ||
|
|
f39a684c8e | ||
|
|
3cb5854786 | ||
|
|
e8192723cc | ||
|
|
3787748eae | ||
|
|
0ad52cf6a7 | ||
|
|
51bee836d4 | ||
|
|
9193b6b971 | ||
|
|
e48b9fab0f | ||
|
|
a14ca24b33 | ||
|
|
761f43d6a1 | ||
|
|
737f9a893e | ||
|
|
579812d717 | ||
|
|
fae39fe650 | ||
|
|
debd8ad617 | ||
|
|
6450ba219c | ||
|
|
a578eda2b1 | ||
|
|
a2ee0bfdbe | ||
|
|
872f0e21cb | ||
|
|
8620dbf337 | ||
|
|
4f51a3b130 | ||
|
|
5f194f066a | ||
|
|
31f6e56333 | ||
|
|
0efbe061ab | ||
|
|
555e5ba6fd | ||
|
|
5d3da60828 | ||
|
|
2ac0d136e6 | ||
|
|
97462cb21a | ||
|
|
afaacd4eeb | ||
|
|
5e8afbe50d | ||
|
|
db371cbc6a | ||
|
|
fd9a5167b1 | ||
|
|
7b76e13bce | ||
|
|
42e7103aa6 | ||
|
|
29ca678f01 | ||
|
|
cca6143420 | ||
|
|
fe7b110577 | ||
|
|
16df55eafa | ||
|
|
905a0ce9ec | ||
|
|
bfa8837e61 | ||
|
|
8d5845b9a2 | ||
|
|
87a7d4958e | ||
|
|
511ebd8a29 | ||
|
|
11f4c8d7a3 | ||
|
|
d417a92843 | ||
|
|
4bd5e52df3 | ||
|
|
788a200d16 | ||
|
|
e18d2004dc | ||
|
|
b326724139 | ||
|
|
fc0b47342b | ||
|
|
ec1a68a133 | ||
|
|
8ca12521d7 | ||
|
|
2362ef4130 | ||
|
|
7e233edcc3 | ||
|
|
a8b98282a1 | ||
|
|
b4506aa718 | ||
|
|
848a3b8888 | ||
|
|
67c711d75f | ||
|
|
3d62f58930 | ||
|
|
a30948d38d | ||
|
|
a8232d2d8b | ||
|
|
d4b8f23a5a | ||
|
|
bcf2a44187 | ||
|
|
f3102ba02c | ||
|
|
0351eab3a7 | ||
|
|
409e2b75ce | ||
|
|
dc968f16bf | ||
|
|
bbbb6482fb | ||
|
|
001968fcf8 | ||
|
|
6abcb186a4 | ||
|
|
f250447fbe | ||
|
|
bfa86f241b | ||
|
|
19459b71b4 | ||
|
|
5e97c3bbbc | ||
|
|
986eadd023 | ||
|
|
c6787d0901 | ||
|
|
3792e06859 | ||
|
|
c77446ba24 | ||
|
|
dba245c517 | ||
|
|
489eb483c0 | ||
|
|
11301846be | ||
|
|
d022e4aec8 | ||
|
|
aa788edb68 | ||
|
|
288adcdf68 | ||
|
|
ddb07ca202 | ||
|
|
524b592e82 | ||
|
|
0124f0f254 | ||
|
|
eddd6a36d6 | ||
|
|
91e309d770 | ||
|
|
5726410f6f | ||
|
|
054f7dc86f | ||
|
|
06b5ebc14e | ||
|
|
f6ee82428f | ||
|
|
e1d45dd79d | ||
|
|
08c455279f | ||
|
|
32dcbc6703 | ||
|
|
c9e733df4e | ||
|
|
606e1e6d3a | ||
|
|
fcb50ea13a | ||
|
|
5b26e77cfd | ||
|
|
9fc5d8a201 | ||
|
|
ba78c5e904 | ||
|
|
6627195fc2 | ||
|
|
b76c4a83ec | ||
|
|
3dcb82b1f5 | ||
|
|
ae55a40ebd | ||
|
|
8ba07419fa | ||
|
|
5f8f735bbe | ||
|
|
47829f3985 | ||
|
|
ec4f655312 | ||
|
|
04fda0a6b4 | ||
|
|
0a8c902790 | ||
|
|
9632279c2f | ||
|
|
262d52ed44 | ||
|
|
74330918e1 | ||
|
|
373598ab26 | ||
|
|
0096477757 | ||
|
|
a2a4a15f32 | ||
|
|
71dd0e5728 | ||
|
|
116cc3a3fe | ||
|
|
92132d6613 | ||
|
|
d6e3292a7d | ||
|
|
227a1ba032 | ||
|
|
953cae6ce8 | ||
|
|
98fc739600 | ||
|
|
fc3ab10984 | ||
|
|
5b8ce8eaa0 | ||
|
|
97cf8b30f6 | ||
|
|
7e66e0db1f | ||
|
|
572bb41b73 | ||
|
|
088fcfb296 | ||
|
|
54172aec6c | ||
|
|
5c1de0a886 | ||
|
|
c292da736b | ||
|
|
987fe38618 | ||
|
|
f4ed813c08 | ||
|
|
a358fba31d | ||
|
|
76783d525a | ||
|
|
3f0f5c7fde | ||
|
|
6df1058aab | ||
|
|
335c5fb69b | ||
|
|
94ed568812 | ||
|
|
1c23720605 | ||
|
|
ccba5d08ef | ||
|
|
641ada001e | ||
|
|
fca80ac649 | ||
|
|
379cc39e38 | ||
|
|
386d3a37f1 | ||
|
|
37612c6f83 | ||
|
|
7984553d96 | ||
|
|
d592e7d35f | ||
|
|
5a0b65b4f2 | ||
|
|
aaefaa5dcd | ||
|
|
f3e66c459a | ||
|
|
16d5e04809 | ||
|
|
b01df515bd | ||
|
|
7fda911931 | ||
|
|
e332aace16 | ||
|
|
c79231c846 | ||
|
|
efad23d482 | ||
|
|
fe8a32ea18 | ||
|
|
31099f6dda | ||
|
|
58f4f791f6 | ||
|
|
b27989f541 | ||
|
|
7bc1a902ed | ||
|
|
358720776e | ||
|
|
417ee4061e | ||
|
|
394cb3854a | ||
|
|
547fa342c4 | ||
|
|
f8b8a41bce | ||
|
|
ba39897b18 | ||
|
|
1437843f08 | ||
|
|
7c705e2baa | ||
|
|
2caeb4fff1 | ||
|
|
84190f3c2a | ||
|
|
46b158a0a0 | ||
|
|
b172a32710 | ||
|
|
f8ef87f7a8 | ||
|
|
ea54d1b794 | ||
|
|
b1780948a8 | ||
|
|
1a0f3a6614 | ||
|
|
580b51381e | ||
|
|
75e9770d5e | ||
|
|
10937de24b | ||
|
|
18aeedc153 | ||
|
|
9ca1a87f8b | ||
|
|
111354f391 | ||
|
|
79879fb326 | ||
|
|
9f6ccdee66 | ||
|
|
bbf469bd54 | ||
|
|
ad97ac2be9 | ||
|
|
9d83017374 | ||
|
|
98ec00a2d6 | ||
|
|
24971bcc86 | ||
|
|
c1c45139a0 | ||
|
|
116425b460 | ||
|
|
48acb6294b | ||
|
|
61f5057528 | ||
|
|
b91ef46243 | ||
|
|
0eddcc30bb | ||
|
|
24ec0fefba | ||
|
|
5ac28cb3fb | ||
|
|
d4635fb615 | ||
|
|
b9774e64e9 | ||
|
|
f29ba8383e | ||
|
|
a15dd33380 | ||
|
|
f22563b36a | ||
|
|
fe17ec5dbb | ||
|
|
85fdf8646d | ||
|
|
bd9acab335 | ||
|
|
0a6941bda5 | ||
|
|
215417a43c | ||
|
|
60c1a5b111 | ||
|
|
5166fbed96 | ||
|
|
851f40e7b0 | ||
|
|
845faf74ff | ||
|
|
c0d4dac2b3 | ||
|
|
f6c3279e86 | ||
|
|
48f0da9343 | ||
|
|
ce0d73cf23 | ||
|
|
1585bd7cd0 | ||
|
|
1603c69156 | ||
|
|
7cd9dc0c8d | ||
|
|
e4304494e1 | ||
|
|
0612d89e9a | ||
|
|
e6f779268a | ||
|
|
815d846695 | ||
|
|
4b74062d80 | ||
|
|
1dd0841f00 | ||
|
|
3a9668fe6c | ||
|
|
93f802f7fe | ||
|
|
8cde0da419 | ||
|
|
14f984ea3e | ||
|
|
253bebb9bb | ||
|
|
483538bbc1 | ||
|
|
c0ef6d8b34 | ||
|
|
7f06863b19 | ||
|
|
8be7ee1b7d | ||
|
|
15e2fde864 | ||
|
|
4e5140c877 | ||
|
|
13ed298ee8 | ||
|
|
e83a6f05bc | ||
|
|
a0c312e5a4 | ||
|
|
1eabb7fdb4 | ||
|
|
9e170b40f6 | ||
|
|
efd5e16511 | ||
|
|
c4e0d7aedc | ||
|
|
d1584bed40 | ||
|
|
689d201b04 | ||
|
|
22407506ff | ||
|
|
009f91b949 | ||
|
|
3bd281bea0 | ||
|
|
30c3a435d6 | ||
|
|
0fe321b0ef | ||
|
|
8f12442ac7 | ||
|
|
40ab3c81dc | ||
|
|
d5a8bf38ad | ||
|
|
0e793036fb | ||
|
|
19b7637d46 | ||
|
|
5609bc6d02 | ||
|
|
fceeeacf88 | ||
|
|
4327108ddf | ||
|
|
cb77f33fc8 | ||
|
|
b687305be2 | ||
|
|
192305c61f | ||
|
|
03faf29bcf | ||
|
|
d389f8b5ac | ||
|
|
56348938fb | ||
|
|
9b0aafbfa8 | ||
|
|
9239d61c74 | ||
|
|
58a110e109 | ||
|
|
b255102780 | ||
|
|
3a14b4c87f | ||
|
|
e1d6bf5961 | ||
|
|
8e546bde0b | ||
|
|
29a97d84a1 | ||
|
|
c526b3ef57 | ||
|
|
032721d246 | ||
|
|
0731084ec0 | ||
|
|
11a3e49daa | ||
|
|
68481844ee | ||
|
|
96a9def513 | ||
|
|
98a4f046ee | ||
|
|
9db8c941dc | ||
|
|
fd4a6906bd | ||
|
|
da65256208 | ||
|
|
0d2615522f | ||
|
|
6e5e5fb666 | ||
|
|
8005ef8432 | ||
|
|
49fe97bbe4 | ||
|
|
95ab97df73 | ||
|
|
3be9833ee0 | ||
|
|
b82223dc1d | ||
|
|
17d97623d5 | ||
|
|
1fca5ba008 | ||
|
|
5bb97ee42f | ||
|
|
ae9a03e58c | ||
|
|
ca12761fb2 | ||
|
|
18a61416fd | ||
|
|
37ff2c7227 | ||
|
|
af4018403b | ||
|
|
d3b9bde5c2 | ||
|
|
d704fef294 | ||
|
|
bb4bb64795 | ||
|
|
402ab092d8 | ||
|
|
9769e4b574 | ||
|
|
e19fe5ccd3 | ||
|
|
11963e1ff7 | ||
|
|
ec0d4fbd07 | ||
|
|
4e66e348fc | ||
|
|
eb6fce5a72 | ||
|
|
21b33bb9cd | ||
|
|
430b3cff96 | ||
|
|
334a8b66bd | ||
|
|
204b9ca6e5 | ||
|
|
93f13113e6 | ||
|
|
ca1f95df7a | ||
|
|
0c9bcca584 | ||
|
|
a27433dc11 | ||
|
|
dbd789f4be | ||
|
|
7efbffb46d | ||
|
|
559383a810 | ||
|
|
1897ac67a0 | ||
|
|
4f2d669897 | ||
|
|
f50b18556e | ||
|
|
1dc8a7f314 | ||
|
|
b526d07eed | ||
|
|
97cd0909e8 | ||
|
|
39cb85fda6 | ||
|
|
498f567e37 | ||
|
|
99cecd6756 | ||
|
|
7ab374b4ee | ||
|
|
22d36bd1c4 | ||
|
|
ebc4d9fdc5 | ||
|
|
b1c41a58f2 | ||
|
|
40710f788d | ||
|
|
5513c46f78 | ||
|
|
8879bd2be8 | ||
|
|
4ab8ced4a3 | ||
|
|
5bb9e1b188 | ||
|
|
db97d4576f | ||
|
|
c581fa27ab | ||
|
|
bef4e476d7 | ||
|
|
e30e35bf4f | ||
|
|
2e1f02163c | ||
|
|
1ce84ec343 | ||
|
|
6dc21ce69b | ||
|
|
8d5621248f | ||
|
|
b73cc378b5 | ||
|
|
564c7b8317 | ||
|
|
f4a61cddaf | ||
|
|
456f5c1d6a | ||
|
|
ae0404b1a7 | ||
|
|
31f91e571d | ||
|
|
20acd56bb9 | ||
|
|
a764006523 | ||
|
|
84b8777c2b | ||
|
|
c0fc7d69a6 | ||
|
|
4807ca32be | ||
|
|
4c841a8f9f | ||
|
|
6babebfec5 | ||
|
|
660666a28b | ||
|
|
34550dd778 | ||
|
|
64bc0636d7 | ||
|
|
aa199da57d | ||
|
|
b265ffd7d6 | ||
|
|
00f4aee80a | ||
|
|
d6973ed88d | ||
|
|
2ada43f6ba | ||
|
|
e800a18b31 | ||
|
|
ea5ceb61ca | ||
|
|
972609281f | ||
|
|
4ea68ebce4 | ||
|
|
d01c6262b6 | ||
|
|
19e3d82d98 | ||
|
|
f06c1b83a9 | ||
|
|
ea504a93cf | ||
|
|
9fe47194ff | ||
|
|
ba3b1fea6f | ||
|
|
58088b2090 | ||
|
|
cca7a505a3 | ||
|
|
ece7466117 | ||
|
|
3451280679 | ||
|
|
bef2894949 | ||
|
|
06b6638926 | ||
|
|
53cf6c162c | ||
|
|
069b83b78d | ||
|
|
c0c56c0040 | ||
|
|
92c298b848 | ||
|
|
831d2a6179 | ||
|
|
90886193c0 | ||
|
|
deed0bb01d | ||
|
|
7f2c705b94 | ||
|
|
6c0401b191 | ||
|
|
331d28b512 | ||
|
|
9fd936c521 | ||
|
|
4a13fc307b | ||
|
|
adef15ce2b | ||
|
|
88340618af | ||
|
|
49b97887b0 | ||
|
|
6843c72149 | ||
|
|
f78c217d83 | ||
|
|
ede91ecf78 | ||
|
|
efe4e69ed1 | ||
|
|
8a3d9edd34 | ||
|
|
b9aa76c367 | ||
|
|
a49b99156b | ||
|
|
54f3dbf35a | ||
|
|
27847424b3 | ||
|
|
a5e94f6ae2 | ||
|
|
9f8b3799eb | ||
|
|
7734919010 | ||
|
|
19f40cb2e5 | ||
|
|
3d4bd15dac | ||
|
|
a3c81c3a31 | ||
|
|
3549f88232 | ||
|
|
59d009bc94 | ||
|
|
a6edafbf2d | ||
|
|
5fab66204c | ||
|
|
2fa7c57357 | ||
|
|
890e924eb0 | ||
|
|
1c6592a6ec | ||
|
|
554c5a7bfc | ||
|
|
7a32c50894 | ||
|
|
3fa8f04a4c | ||
|
|
962d7f601d | ||
|
|
f2aa2b5b8b | ||
|
|
87b485cfa4 | ||
|
|
5a55b5235d | ||
|
|
97adb76eac | ||
|
|
d0d5ab474d | ||
|
|
d396f09b3a | ||
|
|
3baa5bca46 | ||
|
|
c00484026c | ||
|
|
71798afadd | ||
|
|
1ec2f74df9 | ||
|
|
61a0651439 | ||
|
|
eae06059c9 | ||
|
|
a1ff9034b6 | ||
|
|
1085a8d608 | ||
|
|
3a547bf487 | ||
|
|
82489636d5 | ||
|
|
3cafb37a73 | ||
|
|
b4c7cf529d | ||
|
|
ba5c67f936 | ||
|
|
2bd7995ca1 | ||
|
|
cc8c860709 | ||
|
|
7d25e31289 | ||
|
|
936e56835c | ||
|
|
0d848e9311 | ||
|
|
b794b6c77e | ||
|
|
f45d240682 | ||
|
|
1a6f68edd3 | ||
|
|
81683c5d2a | ||
|
|
2b535d59b8 | ||
|
|
ae0bbaaaf8 | ||
|
|
aaca20f9c3 | ||
|
|
245cbb0ea1 | ||
|
|
dbe984c668 | ||
|
|
89088f9480 | ||
|
|
80253c4e07 | ||
|
|
f96ce11c73 | ||
|
|
b8f8cb5ae7 | ||
|
|
b8a2aac95a | ||
|
|
7b090a6346 | ||
|
|
b10c68489f | ||
|
|
2dbb2d9911 | ||
|
|
b3b4c72a77 | ||
|
|
1c040e4583 | ||
|
|
9677e585b6 | ||
|
|
c53806224f | ||
|
|
6fd5927c64 | ||
|
|
920635c6df | ||
|
|
fb1c29b57c | ||
|
|
89bed8be67 | ||
|
|
776e48a501 | ||
|
|
0666a72df7 | ||
|
|
55000a3515 | ||
|
|
8307e259ba | ||
|
|
95b7574d04 | ||
|
|
f6466d3211 | ||
|
|
160e4d7dd1 | ||
|
|
a00980c61f | ||
|
|
72d2fcb59e | ||
|
|
0f503b2a2f | ||
|
|
a79e2e786a | ||
|
|
c9ffa2673f | ||
|
|
0e0fa37f0d | ||
|
|
f7bbd5b3bb | ||
|
|
ba614cd287 | ||
|
|
7d028f3318 | ||
|
|
21b04c244b | ||
|
|
957c2def43 | ||
|
|
35f9cd3821 | ||
|
|
e95d3304bf | ||
|
|
0f7c9da5d2 | ||
|
|
b4008da70c | ||
|
|
34a0f16c74 | ||
|
|
a880109201 | ||
|
|
0607151ac8 | ||
|
|
5c4ad4c01c | ||
|
|
3564504e00 | ||
|
|
49babef495 | ||
|
|
9e3362d004 | ||
|
|
3f0dcdb6d1 | ||
|
|
481116251d |
@@ -1,13 +1,17 @@
|
||||
*.autofetch
|
||||
*.sql
|
||||
*.orig
|
||||
.classpath
|
||||
.project
|
||||
.settings/
|
||||
target/
|
||||
logs/
|
||||
log/
|
||||
ebean-autotune.xml
|
||||
ebean-profiling*.xml
|
||||
/db
|
||||
/mydb.db
|
||||
!src/test/ddl-review/*.sql
|
||||
|
||||
|
||||
# Intellij project files
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
language: java
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
|
||||
addons:
|
||||
postgresql: "9.4"
|
||||
|
||||
services:
|
||||
- postgresql
|
||||
|
||||
before_script:
|
||||
- psql -c 'create extension pgcrypto;' -U postgres
|
||||
- psql -c 'create extension hstore;' -U postgres
|
||||
- psql -c 'create extension postgis;' -U postgres
|
||||
- psql -c 'create database unit;' -U postgres
|
||||
|
||||
env:
|
||||
- EBEAN_DB=h2
|
||||
- EBEAN_DB=pg
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.m2
|
||||
@@ -1,19 +1,11 @@
|
||||
[](https://waffle.io/ebean-orm/avaje-ebeanorm)
|
||||
* [](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebeanorm/avaje-ebeanorm) - avaje-ebeanorm
|
||||
* [](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebeanorm/avaje-ebeanorm-agent) - avaje-ebeanorm-agent
|
||||
* [](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebeanorm/avaje-ebeanorm-mavenenhancer) - avaje-ebeanorm-mavenenhancer
|
||||
|
||||
|
||||
Ebean ORM
|
||||
==============
|
||||
|
||||
Project Website
|
||||
----------------
|
||||
[http://ebean-orm.github.io/](http://ebean-orm.github.io/ "Ebean ORM's Website")
|
||||
|
||||
|
||||
Maven Dependency
|
||||
----------------
|
||||
<dependency>
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm</artifactId>
|
||||
<version>4.7.1</version>
|
||||
</dependency>
|
||||
[https://ebean-orm.github.io/](http://ebean-orm.github.io/ "Ebean ORM's Website")
|
||||
|
||||
|
||||
[Maven central - avaje-ebeanorm](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.avaje.ebeanorm%22%20AND%20a%3A%22avaje-ebeanorm%22 "maven central ebeanorm")
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm</artifactId>
|
||||
<version>4.7.3</version>
|
||||
<version>6.16.2</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>avaje-ebeanorm</name>
|
||||
<url>http://www.avaje.org</url>
|
||||
<url>http://ebean-orm.github.io/</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
@@ -43,6 +43,12 @@
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jetbrains</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>13.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.persistence</groupId>
|
||||
<artifactId>persistence-api</artifactId>
|
||||
@@ -55,6 +61,14 @@
|
||||
<version>1.7.7</version>
|
||||
</dependency>
|
||||
|
||||
<!-- provided scope for Spring boot loader classpath scanning support -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-loader</artifactId>
|
||||
<version>1.2.7.RELEASE</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- provided scope for JsonNode support -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
@@ -103,10 +117,24 @@
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>9.4-1201-jdbc41</version>
|
||||
<version>9.4-1202-jdbc41</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!--<dependency>-->
|
||||
<!--<groupId>oracle</groupId>-->
|
||||
<!--<artifactId>oracle-jdbc</artifactId>-->
|
||||
<!--<version>7.0</version>-->
|
||||
<!--<scope>test</scope>-->
|
||||
<!--</dependency>-->
|
||||
|
||||
<!--<dependency>-->
|
||||
<!--<groupId>microsoft</groupId>-->
|
||||
<!--<artifactId>sqlserver-jdbc</artifactId>-->
|
||||
<!--<version>4.2</version>-->
|
||||
<!--<scope>test</scope>-->
|
||||
<!--</dependency>-->
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
@@ -124,15 +152,17 @@
|
||||
<dependency>
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm-agent</artifactId>
|
||||
<version>4.5.1</version>
|
||||
<version>4.9.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Provided scope so that the H2HistoryTrigger can live in Ebean core
|
||||
and not require a separate module for it -->
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>1.4.182</version>
|
||||
<scope>test</scope>
|
||||
<version>1.4.189</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -152,36 +182,16 @@
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>5.1.27</version>
|
||||
<version>5.1.36</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-integration</artifactId>
|
||||
<version>1.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>1.9.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.0.9</version>
|
||||
<groupId>org.avaje.composite</groupId>
|
||||
<artifactId>avaje-composite-testing</artifactId>
|
||||
<version>1.1</version>
|
||||
<scope>test</scope>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -209,7 +219,7 @@
|
||||
<plugin>
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm-mavenenhancer</artifactId>
|
||||
<version>4.5.1</version>
|
||||
<version>4.8.1</version>
|
||||
<executions>
|
||||
<!-- Not going to enhance Model bean -->
|
||||
<execution>
|
||||
@@ -263,11 +273,11 @@
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.9.1</version>
|
||||
<configuration>
|
||||
<doctitle>Ebean 4</doctitle>
|
||||
<doctitle>Ebean 6</doctitle>
|
||||
<overview>src/main/java/com/avaje/ebean/overview.html</overview>
|
||||
<source>1.8</source>
|
||||
<doclet>org.avaje.doclet.PygmentsDoclet</doclet>
|
||||
<excludePackageNames>com.avaje.ebeaninternal.*:com.avaje.ebean.util</excludePackageNames>
|
||||
<excludePackageNames>com.avaje.ebeaninternal.*:com.avaje.ebean.util:com.avaje.ebean.dbmigration.ddlgeneration:com.avaje.ebean.dbmigration.migration:com.avaje.ebean.dbmigration.migrationreader:com.avaje.ebean.dbmigration.model</excludePackageNames>
|
||||
<docletArtifact>
|
||||
<groupId>org.avaje</groupId>
|
||||
<artifactId>pygments-doclet</artifactId>
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
/**
|
||||
* Administrative control of Autofetch during runtime.
|
||||
*/
|
||||
public interface AdminAutofetch {
|
||||
|
||||
/**
|
||||
* Return true if profiling is enabled.
|
||||
*/
|
||||
boolean isProfiling();
|
||||
|
||||
/**
|
||||
* Set to true to enable profiling.
|
||||
*/
|
||||
void setProfiling(boolean enable);
|
||||
|
||||
/**
|
||||
* Return true if autoFetch automatic query tuning is enabled.
|
||||
*/
|
||||
boolean isQueryTuning();
|
||||
|
||||
/**
|
||||
* Set to true to enable autoFetch automatic query tuning.
|
||||
*/
|
||||
void setQueryTuning(boolean enable);
|
||||
|
||||
/**
|
||||
* Returns the rate which profiling is collected. This is an int between 0 and
|
||||
* 100.
|
||||
*/
|
||||
double getProfilingRate();
|
||||
|
||||
/**
|
||||
* Set the rate at which profiling is collected after the base.
|
||||
*
|
||||
* @param rate
|
||||
* a int between 0 and 100.
|
||||
*/
|
||||
void setProfilingRate(double rate);
|
||||
|
||||
/**
|
||||
* Return the number of queries profiled after which profiling is collected at
|
||||
* a percentage rate.
|
||||
*/
|
||||
int getProfilingBase();
|
||||
|
||||
/**
|
||||
* Set a base number of queries to profile per query point.
|
||||
* <p>
|
||||
* After this amount of profiling has been obtained profiling is collected at
|
||||
* the Profiling Percentage rate.
|
||||
* </p>
|
||||
*/
|
||||
void setProfilingBase(int profilingBase);
|
||||
|
||||
/**
|
||||
* Return the minimum number of queries profiled before autoFetch will start
|
||||
* automatically tuning the queries.
|
||||
* <p>
|
||||
* This could be one which means start autoFetch tuning after the first
|
||||
* profiling information is collected.
|
||||
* </p>
|
||||
*/
|
||||
int getProfilingMin();
|
||||
|
||||
/**
|
||||
* Set the minimum number of queries profiled per query point before autoFetch
|
||||
* will automatically tune the queries.
|
||||
* <p>
|
||||
* Increasing this number will mean more profiling is collected before
|
||||
* autoFetch starts tuning the query.
|
||||
* </p>
|
||||
*/
|
||||
void setProfilingMin(int autoFetchMinThreshold);
|
||||
|
||||
/**
|
||||
* Fire a garbage collection (hint to the JVM). Assuming garbage collection
|
||||
* fires this will gather the usage profiling information.
|
||||
*/
|
||||
String collectUsageViaGC();
|
||||
|
||||
/**
|
||||
* This will take the current profiling information and update the "tuned
|
||||
* query detail".
|
||||
* <p>
|
||||
* This is done periodically and can also be manually invoked.
|
||||
* </p>
|
||||
*
|
||||
* @return a summary of the updates that occurred
|
||||
*/
|
||||
String updateTunedQueryInfo();
|
||||
|
||||
/**
|
||||
* Clear all the tuned query info.
|
||||
* <p>
|
||||
* Should only need do this for testing and playing around.
|
||||
* </p>
|
||||
*
|
||||
* @return the amount of tuned query information cleared.
|
||||
*/
|
||||
int clearTunedQueryInfo();
|
||||
|
||||
/**
|
||||
* Clear all the profiling information.
|
||||
* <p>
|
||||
* This means the profiling information will need to be re-gathered.
|
||||
* </p>
|
||||
* <p>
|
||||
* Should only need do this for testing and playing around.
|
||||
* </p>
|
||||
*
|
||||
* @return the amount of profiled information cleared.
|
||||
*/
|
||||
int clearProfilingInfo();
|
||||
|
||||
/**
|
||||
* Clear the query execution statistics.
|
||||
*/
|
||||
void clearQueryStatistics();
|
||||
|
||||
/**
|
||||
* Return the number of queries tuned by AutoFetch.
|
||||
*/
|
||||
int getTotalTunedQueryCount();
|
||||
|
||||
/**
|
||||
* Return the size of the TuneQuery map.
|
||||
*/
|
||||
int getTotalTunedQuerySize();
|
||||
|
||||
/**
|
||||
* Return the size of the profile map.
|
||||
*/
|
||||
int getTotalProfileSize();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
/**
|
||||
* Administrative control of AutoTune during runtime.
|
||||
*/
|
||||
public interface AutoTune {
|
||||
|
||||
/**
|
||||
* Fire a garbage collection (hint to the JVM). Assuming garbage collection
|
||||
* fires this will gather remaining usage profiling information.
|
||||
*/
|
||||
void collectProfiling();
|
||||
|
||||
/**
|
||||
* Output the profiling.
|
||||
* <p>
|
||||
* When profiling updates are applied to tuning at runtime this reports all tuning and profiling combined.
|
||||
* When profiling is not applied at runtime then this reports the diff report with new and diff entries relative
|
||||
* to the existing tuning.
|
||||
* </p>
|
||||
*/
|
||||
void reportProfiling();
|
||||
|
||||
}
|
||||
@@ -33,6 +33,38 @@ public interface BeanState {
|
||||
*/
|
||||
boolean isDirty();
|
||||
|
||||
/**
|
||||
* This can be called with true to disable lazy loading on the bean.
|
||||
*/
|
||||
void setDisableLazyLoad(boolean disableLazyLoading);
|
||||
|
||||
/**
|
||||
* Set the loaded state of the property given it's name.
|
||||
*
|
||||
* <p>
|
||||
* Typically this would be used to set the loaded state of a property
|
||||
* to false to ensure that the specific property is excluded from a
|
||||
* stateless update.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // populate a bean via say JSON
|
||||
* User user = ...;
|
||||
*
|
||||
* // set loaded state on the email property to false so that
|
||||
* // the email property is not included in a stateless update
|
||||
* Ebean.getBeanState(user).setPropertyLoaded("email", false);
|
||||
*
|
||||
* user.update();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
*
|
||||
* This will throw an IllegalArgumentException if the property is unknown.
|
||||
*/
|
||||
void setPropertyLoaded(String propertyName, boolean loaded);
|
||||
|
||||
/**
|
||||
* For partially populated beans returns the properties that are loaded on the
|
||||
* bean.
|
||||
|
||||
@@ -80,7 +80,7 @@ public interface CallableSql {
|
||||
/**
|
||||
* Return the label that is put into the transaction log.
|
||||
*/
|
||||
public String getLabel();
|
||||
String getLabel();
|
||||
|
||||
/**
|
||||
* Set the label that is put in the transaction log.
|
||||
|
||||
@@ -45,7 +45,7 @@ final class DRawSqlColumnsParser {
|
||||
String colInfo = sqlSelect.substring(start, pos++);
|
||||
colInfo = colInfo.trim();
|
||||
|
||||
String[] split = colInfo.split(" ");
|
||||
String[] split = colInfo.split("\\s(?=[^\\)]*(?:\\(|$))");
|
||||
if (split.length > 1) {
|
||||
ArrayList<String> tmp = new ArrayList<String>(split.length);
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
@@ -80,17 +80,18 @@ final class DRawSqlColumnsParser {
|
||||
return new ColumnMapping.Column(indexPos++, sb.toString(), split[split.length - 1]);
|
||||
}
|
||||
|
||||
private int nextComma() {
|
||||
private void nextComma() {
|
||||
boolean inQuote = false;
|
||||
int inbrackets = 0;
|
||||
while (pos < end) {
|
||||
char c = sqlSelect.charAt(pos);
|
||||
if (c == '\'') {
|
||||
inQuote = !inQuote;
|
||||
} else if (!inQuote && c == ',') {
|
||||
return pos;
|
||||
if (c == '\'') inQuote = !inQuote;
|
||||
else if (c == '(') inbrackets++;
|
||||
else if (c == ')') inbrackets--;
|
||||
else if (!inQuote && inbrackets == 0 && c == ',') {
|
||||
return;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ class DRawSqlParser {
|
||||
private int placeHolderAndWhere;
|
||||
private int placeHolderHaving;
|
||||
private int placeHolderAndHaving;
|
||||
private boolean hasPlaceHolders;
|
||||
private final boolean hasPlaceHolders;
|
||||
|
||||
private int selectPos = -1;
|
||||
private int distinctPos = -1;
|
||||
@@ -46,6 +46,7 @@ class DRawSqlParser {
|
||||
|
||||
private DRawSqlParser(String sqlString) {
|
||||
sqlString = sqlString.trim();
|
||||
sqlString = sqlString.replace('\n',' ');
|
||||
this.sql = sqlString;
|
||||
this.hasPlaceHolders = findAndRemovePlaceHolders();
|
||||
this.textParser = new SimpleTextParser(sqlString);
|
||||
@@ -98,19 +99,7 @@ class DRawSqlParser {
|
||||
}
|
||||
|
||||
private boolean hasPlaceHolders() {
|
||||
if (placeHolderWhere > -1) {
|
||||
return true;
|
||||
}
|
||||
if (placeHolderAndWhere > -1) {
|
||||
return true;
|
||||
}
|
||||
if (placeHolderHaving > -1) {
|
||||
return true;
|
||||
}
|
||||
if (placeHolderAndHaving > -1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return placeHolderWhere > -1 || placeHolderAndWhere > -1 || placeHolderHaving > -1 || placeHolderAndHaving > -1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,8 +121,7 @@ class DRawSqlParser {
|
||||
// trim of distinct keyword
|
||||
String distinct = preWhereExprSql.substring(0, 9);
|
||||
if (!distinct.equalsIgnoreCase("distinct ")) {
|
||||
throw new RuntimeException("Expecting [" + preWhereExprSql
|
||||
+ "] to start with \"select distinct\"");
|
||||
throw new RuntimeException("Expecting [" + preWhereExprSql + "] to start with \"select distinct\"");
|
||||
}
|
||||
preWhereExprSql = preWhereExprSql.substring(9);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.avaje.ebean;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -10,6 +9,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import javax.persistence.OptimisticLockException;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -22,7 +22,7 @@ import com.avaje.ebean.text.json.JsonContext;
|
||||
/**
|
||||
* This Ebean object is effectively a singleton that holds a map of registered
|
||||
* {@link EbeanServer}s. It additionally provides a convenient way to use the
|
||||
* 'default/primary' EbeanServer.
|
||||
* 'default' EbeanServer.
|
||||
* <p>
|
||||
* If you are using a Dependency Injection framework such as
|
||||
* <strong>Spring</strong> or <strong>Guice</strong> you will probably
|
||||
@@ -101,7 +101,7 @@ import com.avaje.ebean.text.json.JsonContext;
|
||||
* specific database.
|
||||
* </p>
|
||||
*
|
||||
* <pre> {@code
|
||||
* <pre>{@code
|
||||
*
|
||||
* // Get access to the Human Resources EbeanServer/Database
|
||||
* EbeanServer hrDb = Ebean.getServer("hr");
|
||||
@@ -146,9 +146,9 @@ public final class Ebean {
|
||||
private final Object monitor = new Object();
|
||||
|
||||
/**
|
||||
* The 'default/primary' EbeanServer.
|
||||
* The 'default' EbeanServer.
|
||||
*/
|
||||
private EbeanServer primaryServer;
|
||||
private EbeanServer defaultServer;
|
||||
|
||||
private ServerManager() {
|
||||
|
||||
@@ -162,31 +162,31 @@ public final class Ebean {
|
||||
|
||||
} else {
|
||||
// look to see if there is a default server defined
|
||||
String primaryName = PrimaryServer.getPrimaryServerName();
|
||||
logger.debug("primaryName:" + primaryName);
|
||||
if (primaryName != null && primaryName.trim().length() > 0) {
|
||||
primaryServer = getWithCreate(primaryName.trim());
|
||||
String defaultName = PrimaryServer.getDefaultServerName();
|
||||
logger.debug("defaultName:" + defaultName);
|
||||
if (defaultName != null && defaultName.trim().length() > 0) {
|
||||
defaultServer = getWithCreate(defaultName.trim());
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
} catch (Throwable e) {
|
||||
logger.error("Error trying to create the default EbeanServer", e);
|
||||
throw e;
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private EbeanServer getPrimaryServer() {
|
||||
if (primaryServer == null) {
|
||||
private EbeanServer getDefaultServer() {
|
||||
if (defaultServer == null) {
|
||||
String msg = "The default EbeanServer has not been defined?";
|
||||
msg += " This is normally set via the ebean.datasource.default property.";
|
||||
msg += " Otherwise it should be registered programatically via registerServer()";
|
||||
msg += " Otherwise it should be registered programmatically via registerServer()";
|
||||
throw new PersistenceException(msg);
|
||||
}
|
||||
return primaryServer;
|
||||
return defaultServer;
|
||||
}
|
||||
|
||||
private EbeanServer get(String name) {
|
||||
if (name == null || name.length() == 0) {
|
||||
return primaryServer;
|
||||
return defaultServer;
|
||||
}
|
||||
// non-synchronized read
|
||||
EbeanServer server = concMap.get(name);
|
||||
@@ -217,16 +217,16 @@ public final class Ebean {
|
||||
/**
|
||||
* Register a server so we can get it by its name.
|
||||
*/
|
||||
private void register(EbeanServer server, boolean isPrimaryServer) {
|
||||
registerWithName(server.getName(), server, isPrimaryServer);
|
||||
private void register(EbeanServer server, boolean isDefaultServer) {
|
||||
registerWithName(server.getName(), server, isDefaultServer);
|
||||
}
|
||||
|
||||
private void registerWithName(String name, EbeanServer server, boolean isPrimaryServer) {
|
||||
private void registerWithName(String name, EbeanServer server, boolean isDefaultServer) {
|
||||
synchronized (monitor) {
|
||||
concMap.put(name, server);
|
||||
syncMap.put(name, server);
|
||||
if (isPrimaryServer) {
|
||||
primaryServer = server;
|
||||
if (isDefaultServer) {
|
||||
defaultServer = server;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,12 +254,22 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*
|
||||
* @param name
|
||||
* the name of the server, use null for the 'default server'
|
||||
* the name of the server, can use null for the 'default server'
|
||||
*/
|
||||
public static EbeanServer getServer(String name) {
|
||||
return serverMgr.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default EbeanServer.
|
||||
* <p>
|
||||
* This is equivalent to <code>Ebean.getServer(null);</code>
|
||||
* </p>
|
||||
*/
|
||||
public static EbeanServer getDefaultServer() {
|
||||
return serverMgr.getDefaultServer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ExpressionFactory from the default server.
|
||||
* <p>
|
||||
@@ -278,23 +288,23 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static ExpressionFactory getExpressionFactory() {
|
||||
return serverMgr.getPrimaryServer().getExpressionFactory();
|
||||
return serverMgr.getDefaultServer().getExpressionFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the server with this Ebean singleton. Specify if the registered
|
||||
* server is the primary/default server.
|
||||
*/
|
||||
public static void register(EbeanServer server, boolean isPrimaryServer) {
|
||||
serverMgr.register(server, isPrimaryServer);
|
||||
public static void register(EbeanServer server, boolean defaultServer) {
|
||||
serverMgr.register(server, defaultServer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Backdoor for registering a mock implementation of EbeanServer as the default server.
|
||||
*/
|
||||
protected static EbeanServer mock(String name, EbeanServer server, boolean isPrimaryServer) {
|
||||
EbeanServer originalPrimaryServer = serverMgr.primaryServer;
|
||||
serverMgr.registerWithName(name, server, isPrimaryServer);
|
||||
protected static EbeanServer mock(String name, EbeanServer server, boolean defaultServer) {
|
||||
EbeanServer originalPrimaryServer = serverMgr.defaultServer;
|
||||
serverMgr.registerWithName(name, server, defaultServer);
|
||||
return originalPrimaryServer;
|
||||
}
|
||||
|
||||
@@ -311,7 +321,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static Object nextId(Class<?> beanType) {
|
||||
return serverMgr.getPrimaryServer().nextId(beanType);
|
||||
return serverMgr.getDefaultServer().nextId(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -359,7 +369,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static Transaction beginTransaction() {
|
||||
return serverMgr.getPrimaryServer().beginTransaction();
|
||||
return serverMgr.getDefaultServer().beginTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -370,7 +380,7 @@ public final class Ebean {
|
||||
*
|
||||
*/
|
||||
public static Transaction beginTransaction(TxIsolation isolation) {
|
||||
return serverMgr.getPrimaryServer().beginTransaction(isolation);
|
||||
return serverMgr.getDefaultServer().beginTransaction(isolation);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -425,7 +435,7 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static Transaction beginTransaction(TxScope scope){
|
||||
return serverMgr.getPrimaryServer().beginTransaction(scope);
|
||||
return serverMgr.getDefaultServer().beginTransaction(scope);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -433,7 +443,7 @@ public final class Ebean {
|
||||
* in scope.
|
||||
*/
|
||||
public static Transaction currentTransaction() {
|
||||
return serverMgr.getPrimaryServer().currentTransaction();
|
||||
return serverMgr.getDefaultServer().currentTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -446,21 +456,21 @@ public final class Ebean {
|
||||
* @throws PersistenceException if there is no currently active transaction
|
||||
*/
|
||||
public static void register(TransactionCallback transactionCallback) throws PersistenceException {
|
||||
serverMgr.getPrimaryServer().register(transactionCallback);
|
||||
serverMgr.getDefaultServer().register(transactionCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit the current transaction.
|
||||
*/
|
||||
public static void commitTransaction() {
|
||||
serverMgr.getPrimaryServer().commitTransaction();
|
||||
serverMgr.getDefaultServer().commitTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback the current transaction.
|
||||
*/
|
||||
public static void rollbackTransaction() {
|
||||
serverMgr.getPrimaryServer().rollbackTransaction();
|
||||
serverMgr.getDefaultServer().rollbackTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -489,7 +499,7 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static void endTransaction() {
|
||||
serverMgr.getPrimaryServer().endTransaction();
|
||||
serverMgr.getDefaultServer().endTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -500,7 +510,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static Map<String, ValuePair> diff(Object a, Object b) {
|
||||
return serverMgr.getPrimaryServer().diff(a, b);
|
||||
return serverMgr.getDefaultServer().diff(a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -523,7 +533,6 @@ public final class Ebean {
|
||||
* public class Order { ...
|
||||
*
|
||||
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
|
||||
* @JoinColumn(name="order_id")
|
||||
* List<OrderDetail> details;
|
||||
* ...
|
||||
* }
|
||||
@@ -537,7 +546,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static void save(Object bean) throws OptimisticLockException {
|
||||
serverMgr.getPrimaryServer().save(bean);
|
||||
serverMgr.getDefaultServer().save(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -545,14 +554,14 @@ public final class Ebean {
|
||||
* want to explicitly insert it.
|
||||
*/
|
||||
public static void insert(Object bean) {
|
||||
serverMgr.getPrimaryServer().insert(bean);
|
||||
serverMgr.getDefaultServer().insert(bean);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Insert a collection of beans.
|
||||
*/
|
||||
public static void insert(Collection<?> beans) {
|
||||
serverMgr.getPrimaryServer().insert(beans);
|
||||
public static void insertAll(Collection<?> beans) {
|
||||
serverMgr.getDefaultServer().insertAll(beans);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -576,7 +585,7 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static void markAsDirty(Object bean) throws OptimisticLockException {
|
||||
serverMgr.getPrimaryServer().markAsDirty(bean);
|
||||
serverMgr.getDefaultServer().markAsDirty(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -616,28 +625,21 @@ public final class Ebean {
|
||||
* @see ServerConfig#setUpdateChangesOnly(boolean)
|
||||
*/
|
||||
public static void update(Object bean) throws OptimisticLockException {
|
||||
serverMgr.getPrimaryServer().update(bean);
|
||||
serverMgr.getDefaultServer().update(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the beans in the collection.
|
||||
*/
|
||||
public static void update(Collection<?> beans) throws OptimisticLockException {
|
||||
serverMgr.getPrimaryServer().update(beans);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save all the beans from an Iterator.
|
||||
*/
|
||||
public static int save(Iterator<?> iterator) throws OptimisticLockException {
|
||||
return serverMgr.getPrimaryServer().save(iterator);
|
||||
public static void updateAll(Collection<?> beans) throws OptimisticLockException {
|
||||
serverMgr.getDefaultServer().updateAll(beans);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save all the beans from a Collection.
|
||||
*/
|
||||
public static int save(Collection<?> beans) throws OptimisticLockException {
|
||||
return serverMgr.getPrimaryServer().save(beans);
|
||||
public static int saveAll(Collection<?> beans) throws OptimisticLockException {
|
||||
return serverMgr.getDefaultServer().saveAll(beans);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -651,7 +653,7 @@ public final class Ebean {
|
||||
* @return the number of associations deleted (from the intersection table).
|
||||
*/
|
||||
public static int deleteManyToManyAssociations(Object ownerBean, String propertyName) {
|
||||
return serverMgr.getPrimaryServer().deleteManyToManyAssociations(ownerBean, propertyName);
|
||||
return serverMgr.getDefaultServer().deleteManyToManyAssociations(ownerBean, propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -669,7 +671,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static void saveManyToManyAssociations(Object ownerBean, String propertyName) {
|
||||
serverMgr.getPrimaryServer().saveManyToManyAssociations(ownerBean, propertyName);
|
||||
serverMgr.getDefaultServer().saveManyToManyAssociations(ownerBean, propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -689,46 +691,65 @@ public final class Ebean {
|
||||
* the property we want to save
|
||||
*/
|
||||
public static void saveAssociation(Object ownerBean, String propertyName) {
|
||||
serverMgr.getPrimaryServer().saveAssociation(ownerBean, propertyName);
|
||||
serverMgr.getDefaultServer().saveAssociation(ownerBean, propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 is configured with <code>@SoftDelete</code> then this will perform a soft
|
||||
* delete rather than a hard/permanent delete.
|
||||
* </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>
|
||||
*/
|
||||
public static void delete(Object bean) throws OptimisticLockException {
|
||||
serverMgr.getPrimaryServer().delete(bean);
|
||||
public static boolean delete(Object bean) throws OptimisticLockException {
|
||||
return serverMgr.getDefaultServer().delete(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the bean in permanent fashion (will not use soft delete).
|
||||
*/
|
||||
public static boolean deletePermanent(Object bean) throws OptimisticLockException {
|
||||
return serverMgr.getDefaultServer().deletePermanent(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the bean given its type and id.
|
||||
*/
|
||||
public static int delete(Class<?> beanType, Object id) {
|
||||
return serverMgr.getPrimaryServer().delete(beanType, id);
|
||||
return serverMgr.getDefaultServer().delete(beanType, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete several beans given their type and id values.
|
||||
*/
|
||||
public static void delete(Class<?> beanType, Collection<?> ids) {
|
||||
serverMgr.getPrimaryServer().delete(beanType, ids);
|
||||
public static void deleteAll(Class<?> beanType, Collection<?> ids) {
|
||||
serverMgr.getDefaultServer().deleteAll(beanType, ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all the beans from an Iterator.
|
||||
* Delete all the beans in the Collection.
|
||||
*/
|
||||
public static int delete(Iterator<?> it) throws OptimisticLockException {
|
||||
return serverMgr.getPrimaryServer().delete(it);
|
||||
public static int deleteAll(Collection<?> beans) throws OptimisticLockException {
|
||||
return serverMgr.getDefaultServer().deleteAll(beans);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all the beans from a Collection.
|
||||
* Delete permanent all the beans in the Collection (will not use soft delete).
|
||||
*/
|
||||
public static int delete(Collection<?> c) throws OptimisticLockException {
|
||||
return delete(c.iterator());
|
||||
public static int deleteAllPermanent(Collection<?> beans) throws OptimisticLockException {
|
||||
return serverMgr.getDefaultServer().deleteAllPermanent(beans);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -739,7 +760,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static void refresh(Object bean) {
|
||||
serverMgr.getPrimaryServer().refresh(bean);
|
||||
serverMgr.getDefaultServer().refresh(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -760,7 +781,7 @@ public final class Ebean {
|
||||
* the property name of the List Set or Map to refresh.
|
||||
*/
|
||||
public static void refreshMany(Object bean, String manyPropertyName) {
|
||||
serverMgr.getPrimaryServer().refreshMany(bean, manyPropertyName);
|
||||
serverMgr.getDefaultServer().refreshMany(bean, manyPropertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -788,7 +809,7 @@ public final class Ebean {
|
||||
* the id value
|
||||
*/
|
||||
public static <T> T getReference(Class<T> beanType, Object id) {
|
||||
return serverMgr.getPrimaryServer().getReference(beanType, id);
|
||||
return serverMgr.getDefaultServer().getReference(beanType, id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -834,7 +855,7 @@ public final class Ebean {
|
||||
* the properties to sort the list by
|
||||
*/
|
||||
public static <T> void sort(List<T> list, String sortByClause) {
|
||||
serverMgr.getPrimaryServer().sort(list, sortByClause);
|
||||
serverMgr.getDefaultServer().sort(list, sortByClause);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -883,8 +904,9 @@ public final class Ebean {
|
||||
* @param id
|
||||
* the id value
|
||||
*/
|
||||
@Nullable
|
||||
public static <T> T find(Class<T> beanType, Object id) {
|
||||
return serverMgr.getPrimaryServer().find(beanType, id);
|
||||
return serverMgr.getDefaultServer().find(beanType, id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -896,7 +918,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static SqlQuery createSqlQuery(String sql) {
|
||||
return serverMgr.getPrimaryServer().createSqlQuery(sql);
|
||||
return serverMgr.getDefaultServer().createSqlQuery(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -909,7 +931,7 @@ public final class Ebean {
|
||||
* the name of the query
|
||||
*/
|
||||
public static SqlQuery createNamedSqlQuery(String namedQuery) {
|
||||
return serverMgr.getPrimaryServer().createNamedSqlQuery(namedQuery);
|
||||
return serverMgr.getDefaultServer().createNamedSqlQuery(namedQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -927,7 +949,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static SqlUpdate createSqlUpdate(String sql) {
|
||||
return serverMgr.getPrimaryServer().createSqlUpdate(sql);
|
||||
return serverMgr.getDefaultServer().createSqlUpdate(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -936,7 +958,7 @@ public final class Ebean {
|
||||
* @see CallableSql
|
||||
*/
|
||||
public static CallableSql createCallableSql(String sql) {
|
||||
return serverMgr.getPrimaryServer().createCallableSql(sql);
|
||||
return serverMgr.getDefaultServer().createCallableSql(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -959,7 +981,7 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static SqlUpdate createNamedSqlUpdate(String namedQuery) {
|
||||
return serverMgr.getPrimaryServer().createNamedSqlUpdate(namedQuery);
|
||||
return serverMgr.getDefaultServer().createNamedSqlUpdate(namedQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -987,7 +1009,7 @@ public final class Ebean {
|
||||
*/
|
||||
public static <T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery) {
|
||||
|
||||
return serverMgr.getPrimaryServer().createNamedQuery(beanType, namedQuery);
|
||||
return serverMgr.getDefaultServer().createNamedQuery(beanType, namedQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1015,7 +1037,7 @@ public final class Ebean {
|
||||
* the object query
|
||||
*/
|
||||
public static <T> Query<T> createQuery(Class<T> beanType, String query) {
|
||||
return serverMgr.getPrimaryServer().createQuery(beanType, query);
|
||||
return serverMgr.getDefaultServer().createQuery(beanType, query);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1074,7 +1096,7 @@ public final class Ebean {
|
||||
*/
|
||||
public static <T> Update<T> createNamedUpdate(Class<T> beanType, String namedUpdate) {
|
||||
|
||||
return serverMgr.getPrimaryServer().createNamedUpdate(beanType, namedUpdate);
|
||||
return serverMgr.getDefaultServer().createNamedUpdate(beanType, namedUpdate);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1108,7 +1130,7 @@ public final class Ebean {
|
||||
*/
|
||||
public static <T> Update<T> createUpdate(Class<T> beanType, String ormUpdate) {
|
||||
|
||||
return serverMgr.getPrimaryServer().createUpdate(beanType, ormUpdate);
|
||||
return serverMgr.getDefaultServer().createUpdate(beanType, ormUpdate);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1116,7 +1138,7 @@ public final class Ebean {
|
||||
*/
|
||||
public static <T> CsvReader<T> createCsvReader(Class<T> beanType) {
|
||||
|
||||
return serverMgr.getPrimaryServer().createCsvReader(beanType);
|
||||
return serverMgr.getDefaultServer().createCsvReader(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1173,7 +1195,7 @@ public final class Ebean {
|
||||
*/
|
||||
public static <T> Query<T> createQuery(Class<T> beanType) {
|
||||
|
||||
return serverMgr.getPrimaryServer().createQuery(beanType);
|
||||
return serverMgr.getDefaultServer().createQuery(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1190,7 +1212,7 @@ public final class Ebean {
|
||||
*/
|
||||
public static <T> Query<T> find(Class<T> beanType) {
|
||||
|
||||
return serverMgr.getPrimaryServer().find(beanType);
|
||||
return serverMgr.getDefaultServer().find(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1204,7 +1226,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static <T> Filter<T> filter(Class<T> beanType) {
|
||||
return serverMgr.getPrimaryServer().filter(beanType);
|
||||
return serverMgr.getDefaultServer().filter(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1251,7 +1273,7 @@ public final class Ebean {
|
||||
* @see Ebean#execute(CallableSql)
|
||||
*/
|
||||
public static int execute(SqlUpdate sqlUpdate) {
|
||||
return serverMgr.getPrimaryServer().execute(sqlUpdate);
|
||||
return serverMgr.getDefaultServer().execute(sqlUpdate);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1280,7 +1302,7 @@ public final class Ebean {
|
||||
* @see Ebean#execute(SqlUpdate)
|
||||
*/
|
||||
public static int execute(CallableSql callableSql) {
|
||||
return serverMgr.getPrimaryServer().execute(callableSql);
|
||||
return serverMgr.getDefaultServer().execute(callableSql);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1305,7 +1327,7 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static void execute(TxScope scope, TxRunnable r) {
|
||||
serverMgr.getPrimaryServer().execute(scope, r);
|
||||
serverMgr.getDefaultServer().execute(scope, r);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1333,7 +1355,7 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static void execute(TxRunnable r) {
|
||||
serverMgr.getPrimaryServer().execute(r);
|
||||
serverMgr.getDefaultServer().execute(r);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1360,7 +1382,7 @@ public final class Ebean {
|
||||
*
|
||||
*/
|
||||
public static <T> T execute(TxScope scope, TxCallable<T> c) {
|
||||
return serverMgr.getPrimaryServer().execute(scope, c);
|
||||
return serverMgr.getDefaultServer().execute(scope, c);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1394,7 +1416,7 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static <T> T execute(TxCallable<T> c) {
|
||||
return serverMgr.getPrimaryServer().execute(c);
|
||||
return serverMgr.getDefaultServer().execute(c);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1431,10 +1453,9 @@ public final class Ebean {
|
||||
* @param deletes
|
||||
* true if rows on the table where deleted
|
||||
*/
|
||||
public static void externalModification(String tableName, boolean inserts, boolean updates,
|
||||
boolean deletes) {
|
||||
public static void externalModification(String tableName, boolean inserts, boolean updates, boolean deletes) {
|
||||
|
||||
serverMgr.getPrimaryServer().externalModification(tableName, inserts, updates, deletes);
|
||||
serverMgr.getDefaultServer().externalModification(tableName, inserts, updates, deletes);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1444,7 +1465,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static BeanState getBeanState(Object bean) {
|
||||
return serverMgr.getPrimaryServer().getBeanState(bean);
|
||||
return serverMgr.getDefaultServer().getBeanState(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1452,7 +1473,7 @@ public final class Ebean {
|
||||
*
|
||||
*/
|
||||
public static ServerCacheManager getServerCacheManager() {
|
||||
return serverMgr.getPrimaryServer().getServerCacheManager();
|
||||
return serverMgr.getDefaultServer().getServerCacheManager();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1460,7 +1481,7 @@ public final class Ebean {
|
||||
* queries.
|
||||
*/
|
||||
public static BackgroundExecutor getBackgroundExecutor() {
|
||||
return serverMgr.getPrimaryServer().getBackgroundExecutor();
|
||||
return serverMgr.getDefaultServer().getBackgroundExecutor();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1471,7 +1492,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static void runCacheWarming() {
|
||||
serverMgr.getPrimaryServer().runCacheWarming();
|
||||
serverMgr.getDefaultServer().runCacheWarming();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1483,22 +1504,14 @@ public final class Ebean {
|
||||
*/
|
||||
public static void runCacheWarming(Class<?> beanType) {
|
||||
|
||||
serverMgr.getPrimaryServer().runCacheWarming(beanType);
|
||||
serverMgr.getDefaultServer().runCacheWarming(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JsonContext for reading/writing JSON.
|
||||
*/
|
||||
public static JsonContext json() {
|
||||
return serverMgr.getPrimaryServer().json();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JsonContext for reading/writing JSON.
|
||||
* @deprecated Please use #json instead.
|
||||
*/
|
||||
public static JsonContext createJsonContext() {
|
||||
return json();
|
||||
return serverMgr.getDefaultServer().json();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.OptimisticLockException;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebean.annotation.CacheStrategy;
|
||||
import com.avaje.ebean.cache.ServerCacheManager;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.meta.MetaInfoManager;
|
||||
import com.avaje.ebean.plugin.SpiServer;
|
||||
import com.avaje.ebean.text.csv.CsvReader;
|
||||
import com.avaje.ebean.text.json.JsonContext;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.persistence.NonUniqueResultException;
|
||||
import javax.persistence.OptimisticLockException;
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Provides the API for fetching and saving beans to a particular DataSource.
|
||||
@@ -106,10 +107,9 @@ public interface EbeanServer {
|
||||
void shutdown(boolean shutdownDataSource, boolean deregisterDriver);
|
||||
|
||||
/**
|
||||
* Return the AdminAutofetch which is used to control and configure the
|
||||
* Autofetch service at runtime.
|
||||
* Return AutoTune which is used to control the AutoTune service at runtime.
|
||||
*/
|
||||
AdminAutofetch getAdminAutofetch();
|
||||
AutoTune getAutoTune();
|
||||
|
||||
/**
|
||||
* Return the name. This is used with {@link Ebean#getServer(String)} to get a
|
||||
@@ -128,6 +128,11 @@ public interface EbeanServer {
|
||||
*/
|
||||
MetaInfoManager getMetaInfoManager();
|
||||
|
||||
/**
|
||||
* Return the extended API intended for use by plugins.
|
||||
*/
|
||||
SpiServer getPluginApi();
|
||||
|
||||
/**
|
||||
* Return the BeanState for a given entity bean.
|
||||
* <p>
|
||||
@@ -148,7 +153,7 @@ public interface EbeanServer {
|
||||
* difference comparison.
|
||||
* </p>
|
||||
*/
|
||||
Map<String, ValuePair> diff(Object a, Object b);
|
||||
Map<String, ValuePair> diff(Object newBean, Object oldBean);
|
||||
|
||||
/**
|
||||
* Create a new instance of T that is an EntityBean.
|
||||
@@ -905,17 +910,13 @@ public interface EbeanServer {
|
||||
<T> void findEachWhile(Query<T> query, QueryEachWhileConsumer<T> consumer, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Deprecated in favor of #findEachWhile which is functionally exactly the same
|
||||
* but has a much better name.
|
||||
* Return versions of a @History entity bean.
|
||||
* <p>
|
||||
* Execute the query visiting the results. This is similar to findIterate in
|
||||
* that not all the result beans need to be held in memory at the same time
|
||||
* and as such is go for processing large queries.
|
||||
* 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>
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
<T> void findVisit(Query<T> query, QueryResultVisitor<T> visitor, Transaction transaction);
|
||||
<T> List<Version<T>> findVersions(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute a query returning a list of beans.
|
||||
@@ -1019,7 +1020,7 @@ public interface EbeanServer {
|
||||
SqlFutureList findFutureList(SqlQuery query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Return a PagedList for this query.
|
||||
* Return a PagedList for this query using pageIndex and pageSize.
|
||||
* <p>
|
||||
* The benefit of using this over just using the normal {@link Query#setFirstRow(int)} and
|
||||
* {@link Query#setMaxRows(int)} is that it additionally wraps an optional call to
|
||||
@@ -1041,6 +1042,38 @@ public interface EbeanServer {
|
||||
*/
|
||||
<T> PagedList<T> findPagedList(Query<T> query, Transaction transaction, int pageIndex, int pageSize);
|
||||
|
||||
/**
|
||||
* 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>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* PagedList<Order> pagedList = Ebean.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>
|
||||
@@ -1091,14 +1124,17 @@ public interface EbeanServer {
|
||||
<T> Map<?, T> findMap(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the query returning at most one entity bean. This will throw a
|
||||
* PersistenceException if the query finds more than one result.
|
||||
* 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#findUnique()} 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
|
||||
@@ -1106,11 +1142,28 @@ public interface EbeanServer {
|
||||
* @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#findUnique()
|
||||
*/
|
||||
@Nullable
|
||||
<T> T findUnique(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 sql query returning a list of MapBean.
|
||||
* <p>
|
||||
@@ -1185,6 +1238,7 @@ public interface EbeanServer {
|
||||
*
|
||||
* @see SqlQuery#findUnique()
|
||||
*/
|
||||
@Nullable
|
||||
SqlRow findUnique(SqlQuery query, Transaction transaction);
|
||||
|
||||
/**
|
||||
@@ -1207,7 +1261,6 @@ public interface EbeanServer {
|
||||
* public class Order { ...
|
||||
*
|
||||
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
|
||||
* @JoinColumn(name="order_id")
|
||||
* List<OrderDetail> details;
|
||||
* ...
|
||||
* }
|
||||
@@ -1222,34 +1275,60 @@ public interface EbeanServer {
|
||||
*/
|
||||
void save(Object bean) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Save all the beans in the iterator.
|
||||
*/
|
||||
int save(Iterator<?> it) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Save all the beans in the collection.
|
||||
*/
|
||||
int save(Collection<?> beans) throws OptimisticLockException;
|
||||
int saveAll(Collection<?> beans) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* 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>
|
||||
*/
|
||||
void delete(Object bean) throws OptimisticLockException;
|
||||
boolean delete(Object bean) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Delete all the beans from an Iterator.
|
||||
* 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>
|
||||
*/
|
||||
int delete(Iterator<?> it) throws OptimisticLockException;
|
||||
boolean delete(Object bean, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Delete all the beans in the collection.
|
||||
* Delete a bean permanently without soft delete.
|
||||
*/
|
||||
int delete(Collection<?> c) throws OptimisticLockException;
|
||||
boolean deletePermanent(Object bean) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Delete a bean permanently without soft delete using an explicit transaction.
|
||||
*/
|
||||
boolean deletePermanent(Object bean, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Delete all the beans in the collection permanently without soft delete.
|
||||
*/
|
||||
int deleteAllPermanent(Collection<?> beans) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Delete all the beans in the collection permanently without soft delete using an explicit transaction.
|
||||
*/
|
||||
int deleteAllPermanent(Collection<?> beans, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Delete the bean given its type and id.
|
||||
@@ -1261,16 +1340,26 @@ public interface EbeanServer {
|
||||
*/
|
||||
int delete(Class<?> beanType, Object id, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Delete all the beans in the collection.
|
||||
*/
|
||||
int deleteAll(Collection<?> beans) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Delete all the beans in the collection using an explicit transaction.
|
||||
*/
|
||||
int deleteAll(Collection<?> beans, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Delete several beans given their type and id values.
|
||||
*/
|
||||
void delete(Class<?> beanType, Collection<?> ids);
|
||||
void deleteAll(Class<?> beanType, Collection<?> ids);
|
||||
|
||||
/**
|
||||
* Delete several beans given their type and id values with an explicit
|
||||
* transaction.
|
||||
*/
|
||||
void delete(Class<?> beanType, Collection<?> ids, Transaction transaction);
|
||||
void deleteAll(Class<?> beanType, Collection<?> ids, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute a Sql Update Delete or Insert statement. This returns the number of
|
||||
@@ -1328,7 +1417,7 @@ public interface EbeanServer {
|
||||
* Execute a ORM insert update or delete statement with an explicit
|
||||
* transaction.
|
||||
*/
|
||||
int execute(Update<?> update, Transaction t);
|
||||
int execute(Update<?> update, Transaction transaction);
|
||||
|
||||
/**
|
||||
* For making calls to stored procedures.
|
||||
@@ -1400,27 +1489,22 @@ public interface EbeanServer {
|
||||
* the type of entity bean to find
|
||||
* @param beanType
|
||||
* the type of entity bean to find
|
||||
* @param uid
|
||||
* @param id
|
||||
* the bean id value
|
||||
* @param transaction
|
||||
* the transaction to use (can be null)
|
||||
*/
|
||||
<T> T find(Class<T> beanType, Object uid, Transaction transaction);
|
||||
<T> T find(Class<T> beanType, Object id, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Insert or update a bean with an explicit transaction.
|
||||
*/
|
||||
void save(Object bean, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Save all the beans in the iterator with an explicit transaction.
|
||||
*/
|
||||
int save(Iterator<?> it, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Save all the beans in the collection with an explicit transaction.
|
||||
*/
|
||||
int save(Collection<?> beans, Transaction transaction) throws OptimisticLockException;
|
||||
int saveAll(Collection<?> beans, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Marks the entity bean as dirty.
|
||||
@@ -1445,7 +1529,7 @@ public interface EbeanServer {
|
||||
void markAsDirty(Object bean);
|
||||
|
||||
/**
|
||||
* Saves the bean using an update. If you know you are updating a bean then it is preferrable to
|
||||
* Saves the bean using an update. If you know you are updating a bean then it is preferable to
|
||||
* use this update() method rather than save().
|
||||
* <p>
|
||||
* <b>Stateless updates:</b> Note that the bean does not have to be previously fetched to call
|
||||
@@ -1485,7 +1569,7 @@ public interface EbeanServer {
|
||||
/**
|
||||
* Update a bean additionally specifying a transaction.
|
||||
*/
|
||||
void update(Object bean, Transaction t) throws OptimisticLockException;
|
||||
void update(Object bean, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Update a bean additionally specifying a transaction and the deleteMissingChildren setting.
|
||||
@@ -1497,7 +1581,6 @@ public interface EbeanServer {
|
||||
* @param deleteMissingChildren
|
||||
* specify false if you do not want 'missing children' of a OneToMany
|
||||
* or ManyToMany to be automatically deleted.
|
||||
|
||||
*/
|
||||
void update(Object bean, Transaction transaction, boolean deleteMissingChildren) throws OptimisticLockException;
|
||||
|
||||
@@ -1505,13 +1588,13 @@ public interface EbeanServer {
|
||||
* Update a collection of beans. If there is no current transaction one is created and used to
|
||||
* update all the beans in the collection.
|
||||
*/
|
||||
void update(Collection<?> beans) throws OptimisticLockException;
|
||||
void updateAll(Collection<?> beans) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Update a collection of beans with an explicit transaction.
|
||||
*/
|
||||
void update(Collection<?> beans, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
void updateAll(Collection<?> beans, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Insert the bean.
|
||||
* <p>
|
||||
@@ -1525,18 +1608,18 @@ public interface EbeanServer {
|
||||
/**
|
||||
* Insert the bean with a transaction.
|
||||
*/
|
||||
void insert(Object bean, Transaction t);
|
||||
void insert(Object bean, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Insert a collection of beans. If there is no current transaction one is created and used to
|
||||
* insert all the beans in the collection.
|
||||
*/
|
||||
void insert(Collection<?> beans);
|
||||
void insertAll(Collection<?> beans);
|
||||
|
||||
/**
|
||||
* Insert a collection of beans with an explicit transaction.
|
||||
*/
|
||||
void insert(Collection<?> beans, Transaction t);
|
||||
void insertAll(Collection<?> beans, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Delete the associations (from the intersection table) of a ManyToMany given
|
||||
@@ -1545,7 +1628,7 @@ public interface EbeanServer {
|
||||
* Typically these deletions occur automatically when persisting a ManyToMany
|
||||
* collection and this provides a way to invoke those deletions directly.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @return the number of associations deleted (from the intersection table).
|
||||
*/
|
||||
int deleteManyToManyAssociations(Object ownerBean, String propertyName);
|
||||
@@ -1560,10 +1643,10 @@ public interface EbeanServer {
|
||||
* Typically these deletions occur automatically when persisting a ManyToMany
|
||||
* collection and this provides a way to invoke those deletions directly.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @return the number of associations deleted (from the intersection table).
|
||||
*/
|
||||
int deleteManyToManyAssociations(Object ownerBean, String propertyName, Transaction t);
|
||||
int deleteManyToManyAssociations(Object ownerBean, String propertyName, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Save the associations of a ManyToMany given the owner bean and the
|
||||
@@ -1585,7 +1668,7 @@ public interface EbeanServer {
|
||||
* way to invoke those insertions directly.
|
||||
* </p>
|
||||
*/
|
||||
void saveManyToManyAssociations(Object ownerBean, String propertyName, Transaction t);
|
||||
void saveManyToManyAssociations(Object ownerBean, String propertyName, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Save the associated collection or bean given the property name.
|
||||
@@ -1622,27 +1705,18 @@ public interface EbeanServer {
|
||||
* @param propertyName
|
||||
* the property we want to save
|
||||
*/
|
||||
void saveAssociation(Object ownerBean, String propertyName, Transaction t);
|
||||
void saveAssociation(Object ownerBean, String propertyName, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Delete the bean with an explicit transaction.
|
||||
*/
|
||||
void delete(Object bean, Transaction t) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Delete all the beans from an iterator.
|
||||
*/
|
||||
int delete(Iterator<?> it, Transaction t) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Execute explicitly passing a transaction.
|
||||
*/
|
||||
int execute(SqlUpdate updSql, Transaction t);
|
||||
int execute(SqlUpdate updSql, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute explicitly passing a transaction.
|
||||
*/
|
||||
int execute(CallableSql callableSql, Transaction t);
|
||||
int execute(CallableSql callableSql, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute a TxRunnable in a Transaction with an explicit scope.
|
||||
@@ -1665,7 +1739,7 @@ public interface EbeanServer {
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
void execute(TxScope scope, TxRunnable r);
|
||||
void execute(TxScope scope, TxRunnable runnable);
|
||||
|
||||
/**
|
||||
* Execute a TxRunnable in a Transaction with the default scope.
|
||||
@@ -1691,7 +1765,7 @@ public interface EbeanServer {
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
void execute(TxRunnable r);
|
||||
void execute(TxRunnable runnable);
|
||||
|
||||
/**
|
||||
* Execute a TxCallable in a Transaction with an explicit scope.
|
||||
@@ -1715,7 +1789,7 @@ public interface EbeanServer {
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
<T> T execute(TxScope scope, TxCallable<T> c);
|
||||
<T> T execute(TxScope scope, TxCallable<T> callable);
|
||||
|
||||
/**
|
||||
* Execute a TxCallable in a Transaction with the default scope.
|
||||
@@ -1747,7 +1821,7 @@ public interface EbeanServer {
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
<T> T execute(TxCallable<T> c);
|
||||
<T> T execute(TxCallable<T> callable);
|
||||
|
||||
/**
|
||||
* Return the manager of the server cache ("L2" cache).
|
||||
@@ -1777,12 +1851,6 @@ public interface EbeanServer {
|
||||
*/
|
||||
void runCacheWarming(Class<?> beanType);
|
||||
|
||||
/**
|
||||
* Return the JsonContext for reading/writing JSON.
|
||||
* @deprecated Please use #json instead.
|
||||
*/
|
||||
JsonContext createJsonContext();
|
||||
|
||||
/**
|
||||
* Return the JsonContext for reading/writing JSON.
|
||||
* <p>
|
||||
@@ -1823,4 +1891,114 @@ public interface EbeanServer {
|
||||
*/
|
||||
JsonContext json();
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param id the id of the entity bean
|
||||
* @param transaction the transaction the publish process should use (can be null)
|
||||
*/
|
||||
<T> T publish(Class<T> beanType, Object id, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Publish a single bean given its type and id returning the resulting live bean.
|
||||
* 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
|
||||
* @param id the id of the entity bean
|
||||
*/
|
||||
<T> T publish(Class<T> beanType, Object id);
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param transaction the transaction the publish process should use (can be null)
|
||||
*/
|
||||
<T> List<T> publish(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Publish the beans that match the query returning the resulting published beans.
|
||||
* 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
|
||||
*/
|
||||
<T> List<T> publish(Query<T> query);
|
||||
|
||||
/**
|
||||
* Restore the draft bean back to the live state.
|
||||
* <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
|
||||
* @param id the id of the entity bean to restore
|
||||
* @param transaction the transaction the restore process should use (can be null)
|
||||
*/
|
||||
<T> T draftRestore(Class<T> beanType, Object id, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Restore the draft bean back to the live state.
|
||||
* <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
|
||||
* @param id the id of the entity bean to restore
|
||||
*/
|
||||
<T> T draftRestore(Class<T> beanType, Object id);
|
||||
|
||||
/**
|
||||
* Restore the draft beans matching the query back to the live state.
|
||||
* <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
|
||||
* @param transaction the transaction the restore process should use (can be null)
|
||||
*/
|
||||
<T> List<T> draftRestore(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Restore the draft beans matching the query back to the live state.
|
||||
* <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
|
||||
*/
|
||||
<T> List<T> draftRestore(Query<T> query);
|
||||
|
||||
/**
|
||||
* Returns the set of properties/paths that are unknown (do not map to known properties or paths).
|
||||
* <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);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,51 @@ import java.util.Map;
|
||||
*/
|
||||
public interface ExpressionFactory {
|
||||
|
||||
/**
|
||||
* Path exists - for the given path in a JSON document.
|
||||
*/
|
||||
Expression jsonExists(String propertyName, String path);
|
||||
|
||||
/**
|
||||
* Path does not exist - for the given path in a JSON document.
|
||||
*/
|
||||
Expression jsonNotExists(String propertyName, String path);
|
||||
|
||||
/**
|
||||
* Equal to - for the given path in a JSON document.
|
||||
*/
|
||||
Expression jsonEqualTo(String propertyName, String path, Object val);
|
||||
|
||||
/**
|
||||
* Not Equal to - for the given path in a JSON document.
|
||||
*/
|
||||
Expression jsonNotEqualTo(String propertyName, String path, Object val);
|
||||
|
||||
/**
|
||||
* Greater than - for the given path in a JSON document.
|
||||
*/
|
||||
Expression jsonGreaterThan(String propertyName, String path, Object val);
|
||||
|
||||
/**
|
||||
* Greater than or equal to - for the given path in a JSON document.
|
||||
*/
|
||||
Expression jsonGreaterOrEqual(String propertyName, String path, Object val);
|
||||
|
||||
/**
|
||||
* Less than - for the given path in a JSON document.
|
||||
*/
|
||||
Expression jsonLessThan(String propertyName, String path, Object val);
|
||||
|
||||
/**
|
||||
* Less than or equal to - for the given path in a JSON document.
|
||||
*/
|
||||
Expression jsonLessOrEqualTo(String propertyName, String path, Object val);
|
||||
|
||||
/**
|
||||
* Between - for the given path in a JSON document.
|
||||
*/
|
||||
Expression jsonBetween(String propertyName, String path, Object lowerValue, Object upperValue);
|
||||
|
||||
/**
|
||||
* Equal To - property equal to the given value.
|
||||
*/
|
||||
@@ -169,7 +214,22 @@ public interface ExpressionFactory {
|
||||
* In - property has a value in the collection of values.
|
||||
*/
|
||||
Expression in(String propertyName, Collection<?> values);
|
||||
|
||||
|
||||
/**
|
||||
* Not In - property has a value in the array of values.
|
||||
*/
|
||||
Expression notIn(String propertyName, Object[] values);
|
||||
|
||||
/**
|
||||
* Not In - property has a value in the collection of values.
|
||||
*/
|
||||
Expression notIn(String propertyName, Collection<?> values);
|
||||
|
||||
/**
|
||||
* Not In - using a subQuery.
|
||||
*/
|
||||
Expression notIn(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Exists expression
|
||||
*/
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import com.avaje.ebean.text.PathProperties;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.persistence.NonUniqueResultException;
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -94,6 +97,39 @@ public interface ExpressionList<T> extends Serializable {
|
||||
*/
|
||||
Query<T> apply(PathProperties pathProperties);
|
||||
|
||||
/**
|
||||
* Perform an 'As of' query using history tables to return the object graph
|
||||
* as of a time in the past.
|
||||
* <p>
|
||||
* To perform this query the DB must have underlying history tables.
|
||||
* </p>
|
||||
*
|
||||
* @param asOf the date time in the past at which you want to view the data
|
||||
*/
|
||||
Query<T> asOf(Timestamp asOf);
|
||||
|
||||
/**
|
||||
* Execute the query against the draft set of tables.
|
||||
*/
|
||||
Query<T> asDraft();
|
||||
|
||||
/**
|
||||
* Execute the query including soft deleted rows.
|
||||
*/
|
||||
Query<T> includeSoftDeletes();
|
||||
|
||||
/**
|
||||
* Execute as a delete query deleting the 'root level' beans that match the predicates
|
||||
* in the query.
|
||||
* <p>
|
||||
* Note that if the query includes joins then the generated delete statement may not be
|
||||
* optimal depending on the database platform.
|
||||
* </p>
|
||||
*
|
||||
* @return the number of beans/rows that were deleted.
|
||||
*/
|
||||
int delete();
|
||||
|
||||
/**
|
||||
* Execute the query iterating over the results.
|
||||
*
|
||||
@@ -116,14 +152,6 @@ public interface ExpressionList<T> extends Serializable {
|
||||
*/
|
||||
void findEachWhile(QueryEachWhileConsumer<T> consumer);
|
||||
|
||||
/**
|
||||
* Deprecated in favor of #findEachWhile which is functionally exactly the same
|
||||
* but has a much better name.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
void findVisit(QueryResultVisitor<T> visitor);
|
||||
|
||||
/**
|
||||
* Execute the query returning a list.
|
||||
*
|
||||
@@ -166,10 +194,18 @@ public interface ExpressionList<T> extends Serializable {
|
||||
<K> Map<K, T> findMap(String keyProperty, Class<K> keyType);
|
||||
|
||||
/**
|
||||
* Execute the query returning a single bean.
|
||||
*
|
||||
* Execute the query returning a single bean or null (if no matching
|
||||
* bean is found).
|
||||
* <p>
|
||||
* If more than 1 row is found for this query then a NonUniqueResultException is
|
||||
* thrown.
|
||||
* </p>
|
||||
*
|
||||
* @throws NonUniqueResultException if more than one result was found
|
||||
*
|
||||
* @see Query#findUnique()
|
||||
*/
|
||||
@Nullable
|
||||
T findUnique();
|
||||
|
||||
/**
|
||||
@@ -209,7 +245,7 @@ public interface ExpressionList<T> extends Serializable {
|
||||
FutureList<T> findFutureList();
|
||||
|
||||
/**
|
||||
* Return a PagedList for this query.
|
||||
* Return a PagedList for this query using pageIndex and pageSize.
|
||||
* <p>
|
||||
* The benefit of using this over just using the normal {@link Query#setFirstRow(int)} and
|
||||
* {@link Query#setMaxRows(int)} is that it additionally wraps an optional call to
|
||||
@@ -229,6 +265,56 @@ public interface ExpressionList<T> extends Serializable {
|
||||
*/
|
||||
PagedList<T> findPagedList(int pageIndex, int pageSize);
|
||||
|
||||
/**
|
||||
* 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>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* PagedList<Order> pagedList = Ebean.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()
|
||||
*/
|
||||
PagedList<T> findPagedList();
|
||||
|
||||
/**
|
||||
* 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>
|
||||
*/
|
||||
List<Version<T>> findVersions();
|
||||
|
||||
/**
|
||||
* Return versions of a @History entity bean between the 2 timestamps.
|
||||
* <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>
|
||||
*/
|
||||
List<Version<T>> findVersionsBetween(Timestamp start, Timestamp end);
|
||||
|
||||
/**
|
||||
* Add some filter predicate expressions to the many property.
|
||||
*/
|
||||
@@ -242,6 +328,24 @@ public interface ExpressionList<T> extends Serializable {
|
||||
*/
|
||||
Query<T> select(String properties);
|
||||
|
||||
/**
|
||||
* Set whether this query uses DISTINCT.
|
||||
* <p>
|
||||
* The select() clause MUST be specified when setDistinct(true) is set. The reason for this is that
|
||||
* generally ORM queries include the "id" property and this doesn't make sense for distinct queries.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<Customer> customers =
|
||||
* Ebean.find(Customer.class)
|
||||
* .setDistinct(true)
|
||||
* .select("name") // only select the customer name
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
Query<T> setDistinct(boolean distinct);
|
||||
|
||||
/**
|
||||
* Set the first row to fetch.
|
||||
*
|
||||
@@ -270,6 +374,13 @@ public interface ExpressionList<T> extends Serializable {
|
||||
*/
|
||||
Query<T> setUseCache(boolean useCache);
|
||||
|
||||
/**
|
||||
* Set to true to use the query for executing this query.
|
||||
*
|
||||
* @see Query#setUseQueryCache(boolean)
|
||||
*/
|
||||
Query<T> setUseQueryCache(boolean useCache);
|
||||
|
||||
/**
|
||||
* Add expressions to the having clause.
|
||||
* <p>
|
||||
@@ -284,20 +395,136 @@ public interface ExpressionList<T> extends Serializable {
|
||||
*/
|
||||
ExpressionList<T> where();
|
||||
|
||||
/**
|
||||
* Path exists - for the given path in a JSON document.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* where().jsonExists("content", "path.other")
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param propertyName the property that holds a JSON document
|
||||
* @param path the nested path in the JSON document in dot notation
|
||||
*/
|
||||
ExpressionList<T> jsonExists(String propertyName, String path);
|
||||
|
||||
/**
|
||||
* Path does not exist - for the given path in a JSON document.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* where().jsonNotExists("content", "path.other")
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param propertyName the property that holds a JSON document
|
||||
* @param path the nested path in the JSON document in dot notation
|
||||
*/
|
||||
ExpressionList<T> jsonNotExists(String propertyName, String path);
|
||||
|
||||
/**
|
||||
* Equal to expression for the value at the given path in the JSON document.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* where().jsonEqualTo("content", "path.other", 34)
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param propertyName the property that holds a JSON document
|
||||
* @param path the nested path in the JSON document in dot notation
|
||||
* @param value the value used to test against the document path's value
|
||||
*/
|
||||
ExpressionList<T> jsonEqualTo(String propertyName, String path, Object value);
|
||||
|
||||
/**
|
||||
* Not Equal to - for the given path in a JSON document.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* where().jsonNotEqualTo("content", "path.other", 34)
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param propertyName the property that holds a JSON document
|
||||
* @param path the nested path in the JSON document in dot notation
|
||||
* @param value the value used to test against the document path's value
|
||||
*/
|
||||
ExpressionList<T> jsonNotEqualTo(String propertyName, String path, Object value);
|
||||
|
||||
/**
|
||||
* Greater than - for the given path in a JSON document.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* where().jsonGreaterThan("content", "path.other", 34)
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
ExpressionList<T> jsonGreaterThan(String propertyName, String path, Object value);
|
||||
|
||||
/**
|
||||
* Greater than or equal to - for the given path in a JSON document.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* where().jsonGreaterOrEqual("content", "path.other", 34)
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
ExpressionList<T> jsonGreaterOrEqual(String propertyName, String path, Object value);
|
||||
|
||||
/**
|
||||
* Less than - for the given path in a JSON document.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* where().jsonLessThan("content", "path.other", 34)
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
ExpressionList<T> jsonLessThan(String propertyName, String path, Object value);
|
||||
|
||||
/**
|
||||
* Less than or equal to - for the given path in a JSON document.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* where().jsonLessOrEqualTo("content", "path.other", 34)
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
ExpressionList<T> jsonLessOrEqualTo(String propertyName, String path, Object value);
|
||||
|
||||
/**
|
||||
* Between - for the given path in a JSON document.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* where().jsonBetween("content", "orderDate", lowerDateTime, upperDateTime)
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
ExpressionList<T> jsonBetween(String propertyName, String path, Object lowerValue, Object upperValue);
|
||||
|
||||
/**
|
||||
* Add an Expression to the list.
|
||||
* <p>
|
||||
* This returns the list so that add() can be chained.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* Query<Customer> query = Ebean.createQuery(Customer.class);
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* Query<Customer> query = Ebean.find(Customer.class);
|
||||
* query.where()
|
||||
* .like("name","Rob%")
|
||||
* .eq("status", Customer.ACTIVE);
|
||||
* List<Customer> list = query.findList();
|
||||
* .like("name","Rob%")
|
||||
* .eq("status", Customer.ACTIVE);
|
||||
*
|
||||
* List<Customer> list = query.findList();
|
||||
* ...
|
||||
* </pre>
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
ExpressionList<T> add(Expression expr);
|
||||
|
||||
@@ -378,33 +605,36 @@ public interface ExpressionList<T> extends Serializable {
|
||||
* those options such as case insensitive etc.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* <pre>{@code
|
||||
*
|
||||
* // create an example bean and set the properties
|
||||
* // with the query parameters you want
|
||||
* Customer example = new Customer();
|
||||
* example.setName("Rob%");
|
||||
* example.setNotes("%something%");
|
||||
* example.setName("Rob%");
|
||||
* example.setNotes("%something%");
|
||||
*
|
||||
* List<Customer> list = Ebean.find(Customer.class).where()
|
||||
* // pass the bean into the where() clause
|
||||
* .exampleLike(example)
|
||||
* // you can add other expressions to the same query
|
||||
* .gt("id", 2).findList();
|
||||
* .gt("id", 2).findList();
|
||||
*
|
||||
* </pre>
|
||||
* }</pre>
|
||||
*
|
||||
* Similarly you can create an ExampleExpression
|
||||
*
|
||||
* <pre>
|
||||
* <pre>{@code
|
||||
*
|
||||
* Customer example = new Customer();
|
||||
* example.setName("Rob%");
|
||||
* example.setNotes("%something%");
|
||||
* example.setName("Rob%");
|
||||
* example.setNotes("%something%");
|
||||
*
|
||||
* // create a ExampleExpression with more control
|
||||
* ExampleExpression qbe = new ExampleExpression(example, true, LikeType.EQUAL_TO).includeZeros();
|
||||
*
|
||||
* List<Customer> list = Ebean.find(Customer.class).where().add(qbe).findList();
|
||||
* </pre>
|
||||
* List<Customer> list = Ebean.find(Customer.class).where().add(qbe).findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
ExpressionList<T> exampleLike(Object example);
|
||||
|
||||
@@ -473,7 +703,22 @@ public interface ExpressionList<T> extends Serializable {
|
||||
* In - property has a value in the collection of values.
|
||||
*/
|
||||
ExpressionList<T> in(String propertyName, Collection<?> values);
|
||||
|
||||
|
||||
/**
|
||||
* Not In - property has a value in the array of values.
|
||||
*/
|
||||
ExpressionList<T> notIn(String propertyName, Object... values);
|
||||
|
||||
/**
|
||||
* Not In - property has a value in the collection of values.
|
||||
*/
|
||||
ExpressionList<T> notIn(String propertyName, Collection<?> values);
|
||||
|
||||
/**
|
||||
* Not In - using a subQuery.
|
||||
*/
|
||||
ExpressionList<T> notIn(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Exists expression
|
||||
*/
|
||||
@@ -517,6 +762,14 @@ public interface ExpressionList<T> extends Serializable {
|
||||
* then they are not translated. logical property name names (not fully
|
||||
* qualified) will still be translated to their physical name.
|
||||
* </p>
|
||||
*
|
||||
* <h4>Example:</h4>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // use a database function
|
||||
* raw("add_days(orderDate, 10) < ?", someDate)
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
ExpressionList<T> raw(String raw, Object value);
|
||||
|
||||
@@ -532,7 +785,7 @@ public interface ExpressionList<T> extends Serializable {
|
||||
* qualified) will still be translated to their physical name.
|
||||
* </p>
|
||||
*/
|
||||
ExpressionList<T> raw(String raw, Object[] values);
|
||||
ExpressionList<T> raw(String raw, Object... values);
|
||||
|
||||
/**
|
||||
* Add raw expression with no parameters.
|
||||
@@ -541,6 +794,12 @@ public interface ExpressionList<T> extends Serializable {
|
||||
* then they are not translated. logical property name names (not fully
|
||||
* qualified) will still be translated to their physical name.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* raw("orderQty < shipQty")
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
ExpressionList<T> raw(String raw);
|
||||
|
||||
|
||||
@@ -22,57 +22,57 @@ import java.io.Serializable;
|
||||
* efficient loaded as 2 SQL queries.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* <pre>{@code
|
||||
* // Normal fetch join results in a single SQL query
|
||||
* List<Order> list = Ebean.find(Order.class).fetch("details").findList();
|
||||
* List<Order> list = Ebean.find(Order.class).fetch("details").findList();
|
||||
*
|
||||
* // Find Orders join details using a single SQL query
|
||||
* </pre>
|
||||
* }</pre>
|
||||
* <p>
|
||||
* Example: Using a "query join" instead of a "fetch join" we instead use 2 SQL
|
||||
* queries
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* <pre>{@code
|
||||
* // This will use 2 SQL queries to build this object graph
|
||||
* List<Order> list =
|
||||
* List<Order> list =
|
||||
* Ebean.find(Order.class)
|
||||
* .fetch("details", new FetchConfig().query())
|
||||
* .fetch("details", new FetchConfig().query())
|
||||
* .findList();
|
||||
*
|
||||
* // query 1) find order
|
||||
* // query 2) find orderDetails where order.id in (?,?...) // first 100 order id's
|
||||
* </pre>
|
||||
* }</pre>
|
||||
* <p>
|
||||
* Example: Using 2 "query joins"
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* <pre>{@code
|
||||
* // This will use 3 SQL queries to build this object graph
|
||||
* List<Order> list =
|
||||
* List<Order> list =
|
||||
* Ebean.find(Order.class)
|
||||
* .fetch("details", new FetchConfig().query())
|
||||
* .fetch("customer", new FetchConfig().queryFirst(5))
|
||||
* .fetch("details", new FetchConfig().query())
|
||||
* .fetch("customer", new FetchConfig().queryFirst(5))
|
||||
* .findList();
|
||||
*
|
||||
* // query 1) find order
|
||||
* // query 2) find orderDetails where order.id in (?,?...) // first 100 order id's
|
||||
* // query 3) find customer where id in (?,?,?,?,?) // first 5 customers
|
||||
* </pre>
|
||||
* }</pre>
|
||||
* <p>
|
||||
* Example: Using "query joins" and partial objects
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* <pre>{@code
|
||||
* // This will use 3 SQL queries to build this object graph
|
||||
* List<Order> list =
|
||||
* List<Order> list =
|
||||
* Ebean.find(Order.class)
|
||||
* .select("status, shipDate")
|
||||
* .fetch("details", "quantity, price", new FetchConfig().query())
|
||||
* .fetch("details.product", "sku, name")
|
||||
* .fetch("customer", "name", new FetchConfig().queryFirst(5))
|
||||
* .fetch("customer.contacts")
|
||||
* .fetch("customer.shippingAddress")
|
||||
* .select("status, shipDate")
|
||||
* .fetch("details", "quantity, price", new FetchConfig().query())
|
||||
* .fetch("details.product", "sku, name")
|
||||
* .fetch("customer", "name", new FetchConfig().queryFirst(5))
|
||||
* .fetch("customer.contacts")
|
||||
* .fetch("customer.shippingAddress")
|
||||
* .findList();
|
||||
*
|
||||
* // query 1) find order (status, shipDate)
|
||||
@@ -81,22 +81,22 @@ import java.io.Serializable;
|
||||
* // query 3) find customer (name) fetch contacts (*) fetch shippingAddress (*)
|
||||
* // where id in (?,?,?,?,?)
|
||||
*
|
||||
* // Note: the fetch of "details.product" is automatically included into the
|
||||
* // fetch of "details"
|
||||
* // Note: the fetch of "details.product" is automatically included into the
|
||||
* // fetch of "details"
|
||||
* //
|
||||
* // Note: the fetch of "customer.contacts" and "customer.shippingAddress"
|
||||
* // are automatically included in the fetch of "customer"
|
||||
* </pre>
|
||||
* // Note: the fetch of "customer.contacts" and "customer.shippingAddress"
|
||||
* // are automatically included in the fetch of "customer"
|
||||
* }</pre>
|
||||
* <p>
|
||||
* You can use query() and lazy together on a single join. The query is executed
|
||||
* immediately and the lazy defines the batch size to use for further lazy
|
||||
* loading (if lazy loading is invoked).
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* List<Order> list =
|
||||
* <pre>{@code
|
||||
* List<Order> list =
|
||||
* Ebean.find(Order.class)
|
||||
* .fetch("customer", new FetchConfig().query(10).lazy(5))
|
||||
* .fetch("customer", new FetchConfig().query(10).lazy(5))
|
||||
* .findList();
|
||||
*
|
||||
* // query 1) find order
|
||||
@@ -104,7 +104,7 @@ import java.io.Serializable;
|
||||
* // .. then if lazy loading of customers is invoked
|
||||
* // .. use a batch size of 5 to load the customers
|
||||
*
|
||||
* </pre>
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* Example of controlling the lazy loading query:
|
||||
@@ -114,12 +114,12 @@ import java.io.Serializable;
|
||||
* case.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* List<Order> list = Ebean.find(Order.class)
|
||||
* .fetch("customer","name", new FetchConfig().lazy(5))
|
||||
* .fetch("customer.contacts","contactName, phone, email")
|
||||
* .fetch("customer.shippingAddress")
|
||||
* .where().eq("status",Order.Status.NEW)
|
||||
* <pre>{@code
|
||||
* List<Order> list = Ebean.find(Order.class)
|
||||
* .fetch("customer","name", new FetchConfig().lazy(5))
|
||||
* .fetch("customer.contacts","contactName, phone, email")
|
||||
* .fetch("customer.shippingAddress")
|
||||
* .where().eq("status",Order.Status.NEW)
|
||||
* .findList();
|
||||
*
|
||||
* // query 1) find order where status = Order.Status.NEW
|
||||
@@ -132,7 +132,7 @@ import java.io.Serializable;
|
||||
* fetch customer.shippingAddress (*)
|
||||
* where id in (?,?,?,?,?)
|
||||
*
|
||||
* </pre>
|
||||
* }</pre>
|
||||
*
|
||||
* @author mario
|
||||
* @author rbygrave
|
||||
|
||||
@@ -36,7 +36,7 @@ import java.util.Set;
|
||||
* .sort("avgTimeMicros desc")
|
||||
* .gt("executionCount", 0)
|
||||
* .gt("lastQueryTime", nowMinus24Hrs)
|
||||
* .eq("autofetchTuned", true)
|
||||
* .eq("autoTuned", true)
|
||||
* .maxRows(10)
|
||||
* .filter(list);
|
||||
*
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
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>
|
||||
* 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>
|
||||
*
|
||||
* <h3>Testing</h3>
|
||||
* <p>
|
||||
* For testing the mocki-ebean project has the ability to replace the finder implementation
|
||||
*
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* public class CustomerFinder extends Finder<Customer> {
|
||||
*
|
||||
* public CustomerFinder() {
|
||||
* super(Customer.class);
|
||||
* }
|
||||
*
|
||||
* // Add your customer finder methods ...
|
||||
*
|
||||
* public Customer byName(String name) {
|
||||
* return query().eq("name", name).findUnique();
|
||||
* }
|
||||
*
|
||||
* public List<Customer> findNew() {
|
||||
* return query()
|
||||
* .eq("status", Customer.Status.NEW)
|
||||
* .orderBy("name")
|
||||
* .findList()
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @Entity
|
||||
* public class Customer extends BaseModel {
|
||||
*
|
||||
* public static final CustomerFinder find = new CustomerFinder();
|
||||
* ...
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
public class Finder<I, T> {
|
||||
|
||||
/**
|
||||
* The entity bean type.
|
||||
*/
|
||||
private final Class<T> type;
|
||||
|
||||
/**
|
||||
* The name of the EbeanServer, null for the default server.
|
||||
*/
|
||||
private final String serverName;
|
||||
|
||||
/**
|
||||
* Create with the type of the entity bean.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* public class CustomerFinder extends Finder<Customer> {
|
||||
*
|
||||
* public CustomerFinder() {
|
||||
* super(Customer.class);
|
||||
* }
|
||||
*
|
||||
* // ... add extra customer specific finder methods
|
||||
* }
|
||||
*
|
||||
* @Entity
|
||||
* public class Customer extends BaseModel {
|
||||
*
|
||||
* public static final CustomerFinder find = new CustomerFinder();
|
||||
* ...
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
public Finder(Class<T> type) {
|
||||
this.type = type;
|
||||
this.serverName = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create with the type of the entity bean and specific server name.
|
||||
*/
|
||||
public Finder(Class<T> type, String serverName) {
|
||||
this.type = type;
|
||||
this.serverName = serverName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying 'default' EbeanServer.
|
||||
*
|
||||
* <p>
|
||||
* This provides full access to the API such as explicit transaction demarcation etc.
|
||||
*
|
||||
*/
|
||||
public EbeanServer db() {
|
||||
return Ebean.getServer(serverName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return typically a different EbeanServer to the default.
|
||||
* <p>
|
||||
* This is equivalent to {@link Ebean#getServer(String)}
|
||||
*
|
||||
* @param server
|
||||
* The name of the EbeanServer. If this is null then the default EbeanServer is
|
||||
* returned.
|
||||
*/
|
||||
public EbeanServer db(String server) {
|
||||
return Ebean.getServer(server);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an entity reference for this ID.
|
||||
*
|
||||
* <p>
|
||||
* Equivalent to {@link EbeanServer#getReference(Class, Object)}
|
||||
*/
|
||||
public T ref(I id) {
|
||||
return db().getReference(type, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an entity by ID.
|
||||
*
|
||||
* <p>
|
||||
* Equivalent to {@link EbeanServer#find(Class, Object)}
|
||||
*/
|
||||
@Nullable
|
||||
public T byId(I id) {
|
||||
return db().find(type, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a bean by Id.
|
||||
* <p>
|
||||
* Equivalent to {@link EbeanServer#delete(Class, Object)}
|
||||
*/
|
||||
public void deleteById(I id) {
|
||||
db().delete(type, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all entities of the given type.
|
||||
*/
|
||||
public List<T> all() {
|
||||
return query().findList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a query.
|
||||
* <p>
|
||||
* Equivalent to {@link EbeanServer#find(Class)}
|
||||
*/
|
||||
public Query<T> query() {
|
||||
return db().find(type);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package com.avaje.ebean;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.text.PathProperties;
|
||||
import com.avaje.ebean.util.ClassUtil;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* A MappedSuperclass base class that provides convenience methods for inserting, updating and
|
||||
@@ -152,7 +152,7 @@ public abstract class Model {
|
||||
* }</pre>
|
||||
*/
|
||||
public static EbeanServer db() {
|
||||
return Ebean.getServer(null);
|
||||
return Ebean.getDefaultServer();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -194,7 +194,31 @@ public abstract class Model {
|
||||
public void markAsDirty() {
|
||||
db().markAsDirty(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mark the property as unset or 'not loaded'.
|
||||
* <p>
|
||||
* This would be used to specify a property that we did not wish to include in a stateless update.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // populate an entity bean from JSON or whatever
|
||||
* User user = ...;
|
||||
*
|
||||
* // mark the email property as 'unset' so that it is not
|
||||
* // included in a 'stateless update'
|
||||
* user.markPropertyUnset("email");
|
||||
*
|
||||
* user.update();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param propertyName the name of the property on the bean to be marked as 'unset'
|
||||
*/
|
||||
public void markPropertyUnset(String propertyName) {
|
||||
((EntityBean)this)._ebean_getIntercept().setPropertyLoaded(propertyName, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert or update this entity depending on its state.
|
||||
*
|
||||
@@ -227,12 +251,24 @@ public abstract class Model {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete this entity.
|
||||
* Delete this 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>
|
||||
*
|
||||
* @see EbeanServer#delete(Object)
|
||||
*/
|
||||
public void delete() {
|
||||
db().delete(this);
|
||||
public boolean delete() {
|
||||
return db().delete(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -252,8 +288,8 @@ public abstract class Model {
|
||||
/**
|
||||
* Perform a delete using this entity against the specified server.
|
||||
*/
|
||||
public void delete(String server) {
|
||||
db(server).delete(this);
|
||||
public boolean delete(String server) {
|
||||
return db(server).delete(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -442,6 +478,7 @@ public abstract class Model {
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Find() {
|
||||
this.serverName = null;
|
||||
this.type = (Class<T>)ClassUtil.getSecondArgumentType(getClass());
|
||||
@@ -451,8 +488,8 @@ public abstract class Model {
|
||||
* Construct passing the class literal type of the entity type.
|
||||
*/
|
||||
protected Find(String serverName, Class<T> type) {
|
||||
this.type = type;
|
||||
this.serverName = serverName;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -514,6 +551,7 @@ public abstract class Model {
|
||||
* <p>
|
||||
* Equivalent to {@link EbeanServer#find(Class, Object)}
|
||||
*/
|
||||
@Nullable
|
||||
public T byId(I id) {
|
||||
return db().find(type, id);
|
||||
}
|
||||
@@ -835,10 +873,10 @@ public abstract class Model {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a query with explicit 'Autofetch' use.
|
||||
* Create a query with explicit 'AutoTune' use.
|
||||
*/
|
||||
public Query<T> setAutofetch(boolean autofetch) {
|
||||
return query().setAutofetch(autofetch);
|
||||
public Query<T> setAutoTune(boolean autoTune) {
|
||||
return query().setAutoTune(autoTune);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,7 +28,7 @@ public final class OrderBy<T> implements Serializable {
|
||||
* Create an empty OrderBy with no associated query.
|
||||
*/
|
||||
public OrderBy() {
|
||||
this.list = new ArrayList<Property>(2);
|
||||
this.list = new ArrayList<Property>(3);
|
||||
}
|
||||
|
||||
private OrderBy(List<Property> list) {
|
||||
@@ -52,7 +52,7 @@ public final class OrderBy<T> implements Serializable {
|
||||
*/
|
||||
public OrderBy(Query<T> query, String orderByClause) {
|
||||
this.query = query;
|
||||
this.list = new ArrayList<Property>(2);
|
||||
this.list = new ArrayList<Property>(3);
|
||||
parse(orderByClause);
|
||||
}
|
||||
|
||||
@@ -83,6 +83,19 @@ public final class OrderBy<T> implements Serializable {
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the property is known to be contained in the order by clause.
|
||||
*/
|
||||
public boolean containsProperty(String propertyName) {
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (propertyName.equals(list.get(i).getProperty())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a copy of this OrderBy with the path trimmed.
|
||||
*/
|
||||
@@ -185,6 +198,18 @@ public final class OrderBy<T> implements Serializable {
|
||||
return list.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the orderBy removing any current order by properties.
|
||||
* <p>
|
||||
* This is intended to be used when some code creates a query with a
|
||||
* 'default' order by clause and some other code may clear the 'default'
|
||||
* order by clause and replace.
|
||||
* </p>
|
||||
*/
|
||||
public void clear() {
|
||||
list.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* A property and its ascending descending order.
|
||||
*/
|
||||
|
||||
@@ -17,6 +17,33 @@ import java.util.concurrent.Future;
|
||||
* limit the result set.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <h4>Example: typical use including total row count</h4>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // We want to find the first 50 new orders
|
||||
* // ... so we don't really need setFirstRow(0)
|
||||
*
|
||||
* PagedList<Order> pagedList
|
||||
* = ebeanServer.find(Order.class)
|
||||
* .where().eq("status", Order.Status.NEW)
|
||||
* .order().asc("id")
|
||||
* .setFirstRow(0)
|
||||
* .setMaxRows(50)
|
||||
* .findPagedList();
|
||||
*
|
||||
* // Optional: initiate the loading of the total
|
||||
* // row count in a background thread
|
||||
* pagedList.loadRowCount();
|
||||
*
|
||||
* // fetch and return the list in the foreground thread
|
||||
* List<Order> orders = pagedList.getList();
|
||||
*
|
||||
* // get the total row count (from the future)
|
||||
* int totalRowCount = pagedList.getTotalRowCount();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h4>Example: typical use including total row count</h4>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -156,9 +183,18 @@ public interface PagedList<T> {
|
||||
|
||||
/**
|
||||
* Return the index position of this page. Zero based.
|
||||
* <p>
|
||||
* Note that if firstRows/maxRows is used rather than pageIndex/pageSize then
|
||||
* this always returns 0.
|
||||
* </p>
|
||||
*/
|
||||
int getPageIndex();
|
||||
|
||||
/**
|
||||
* Return the page size used for this query. This is the same value as maxRows used by the query.
|
||||
*/
|
||||
int getPageSize();
|
||||
|
||||
/**
|
||||
* Return true if there is a next page.
|
||||
* <p>
|
||||
|
||||
@@ -34,7 +34,7 @@ class PrimaryServer {
|
||||
/**
|
||||
* Return the default server name.
|
||||
*/
|
||||
static synchronized String getPrimaryServerName() {
|
||||
static synchronized String getDefaultServerName() {
|
||||
getProperties();
|
||||
return defaultServerName;
|
||||
}
|
||||
@@ -58,15 +58,18 @@ class PrimaryServer {
|
||||
*/
|
||||
private static String determineDefaultServerName() {
|
||||
|
||||
String defaultServerName = System.getProperty("datasource.default");
|
||||
String defaultServerName = System.getenv("EBEAN_DB");
|
||||
if (isEmpty(defaultServerName)) {
|
||||
defaultServerName = System.getProperty("ebean.default.datasource");
|
||||
}
|
||||
if (isEmpty(defaultServerName)) {
|
||||
defaultServerName = globalProperties.getProperty("datasource.default");
|
||||
}
|
||||
if (isEmpty(defaultServerName)) {
|
||||
defaultServerName = globalProperties.getProperty("ebean.default.datasource");
|
||||
defaultServerName = System.getProperty("datasource.default");
|
||||
if (isEmpty(defaultServerName)) {
|
||||
defaultServerName = System.getProperty("ebean.default.datasource");
|
||||
if (isEmpty(defaultServerName)) {
|
||||
defaultServerName = globalProperties.getProperty("datasource.default");
|
||||
if (isEmpty(defaultServerName)) {
|
||||
defaultServerName = globalProperties.getProperty("ebean.default.datasource");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return defaultServerName;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import com.avaje.ebean.text.PathProperties;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.persistence.NonUniqueResultException;
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -65,9 +68,9 @@ import java.util.Set;
|
||||
* ...
|
||||
* }</pre>
|
||||
*
|
||||
* <h3>Autofetch</h3>
|
||||
* <h3>AutoTune</h3>
|
||||
* <p>
|
||||
* Ebean has built in support for "Autofetch". This is a mechanism where a query
|
||||
* Ebean has built in support for "AutoTune". This is a mechanism where a query
|
||||
* can be automatically tuned based on profiling information that is collected.
|
||||
* </p>
|
||||
* <p>
|
||||
@@ -76,7 +79,7 @@ import java.util.Set;
|
||||
* more.
|
||||
* </p>
|
||||
* <p>
|
||||
* It is expected that Autofetch will be the default approach for many queries
|
||||
* It is expected that AutoTune will be the default approach for many queries
|
||||
* in a system. It is possibly not as useful where the result of a query is sent
|
||||
* to a remote client or where there is some requirement for "Read Consistency"
|
||||
* guarantees.
|
||||
@@ -284,6 +287,27 @@ public interface Query<T> extends Serializable {
|
||||
*/
|
||||
Query<T> setRawSql(RawSql rawSql);
|
||||
|
||||
/**
|
||||
* Perform an 'As of' query using history tables to return the object graph
|
||||
* as of a time in the past.
|
||||
* <p>
|
||||
* To perform this query the DB must have underlying history tables.
|
||||
* </p>
|
||||
*
|
||||
* @param asOf the date time in the past at which you want to view the data
|
||||
*/
|
||||
Query<T> asOf(Timestamp asOf);
|
||||
|
||||
/**
|
||||
* Execute the query against the draft set of tables.
|
||||
*/
|
||||
Query<T> asDraft();
|
||||
|
||||
/**
|
||||
* Execute the query including soft deleted rows.
|
||||
*/
|
||||
Query<T> includeSoftDeletes();
|
||||
|
||||
/**
|
||||
* Cancel the query execution if supported by the underlying database and
|
||||
* driver.
|
||||
@@ -325,23 +349,23 @@ public interface Query<T> extends Serializable {
|
||||
ExpressionFactory getExpressionFactory();
|
||||
|
||||
/**
|
||||
* Returns true if this query was tuned by autoFetch.
|
||||
* Returns true if this query was tuned by autoTune.
|
||||
*/
|
||||
boolean isAutofetchTuned();
|
||||
boolean isAutoTuned();
|
||||
|
||||
/**
|
||||
* Explicitly specify whether to use Autofetch for this query.
|
||||
* Explicitly specify whether to use AutoTune for this query.
|
||||
* <p>
|
||||
* If you do not call this method on a query the "Implicit Autofetch mode" is
|
||||
* used to determine if Autofetch should be used for a given query.
|
||||
* If you do not call this method on a query the "Implicit AutoTune mode" is
|
||||
* used to determine if AutoTune should be used for a given query.
|
||||
* </p>
|
||||
* <p>
|
||||
* Autofetch can add additional fetch paths to the query and specify which
|
||||
* AutoTune can add additional fetch paths to the query and specify which
|
||||
* properties are included for each path. If you have explicitly defined some
|
||||
* fetch paths Autofetch will not remove.
|
||||
* fetch paths AutoTune will not remove them.
|
||||
* </p>
|
||||
*/
|
||||
Query<T> setAutofetch(boolean autofetch);
|
||||
Query<T> setAutoTune(boolean autoTune);
|
||||
|
||||
/**
|
||||
* Set the default lazy loading batch size to use.
|
||||
@@ -353,6 +377,16 @@ public interface Query<T> extends Serializable {
|
||||
*/
|
||||
Query<T> setLazyLoadBatchSize(int lazyLoadBatchSize);
|
||||
|
||||
/**
|
||||
* Disable read auditing for this query.
|
||||
* <p>
|
||||
* This is intended to be used when the query is not a user initiated query and instead
|
||||
* part of the internal processing in an application to load a cache or document store etc.
|
||||
* In these cases we don't want the query to be part of read auditing.
|
||||
* </p>
|
||||
*/
|
||||
Query<T> setDisableReadAuditing();
|
||||
|
||||
/**
|
||||
* Explicitly set a comma delimited list of the properties to fetch on the
|
||||
* 'main' root level entity bean (aka partial object). Note that '*' means all
|
||||
@@ -483,7 +517,7 @@ public interface Query<T> extends Serializable {
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
Query<T> fetch(String path, FetchConfig joinConfig);
|
||||
Query<T> fetch(String path, FetchConfig fetchConfig);
|
||||
|
||||
/**
|
||||
* Apply the path properties replacing the select and fetch clauses.
|
||||
@@ -520,19 +554,7 @@ public interface Query<T> extends Serializable {
|
||||
*/
|
||||
QueryIterator<T> findIterate();
|
||||
|
||||
/**
|
||||
* This is deprecated in favor of #findEachWhile.
|
||||
* <p>
|
||||
* This is functionally exactly the same as #findEachWhile. It is
|
||||
* replaced by findEachWhile because the method name is much better.
|
||||
* </p>
|
||||
*
|
||||
* @param visitor
|
||||
* the visitor used to process the queried beans.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
void findVisit(QueryResultVisitor<T> visitor);
|
||||
|
||||
|
||||
/**
|
||||
* Execute the query processing the beans one at a time.
|
||||
@@ -679,7 +701,7 @@ public interface Query<T> extends Serializable {
|
||||
* Execute the query returning either a single bean or null (if no matching
|
||||
* bean is found).
|
||||
* <p>
|
||||
* If more than 1 row is found for this query then a PersistenceException is
|
||||
* If more than 1 row is found for this query then a NonUniqueResultException is
|
||||
* thrown.
|
||||
* </p>
|
||||
* <p>
|
||||
@@ -715,9 +737,47 @@ public interface Query<T> extends Serializable {
|
||||
* List<OrderDetail> details = order.getDetails();
|
||||
* ...
|
||||
* }</pre>
|
||||
*
|
||||
* @throws NonUniqueResultException if more than one result was found
|
||||
*/
|
||||
@Nullable
|
||||
T findUnique();
|
||||
|
||||
/**
|
||||
* Return versions of a @History entity bean.
|
||||
* <p>
|
||||
* Note that this query will work against view based history implementations
|
||||
* but not sql2011 standards based implementations that require a start and
|
||||
* end timestamp to be specified.
|
||||
* </p>
|
||||
* <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>
|
||||
*/
|
||||
List<Version<T>> findVersions();
|
||||
|
||||
/**
|
||||
* Return versions of a @History entity bean between the 2 timestamps.
|
||||
* <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>
|
||||
*/
|
||||
List<Version<T>> findVersionsBetween(Timestamp start, Timestamp end);
|
||||
|
||||
/**
|
||||
* Execute as a delete query deleting the 'root level' beans that match the predicates
|
||||
* in the query.
|
||||
* <p>
|
||||
* Note that if the query includes joins then the generated delete statement may not be
|
||||
* optimal depending on the database platform.
|
||||
* </p>
|
||||
*
|
||||
* @return the number of beans/rows that were deleted.
|
||||
*/
|
||||
int delete();
|
||||
|
||||
/**
|
||||
* Return the count of entities this query should return.
|
||||
* <p>
|
||||
@@ -762,7 +822,7 @@ public interface Query<T> extends Serializable {
|
||||
FutureList<T> findFutureList();
|
||||
|
||||
/**
|
||||
* Return a PagedList for this query.
|
||||
* Return a PagedList for this query using pageIndex and pageSize.
|
||||
* <p>
|
||||
* The benefit of using this over just using the normal {@link Query#setFirstRow(int)} and
|
||||
* {@link Query#setMaxRows(int)} is that it additionally wraps an optional call to
|
||||
@@ -807,6 +867,36 @@ public interface Query<T> extends Serializable {
|
||||
*/
|
||||
PagedList<T> findPagedList(int pageIndex, int pageSize);
|
||||
|
||||
/**
|
||||
* 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>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* PagedList<Order> pagedList = Ebean.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
|
||||
*/
|
||||
PagedList<T> findPagedList();
|
||||
|
||||
/**
|
||||
* Set a named bind parameter. Named parameters have a colon to prefix the name.
|
||||
*
|
||||
@@ -878,6 +968,11 @@ public interface Query<T> extends Serializable {
|
||||
*/
|
||||
Query<T> setId(Object id);
|
||||
|
||||
/**
|
||||
* Return the Id value.
|
||||
*/
|
||||
Object getId();
|
||||
|
||||
/**
|
||||
* Add additional clause(s) to the where clause.
|
||||
* <p>
|
||||
@@ -1113,6 +1208,19 @@ public interface Query<T> extends Serializable {
|
||||
|
||||
/**
|
||||
* Set whether this query uses DISTINCT.
|
||||
* <p>
|
||||
* The select() clause MUST be specified when setDistinct(true) is set. The reason for this is that
|
||||
* generally ORM queries include the "id" property and this doesn't make sense for distinct queries.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<Customer> customers =
|
||||
* Ebean.find(Customer.class)
|
||||
* .setDistinct(true)
|
||||
* .select("name")
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
Query<T> setDistinct(boolean isDistinct);
|
||||
|
||||
@@ -1123,8 +1231,8 @@ public interface Query<T> extends Serializable {
|
||||
|
||||
/**
|
||||
* Set the first row to return for this query.
|
||||
*
|
||||
* @param firstRow
|
||||
*
|
||||
* @param firstRow the first row to include in the query result.
|
||||
*/
|
||||
Query<T> setFirstRow(int firstRow);
|
||||
|
||||
@@ -1235,4 +1343,26 @@ public interface Query<T> extends Serializable {
|
||||
* Set root table alias.
|
||||
*/
|
||||
Query<T> alias(String alias);
|
||||
|
||||
/**
|
||||
* Return the type of beans being queried.
|
||||
*/
|
||||
Class<T> getBeanType();
|
||||
|
||||
/**
|
||||
* Set true if you want to disable lazy loading.
|
||||
* <p>
|
||||
* That is, once the object graph is returned further lazy loading is disabled.
|
||||
* </p>
|
||||
*/
|
||||
Query<T> setDisableLazyLoading(boolean disableLazyLoading);
|
||||
|
||||
/**
|
||||
* Returns the set of properties or paths that are unknown (do not map to known properties or paths).
|
||||
* <p>
|
||||
* Validate the query checking the where and orderBy expression paths to confirm if
|
||||
* they represent valid properties or paths for the given bean type.
|
||||
* </p>
|
||||
*/
|
||||
Set<String> validate();
|
||||
}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
/**
|
||||
* Used to process a query result one bean at a time via a callback to this
|
||||
* visitor.
|
||||
* <p>
|
||||
* If you wish to stop further processing return false from the accept method.
|
||||
* </p>
|
||||
* <p>
|
||||
* Unlike findList() and findSet() using a QueryResultVisitor does not require
|
||||
* all the beans in the query result to be held in memory at once. This makes
|
||||
* QueryResultVisitor useful for processing large queries.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
*
|
||||
* Query<Customer> query = server.find(Customer.class)
|
||||
* .fetch("contacts", new FetchConfig().query(2))
|
||||
* .where().gt("id", 0)
|
||||
* .orderBy("id")
|
||||
* .setMaxRows(2);
|
||||
*
|
||||
* query.findVisit(new QueryResultVisitor<Customer>() {
|
||||
*
|
||||
* public boolean accept(Customer customer) {
|
||||
* // do something with customer
|
||||
* System.out.println("-- visit " + customer);
|
||||
* return true;
|
||||
* }
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @author rbygrave
|
||||
*
|
||||
* @param <T>
|
||||
* the type of entity bean being queried.
|
||||
*/
|
||||
public interface QueryResultVisitor<T> {
|
||||
|
||||
/**
|
||||
* Process the bean and return true if you want to continue processing more
|
||||
* beans. Return false if you want to stop processing further.
|
||||
*
|
||||
* @param bean
|
||||
* the entity bean to process
|
||||
* @return true to continue processing or false to stop.
|
||||
*/
|
||||
boolean accept(T bean);
|
||||
}
|
||||
@@ -480,6 +480,13 @@ public final class RawSql implements Serializable {
|
||||
this.queryHashCode = hc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the property is mapped.
|
||||
*/
|
||||
public boolean contains(String property) {
|
||||
return this.propertyColumnMap.containsKey(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an immutable copy of this ColumnMapping.
|
||||
*
|
||||
|
||||
@@ -153,7 +153,7 @@ public interface SqlRow extends Serializable, Map<String, Object> {
|
||||
/**
|
||||
* Put all the values from t into this map.
|
||||
*/
|
||||
void putAll(Map<? extends String, ? extends Object> t);
|
||||
void putAll(Map<? extends String, ?> t);
|
||||
|
||||
/**
|
||||
* Return the size of the map.
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.avaje.ebean;
|
||||
|
||||
import com.avaje.ebean.config.PersistBatch;
|
||||
|
||||
import javax.persistence.OptimisticLockException;
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.RollbackException;
|
||||
import java.io.Closeable;
|
||||
@@ -97,6 +96,17 @@ public interface Transaction extends Closeable {
|
||||
*/
|
||||
void setPersistCascade(boolean persistCascade);
|
||||
|
||||
/**
|
||||
* Set to true when you want all loaded properties to be included in the update
|
||||
* (rather than just the changed properties).
|
||||
* <p>
|
||||
* You might set this when using JDBC batch in order to get multiple updates
|
||||
* with slightly different sets of changed properties into the same statement
|
||||
* and hence better JDBC batch performance.
|
||||
* </p>
|
||||
*/
|
||||
void setUpdateAllLoadedProperties(boolean updateAllLoadedProperties);
|
||||
|
||||
/**
|
||||
* Turn on or off statement batching. Statement batching can be transparent
|
||||
* for drivers and databases that support getGeneratedKeys. Otherwise you may
|
||||
@@ -279,7 +289,7 @@ public interface Transaction extends Closeable {
|
||||
* <li>Transaction commit occurs</li>
|
||||
* </ul>
|
||||
*/
|
||||
void flushBatch() throws PersistenceException, OptimisticLockException;
|
||||
void flushBatch() throws PersistenceException;
|
||||
|
||||
/**
|
||||
* Return the underlying Connection object.
|
||||
|
||||
@@ -46,5 +46,5 @@ public enum TxType {
|
||||
* If there is an existing transaction throws an Exception. Method runs
|
||||
* without a transaction.
|
||||
*/
|
||||
NEVER;
|
||||
NEVER
|
||||
}
|
||||
|
||||
@@ -5,10 +5,19 @@ package com.avaje.ebean;
|
||||
*/
|
||||
public class ValuePair {
|
||||
|
||||
private final Object newValue;
|
||||
protected Object newValue;
|
||||
|
||||
private final Object oldValue;
|
||||
protected Object oldValue;
|
||||
|
||||
/**
|
||||
* Default constructor for JSON tools.
|
||||
*/
|
||||
public ValuePair() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct with the pair of new and old values.
|
||||
*/
|
||||
public ValuePair(Object newValue, Object oldValue) {
|
||||
this.newValue = newValue;
|
||||
this.oldValue = oldValue;
|
||||
@@ -27,21 +36,19 @@ public class ValuePair {
|
||||
public Object getOldValue() {
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the new value.
|
||||
* Set the new value.
|
||||
*/
|
||||
@Deprecated
|
||||
public Object getValue1() {
|
||||
return newValue;
|
||||
public void setNewValue(Object newValue) {
|
||||
this.newValue = newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the old value.
|
||||
* Set the old value.
|
||||
*/
|
||||
@Deprecated
|
||||
public Object getValue2() {
|
||||
return oldValue;
|
||||
public void setOldValue(Object oldValue) {
|
||||
this.oldValue = oldValue;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Wraps a version of a @History bean.
|
||||
*/
|
||||
public class Version<T> {
|
||||
|
||||
/**
|
||||
* The version of the bean.
|
||||
*/
|
||||
protected T bean;
|
||||
|
||||
/**
|
||||
* The effective start date time of this version.
|
||||
*/
|
||||
protected Timestamp start;
|
||||
|
||||
/**
|
||||
* The effective end date time of this version.
|
||||
*/
|
||||
protected Timestamp end;
|
||||
|
||||
/**
|
||||
* The map of changed properties.
|
||||
*/
|
||||
protected Map<String, ValuePair> diff;
|
||||
|
||||
/**
|
||||
* Construct with bean and an effective date time range.
|
||||
*/
|
||||
public Version(T bean, Timestamp start, Timestamp end) {
|
||||
this.bean = bean;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor - useful for JSON tools such as Jackson.
|
||||
*/
|
||||
public Version() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bean instance for this version.
|
||||
*/
|
||||
public T getBean() {
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bean instance for this version.
|
||||
*/
|
||||
public void setBean(T bean) {
|
||||
this.bean = bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the effective start date time of this version.
|
||||
*/
|
||||
public Timestamp getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the effective start date time of this version.
|
||||
*/
|
||||
public void setStart(Timestamp start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the effective end date time of this version.
|
||||
*/
|
||||
public Timestamp getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the effective end date time of this version.
|
||||
*/
|
||||
public void setEnd(Timestamp end) {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the map of differences from this bean to the prior version.
|
||||
*/
|
||||
public void setDiff(Map<String, ValuePair> diff) {
|
||||
this.diff = diff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the map of differences from this bean to the prior version.
|
||||
*/
|
||||
public Map<String, ValuePair> getDiff() {
|
||||
return diff;
|
||||
}
|
||||
}
|
||||
@@ -44,4 +44,12 @@ public @interface CacheTuning {
|
||||
* </p>
|
||||
*/
|
||||
int maxSecsToLive() default 0;
|
||||
|
||||
/**
|
||||
* The frequency (in seconds) that cache trimming should occur.
|
||||
* <p>
|
||||
* This is a hint for cache implementations that use background cache trimming.
|
||||
* </p>
|
||||
*/
|
||||
int trimFrequency() default 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Marks an entity bean as being included in the change logging.
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ChangeLog {
|
||||
|
||||
/**
|
||||
* Specify if inserts should be explicitly Included or Excluded.
|
||||
* <p>
|
||||
* If not defined explicitly then the server default behaviour defined
|
||||
* on ServerConfig is used.
|
||||
* </p>
|
||||
*/
|
||||
ChangeLogInsertMode inserts() default ChangeLogInsertMode.DEFAULT;
|
||||
|
||||
/**
|
||||
* When specified only include update requests that have at least one
|
||||
* of the given properties as a dirty property.
|
||||
* <p>
|
||||
* This provides a way to filter requests to include in the change log such that
|
||||
* only updates that include at least one of the given properties is included
|
||||
* in the change log.
|
||||
* </p>
|
||||
*/
|
||||
String[] updatesThatInclude() default {};
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
/**
|
||||
* The mode used to determine if inserts should be included or not for a given bean type.
|
||||
*/
|
||||
public enum ChangeLogInsertMode {
|
||||
|
||||
/**
|
||||
* Use the default behaviour as defined on ServerConfig.
|
||||
*/
|
||||
DEFAULT,
|
||||
|
||||
/**
|
||||
* Include inserts in the change log.
|
||||
*/
|
||||
INCLUDE,
|
||||
|
||||
/**
|
||||
* Exclude inserts in the change log.
|
||||
*/
|
||||
EXCLUDE
|
||||
}
|
||||
@@ -9,6 +9,10 @@ import java.lang.annotation.Target;
|
||||
* For a timestamp property that is set to the datetime when the entity is
|
||||
* created/inserted.
|
||||
* <p>
|
||||
* This is effectively an alias for @WhenCreated which was added as it hints
|
||||
* towards a better naming convention (WhenCreated, WhenModified).
|
||||
* </p>
|
||||
* <p>
|
||||
* An alternative to using this annotation would be to use insertable=false,
|
||||
* updateable=false with @Column and have the DB insert the current time
|
||||
* (default value on the DB column is SYSTIME etc).
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* A database table or column comment.
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
|
||||
public @interface DbComment {
|
||||
|
||||
/**
|
||||
* The database table or column comment.
|
||||
*/
|
||||
String value();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
/**
|
||||
* Specify the DB storage type used to with <code>@DbEnumValue</code>.
|
||||
*/
|
||||
public enum DbEnumType {
|
||||
|
||||
/**
|
||||
* Store values as database INTEGER.
|
||||
*/
|
||||
INTEGER,
|
||||
|
||||
/**
|
||||
* Store values as database VARCHAR.
|
||||
*/
|
||||
VARCHAR
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Specify a method on an Enum that returns the value that should be stored in the DB.
|
||||
* <p>
|
||||
* This is the preferred option for mapping Enum's to DB values (preferred over the JPA
|
||||
* standard @Enumerated and Ebean's @EnumValue annotations).
|
||||
* </p>
|
||||
* <h3>Example:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* public enum Status {
|
||||
* NEW("N"),
|
||||
* ACTIVE("A"),
|
||||
* INACTIVE("I");
|
||||
*
|
||||
* String dbValue;
|
||||
* Status(String dbValue) {
|
||||
* this.dbValue = dbValue;
|
||||
* }
|
||||
*
|
||||
* @DbEnumValue
|
||||
* public String getValue() {
|
||||
* return dbValue;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public @interface DbEnumValue {
|
||||
|
||||
/**
|
||||
* Specify the database type used to store the values (VARCHAR or INTEGER).
|
||||
*/
|
||||
DbEnumType storage() default DbEnumType.VARCHAR;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Marks a boolean property on a @Draftable bean that indicates if the bean instance is a 'draft' or 'live' bean.
|
||||
* The property is transient and has no underlying DB column.
|
||||
* <p>
|
||||
* For beans returned from an <code>asDraft()</code> query this property will be set to true.
|
||||
* </p>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface Draft {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Marks a boolean property on a @Draftable bean that only exists on the 'draft' table
|
||||
* and is used to detect when a draft has unpublished changes.
|
||||
* <p>
|
||||
* This property will automatically have it's value set to true when a draft is saved and
|
||||
* automatically have it's value set to false when the bean is published.
|
||||
* </p>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface DraftDirty {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Marks a property on a @Draftable bean that only exists on the 'draft' and not the 'live' table.
|
||||
* <p>
|
||||
* Typically this would be used on a property that is used as part of application 'workflow' such as
|
||||
* a publish workflow status or when publish timestamp.
|
||||
* </p>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface DraftOnly {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Marks a property on a @Draftable bean that is set to null on the 'draft bean' on publish.
|
||||
* <p>
|
||||
* This is expected to be put on properties that get 'reset' or 'cleared' after a publish.
|
||||
* These properties might represent a publish comment or publish timestamp.
|
||||
* </p>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface DraftReset {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Used to indicate an entity bean that has 'draftable' support.
|
||||
* <p>
|
||||
* This means that a second set of tables is created to hold draft versions of
|
||||
* the rows and that these can then be published which effectively copies/transfers
|
||||
* the values from the 'draft' table to the 'live' table.
|
||||
* </p>
|
||||
* <p>
|
||||
* Ebean Query supports 'find as draft' which builds the resulting object graph using
|
||||
* the draft tables. This object graph is typically edited, approved in some application
|
||||
* specific manor and then published.
|
||||
* </p>
|
||||
* <p>
|
||||
* EbeanServer has a publish method which transfers/copies the draft object graph to
|
||||
* the 'live' tables.
|
||||
* </p>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface Draftable {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Used to indicate an entity bean that has 'draftable' support but it not a 'top level'
|
||||
* (or root level) bean but instead child related to another @Draftable entity bean.
|
||||
* <p>
|
||||
* Relationships to @DraftableElements (@OneToMany, @ManyToMany etc) are automatically
|
||||
* deemed to have Cascade.ALL for save and delete (as well as orphan removal mode).
|
||||
* </p>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface DraftableElement {
|
||||
|
||||
}
|
||||
@@ -25,7 +25,7 @@ import java.lang.annotation.Target;
|
||||
* }</pre>
|
||||
* <p>
|
||||
* This is an alternative to using the JPA standard approach or Ebean's
|
||||
* {@link EnumMapping} annotation.
|
||||
* {@link DbEnumValue} annotation.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that if all the EnumValue values are parsable as Integers then Ebean
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Marks an entity bean as having history support.
|
||||
* <p>
|
||||
* In Postgres for example this means there is an associated history table which is
|
||||
* typically automatically populated via database triggers.
|
||||
* </p>
|
||||
*/
|
||||
@Target({ ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface History {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Marks a property as being excluded from history.
|
||||
* <p>
|
||||
* This means the property values are not maintained in the history table. Typically this
|
||||
* would be placed on relatively large properties (Clobs, Blobs, large varchar columns etc)
|
||||
* that are considered not interesting enough to maintain history on excluding them reduces
|
||||
* underlying database costs.
|
||||
* </p>
|
||||
* <p>
|
||||
* When placed on a ManyToMany this means that the intersection table does not have history
|
||||
* support.
|
||||
* </p>
|
||||
*/
|
||||
@Target({ ElementType.FIELD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface HistoryExclude {
|
||||
|
||||
}
|
||||
@@ -10,15 +10,24 @@ import java.lang.annotation.Target;
|
||||
*
|
||||
* @author rvbiljouw
|
||||
*/
|
||||
@Target({ElementType.FIELD})
|
||||
@Target({ElementType.TYPE, ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Index {
|
||||
|
||||
/**
|
||||
* Name of the index
|
||||
*
|
||||
* @return index name
|
||||
* Name of the index. If left blank a name is derived using the built in naming convention.
|
||||
*/
|
||||
String value() default "";
|
||||
String name() default "";
|
||||
|
||||
/**
|
||||
* If set true indicates this is a unique index.
|
||||
*/
|
||||
boolean unique() default false;
|
||||
|
||||
/**
|
||||
* When placed on the class (rather than field) you can specify the columns
|
||||
* to include in the index in order.
|
||||
*/
|
||||
String[] columnNames() default {};
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Similar to Jackson JsonIgnore but provides the option to just ignore serialize or deserialize.
|
||||
* <p>
|
||||
* This provides the same features as Expose but from the opposite perspective which is probably
|
||||
* more common and more familiar to Jackson users.
|
||||
* </p>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface JsonIgnore {
|
||||
|
||||
/**
|
||||
* If {@code true}, the field marked with this annotation is written out in the JSON while
|
||||
* serializing. If {@code false}, the field marked with this annotation is skipped from the
|
||||
* serialized output. Defaults to {@code false}.
|
||||
*/
|
||||
boolean serialize() default false;
|
||||
|
||||
/**
|
||||
* If {@code true}, the field marked with this annotation is deserialized from the JSON.
|
||||
* If {@code false}, the field marked with this annotation is skipped during deserialization.
|
||||
* Defaults to {@code false}.
|
||||
*/
|
||||
boolean deserialize() default false;
|
||||
}
|
||||
+4
-6
@@ -6,12 +6,10 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Deprecated - please use @DbHstore instead.
|
||||
* @see DbHstore
|
||||
* Marks an entity bean as being included in read auditing.
|
||||
*/
|
||||
@Deprecated
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface ColumnHstore {
|
||||
public @interface ReadAudit {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Used to indicate a property on an entity bean used to control 'soft delete'
|
||||
* (also known as 'logical delete').
|
||||
* <p>
|
||||
* The property should be of type boolean.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* @SoftDelete
|
||||
* boolean deleted;
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface SoftDelete {
|
||||
|
||||
}
|
||||
@@ -8,6 +8,10 @@ import java.lang.annotation.Target;
|
||||
/**
|
||||
* For a timestamp property that is set to the datetime when the entity was last
|
||||
* updated.
|
||||
* <p>
|
||||
* This is effectively an alias for @WhenModified which was added as it hints
|
||||
* towards a better naming convention (WhenCreated, WhenModified).
|
||||
* </p>
|
||||
*/
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* For a timestamp property that is set to the datetime when the entity is
|
||||
* created/inserted.
|
||||
* <p>
|
||||
* This is effectively an alias for @CreatedTimestamp and added to hint
|
||||
* towards a better naming convention (WhenCreated, WhenModified).
|
||||
* </p>
|
||||
* <p>
|
||||
* An alternative to using this annotation would be to use insertable=false,
|
||||
* updateable=false with @Column and have the DB insert the current time
|
||||
* (default value on the DB column is SYSTIME etc).
|
||||
* </p>
|
||||
* <p>
|
||||
* The downside to this approach is that the inserted entity does not have the
|
||||
* timestamp value after the insert has occurred. You need to fetch the entity
|
||||
* back to get the inserted timestamp if you want to used it.
|
||||
* </p>
|
||||
*
|
||||
* <h3>Example:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* @WhenCreated
|
||||
* Timestamp whenCreated;
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface WhenCreated {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* For a timestamp property that is set to the datetime when the entity was last modified.
|
||||
* <p>
|
||||
* This is effectively an alias for @UpdatedTimestamp and added to hint
|
||||
* towards a better naming convention (WhenCreated, WhenModified).
|
||||
* </p>
|
||||
*/
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface WhenModified {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Mapped onto a entity bean property that represents the user id of
|
||||
* who created the entity>
|
||||
* <p>
|
||||
* To use this annotation you need to implement CurrentUserProvider.
|
||||
* The type of the bean property should match the type returned by
|
||||
* CurrentUserProvider.
|
||||
*</p>
|
||||
|
||||
* <h3>Example:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* @WhoCreated
|
||||
* String whoCreated;
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface WhoCreated {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Mapped onto a entity bean property that represents the user id of
|
||||
* who last modified the entity>
|
||||
* <p>
|
||||
* To use this annotation you need to implement CurrentUserProvider.
|
||||
* The type of the bean property should match the type returned by
|
||||
* CurrentUserProvider.
|
||||
* </p>
|
||||
*
|
||||
* <h3>Example:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* @WhoModified
|
||||
* String whoModified;
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface WhoModified {
|
||||
|
||||
}
|
||||
@@ -31,6 +31,16 @@ public interface BeanCollection<E> extends Serializable {
|
||||
ALL
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a bean to the list/set with modifyListen notification.
|
||||
*/
|
||||
void addBean(E bean);
|
||||
|
||||
/**
|
||||
* Remove a bean to the list/set with modifyListen notification.
|
||||
*/
|
||||
void removeBean(E bean);
|
||||
|
||||
/**
|
||||
* Reset the collection back to an empty state ready for reloading.
|
||||
* <p>
|
||||
|
||||
@@ -12,5 +12,5 @@ public interface BeanCollectionAdd {
|
||||
/**
|
||||
* Add a loaded bean to the collection.
|
||||
*/
|
||||
void addBean(EntityBean bean);
|
||||
void addEntityBean(EntityBean bean);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import java.util.Arrays;
|
||||
/**
|
||||
* Represent the call stack (stack trace elements).
|
||||
* <p>
|
||||
* Used with a query to identify a CallStackQuery for AutoFetch automatic query
|
||||
* Used with a query to identify a CallStackQuery for AutoTune automatic query
|
||||
* tuning.
|
||||
* </p>
|
||||
* <p>
|
||||
@@ -26,16 +26,12 @@ public final class CallStack implements Serializable {
|
||||
|
||||
private final StackTraceElement[] callStack;
|
||||
|
||||
public CallStack(StackTraceElement[] callStack) {
|
||||
public CallStack(StackTraceElement[] callStack, int zeroHash, int pathHash) {
|
||||
this.callStack = callStack;
|
||||
this.zeroHash = enc(callStack[0].hashCode());
|
||||
int hc = 0;
|
||||
for (int i = 1; i < callStack.length; i++) {
|
||||
hc = 31 * hc + callStack[i].hashCode();
|
||||
}
|
||||
this.pathHash = enc(hc);
|
||||
this.zeroHash = enc(zeroHash);
|
||||
this.pathHash = enc(pathHash);
|
||||
}
|
||||
|
||||
|
||||
public int hashCode() {
|
||||
int hc = 0;
|
||||
for (int i = 0; i < callStack.length; i++) {
|
||||
@@ -87,8 +83,19 @@ public final class CallStack implements Serializable {
|
||||
return zeroHash + ":" + pathHash + ":" + callStack[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the call stack lines appended with the given newLine string.
|
||||
*/
|
||||
public String description(String newLine) {
|
||||
StringBuilder sb = new StringBuilder(400);
|
||||
for (int i = 0; i < callStack.length; i++) {
|
||||
sb.append(callStack[i].toString()).append(newLine);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getOriginKey(int queryHash) {
|
||||
return zeroHash + "." + enc(queryHash) + "." + pathHash;
|
||||
return enc(queryHash)+ "." + zeroHash + "." + pathHash;
|
||||
}
|
||||
|
||||
private static final int radix = 1 << 6;
|
||||
|
||||
@@ -73,16 +73,6 @@ public interface EntityBean extends Serializable {
|
||||
*/
|
||||
EntityBeanIntercept _ebean_intercept();
|
||||
|
||||
/**
|
||||
* Create a copy of this entity bean.
|
||||
* <p>
|
||||
* This occurs when a bean is changed. The copy represents the bean as it was
|
||||
* initially (oldValues) before any changes where made. This is used for
|
||||
* optimistic concurrency control.
|
||||
* </p>
|
||||
*/
|
||||
Object _ebean_createCopy();
|
||||
|
||||
/**
|
||||
* Set the value of a field of an entity bean of this type.
|
||||
* <p>
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
package com.avaje.ebean.bean;
|
||||
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.ValuePair;
|
||||
|
||||
import javax.persistence.EntityNotFoundException;
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
@@ -11,12 +16,6 @@ import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.EntityNotFoundException;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.ValuePair;
|
||||
|
||||
/**
|
||||
* This is the object added to every entity bean using byte code enhancement.
|
||||
* <p>
|
||||
@@ -45,7 +44,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
/**
|
||||
* The actual entity bean that 'owns' this intercept.
|
||||
*/
|
||||
private EntityBean owner;
|
||||
private final EntityBean owner;
|
||||
|
||||
private EntityBean embeddedOwner;
|
||||
private int embeddedOwnerIndex;
|
||||
@@ -72,7 +71,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
/**
|
||||
* Used when a bean is partially filled.
|
||||
*/
|
||||
private boolean[] loadedProps;
|
||||
private final boolean[] loadedProps;
|
||||
|
||||
private boolean fullyLoadedBean;
|
||||
|
||||
@@ -92,6 +91,8 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
|
||||
private int lazyLoadProperty = -1;
|
||||
|
||||
private Object ownerId;
|
||||
|
||||
/**
|
||||
* Create a intercept with a given entity.
|
||||
* <p>
|
||||
@@ -349,11 +350,22 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* lazy loading and this bean might not be used by the client code at all.
|
||||
* Instead we will fail as soon as the client code tries to use this bean.
|
||||
* </p>
|
||||
* @param lazyLoadPropertyIndex the property that is expected to be loaded
|
||||
*/
|
||||
public void checkLazyLoadFailure() {
|
||||
if (lazyLoadProperty != -1) {
|
||||
this.lazyLoadFailure = true;
|
||||
public boolean isLazyLoadFailure(int lazyLoadPropertyIndex) {
|
||||
if (lazyLoadProperty != -1 || !isLoadedProperty(lazyLoadPropertyIndex)) {
|
||||
lazyLoadFailure = true;
|
||||
return true;
|
||||
}
|
||||
lazyLoadFailure = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Id of the owner bean.
|
||||
*/
|
||||
public void setOwnerId(Object ownerId) {
|
||||
this.ownerId = ownerId;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -449,7 +461,18 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
public int getPropertyLength() {
|
||||
return owner._ebean_getPropertyNames().length;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the loaded state of the property given it's name.
|
||||
*/
|
||||
public void setPropertyLoaded(String propertyName, boolean loaded) {
|
||||
int position = findProperty(propertyName);
|
||||
if (position == -1) {
|
||||
throw new IllegalArgumentException("Property "+propertyName+" not found");
|
||||
}
|
||||
loadedProps[position] = loaded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the property to be treated as unloaded. Used for properties initialised in default
|
||||
* constructor.
|
||||
@@ -496,7 +519,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
setDirty(true);
|
||||
}
|
||||
|
||||
private void setChangedProperty(int propertyIndex) {
|
||||
public void setChangedProperty(int propertyIndex) {
|
||||
if (changedProps == null) {
|
||||
changedProps = new boolean[owner._ebean_getPropertyNames().length];
|
||||
}
|
||||
@@ -581,7 +604,29 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if any of the given property names are dirty.
|
||||
*/
|
||||
public boolean hasDirtyProperty(Set<String> propertyNames) {
|
||||
|
||||
String[] names = owner._ebean_getPropertyNames();
|
||||
int len = getPropertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (changedProps != null && changedProps[i]) {
|
||||
// the property has been changed on this bean
|
||||
if (propertyNames.contains(names[i])) {
|
||||
return true;
|
||||
}
|
||||
} else if (embeddedDirty != null && embeddedDirty[i]) {
|
||||
if (propertyNames.contains(names[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a map of dirty properties with their new and old values.
|
||||
*/
|
||||
@@ -608,7 +653,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
} else if (embeddedDirty != null && embeddedDirty[i]) {
|
||||
// an embedded property has been changed - recurse
|
||||
EntityBean embeddedBean = (EntityBean)owner._ebean_getField(i);
|
||||
embeddedBean._ebean_getIntercept().addDirtyPropertyValues(dirtyValues, getProperty(i)+".");
|
||||
embeddedBean._ebean_getIntercept().addDirtyPropertyValues(dirtyValues, getProperty(i) + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -638,6 +683,20 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a loaded property hash.
|
||||
*/
|
||||
public int getLoadedPropertyHash() {
|
||||
int hash = 37;
|
||||
int len = getPropertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (isLoadedProperty(i)) {
|
||||
hash = hash * 31 + (i+1);
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the set of property names for changed properties.
|
||||
*/
|
||||
@@ -701,7 +760,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
|
||||
if (lazyLoadFailure) {
|
||||
// failed when batch lazy loaded by another bean in the batch
|
||||
throw new EntityNotFoundException("Bean has been deleted - lazy loading failed");
|
||||
throw new EntityNotFoundException("Lazy loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted");
|
||||
}
|
||||
|
||||
if (lazyLoadProperty == -1) {
|
||||
@@ -716,7 +775,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
|
||||
if (lazyLoadFailure) {
|
||||
// failed when lazy loading this bean
|
||||
throw new EntityNotFoundException("Bean has been deleted - lazy loading failed");
|
||||
throw new EntityNotFoundException("Lazy loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted.");
|
||||
}
|
||||
|
||||
// bean should be loaded and intercepting now. setLoaded() has
|
||||
@@ -877,7 +936,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
|
||||
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -892,7 +951,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Integer.valueOf(oldValue), Integer.valueOf(newValue));
|
||||
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -908,7 +967,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Long.valueOf(oldValue), Long.valueOf(newValue));
|
||||
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -923,7 +982,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Double.valueOf(oldValue), Double.valueOf(newValue));
|
||||
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -938,7 +997,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Float.valueOf(oldValue), Float.valueOf(newValue));
|
||||
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -953,7 +1012,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Short.valueOf(oldValue), Short.valueOf(newValue));
|
||||
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -968,7 +1027,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Character.valueOf(oldValue), Character.valueOf(newValue));
|
||||
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -983,7 +1042,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Byte.valueOf(oldValue), Byte.valueOf(newValue));
|
||||
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package com.avaje.ebean.bean;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Collects profile information for a bean (or reference/proxy bean) at a given
|
||||
* AutoFetchNode.
|
||||
* Collects profile information for a bean (or reference/proxy bean) at a given node.
|
||||
* <p>
|
||||
* The AutoFetchNode identifies the location of the bean in the object graph.
|
||||
* The node identifies the location of the bean in the object graph.
|
||||
* </p>
|
||||
* <p>
|
||||
* It has to use a weak reference so as to ensure that it does not stop the
|
||||
@@ -29,7 +29,7 @@ public final class NodeUsageCollector {
|
||||
/**
|
||||
* The properties used at this profile point.
|
||||
*/
|
||||
private final HashSet<String> used = new HashSet<String>();
|
||||
private final Set<String> used = new LinkedHashSet<String>();
|
||||
|
||||
/**
|
||||
* set to true if the bean is modified (setter called)
|
||||
@@ -105,7 +105,7 @@ public final class NodeUsageCollector {
|
||||
/**
|
||||
* Return the set of used properties.
|
||||
*/
|
||||
public HashSet<String> getUsed() {
|
||||
public Set<String> getUsed() {
|
||||
return used;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ public interface NodeUsageListener {
|
||||
* Collect node usage "profiling" information.
|
||||
* <p>
|
||||
* This is the properties that are used for a given bean in the object graph.
|
||||
* This information is used by autoFetch to tune queries.
|
||||
* This information is used by autoTune to tune queries.
|
||||
* </p>
|
||||
*/
|
||||
void collectNodeUsage(NodeUsageCollector collector);
|
||||
|
||||
@@ -82,6 +82,7 @@ public final class ObjectGraphNode implements Serializable {
|
||||
}
|
||||
|
||||
ObjectGraphNode e = (ObjectGraphNode) obj;
|
||||
//noinspection StringEquality
|
||||
return ((e.path == path) || (e.path != null && e.path.equals(path)))
|
||||
&& e.originQueryPoint.equals(originQueryPoint);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import java.io.Serializable;
|
||||
* The call stack is included so that the query can have different tuned fetches
|
||||
* for each unique call stack. For example, a query to fetch a customer could be
|
||||
* called by three different methods and each can be treated as a separate
|
||||
* origin point (and autoFetch can tune each one separately).
|
||||
* origin point (and autoTune can tune each one separately).
|
||||
* </p>
|
||||
*/
|
||||
public final class ObjectGraphOrigin implements Serializable {
|
||||
|
||||
@@ -74,12 +74,12 @@ public interface PersistenceContext {
|
||||
* The bean was previously deleted from this persistence context (can't hit
|
||||
* L2 cache).
|
||||
*/
|
||||
public static WithOption DELETED = new WithOption(true);
|
||||
public static final WithOption DELETED = new WithOption();
|
||||
|
||||
private final boolean deleted;
|
||||
private final Object bean;
|
||||
|
||||
private WithOption(boolean deleted) {
|
||||
private WithOption() {
|
||||
this.deleted = true;
|
||||
this.bean = null;
|
||||
}
|
||||
|
||||
@@ -48,12 +48,6 @@ public interface ServerCache {
|
||||
*/
|
||||
Object put(Object id, Object value);
|
||||
|
||||
/**
|
||||
* Put the value in the cache but only if a matching value is not already in
|
||||
* the cache.
|
||||
*/
|
||||
Object putIfAbsent(Object id, Object value);
|
||||
|
||||
/**
|
||||
* Remove a entry from the cache given its id.
|
||||
*/
|
||||
|
||||
+24
-5
@@ -10,6 +10,7 @@ public class ServerCacheOptions {
|
||||
private int maxSize;
|
||||
private int maxIdleSecs;
|
||||
private int maxSecsToLive;
|
||||
private int trimFrequency;
|
||||
|
||||
/**
|
||||
* Construct with no set options.
|
||||
@@ -25,15 +26,17 @@ public class ServerCacheOptions {
|
||||
this.maxSize = cacheTuning.maxSize();
|
||||
this.maxIdleSecs = cacheTuning.maxIdleSecs();
|
||||
this.maxSecsToLive = cacheTuning.maxSecsToLive();
|
||||
this.trimFrequency = cacheTuning.trimFrequency();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create merging default options with the deployment specified ones.
|
||||
*/
|
||||
public ServerCacheOptions(ServerCacheOptions d) {
|
||||
this.maxSize = d.getMaxSize();
|
||||
this.maxIdleSecs = d.getMaxIdleSecs();
|
||||
this.maxSecsToLive = d.getMaxIdleSecs();
|
||||
public ServerCacheOptions(ServerCacheOptions defaults) {
|
||||
this.maxSize = defaults.getMaxSize();
|
||||
this.maxIdleSecs = defaults.getMaxIdleSecs();
|
||||
this.maxSecsToLive = defaults.getMaxIdleSecs();
|
||||
this.trimFrequency = defaults.getTrimFrequency();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,6 +53,9 @@ public class ServerCacheOptions {
|
||||
if (maxSecsToLive == 0) {
|
||||
maxSecsToLive = defaults.getMaxSecsToLive();
|
||||
}
|
||||
if (trimFrequency == 0) {
|
||||
trimFrequency = defaults.getTrimFrequency();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,7 +67,7 @@ public class ServerCacheOptions {
|
||||
copy.maxSize = maxSize;
|
||||
copy.maxIdleSecs = maxIdleSecs;
|
||||
copy.maxSecsToLive = maxSecsToLive;
|
||||
|
||||
copy.trimFrequency = trimFrequency;
|
||||
return copy;
|
||||
}
|
||||
|
||||
@@ -107,4 +113,17 @@ public class ServerCacheOptions {
|
||||
this.maxSecsToLive = maxSecsToLive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the trim frequency in seconds.
|
||||
*/
|
||||
public int getTrimFrequency() {
|
||||
return trimFrequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the trim frequency in seconds.
|
||||
*/
|
||||
public void setTrimFrequency(int trimFrequency) {
|
||||
this.trimFrequency = trimFrequency;
|
||||
}
|
||||
}
|
||||
|
||||
+177
-24
@@ -5,9 +5,9 @@ package com.avaje.ebean.cache;
|
||||
* <p>
|
||||
* These can be monitored to review the effectiveness of a particular cache.
|
||||
* </p>
|
||||
*
|
||||
* @author rbygrave
|
||||
*
|
||||
* <p>
|
||||
* Depending on the cache implementation not all the statistics may be collected.
|
||||
* </p>
|
||||
*/
|
||||
public class ServerCacheStatistics {
|
||||
|
||||
@@ -17,21 +17,64 @@ public class ServerCacheStatistics {
|
||||
|
||||
protected int size;
|
||||
|
||||
protected int hitCount;
|
||||
protected long hitCount;
|
||||
|
||||
protected int missCount;
|
||||
protected long missCount;
|
||||
|
||||
protected long insertCount;
|
||||
|
||||
protected long updateCount;
|
||||
|
||||
protected long removeCount;
|
||||
|
||||
protected long clearCount;
|
||||
|
||||
protected long evictionRunCount;
|
||||
|
||||
protected long evictionRunMicros;
|
||||
|
||||
protected long evictByIdle;
|
||||
|
||||
protected long evictByTTL;
|
||||
|
||||
protected long evictByLRU;
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
//noinspection StringBufferReplaceableByString
|
||||
StringBuilder sb = new StringBuilder(80);
|
||||
sb.append(cacheName);
|
||||
sb.append(" maxSize:").append(maxSize);
|
||||
sb.append(" size:").append(size);
|
||||
sb.append(" hitRatio:").append(getHitRatio());
|
||||
sb.append(" hitCount:").append(hitCount);
|
||||
sb.append(" missCount:").append(missCount);
|
||||
sb.append(" maxSize:").append(maxSize);
|
||||
sb.append(" hit:").append(hitCount);
|
||||
sb.append(" miss:").append(missCount);
|
||||
sb.append(" insert:").append(insertCount);
|
||||
sb.append(" update:").append(updateCount);
|
||||
sb.append(" remove:").append(removeCount);
|
||||
sb.append(" clear:").append(clearCount);
|
||||
sb.append(" evictByIdle:").append(evictByIdle);
|
||||
sb.append(" evictByTTL:").append(evictByTTL);
|
||||
sb.append(" evictByLRU:").append(evictByLRU);
|
||||
sb.append(" evictionRunCount:").append(evictionRunCount);
|
||||
sb.append(" evictionRunMicros:").append(evictionRunMicros);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an int from 0 to 100 (percentage) for the hit ratio.
|
||||
* <p>
|
||||
* A hit ratio of 100 means every get request against the cache hits an entry.
|
||||
* </p>
|
||||
*/
|
||||
public int getHitRatio() {
|
||||
long totalCount = hitCount + missCount;
|
||||
if (totalCount == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return (int)(hitCount * 100 / totalCount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the cache.
|
||||
*/
|
||||
@@ -49,28 +92,28 @@ public class ServerCacheStatistics {
|
||||
/**
|
||||
* Return the hit count. The number of successful gets.
|
||||
*/
|
||||
public int getHitCount() {
|
||||
public long getHitCount() {
|
||||
return hitCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the hit count.
|
||||
*/
|
||||
public void setHitCount(int hitCount) {
|
||||
public void setHitCount(long hitCount) {
|
||||
this.hitCount = hitCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the miss count. The number of gets that returned null.
|
||||
*/
|
||||
public int getMissCount() {
|
||||
public long getMissCount() {
|
||||
return missCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the miss count.
|
||||
*/
|
||||
public void setMissCount(int missCount) {
|
||||
public void setMissCount(long missCount) {
|
||||
this.missCount = missCount;
|
||||
}
|
||||
|
||||
@@ -107,18 +150,128 @@ public class ServerCacheStatistics {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an int from 0 to 100 (percentage) for the hit ratio.
|
||||
* <p>
|
||||
* A hit ratio of 100 means every get request against the cache hits an entry.
|
||||
* </p>
|
||||
* Set the put insert count.
|
||||
*/
|
||||
public int getHitRatio() {
|
||||
int totalCount = hitCount + missCount;
|
||||
if (totalCount == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return hitCount * 100 / totalCount;
|
||||
}
|
||||
public void setInsertCount(long insertCount) {
|
||||
this.insertCount = insertCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the put insert count.
|
||||
*/
|
||||
public long getInsertCount() {
|
||||
return insertCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the put update count.
|
||||
*/
|
||||
public void setUpdateCount(long updateCount) {
|
||||
this.updateCount = updateCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the put update count.
|
||||
*/
|
||||
public long getUpdateCount() {
|
||||
return updateCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the remove count.
|
||||
*/
|
||||
public void setRemoveCount(long removeCount) {
|
||||
this.removeCount = removeCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the remove count.
|
||||
*/
|
||||
public long getRemoveCount() {
|
||||
return removeCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the clear count.
|
||||
*/
|
||||
public void setClearCount(long clearCount) {
|
||||
this.clearCount = clearCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the clear count.
|
||||
*/
|
||||
public long getClearCount() {
|
||||
return clearCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the eviction run count.
|
||||
*/
|
||||
public void setEvictionRunCount(long evictCount) {
|
||||
this.evictionRunCount = evictCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the eviction run count.
|
||||
*/
|
||||
public long getEvictionRunCount() {
|
||||
return evictionRunCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the eviction run time in micros.
|
||||
*/
|
||||
public void setEvictionRunMicros(long evictionRunMicros) {
|
||||
this.evictionRunMicros = evictionRunMicros;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the eviction run time in micros.
|
||||
*/
|
||||
public long getEvictionRunMicros() {
|
||||
return evictionRunMicros;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the count of entries evicted due to idle time.
|
||||
*/
|
||||
public void setEvictByIdle(long evictByIdle) {
|
||||
this.evictByIdle = evictByIdle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of entries evicted due to idle time.
|
||||
*/
|
||||
public long getEvictByIdle() {
|
||||
return evictByIdle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the count of entries evicted due to time to live.
|
||||
*/
|
||||
public void setEvictByTTL(long evictByTTL) {
|
||||
this.evictByTTL = evictByTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of entries evicted due to time to live.
|
||||
*/
|
||||
public long getEvictByTTL() {
|
||||
return evictByTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the count of entries evicted due to time least recently used.
|
||||
*/
|
||||
public void setEvictByLRU(long evictByLRU) {
|
||||
this.evictByLRU = evictByLRU;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of entries evicted due to time least recently used.
|
||||
*/
|
||||
public long getEvictByLRU() {
|
||||
return evictByLRU;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void addBean(EntityBean bean) {
|
||||
public void addEntityBean(EntityBean bean) {
|
||||
list.add((E) bean);
|
||||
}
|
||||
|
||||
@@ -206,6 +206,11 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
list.add(index, element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBean(E bean) {
|
||||
add(bean);
|
||||
}
|
||||
|
||||
public boolean add(E o) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
@@ -319,6 +324,13 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
return list.listIterator(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeBean(E bean) {
|
||||
if (list.remove(bean)) {
|
||||
getModifyHolder().modifyRemoval(bean);
|
||||
}
|
||||
}
|
||||
|
||||
public E remove(int index) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
@@ -343,41 +355,41 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
return list.remove(o);
|
||||
}
|
||||
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
public boolean removeAll(Collection<?> beans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyRemoveListening) {
|
||||
boolean changed = false;
|
||||
Iterator<?> it = c.iterator();
|
||||
while (it.hasNext()) {
|
||||
Object o = it.next();
|
||||
if (list.remove(o)) {
|
||||
modifyRemoval(o);
|
||||
for (Object bean : beans) {
|
||||
if (list.remove(bean)) {
|
||||
// register this bean as having been removed
|
||||
modifyRemoval(bean);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
return list.removeAll(c);
|
||||
return list.removeAll(beans);
|
||||
}
|
||||
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
public boolean retainAll(Collection<?> retainBeans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyRemoveListening) {
|
||||
boolean changed = false;
|
||||
Iterator<E> it = list.iterator();
|
||||
while (it.hasNext()) {
|
||||
Object o = it.next();
|
||||
if (!c.contains(o)) {
|
||||
Object bean = it.next();
|
||||
if (!retainBeans.contains(bean)) {
|
||||
// removing this bean
|
||||
it.remove();
|
||||
modifyRemoval(o);
|
||||
modifyRemoval(bean);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
return list.retainAll(c);
|
||||
return list.retainAll(retainBeans);
|
||||
}
|
||||
|
||||
public E set(int index, E element) {
|
||||
@@ -415,6 +427,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
public <T> T[] toArray(T[] a) {
|
||||
init();
|
||||
//noinspection SuspiciousToArrayCall
|
||||
return list.toArray(a);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
package com.avaje.ebean.common;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.avaje.ebean.bean.BeanCollectionLoader;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Map capable of lazy loading.
|
||||
*/
|
||||
@@ -148,8 +147,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
public Collection<E> getActualDetails() {
|
||||
return map.values();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the map entrySet.
|
||||
* <p>
|
||||
@@ -159,7 +157,6 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
*/
|
||||
public Collection<?> getActualEntries() {
|
||||
return map.entrySet();
|
||||
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
@@ -195,9 +192,9 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
checkReadOnly();
|
||||
initClear();
|
||||
if (modifyRemoveListening) {
|
||||
for (K key : map.keySet()) {
|
||||
E o = map.remove(key);
|
||||
modifyRemoval(o);
|
||||
// add all beans to the removal list
|
||||
for (E bean : map.values()) {
|
||||
modifyRemoval(bean);
|
||||
}
|
||||
}
|
||||
map.clear();
|
||||
@@ -249,27 +246,40 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
Object o = map.put(key, value);
|
||||
modifyAddition(value);
|
||||
modifyRemoval(o);
|
||||
Object oldBean = map.put(key, value);
|
||||
if (value != oldBean) {
|
||||
// register the add of the new and the removal of the old
|
||||
modifyAddition(value);
|
||||
modifyRemoval(oldBean);
|
||||
}
|
||||
}
|
||||
return map.put(key, value);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public void putAll(Map<? extends K, ? extends E> t) {
|
||||
public void putAll(Map<? extends K, ? extends E> puts) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
Iterator it = t.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
Map.Entry entry = (Map.Entry) it.next();
|
||||
Object o = map.put((K) entry.getKey(), (E) entry.getValue());
|
||||
modifyAddition((E) entry.getValue());
|
||||
modifyRemoval(o);
|
||||
for (Entry<? extends K, ? extends E> entry : puts.entrySet()) {
|
||||
Object oldBean = map.put(entry.getKey(), entry.getValue());
|
||||
if (entry.getValue() != oldBean) {
|
||||
modifyAddition(entry.getValue());
|
||||
modifyRemoval(oldBean);
|
||||
}
|
||||
}
|
||||
}
|
||||
map.putAll(t);
|
||||
map.putAll(puts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBean(E bean) {
|
||||
throw new IllegalStateException("Method not allowed on Map. Please use List instead.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeBean(E bean) {
|
||||
throw new IllegalStateException("Method not allowed on Map. Please use List instead.");
|
||||
}
|
||||
|
||||
public E remove(Object key) {
|
||||
|
||||
@@ -53,7 +53,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void addBean(EntityBean bean) {
|
||||
public void addEntityBean(EntityBean bean) {
|
||||
set.add((E) bean);
|
||||
}
|
||||
|
||||
@@ -174,6 +174,18 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
return set.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBean(E bean) {
|
||||
add(bean);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeBean(E bean) {
|
||||
if (set.remove(bean)) {
|
||||
getModifyHolder().modifyRemoval(bean);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------//
|
||||
// proxy method for map
|
||||
// -----------------------------------------------------//
|
||||
@@ -192,32 +204,29 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
return set.add(o);
|
||||
}
|
||||
|
||||
public boolean addAll(Collection<? extends E> c) {
|
||||
public boolean addAll(Collection<? extends E> addCollection) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyAddListening) {
|
||||
boolean changed = false;
|
||||
Iterator<? extends E> it = c.iterator();
|
||||
while (it.hasNext()) {
|
||||
E o = it.next();
|
||||
if (set.add(o)) {
|
||||
modifyAddition(o);
|
||||
for (E bean : addCollection) {
|
||||
if (set.add(bean)) {
|
||||
// register the addition of the bean
|
||||
modifyAddition(bean);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
return set.addAll(c);
|
||||
return set.addAll(addCollection);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
checkReadOnly();
|
||||
initClear();
|
||||
if (modifyRemoveListening) {
|
||||
Iterator<E> it = set.iterator();
|
||||
while (it.hasNext()) {
|
||||
E e = it.next();
|
||||
modifyRemoval(e);
|
||||
for (E bean : set) {
|
||||
modifyRemoval(bean);
|
||||
}
|
||||
}
|
||||
set.clear();
|
||||
@@ -262,41 +271,40 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
return set.remove(o);
|
||||
}
|
||||
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
public boolean removeAll(Collection<?> beans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyRemoveListening) {
|
||||
boolean changed = false;
|
||||
Iterator<?> it = c.iterator();
|
||||
while (it.hasNext()) {
|
||||
Object o = it.next();
|
||||
if (set.remove(o)) {
|
||||
modifyRemoval(o);
|
||||
for (Object bean : beans) {
|
||||
if (set.remove(bean)) {
|
||||
modifyRemoval(bean);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
return set.removeAll(c);
|
||||
return set.removeAll(beans);
|
||||
}
|
||||
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
public boolean retainAll(Collection<?> beans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyRemoveListening) {
|
||||
boolean changed = false;
|
||||
Iterator<?> it = set.iterator();
|
||||
while (it.hasNext()) {
|
||||
Object o = it.next();
|
||||
if (!c.contains(o)) {
|
||||
Object bean = it.next();
|
||||
if (!beans.contains(bean)) {
|
||||
// not retaining this bean so add it to the removal list
|
||||
it.remove();
|
||||
modifyRemoval(o);
|
||||
modifyRemoval(bean);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
return set.retainAll(c);
|
||||
return set.retainAll(beans);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
@@ -311,6 +319,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
|
||||
public <T> T[] toArray(T[] a) {
|
||||
init();
|
||||
//noinspection SuspiciousToArrayCall
|
||||
return set.toArray(a);
|
||||
}
|
||||
|
||||
|
||||
@@ -40,9 +40,7 @@ class ModifyCollection<E> implements Collection<E> {
|
||||
|
||||
public boolean addAll(Collection<? extends E> collection) {
|
||||
boolean changed = false;
|
||||
Iterator<? extends E> it = collection.iterator();
|
||||
while (it.hasNext()) {
|
||||
E o = it.next();
|
||||
for (E o : collection) {
|
||||
if (c.add(o)) {
|
||||
owner.modifyAddition(o);
|
||||
changed = true;
|
||||
@@ -51,27 +49,33 @@ class ModifyCollection<E> implements Collection<E> {
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
c.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return c.contains(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> collection) {
|
||||
return c.containsAll(collection);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return c.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
Iterator<E> it = c.iterator();
|
||||
return new ModifyIterator<E>(owner, it);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
if (c.remove(o)) {
|
||||
owner.modifyRemoval(o);
|
||||
@@ -80,42 +84,47 @@ class ModifyCollection<E> implements Collection<E> {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> collection) {
|
||||
boolean changed = false;
|
||||
Iterator<?> it = collection.iterator();
|
||||
while (it.hasNext()) {
|
||||
Object o = (Object) it.next();
|
||||
if (c.remove(o)) {
|
||||
owner.modifyRemoval(o);
|
||||
for (Object bean : collection) {
|
||||
if (c.remove(bean)) {
|
||||
owner.modifyRemoval(bean);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> collection) {
|
||||
boolean changed = false;
|
||||
Iterator<?> it = c.iterator();
|
||||
while (it.hasNext()) {
|
||||
Object o = (Object) it.next();
|
||||
if (!collection.contains(o)) {
|
||||
Object bean = it.next();
|
||||
if (!collection.contains(bean)) {
|
||||
// not retaining this bean so add to removals
|
||||
it.remove();
|
||||
owner.modifyRemoval(o);
|
||||
owner.modifyRemoval(bean);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return c.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return c.toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T[] toArray(T[] a) {
|
||||
//noinspection SuspiciousToArrayCall
|
||||
return c.toArray(a);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ class ModifyHolder<E> implements Serializable {
|
||||
void modifyRemoval(Object bean) {
|
||||
if (bean != null) {
|
||||
// If it is to be added then just remove the addition
|
||||
if (!modifyAdditions.remove((E) bean)) {
|
||||
if (!modifyAdditions.remove(bean)) {
|
||||
modifyDeletions.add((E) bean);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.avaje.ebean.common;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
@@ -39,12 +38,10 @@ class ModifyList<E> extends ModifyCollection<E> implements List<E> {
|
||||
owner.modifyAddition(element);
|
||||
}
|
||||
|
||||
public boolean addAll(int index, Collection<? extends E> co) {
|
||||
if (list.addAll(index, co)) {
|
||||
Iterator<? extends E> it = co.iterator();
|
||||
while (it.hasNext()) {
|
||||
E o = it.next();
|
||||
owner.modifyAddition(o);
|
||||
public boolean addAll(int index, Collection<? extends E> addCollection) {
|
||||
if (list.addAll(index, addCollection)) {
|
||||
for (E bean : addCollection) {
|
||||
owner.modifyAddition(bean);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -67,9 +67,7 @@ class ModifyListIterator<E> implements ListIterator<E> {
|
||||
}
|
||||
|
||||
public void set(E o) {
|
||||
if (last == null) {
|
||||
// in theory this is not allowed
|
||||
} else {
|
||||
if (last != null) {
|
||||
owner.modifyRemoval(last);
|
||||
owner.modifyAddition(o);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
package com.avaje.ebean.config;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
|
||||
|
||||
import javax.persistence.Inheritance;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Provides some base implementation for NamingConventions.
|
||||
*
|
||||
@@ -14,31 +12,39 @@ import org.slf4j.LoggerFactory;
|
||||
*/
|
||||
public abstract class AbstractNamingConvention implements NamingConvention {
|
||||
|
||||
/** The Constant logger. */
|
||||
private static final Logger logger = LoggerFactory.getLogger(AbstractNamingConvention.class);
|
||||
|
||||
/** The Constant DEFAULT_SEQ_FORMAT. */
|
||||
/**
|
||||
* The Constant DEFAULT_SEQ_FORMAT.
|
||||
*/
|
||||
public static final String DEFAULT_SEQ_FORMAT = "{table}_seq";
|
||||
|
||||
/** Sequence Format that includes the Primary Key column */
|
||||
/**
|
||||
* Sequence Format that includes the Primary Key column
|
||||
*/
|
||||
public static final String TABLE_PKCOLUMN_SEQ_FORMAT = "{table}_{column}_seq";
|
||||
|
||||
/** The catalog. */
|
||||
/**
|
||||
* The catalog.
|
||||
*/
|
||||
private String catalog;
|
||||
|
||||
/** The schema. */
|
||||
/**
|
||||
* The schema.
|
||||
*/
|
||||
private String schema;
|
||||
|
||||
/** The sequence format. */
|
||||
/**
|
||||
* The sequence format.
|
||||
*/
|
||||
private String sequenceFormat;
|
||||
|
||||
/** The database platform. */
|
||||
/**
|
||||
* The database platform.
|
||||
*/
|
||||
protected DatabasePlatform databasePlatform;
|
||||
|
||||
/** The max length of constraint names. */
|
||||
protected int maxConstraintNameLength;
|
||||
|
||||
/** Used to trim off extra prefix for M2M. */
|
||||
/**
|
||||
* Used to trim off extra prefix for M2M.
|
||||
*/
|
||||
protected int rhsPrefixLength = 3;
|
||||
|
||||
protected boolean useForeignKeyPrefix;
|
||||
@@ -62,8 +68,7 @@ public abstract class AbstractNamingConvention implements NamingConvention {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct with the default sequence format ("{table}_seq") and
|
||||
* useForeignKeyPrefix as true.
|
||||
* Construct with the default sequence format ("{table}_seq") and useForeignKeyPrefix as true.
|
||||
*/
|
||||
public AbstractNamingConvention() {
|
||||
this(DEFAULT_SEQ_FORMAT);
|
||||
@@ -71,9 +76,6 @@ public abstract class AbstractNamingConvention implements NamingConvention {
|
||||
|
||||
public void setDatabasePlatform(DatabasePlatform databasePlatform) {
|
||||
this.databasePlatform = databasePlatform;
|
||||
this.maxConstraintNameLength = databasePlatform.getDbDdlSyntax().getMaxConstraintNameLength();
|
||||
|
||||
logger.trace("Using maxConstraintNameLength of " + maxConstraintNameLength);
|
||||
}
|
||||
|
||||
public String getSequenceName(String tableName, String pkColumn) {
|
||||
@@ -218,11 +220,11 @@ public abstract class AbstractNamingConvention implements NamingConvention {
|
||||
}
|
||||
buffer.append(rhsTableName);
|
||||
|
||||
int maxConstraintNameLength = databasePlatform.getDbDdlSyntax().getMaxConstraintNameLength();
|
||||
int maxTableNameLength = databasePlatform.getMaxTableNameLength();
|
||||
|
||||
// maxConstraintNameLength is used as the max table name length.
|
||||
if (buffer.length() > maxConstraintNameLength) {
|
||||
buffer.setLength(maxConstraintNameLength);
|
||||
if (buffer.length() > maxTableNameLength) {
|
||||
buffer.setLength(maxTableNameLength);
|
||||
}
|
||||
|
||||
return new TableName(lhsTable.getCatalog(), lhsTable.getSchema(), buffer.toString());
|
||||
@@ -239,7 +241,7 @@ public abstract class AbstractNamingConvention implements NamingConvention {
|
||||
if (t != null && !isEmpty(t.name())) {
|
||||
// Note: empty catalog and schema are converted to null
|
||||
// Only need to convert quoted identifiers from annotations
|
||||
return new TableName(quoteIdentifiers(t.catalog()), quoteIdentifiers(t.schema()), quoteIdentifiers(t.name()));
|
||||
return new TableName(quoteIdentifiers(t.catalog()), quoteIdentifiers(t.schema()), quoteIdentifiers(t.name()));
|
||||
}
|
||||
|
||||
// No annotation
|
||||
@@ -272,10 +274,7 @@ public abstract class AbstractNamingConvention implements NamingConvention {
|
||||
* Checks string is null or empty .
|
||||
*/
|
||||
protected boolean isEmpty(String s) {
|
||||
if (s == null || s.trim().length() == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return s == null || s.trim().length() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
package com.avaje.ebean.config;
|
||||
|
||||
/**
|
||||
* Defines the AutoTune behaviour for a EbeanServer.
|
||||
*/
|
||||
public class AutoTuneConfig {
|
||||
|
||||
private AutoTuneMode mode = AutoTuneMode.DEFAULT_ON;
|
||||
|
||||
private String queryTuningFile = "ebean-autotune.xml";
|
||||
|
||||
private boolean queryTuning;
|
||||
|
||||
private boolean queryTuningAddVersion;
|
||||
|
||||
private boolean profiling;
|
||||
|
||||
private String profilingFile = "ebean-profiling";
|
||||
|
||||
private int profilingBase = 5;
|
||||
|
||||
private double profilingRate = 0.01;
|
||||
|
||||
private int profilingUpdateFrequency;
|
||||
|
||||
private int garbageCollectionWait = 100;
|
||||
|
||||
private boolean skipGarbageCollectionOnShutdown;
|
||||
|
||||
private boolean skipProfileReportingOnShutdown;
|
||||
|
||||
public AutoTuneConfig() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the file that holds the query tuning information.
|
||||
*/
|
||||
public String getQueryTuningFile() {
|
||||
return queryTuningFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the file that holds the query tuning information.
|
||||
*/
|
||||
public void setQueryTuningFile(String queryTuningFile) {
|
||||
this.queryTuningFile = queryTuningFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the file that profiling information is written to.
|
||||
*/
|
||||
public String getProfilingFile() {
|
||||
return profilingFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the file that profiling information is written to.
|
||||
*/
|
||||
public void setProfilingFile(String profilingFile) {
|
||||
this.profilingFile = profilingFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the frequency in seconds the profiling should be collected and automatically applied to the tuning.
|
||||
*/
|
||||
public int getProfilingUpdateFrequency() {
|
||||
return profilingUpdateFrequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the frequency in seconds the profiling should be collected and automatically applied to the tuning.
|
||||
*/
|
||||
public void setProfilingUpdateFrequency(int profilingUpdateFrequency) {
|
||||
this.profilingUpdateFrequency = profilingUpdateFrequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mode used when autoTune has not been explicit defined on a
|
||||
* query.
|
||||
*/
|
||||
public AutoTuneMode getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mode used when autoTune has not been explicit defined on a query.
|
||||
*/
|
||||
public void setMode(AutoTuneMode mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the queries are being tuned.
|
||||
*/
|
||||
public boolean isQueryTuning() {
|
||||
return queryTuning;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if the queries should be tuned by autoTune.
|
||||
*/
|
||||
public void setQueryTuning(boolean queryTuning) {
|
||||
this.queryTuning = queryTuning;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the version property should be added when the query is
|
||||
* tuned.
|
||||
* <p>
|
||||
* If this is false then the version property will be added when profiling
|
||||
* detects that the bean is possibly going to be modified.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isQueryTuningAddVersion() {
|
||||
return queryTuningAddVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true to force the version property to be always added by the query
|
||||
* tuning.
|
||||
* <p>
|
||||
* If this is false then the version property will be added when profiling
|
||||
* detects that the bean is possibly going to be modified.
|
||||
* </p>
|
||||
* <p>
|
||||
* Generally this is not expected to be turned on.
|
||||
* </p>
|
||||
*/
|
||||
public void setQueryTuningAddVersion(boolean queryTuningAddVersion) {
|
||||
this.queryTuningAddVersion = queryTuningAddVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if profiling information should be collected.
|
||||
*/
|
||||
public boolean isProfiling() {
|
||||
return profiling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if profiling information should be collected.
|
||||
* <p>
|
||||
* The profiling information is collected and then used to generate the tuned
|
||||
* queries for autoTune.
|
||||
* </p>
|
||||
*/
|
||||
public void setProfiling(boolean profiling) {
|
||||
this.profiling = profiling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base number of queries to profile before changing to profile
|
||||
* only a percentage of following queries (profileRate).
|
||||
*/
|
||||
public int getProfilingBase() {
|
||||
return profilingBase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the based number of queries to profile.
|
||||
*/
|
||||
public void setProfilingBase(int profilingBase) {
|
||||
this.profilingBase = profilingBase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the rate (%) of queries to be profiled after the 'base' amount of
|
||||
* profiling.
|
||||
*/
|
||||
public double getProfilingRate() {
|
||||
return profilingRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the rate (%) of queries to be profiled after the 'base' amount of
|
||||
* profiling.
|
||||
*/
|
||||
public void setProfilingRate(double profilingRate) {
|
||||
this.profilingRate = profilingRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the time in millis to wait after a system gc to collect profiling
|
||||
* information.
|
||||
* <p>
|
||||
* The profiling information is collected on object finalise. As such we
|
||||
* generally don't want to trigger GC (let the JVM do its thing) but on
|
||||
* shutdown the autoTune manager will trigger System.gc() and then wait
|
||||
* (default 100 millis) to hopefully collect profiling information -
|
||||
* especially for short run unit tests.
|
||||
* </p>
|
||||
*/
|
||||
public int getGarbageCollectionWait() {
|
||||
return garbageCollectionWait;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the time in millis to wait after a System.gc() to collect profiling information.
|
||||
*/
|
||||
public void setGarbageCollectionWait(int garbageCollectionWait) {
|
||||
this.garbageCollectionWait = garbageCollectionWait;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if triggering garbage collection should be skipped on shutdown.
|
||||
* You might set this when System.GC() slows a application shutdown too much.
|
||||
*/
|
||||
public boolean isSkipGarbageCollectionOnShutdown() {
|
||||
return skipGarbageCollectionOnShutdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if triggering garbage collection should be skipped on shutdown.
|
||||
* You might set this when System.GC() slows a application shutdown too much.
|
||||
*/
|
||||
public void setSkipGarbageCollectionOnShutdown(boolean skipGarbageCollectionOnShutdown) {
|
||||
this.skipGarbageCollectionOnShutdown = skipGarbageCollectionOnShutdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if profile reporting should be skipped on shutdown.
|
||||
*/
|
||||
public boolean isSkipProfileReportingOnShutdown() {
|
||||
return skipProfileReportingOnShutdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if profile reporting should be skipped on shutdown.
|
||||
*/
|
||||
public void setSkipProfileReportingOnShutdown(boolean skipProfileReportingOnShutdown) {
|
||||
this.skipProfileReportingOnShutdown = skipProfileReportingOnShutdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the settings from the properties file.
|
||||
*/
|
||||
public void loadSettings(PropertiesWrapper p) {
|
||||
|
||||
queryTuning = p.getBoolean("autoTune.queryTuning", queryTuning);
|
||||
queryTuningAddVersion = p.getBoolean("autoTune.queryTuningAddVersion", queryTuningAddVersion);
|
||||
queryTuningFile = p.get("autoTune.queryTuningFile", queryTuningFile);
|
||||
|
||||
skipGarbageCollectionOnShutdown = p.getBoolean("autoTune.skipGarbageCollectionOnShutdown", skipGarbageCollectionOnShutdown);
|
||||
skipProfileReportingOnShutdown = p.getBoolean("autoTune.skipProfileReportingOnShutdown", skipProfileReportingOnShutdown);
|
||||
|
||||
mode = p.getEnum(AutoTuneMode.class, "autoTune.mode", mode);
|
||||
|
||||
profiling = p.getBoolean("autoTune.profiling", profiling);
|
||||
profilingBase = p.getInt("autoTune.profilingBase", profilingBase);
|
||||
profilingRate = p.getDouble("autoTune.profilingRate", profilingRate);
|
||||
profilingFile = p.get("autoTune.profilingFile", profilingFile);
|
||||
profilingUpdateFrequency = p.getInt("autoTune.profilingUpdateFrequency", profilingUpdateFrequency);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.avaje.ebean.config;
|
||||
|
||||
import com.avaje.ebean.Query;
|
||||
|
||||
/**
|
||||
* The mode for determining if AutoTune will be used for a given query when
|
||||
* {@link Query#setAutoTune(boolean)} has not been explicitly set on a query.
|
||||
* <p>
|
||||
* The explicit control of {@link Query#setAutoTune(boolean)} will always take
|
||||
* precedence. This mode is used when this has not been explicitly set on a
|
||||
* query.
|
||||
* </p>
|
||||
*/
|
||||
public enum AutoTuneMode {
|
||||
|
||||
/**
|
||||
* Don't implicitly use AutoTune. Must explicitly turn it on.
|
||||
*/
|
||||
DEFAULT_OFF,
|
||||
|
||||
/**
|
||||
* Use AutoTune implicitly. Must explicitly turn it off.
|
||||
*/
|
||||
DEFAULT_ON,
|
||||
|
||||
/**
|
||||
* Implicitly use AutoTune if the query has not got either select() or join()
|
||||
* defined.
|
||||
*/
|
||||
DEFAULT_ONIFEMPTY
|
||||
|
||||
}
|
||||
@@ -1,245 +0,0 @@
|
||||
package com.avaje.ebean.config;
|
||||
|
||||
/**
|
||||
* Defines the Autofetch behaviour for a EbeanServer.
|
||||
*/
|
||||
public class AutofetchConfig {
|
||||
|
||||
private AutofetchMode mode = AutofetchMode.DEFAULT_ONIFEMPTY;
|
||||
|
||||
private boolean queryTuning = false;
|
||||
|
||||
private boolean queryTuningAddVersion = false;
|
||||
|
||||
private boolean profiling = false;
|
||||
|
||||
private int profilingMin = 1;
|
||||
|
||||
private int profilingBase = 10;
|
||||
|
||||
private double profilingRate = 0.05;
|
||||
|
||||
private String logDirectory;
|
||||
|
||||
private int profileUpdateFrequency = 60;
|
||||
|
||||
private int garbageCollectionWait = 100;
|
||||
|
||||
private boolean garbageCollectionOnShutdown;
|
||||
|
||||
public AutofetchConfig() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mode used when autofetch has not been explicit defined on a
|
||||
* query.
|
||||
*/
|
||||
public AutofetchMode getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mode used when autofetch has not been explicit defined on a query.
|
||||
*/
|
||||
public void setMode(AutofetchMode mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the queries are being tuned.
|
||||
*/
|
||||
public boolean isQueryTuning() {
|
||||
return queryTuning;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if the queries should be tuned by autofetch.
|
||||
*/
|
||||
public void setQueryTuning(boolean queryTuning) {
|
||||
this.queryTuning = queryTuning;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the version property should be added when the query is
|
||||
* tuned.
|
||||
* <p>
|
||||
* If this is false then the version property will be added when profiling
|
||||
* detects that the bean is possibly going to be modified.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isQueryTuningAddVersion() {
|
||||
return queryTuningAddVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true to force the version property to be always added by the query
|
||||
* tuning.
|
||||
* <p>
|
||||
* If this is false then the version property will be added when profiling
|
||||
* detects that the bean is possibly going to be modified.
|
||||
* </p>
|
||||
*/
|
||||
public void setQueryTuningAddVersion(boolean queryTuningAddVersion) {
|
||||
this.queryTuningAddVersion = queryTuningAddVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if profiling information should be collected.
|
||||
*/
|
||||
public boolean isProfiling() {
|
||||
return profiling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if profiling information should be collected.
|
||||
* <p>
|
||||
* The profiling information is collected and then used to generate the tuned
|
||||
* queries for autofetch.
|
||||
* </p>
|
||||
*/
|
||||
public void setProfiling(boolean profiling) {
|
||||
this.profiling = profiling;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the minimum number of queries to profile before autofetch will start
|
||||
* tuning the queries.
|
||||
*/
|
||||
public int getProfilingMin() {
|
||||
return profilingMin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the minimum number of queries to profile before autofetch will start
|
||||
* tuning the queries.
|
||||
*/
|
||||
public void setProfilingMin(int profilingMin) {
|
||||
this.profilingMin = profilingMin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base number of queries to profile before changing to profile
|
||||
* only a percentage of following queries (profileRate).
|
||||
*/
|
||||
public int getProfilingBase() {
|
||||
return profilingBase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the based number of queries to profile.
|
||||
*/
|
||||
public void setProfilingBase(int profilingBase) {
|
||||
this.profilingBase = profilingBase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the rate (%) of queries to be profiled after the 'base' amount of
|
||||
* profiling.
|
||||
*/
|
||||
public double getProfilingRate() {
|
||||
return profilingRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the rate (%) of queries to be profiled after the 'base' amount of
|
||||
* profiling.
|
||||
*/
|
||||
public void setProfilingRate(double profilingRate) {
|
||||
this.profilingRate = profilingRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the log directory to put the autofetch log.
|
||||
*/
|
||||
public String getLogDirectory() {
|
||||
return logDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the directory to put the autofetch log in.
|
||||
*/
|
||||
public void setLogDirectory(String logDirectory) {
|
||||
this.logDirectory = logDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the frequency in seconds to update the autofetch tuned queries from
|
||||
* the profiled information.
|
||||
*/
|
||||
public int getProfileUpdateFrequency() {
|
||||
return profileUpdateFrequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the frequency in seconds to update the autofetch tuned queries from the
|
||||
* profiled information.
|
||||
*/
|
||||
public void setProfileUpdateFrequency(int profileUpdateFrequency) {
|
||||
this.profileUpdateFrequency = profileUpdateFrequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the time in millis to wait after a system gc to collect profiling
|
||||
* information.
|
||||
* <p>
|
||||
* The profiling information is collected on object finalise. As such we
|
||||
* generally don't want to trigger GC (let the JVM do its thing) but on
|
||||
* shutdown the autofetch manager will trigger System.gc() and then wait
|
||||
* (default 100 millis) to hopefully collect profiling information -
|
||||
* especially for short run unit tests.
|
||||
* </p>
|
||||
*/
|
||||
public int getGarbageCollectionWait() {
|
||||
return garbageCollectionWait;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the time in millis to wait after a System.gc() to collect profiling
|
||||
* information.
|
||||
*/
|
||||
public void setGarbageCollectionWait(int garbageCollectionWait) {
|
||||
this.garbageCollectionWait = garbageCollectionWait;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if GC should be trigger on shutdown.
|
||||
* <p>
|
||||
* Autofetch profiling information is collected as part of garbage collection.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isGarbageCollectionOnShutdown() {
|
||||
return garbageCollectionOnShutdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if you want GC to trigger on shutdown.
|
||||
* <p>
|
||||
* This would be done if you want to try and collect Autofetch profiling information
|
||||
* on shutdown.
|
||||
* </p>
|
||||
*/
|
||||
public void setGarbageCollectionOnShutdown(boolean garbageCollectionOnShutdown) {
|
||||
this.garbageCollectionOnShutdown = garbageCollectionOnShutdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the settings from the properties file.
|
||||
*/
|
||||
public void loadSettings(PropertiesWrapper p) {
|
||||
|
||||
logDirectory = p.get("autofetch.logDirectory", logDirectory);
|
||||
queryTuning = p.getBoolean("autofetch.querytuning", queryTuning);
|
||||
queryTuningAddVersion = p.getBoolean("autofetch.queryTuningAddVersion", queryTuningAddVersion);
|
||||
garbageCollectionOnShutdown = p.getBoolean("autofetch.garbageCollectionOnShutdown", garbageCollectionOnShutdown);
|
||||
|
||||
profiling = p.getBoolean("autofetch.profiling", profiling);
|
||||
mode = p.getEnum(AutofetchMode.class, "autofetch.implicitmode", mode);
|
||||
|
||||
profilingMin = p.getInt("autofetch.profiling.min", profilingMin);
|
||||
profilingBase = p.getInt("autofetch.profiling.base", profilingBase);
|
||||
|
||||
profilingRate = p.getDouble("autofetch.profiling.rate", profilingRate);
|
||||
profileUpdateFrequency = p.getInt("autofetch.profiling.updatefrequency", profileUpdateFrequency);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package com.avaje.ebean.config;
|
||||
|
||||
import com.avaje.ebean.Query;
|
||||
|
||||
/**
|
||||
* The mode for determining if Autofetch will be used for a given query when
|
||||
* {@link Query#setAutofetch(boolean)} has not been explicitly set on a query.
|
||||
* <p>
|
||||
* The explicit control of {@link Query#setAutofetch(boolean)} will always take
|
||||
* precedence. This mode is used when this has not been explicitly set on a
|
||||
* query.
|
||||
* </p>
|
||||
*/
|
||||
public enum AutofetchMode {
|
||||
|
||||
/**
|
||||
* Don't implicitly use Autofetch. Must explicitly turn it on.
|
||||
*/
|
||||
DEFAULT_OFF,
|
||||
|
||||
/**
|
||||
* Use Autofetch implicitly. Must explicitly turn it off.
|
||||
*/
|
||||
DEFAULT_ON,
|
||||
|
||||
/**
|
||||
* Implicitly use Autofetch if the query has not got either select() or join()
|
||||
* defined.
|
||||
*/
|
||||
DEFAULT_ONIFEMPTY
|
||||
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package com.avaje.ebean.config;
|
||||
|
||||
|
||||
/**
|
||||
* Helper to find classes taking into account the context class loader.
|
||||
*/
|
||||
public class ClassLoadConfig {
|
||||
|
||||
protected final ClassLoaderContext context;
|
||||
|
||||
/**
|
||||
* Construct with the default classLoader search with context classLoader first.
|
||||
*/
|
||||
public ClassLoadConfig() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the classLoader to use for class detection and new instance creation.
|
||||
*/
|
||||
public ClassLoadConfig(ClassLoader classLoader) {
|
||||
this.context = new ClassLoaderContext(classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the Java.time types are available and should be supported.
|
||||
*/
|
||||
public boolean isJavaTimePresent() {
|
||||
return isPresent("java.time.LocalDate");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the Joda types are available and should be supported.
|
||||
*/
|
||||
public boolean isJodaTimePresent() {
|
||||
return isPresent("org.joda.time.LocalDateTime");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if javax validation annotations like Size and NotNull are present.
|
||||
*/
|
||||
public boolean isJavaxValidationAnnotationsPresent() {
|
||||
return isPresent("javax.validation.constraints.NotNull");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if Jackson annotations like JsonIgnore are present.
|
||||
*/
|
||||
public boolean isJacksonAnnotationsPresent() {
|
||||
return isPresent("com.fasterxml.jackson.annotation.JsonIgnore");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if Jackson ObjectMapper is present.
|
||||
*/
|
||||
public boolean isJacksonObjectMapperPresent() {
|
||||
return isPresent("com.fasterxml.jackson.databind.ObjectMapper");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new instance of the class using the default constructor.
|
||||
*/
|
||||
public Object newInstance(String className) {
|
||||
|
||||
try {
|
||||
Class<?> cls = forName(className);
|
||||
return cls.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("Error constructing " + className, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the given class is present.
|
||||
*/
|
||||
protected boolean isPresent(String className) {
|
||||
try {
|
||||
forName(className);
|
||||
return true;
|
||||
} catch (Throwable ex) {
|
||||
// Class or one of its dependencies is not present...
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a class taking into account a context class loader (if present).
|
||||
*/
|
||||
protected Class<?> forName(String name) throws ClassNotFoundException {
|
||||
return context.forName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the preferred, caller and context class loaders.
|
||||
*/
|
||||
protected class ClassLoaderContext {
|
||||
|
||||
/**
|
||||
* Optional - if set only use this classLoader (no fallback).
|
||||
*/
|
||||
protected final ClassLoader preferredLoader;
|
||||
|
||||
protected final ClassLoader contextLoader;
|
||||
|
||||
protected final ClassLoader callerLoader;
|
||||
|
||||
ClassLoaderContext(ClassLoader preferredLoader) {
|
||||
this.preferredLoader = preferredLoader;
|
||||
this.callerLoader = ServerConfig.class.getClassLoader();
|
||||
this.contextLoader = contextLoader();
|
||||
}
|
||||
|
||||
ClassLoader contextLoader() {
|
||||
ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
||||
return (loader != null) ? loader: callerLoader;
|
||||
}
|
||||
|
||||
Class<?> forName(String name) throws ClassNotFoundException {
|
||||
|
||||
if (preferredLoader != null) {
|
||||
// only use the explicitly set classLoader
|
||||
return classForName(name, preferredLoader);
|
||||
}
|
||||
try {
|
||||
// try the context loader first
|
||||
return classForName(name, contextLoader);
|
||||
} catch (ClassNotFoundException e) {
|
||||
if (callerLoader == contextLoader) {
|
||||
throw e;
|
||||
} else {
|
||||
// fallback to the caller classLoader
|
||||
return classForName(name, callerLoader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Class<?> classForName(String name, ClassLoader classLoader) throws ClassNotFoundException {
|
||||
return Class.forName(name, true, classLoader);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.avaje.ebean.config;
|
||||
|
||||
/**
|
||||
* Provides the current user in order to support 'Who created', 'Who modified' and other audit features.
|
||||
*/
|
||||
public interface CurrentUserProvider {
|
||||
|
||||
/**
|
||||
* Return the current user id.
|
||||
* <p>
|
||||
* The type returned should match the type of the properties annotated
|
||||
* with @WhoCreated and @WhoModified. These are typically String, Long or UUID.
|
||||
* </p>
|
||||
*/
|
||||
Object currentUser();
|
||||
}
|
||||
@@ -507,8 +507,7 @@ public class DataSourceConfig {
|
||||
|
||||
String customProperties = properties.get("customProperties", null);
|
||||
if (customProperties != null && customProperties.length() > 0) {
|
||||
Map<String, String> custProps = StringHelper.delimitedToMap(customProperties, ";", "=");
|
||||
this.customProperties = custProps;
|
||||
this.customProperties = StringHelper.delimitedToMap(customProperties, ";", "=");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,209 @@
|
||||
package com.avaje.ebean.config;
|
||||
|
||||
/**
|
||||
* Naming convention used for constraint names.
|
||||
* <p>
|
||||
* Note that these constraint names are trimmed in the PlatformDdl which can be overridden
|
||||
* but provides a decent default implementation.
|
||||
* </p>
|
||||
*/
|
||||
public class DbConstraintNaming {
|
||||
|
||||
/**
|
||||
* Defines how constraint names are shortened if required based on platform limitations.
|
||||
*/
|
||||
public interface MaxLength {
|
||||
|
||||
/**
|
||||
* Truncate or shorten the constraint name to support DB platform limitations.
|
||||
* <p>
|
||||
* There is a default implementation of this which is used if an implementation is
|
||||
* not specified.
|
||||
* </p>
|
||||
*/
|
||||
String maxLength(String constraintName, int count);
|
||||
}
|
||||
|
||||
protected String pkPrefix = "pk_";
|
||||
protected String pkSuffix = "";
|
||||
|
||||
protected String fkPrefix = "fk_";
|
||||
protected String fkMiddle = "_";
|
||||
protected String fkSuffix = "";
|
||||
|
||||
protected String fkIndexPrefix = "ix_";
|
||||
protected String fkIndexMiddle = "_";
|
||||
protected String fkIndexSuffix = "";
|
||||
|
||||
protected String indexPrefix = "ix_";
|
||||
protected String indexMiddle = "_";
|
||||
protected String indexSuffix = "";
|
||||
|
||||
protected String uqPrefix = "uq_";
|
||||
protected String uqSuffix = "";
|
||||
|
||||
protected String ckPrefix = "ck_";
|
||||
protected String ckSuffix = "";
|
||||
|
||||
protected MaxLength maxLength;
|
||||
|
||||
protected DbConstraintNormalise normalise;
|
||||
|
||||
/**
|
||||
* Construct using default of lower case for both table and column names.
|
||||
*/
|
||||
public DbConstraintNaming() {
|
||||
this(true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct specifying if lower case should be used (for both table and column names).
|
||||
*/
|
||||
public DbConstraintNaming(boolean lowerCase) {
|
||||
this(lowerCase, lowerCase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct specifying if lower case should be used for both table and column names.
|
||||
*/
|
||||
public DbConstraintNaming(boolean lowerCaseTableNames, boolean lowerCaseColumnNames) {
|
||||
this.normalise = new DbConstraintNormalise(lowerCaseTableNames, lowerCaseColumnNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the MaxLength implementation used to truncate/shorten db constraint names as necessary.
|
||||
*/
|
||||
public MaxLength getMaxLength() {
|
||||
return maxLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the MaxLength implementation used to truncate/shorten db constraint names as necessary.
|
||||
*/
|
||||
public void setMaxLength(MaxLength maxLength) {
|
||||
this.maxLength = maxLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the primary key constraint name.
|
||||
*/
|
||||
public String primaryKeyName(String tableName) {
|
||||
|
||||
return pkPrefix + normaliseTable(tableName) + pkSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the foreign key constraint name given a single column foreign key.
|
||||
*/
|
||||
public String foreignKeyConstraintName(String tableName, String columnName) {
|
||||
return fkPrefix + normaliseTable(tableName) + fkMiddle + normaliseColumn(columnName) + fkSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index name associated with a foreign key constraint given multiple columns.
|
||||
*/
|
||||
public String foreignKeyIndexName(String tableName, String[] columns) {
|
||||
|
||||
String colPart = joinColumnNames(columns);
|
||||
return fkIndexPrefix + normaliseTable(tableName) + fkIndexMiddle + colPart + fkIndexSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index name associated with a foreign key constraint given a single column foreign key.
|
||||
*/
|
||||
public String foreignKeyIndexName(String tableName, String column) {
|
||||
|
||||
String colPart = normaliseTable(column);
|
||||
return fkIndexPrefix + normaliseTable(tableName) + fkIndexMiddle + colPart + fkIndexSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index name for a general index (not associated with a foreign key).
|
||||
*/
|
||||
public String indexName(String tableName, String column) {
|
||||
|
||||
String colPart = normaliseTable(column);
|
||||
return indexPrefix + normaliseTable(tableName) + indexMiddle + colPart + indexSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index name for a general index (not associated with a foreign key).
|
||||
*/
|
||||
public String indexName(String tableName, String[] columns) {
|
||||
|
||||
String colPart = joinColumnNames(columns);
|
||||
return indexPrefix + normaliseTable(tableName) + indexMiddle + colPart + indexSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join the column names together with underscores.
|
||||
*/
|
||||
protected String joinColumnNames(String[] columns) {
|
||||
|
||||
if (columns.length == 1) {
|
||||
return normaliseColumn(columns[0]);
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append("_");
|
||||
}
|
||||
sb.append(normaliseColumn(columns[i]));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the unique constraint name.
|
||||
*/
|
||||
public String uniqueConstraintName(String tableName, String columnName) {
|
||||
|
||||
return uqPrefix + normaliseTable(tableName) + "_" + normaliseColumn(columnName) + uqSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the unique constraint name.
|
||||
*/
|
||||
public String uniqueConstraintName(String tableName, String[] columns) {
|
||||
|
||||
String colPart = joinColumnNames(columns);
|
||||
return uqPrefix + normaliseTable(tableName) + "_" + colPart + uqSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the check constraint name.
|
||||
*/
|
||||
public String checkConstraintName(String tableName, String columnName) {
|
||||
|
||||
return ckPrefix + normaliseTable(tableName) + "_" + normaliseColumn(columnName) + ckSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalise the table name by trimming catalog and schema and removing any
|
||||
* quoted identifier characters (",',[,] etc).
|
||||
*/
|
||||
public String normaliseTable(String tableName) {
|
||||
return normalise.normaliseTable(tableName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalise the column name by removing any quoted identifier characters (",',[,] etc).
|
||||
*/
|
||||
public String normaliseColumn(String tableName) {
|
||||
return normalise.normaliseColumn(tableName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lower case the table name checking for quoted identifiers.
|
||||
*/
|
||||
public String lowerTableName(String tableName) {
|
||||
return normalise.lowerTableName(tableName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lower case the column name checking for quoted identifiers.
|
||||
*/
|
||||
public String lowerColumnName(String name) {
|
||||
return normalise.lowerColumnName(name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package com.avaje.ebean.config;
|
||||
|
||||
/**
|
||||
* Used to normalise table and column names which means stripping out
|
||||
* quoted identifier characters and any catalog or schema prefix.
|
||||
*/
|
||||
public class DbConstraintNormalise {
|
||||
|
||||
protected final String[] quotedIdentifiers;
|
||||
|
||||
protected final boolean lowerCaseTables;
|
||||
|
||||
protected final boolean lowerCaseColumns;
|
||||
|
||||
public DbConstraintNormalise() {
|
||||
this(true, true);
|
||||
}
|
||||
|
||||
public DbConstraintNormalise(boolean lowerCaseTables, boolean lowerCaseColumns) {
|
||||
this.lowerCaseTables = lowerCaseTables;
|
||||
this.lowerCaseColumns = lowerCaseColumns;
|
||||
this.quotedIdentifiers = new String[]{"\"", "'", "[", "]", "`"};
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalise the table name by trimming catalog and schema and removing any
|
||||
* quoted identifier characters (",',[,] etc).
|
||||
*/
|
||||
public String normaliseTable(String tableName) {
|
||||
|
||||
tableName = trimQuotes(tableName);
|
||||
int lastPeriod = tableName.lastIndexOf('.');
|
||||
if (lastPeriod > -1) {
|
||||
// trim off catalog and schema prefix
|
||||
tableName = tableName.substring(lastPeriod + 1);
|
||||
}
|
||||
if (lowerCaseTables) {
|
||||
tableName = tableName.toLowerCase();
|
||||
}
|
||||
return tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalise the column name by removing any quoted identifier characters.
|
||||
*/
|
||||
public String normaliseColumn(String columnName) {
|
||||
|
||||
columnName = trimQuotes(columnName);
|
||||
if (lowerCaseColumns) {
|
||||
columnName = columnName.toLowerCase();
|
||||
}
|
||||
return columnName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lower case the table name checking for quoted identifiers.
|
||||
*/
|
||||
public String lowerTableName(String tableName) {
|
||||
if (lowerCaseTables && notQuoted(tableName)) {
|
||||
return tableName.toLowerCase();
|
||||
}
|
||||
return tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lower case the column name checking for quoted identifiers.
|
||||
*/
|
||||
public String lowerColumnName(String name) {
|
||||
if (lowerCaseColumns && notQuoted(name)) {
|
||||
return name.toLowerCase();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim off the platform quoted identifier quotes like [ ' and ".
|
||||
*/
|
||||
public boolean notQuoted(String tableName) {
|
||||
|
||||
// remove quoted identifier characters
|
||||
for (int i = 0; i < quotedIdentifiers.length; i++) {
|
||||
if (tableName.contains(quotedIdentifiers[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trim off the platform quoted identifier quotes like [ ' and ".
|
||||
*/
|
||||
public String trimQuotes(String tableName) {
|
||||
|
||||
if (tableName == null) {
|
||||
return "";
|
||||
}
|
||||
// remove quoted identifier characters
|
||||
for (int i = 0; i < quotedIdentifiers.length; i++) {
|
||||
tableName = tableName.replace(quotedIdentifiers[i], "");
|
||||
}
|
||||
return tableName;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,393 @@
|
||||
package com.avaje.ebean.config;
|
||||
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebean.config.dbplatform.DbPlatformName;
|
||||
import com.avaje.ebean.dbmigration.DbMigration;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Configuration for the DB migration processing.
|
||||
*/
|
||||
public class DbMigrationConfig {
|
||||
|
||||
protected static final Logger logger = LoggerFactory.getLogger(DbMigrationConfig.class);
|
||||
|
||||
/**
|
||||
* The database platform to generate migration DDL for.
|
||||
*/
|
||||
protected DbPlatformName platform;
|
||||
|
||||
/**
|
||||
* Set to true if the DB migration should be generated on server start.
|
||||
*/
|
||||
protected boolean generate;
|
||||
|
||||
/**
|
||||
* Set to true to suppress the output of the rollback script.
|
||||
*/
|
||||
protected boolean suppressRollback;
|
||||
|
||||
/**
|
||||
* The migration version name (typically FlywayDb compatible).
|
||||
* <p>
|
||||
* Example: 1.1.1_2
|
||||
* <p>
|
||||
* The version is expected to be the combination of the current pom version plus
|
||||
* a 'feature' id. The combined version must be unique and ordered to work with
|
||||
* FlywayDb so each developer sets a unique version so that the migration script
|
||||
* generated is unique (typically just prior to being submitted as a merge request).
|
||||
*/
|
||||
protected String version;
|
||||
|
||||
/**
|
||||
* Description text that can be appended to the version to become the ddl script file name.
|
||||
* <p>
|
||||
* So if the name is "a foo table" then the ddl script file could be:
|
||||
* "1.1.1_2__a-foo-table.sql"
|
||||
* <p>
|
||||
* When the DB migration relates to a git feature (merge request) then this description text
|
||||
* is a short description of the feature.
|
||||
*/
|
||||
protected String name;
|
||||
|
||||
/**
|
||||
* Resource path for the migration xml and sql.
|
||||
*/
|
||||
protected String migrationPath = "dbmigration";
|
||||
|
||||
/**
|
||||
* Subdirectory the model xml files go into.
|
||||
*/
|
||||
protected String modelPath = "model";
|
||||
|
||||
/**
|
||||
* Subdirectory the drop ddl scripts go into.
|
||||
*/
|
||||
protected String dropPath = "drop";
|
||||
|
||||
/**
|
||||
* Subdirectory the rollback ddl scripts go into.
|
||||
*/
|
||||
protected String rollbackPath = "rollback";
|
||||
|
||||
/**
|
||||
* Apply script suffix.
|
||||
*/
|
||||
protected String applySuffix = ".sql";
|
||||
|
||||
/**
|
||||
* Default drop script suffix to ddl so that it isn't picked up by FlywayDb.
|
||||
*/
|
||||
protected String dropSuffix = ".drop.ddl";
|
||||
|
||||
/**
|
||||
* Default rollback script suffix to ddl so that it isn't picked up by FlywayDb.
|
||||
*/
|
||||
protected String rollbackSuffix = ".rollback.ddl";
|
||||
|
||||
protected String modelSuffix = ".model.xml";
|
||||
|
||||
/**
|
||||
* Return the DB platform to generate migration DDL for.
|
||||
*
|
||||
* We typically need to explicitly specify this as migration can often be generated
|
||||
* when running against H2.
|
||||
*/
|
||||
public DbPlatformName getPlatform() {
|
||||
return platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the DB platform to generate migration DDL for.
|
||||
*/
|
||||
public void setPlatform(DbPlatformName platform) {
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the resource path for db migrations.
|
||||
*/
|
||||
public String getMigrationPath() {
|
||||
return migrationPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the resource path for db migrations.
|
||||
* <p>
|
||||
* The default of "dbmigration" is reasonable in most cases. You may look to set this
|
||||
* to be something like "dbmigration/myapp" where myapp gives it a unique resource path
|
||||
* in the case there are multiple EbeanServer applications in the single classpath.
|
||||
* </p>
|
||||
*/
|
||||
public void setMigrationPath(String migrationPath) {
|
||||
this.migrationPath = migrationPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the relative path for the model files (defaults to model).
|
||||
*/
|
||||
public String getModelPath() {
|
||||
return modelPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the relative path for the model files.
|
||||
*/
|
||||
public void setModelPath(String modelPath) {
|
||||
this.modelPath = modelPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the relative path for the drop ddl scripts (defaults to drop).
|
||||
*/
|
||||
public String getDropPath() {
|
||||
return dropPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the relative path for the drop ddl scripts (defaults to drop).
|
||||
*/
|
||||
public void setDropPath(String dropPath) {
|
||||
this.dropPath = dropPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the relative path for the rollback ddl scripts (defaults to rollback).
|
||||
*/
|
||||
public String getRollbackPath() {
|
||||
return rollbackPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the relative path for the rollback ddl scripts (defaults to rollback).
|
||||
*/
|
||||
public void setRollbackPath(String rollbackPath) {
|
||||
this.rollbackPath = rollbackPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the model suffix (defaults to model.xml)
|
||||
*/
|
||||
public String getModelSuffix() {
|
||||
return modelSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the model suffix.
|
||||
*/
|
||||
public void setModelSuffix(String modelSuffix) {
|
||||
this.modelSuffix = modelSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the rollback script should not be output.
|
||||
*/
|
||||
public boolean isSuppressRollback() {
|
||||
return suppressRollback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true to suppress the output of the rollback script.
|
||||
*/
|
||||
public void setSuppressRollback(boolean suppressRollback) {
|
||||
this.suppressRollback = suppressRollback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the apply script suffix (defaults to sql).
|
||||
*/
|
||||
public String getApplySuffix() {
|
||||
return applySuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the apply script suffix (defaults to sql).
|
||||
*/
|
||||
public void setApplySuffix(String applySuffix) {
|
||||
this.applySuffix = applySuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the drop script suffix (defaults to ddl so that it isn't picked up by FlywayDb).
|
||||
*/
|
||||
public String getDropSuffix() {
|
||||
return dropSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the drop script suffix (defaults to ddl so that it isn't picked up by FlywayDb).
|
||||
*/
|
||||
public void setDropSuffix(String dropSuffix) {
|
||||
this.dropSuffix = dropSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the rollback script suffix (defaults to ddl so that it isn't picked up by FlywayDb).
|
||||
*/
|
||||
public String getRollbackSuffix() {
|
||||
return rollbackSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the rollback script suffix (defaults to ddl so that it isn't picked up by FlywayDb).
|
||||
*/
|
||||
public void setRollbackSuffix(String rollbackSuffix) {
|
||||
this.rollbackSuffix = rollbackSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the migration version.
|
||||
* <p>
|
||||
* Note that version set via System property or environment variable <code>ddl.migration.version</code> takes precedence.
|
||||
*/
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the migration name.
|
||||
* <p>
|
||||
* Note that name set via System property or environment variable <code>ddl.migration.name</code> takes precedence.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the model, rollback and drop paths to be empty such that all the migration files are generated
|
||||
* into a single directory.
|
||||
*/
|
||||
public void singleDirectory() {
|
||||
this.dropPath = "";
|
||||
this.rollbackPath = "";
|
||||
this.modelPath = "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the settings from the PropertiesWrapper.
|
||||
*/
|
||||
public void loadSettings(PropertiesWrapper properties) {
|
||||
|
||||
migrationPath = properties.get("migration.migrationPath", migrationPath);
|
||||
if (properties.getBoolean("migration.singleDirectory", false)) {
|
||||
singleDirectory();
|
||||
} else {
|
||||
modelPath = properties.get("migration.modelPath", modelPath);
|
||||
rollbackPath = properties.get("migration.rollbackPath", rollbackPath);
|
||||
dropPath = properties.get("migration.dropPath", dropPath);
|
||||
}
|
||||
applySuffix = properties.get("migration.applySuffix", applySuffix);
|
||||
dropSuffix = properties.get("migration.dropSuffix", dropSuffix);
|
||||
rollbackSuffix = properties.get("migration.rollbackSuffix", rollbackSuffix);
|
||||
modelSuffix = properties.get("migration.modelSuffix", modelSuffix);
|
||||
|
||||
platform = properties.getEnum(DbPlatformName.class, "migration.platform", platform);
|
||||
suppressRollback = properties.getBoolean("migration.suppressRollback", suppressRollback);
|
||||
|
||||
generate = properties.getBoolean("migration.generate", generate);
|
||||
version = properties.get("migration.version", version);
|
||||
name = properties.get("migration.name", name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the migration should be generated.
|
||||
* <p>
|
||||
* It is expected that when an environment variable <code>ddl.migration.enabled</code>
|
||||
* is set to <code>true</code> then the DB migration will generate the migration DDL.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isGenerateOnStart() {
|
||||
|
||||
// environment properties take precedence
|
||||
String envGenerate = readEnvironment("ddl.migration.generate");
|
||||
if (envGenerate != null) {
|
||||
return "true".equalsIgnoreCase(envGenerate.trim());
|
||||
}
|
||||
return generate;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called by EbeanServer on start.
|
||||
*
|
||||
* <p>
|
||||
* If enabled this generates the migration xml and DDL scripts.
|
||||
* </p>
|
||||
*/
|
||||
public void generateOnStart(EbeanServer server) {
|
||||
|
||||
if (isGenerateOnStart()) {
|
||||
if (platform == null) {
|
||||
logger.warn("No platform set for migration DDL generation");
|
||||
} else {
|
||||
// generate the migration xml and platform specific DDL
|
||||
DbMigration migration = new DbMigration(server);
|
||||
migration.setPlatform(platform);
|
||||
try {
|
||||
migration.generateMigration();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error generating DB migration", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the migration version (typically FlywayDb compatible).
|
||||
* <p>
|
||||
* Example: 1.1.1_2
|
||||
* <p>
|
||||
* The version is expected to be the combination of the current pom version plus
|
||||
* a 'feature' id. The combined version must be unique and ordered to work with
|
||||
* FlywayDb so each developer sets a unique version so that the migration script
|
||||
* generated is unique (typically just prior to being submitted as a merge request).
|
||||
*/
|
||||
public String getVersion() {
|
||||
String envVersion = readEnvironment("ddl.migration.version");
|
||||
if (!isEmpty(envVersion)) {
|
||||
return envVersion.trim();
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the migration name which is short description text that can be appended to
|
||||
* the migration version to become the ddl script file name.
|
||||
* <p>
|
||||
* So if the name is "a foo table" then the ddl script file could be:
|
||||
* "1.1.1_2__a-foo-table.sql"
|
||||
* </p>
|
||||
* <p>
|
||||
* When the DB migration relates to a git feature (merge request) then this description text
|
||||
* is a short description of the feature.
|
||||
* </p>
|
||||
*/
|
||||
public String getName() {
|
||||
String envName = readEnvironment("ddl.migration.name");
|
||||
if (!isEmpty(envName)) {
|
||||
return envName.trim();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the system or environment property.
|
||||
*/
|
||||
protected String readEnvironment(String key) {
|
||||
|
||||
String val = System.getProperty(key);
|
||||
if (val == null) {
|
||||
val = System.getenv(key);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the string is null or empty.
|
||||
*/
|
||||
protected boolean isEmpty(String val) {
|
||||
return val == null || val.trim().isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,4 +26,22 @@ public abstract class JsonConfig {
|
||||
ISO8601
|
||||
}
|
||||
|
||||
|
||||
public enum Include {
|
||||
|
||||
/**
|
||||
* Include all values including null and empty collections.
|
||||
*/
|
||||
ALL,
|
||||
|
||||
/**
|
||||
* Exclude null values (include empty collections).
|
||||
*/
|
||||
NON_NULL,
|
||||
|
||||
/**
|
||||
* Exclude null values and empty collections.
|
||||
*/
|
||||
NON_EMPTY
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,8 +82,7 @@ public interface NamingConvention {
|
||||
String getPropertyFromColumn(Class<?> beanClass, String dbColumnName);
|
||||
|
||||
/**
|
||||
* Return the sequence name given the table name (for DB's that use
|
||||
* sequences).
|
||||
* Return the sequence name given the table name (for DB's that use sequences).
|
||||
* <p>
|
||||
* Typically you might append "_seq" to the table name as an example.
|
||||
* </p>
|
||||
@@ -99,14 +98,14 @@ public interface NamingConvention {
|
||||
* Return true if a prefix should be used building a foreign key name.
|
||||
* <p>
|
||||
* This by default is true and this works well when the primary key column
|
||||
* names are simply "ID". In this case a prefix (such as "ORDER" and
|
||||
* "CUSTOMER" etc) is added to the foreign key column producing "ORDER_ID" and
|
||||
* "CUSTOMER_ID".
|
||||
* names are simply "id". In this case a prefix (such as "order" and
|
||||
* "customer" etc) is added to the foreign key column producing "order_id" and
|
||||
* "customer_id".
|
||||
* </p>
|
||||
* <p>
|
||||
* This should return false when your primary key columns are the same as the
|
||||
* foreign key columns. For example, when the primary key columns are
|
||||
* "ORDER_ID", "CUST_ID" etc ... and they are the same as the foreign key
|
||||
* "order_id", "cust_id" etc ... and they are the same as the foreign key
|
||||
* column names.
|
||||
* </p>
|
||||
*/
|
||||
|
||||
@@ -36,7 +36,7 @@ public enum PersistBatch {
|
||||
INHERIT(false);
|
||||
|
||||
|
||||
boolean forInsert;
|
||||
final boolean forInsert;
|
||||
|
||||
PersistBatch(boolean forInsert) {
|
||||
this.forInsert = forInsert;
|
||||
|
||||
@@ -141,8 +141,8 @@ public class PropertiesWrapper {
|
||||
* Return a Enum property value.
|
||||
*/
|
||||
public <T extends Enum<T>> T getEnum(Class<T> enumType, String key, T defaultValue) {
|
||||
String level = get(key, defaultValue.name());
|
||||
return Enum.valueOf(enumType, level.toUpperCase());
|
||||
String level = get(key, null);
|
||||
return (level == null) ? defaultValue : Enum.valueOf(enumType, level.toUpperCase());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,12 +27,12 @@ final class PropertyExpression {
|
||||
/**
|
||||
* Used to detect the start of an expression.
|
||||
*/
|
||||
private static String START = "${";
|
||||
private static final String START = "${";
|
||||
|
||||
/**
|
||||
* Used to detect the end of an expression.
|
||||
*/
|
||||
private static String END = "}";
|
||||
private static final String END = "}";
|
||||
|
||||
/**
|
||||
* Specify the PropertyHolder.
|
||||
@@ -144,13 +144,7 @@ final class PropertyExpression {
|
||||
}
|
||||
|
||||
private static boolean isJndiExpression(String exp) {
|
||||
if (exp.startsWith("JNDI:")) {
|
||||
return true;
|
||||
}
|
||||
if (exp.startsWith("jndi:")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return exp.startsWith("JNDI:") || exp.startsWith("jndi:");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,7 +16,15 @@ public final class PropertyMap implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
|
||||
private final LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
|
||||
|
||||
/**
|
||||
* Return properties loaded from test-ebean.properties.
|
||||
*/
|
||||
public static Properties testProperties() {
|
||||
PropertyMap propertyMap = PropertyMapLoader.loadTestProperties();
|
||||
return (propertyMap == null) ? new Properties() : propertyMap.asProperties();
|
||||
}
|
||||
|
||||
public static Properties defaultProperties() {
|
||||
PropertyMap propertyMap = PropertyMapLoader.loadGlobalProperties();
|
||||
|
||||
@@ -14,17 +14,34 @@ final class PropertyMapLoader {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PropertyMapLoader.class);
|
||||
|
||||
/**
|
||||
* Load the <code>test-ebean.properties</code>.
|
||||
*/
|
||||
public static PropertyMap loadTestProperties() {
|
||||
return load(null, "test-ebean.properties");
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the ebean.properties (and test-ebean.properties if present).
|
||||
*/
|
||||
public static PropertyMap loadGlobalProperties() {
|
||||
|
||||
boolean loadTestProperties = false;
|
||||
String fileName = System.getenv("EBEAN_PROPS_FILE");
|
||||
if (fileName == null) {
|
||||
fileName = System.getProperty("ebean.props.file");
|
||||
if (fileName == null) {
|
||||
loadTestProperties = true;
|
||||
fileName = "ebean.properties";
|
||||
}
|
||||
}
|
||||
|
||||
return load(null, fileName);
|
||||
PropertyMap map = load(null, fileName);
|
||||
if (loadTestProperties) {
|
||||
// load test properties if present in classpath
|
||||
map = load(map, "test-ebean.properties");
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,7 +56,6 @@ final class PropertyMapLoader {
|
||||
|
||||
InputStream is = findInputStream(fileName);
|
||||
if (is == null) {
|
||||
logger.error(fileName + " not found");
|
||||
return p;
|
||||
} else {
|
||||
return load(p, is);
|
||||
@@ -47,7 +63,7 @@ final class PropertyMapLoader {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the inputstream returning the property map.
|
||||
* Load the InputStream returning the property map.
|
||||
*
|
||||
* @param p
|
||||
* an existing property map to load into.
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
package com.avaje.ebean.config;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
|
||||
/**
|
||||
* Unwrap the PreparedStatement to get the specific underlying implementation.
|
||||
* <p>
|
||||
* This is used to handle specific JDBC driver issues. Typically this means
|
||||
* getting the OraclePreparedStatement to handle Oracle specific issues etc.
|
||||
* </p>
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public interface PstmtDelegate {
|
||||
|
||||
/**
|
||||
* Unwrap the PreparedStatement to get the specific underlying implementation.
|
||||
*
|
||||
* @param pstmt
|
||||
* the PreparedStatement coming out of the connection pool
|
||||
* @return the underlying PreparedStatement
|
||||
*/
|
||||
PreparedStatement unwrap(PreparedStatement pstmt);
|
||||
}
|
||||
@@ -7,9 +7,20 @@ import com.avaje.ebean.cache.ServerCacheFactory;
|
||||
import com.avaje.ebean.cache.ServerCacheManager;
|
||||
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
|
||||
import com.avaje.ebean.config.dbplatform.DbEncrypt;
|
||||
import com.avaje.ebean.event.*;
|
||||
import com.avaje.ebean.event.BeanFindController;
|
||||
import com.avaje.ebean.event.BeanPersistController;
|
||||
import com.avaje.ebean.event.BeanPersistListener;
|
||||
import com.avaje.ebean.event.BeanPostLoad;
|
||||
import com.avaje.ebean.event.BeanQueryAdapter;
|
||||
import com.avaje.ebean.event.BulkTableEventListener;
|
||||
import com.avaje.ebean.event.ServerConfigStartup;
|
||||
import com.avaje.ebean.event.TransactionEventListener;
|
||||
import com.avaje.ebean.event.changelog.ChangeLogListener;
|
||||
import com.avaje.ebean.event.changelog.ChangeLogPrepare;
|
||||
import com.avaje.ebean.event.changelog.ChangeLogRegister;
|
||||
import com.avaje.ebean.event.readaudit.ReadAuditLogger;
|
||||
import com.avaje.ebean.event.readaudit.ReadAuditPrepare;
|
||||
import com.avaje.ebean.meta.MetaInfoManager;
|
||||
import com.avaje.ebean.util.ClassUtil;
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
@@ -70,6 +81,11 @@ public class ServerConfig {
|
||||
|
||||
private ContainerConfig containerConfig;
|
||||
|
||||
/**
|
||||
* The underlying properties that were used during configuration.
|
||||
*/
|
||||
private Properties properties;
|
||||
|
||||
/**
|
||||
* The resource directory.
|
||||
*/
|
||||
@@ -113,16 +129,28 @@ public class ServerConfig {
|
||||
*/
|
||||
private String classPathReaderClassName;
|
||||
|
||||
/**
|
||||
* Config controlling the autofetch behaviour.
|
||||
/**
|
||||
* This is used to populate @WhoCreated, @WhoModified and
|
||||
* support other audit features (who executed a query etc).
|
||||
*/
|
||||
private AutofetchConfig autofetchConfig = new AutofetchConfig();
|
||||
private CurrentUserProvider currentUserProvider;
|
||||
|
||||
/**
|
||||
* Config controlling the AutoTune behaviour.
|
||||
*/
|
||||
private AutoTuneConfig autoTuneConfig = new AutoTuneConfig();
|
||||
|
||||
/**
|
||||
* The JSON format used for DateTime types. Default to millis.
|
||||
*/
|
||||
private JsonConfig.DateTime jsonDateTime = JsonConfig.DateTime.MILLIS;
|
||||
|
||||
/**
|
||||
* For writing JSON specify if null values or empty collections should be exluded.
|
||||
* By default all values are included.
|
||||
*/
|
||||
private JsonConfig.Include jsonInclude = JsonConfig.Include.ALL;
|
||||
|
||||
/**
|
||||
* The database platform name. Used to imply a DatabasePlatform to use.
|
||||
*/
|
||||
@@ -138,6 +166,24 @@ public class ServerConfig {
|
||||
*/
|
||||
private int databaseSequenceBatchSize = 20;
|
||||
|
||||
/**
|
||||
* Suffix appended to the base table to derive the view that contains the union
|
||||
* of the base table and the history table in order to support asOf queries.
|
||||
*/
|
||||
private String asOfViewSuffix = "_with_history";
|
||||
|
||||
/**
|
||||
* Column used to support history and 'As of' queries. This column is a timestamp range
|
||||
* or equivalent.
|
||||
*/
|
||||
private String asOfSysPeriod = "sys_period";
|
||||
|
||||
/**
|
||||
* Suffix appended to the base table to derive the view that contains the union
|
||||
* of the base table and the history table in order to support asOf queries.
|
||||
*/
|
||||
private String historyTableSuffix = "_history";
|
||||
|
||||
/**
|
||||
* Use for transaction scoped batch mode.
|
||||
*/
|
||||
@@ -166,6 +212,12 @@ public class ServerConfig {
|
||||
|
||||
private boolean ddlRun;
|
||||
|
||||
private boolean ddlCreateOnly;
|
||||
|
||||
private String ddlInitSql;
|
||||
|
||||
private String ddlSeedSql;
|
||||
|
||||
private boolean useJtaTransactionManager;
|
||||
|
||||
/**
|
||||
@@ -174,11 +226,6 @@ public class ServerConfig {
|
||||
private ExternalTransactionManager externalTransactionManager;
|
||||
|
||||
/**
|
||||
* Used to unwrap PreparedStatements to perform JDBC Driver specific functions
|
||||
*/
|
||||
private PstmtDelegate pstmtDelegate;
|
||||
|
||||
/**
|
||||
* The data source (if programmatically provided).
|
||||
*/
|
||||
private DataSource dataSource;
|
||||
@@ -188,13 +235,28 @@ public class ServerConfig {
|
||||
*/
|
||||
private DataSourceConfig dataSourceConfig = new DataSourceConfig();
|
||||
|
||||
/**
|
||||
* The db migration config (migration resource path etc).
|
||||
*/
|
||||
private DbMigrationConfig migrationConfig = new DbMigrationConfig();
|
||||
|
||||
/**
|
||||
* The ClassLoadConfig used to detect Joda, Java8, Jackson etc and create plugin instances given a className.
|
||||
*/
|
||||
private ClassLoadConfig classLoadConfig = new ClassLoadConfig();
|
||||
|
||||
/**
|
||||
* Set to true if the DataSource uses autoCommit.
|
||||
* <p>
|
||||
* Indicates that Ebean should use autoCommit friendly Transactions and TransactionManager.
|
||||
*/
|
||||
private boolean autoCommitMode;
|
||||
|
||||
|
||||
/**
|
||||
* Set to true if transaction begin should be started with explicit statement.
|
||||
*/
|
||||
private boolean explicitTransactionBeginMode;
|
||||
|
||||
/**
|
||||
* The data source JNDI name if using a JNDI DataSource.
|
||||
*/
|
||||
@@ -215,30 +277,56 @@ public class ServerConfig {
|
||||
*/
|
||||
private NamingConvention namingConvention = new UnderscoreNamingConvention();
|
||||
|
||||
/**
|
||||
* Naming convention used in DDL generation for primary keys, foreign keys etc.
|
||||
*/
|
||||
private DbConstraintNaming constraintNaming = new DbConstraintNaming();
|
||||
|
||||
/**
|
||||
* Behaviour of update to include on the change properties.
|
||||
*/
|
||||
private boolean updateChangesOnly = true;
|
||||
|
||||
|
||||
/**
|
||||
* Behaviour of updates in JDBC batch to by default include all properties.
|
||||
*/
|
||||
private boolean updateAllPropertiesInBatch = true;
|
||||
|
||||
/**
|
||||
* Default behaviour for updates when cascade save on a O2M or M2M to delete any missing children.
|
||||
*/
|
||||
private boolean updatesDeleteMissingChildren = true;
|
||||
|
||||
/**
|
||||
* Setting to indicate if UUID should be stored as binary(16) or varchar(40).
|
||||
* Setting to indicate if UUID should be stored as binary(16) or varchar(40) or native DB type (for H2 and Postgres).
|
||||
*/
|
||||
private boolean uuidStoreAsBinary;
|
||||
private DbUuid dbUuid = DbUuid.AUTO;
|
||||
|
||||
|
||||
private List<BeanFindController> findControllers = new ArrayList<BeanFindController>();
|
||||
private List<BeanPersistController> persistControllers = new ArrayList<BeanPersistController>();
|
||||
private List<BeanPostLoad> postLoaders = new ArrayList<BeanPostLoad>();
|
||||
private List<BeanPersistListener> persistListeners = new ArrayList<BeanPersistListener>();
|
||||
private List<BeanQueryAdapter> queryAdapters = new ArrayList<BeanQueryAdapter>();
|
||||
private List<BulkTableEventListener> bulkTableEventListeners = new ArrayList<BulkTableEventListener>();
|
||||
private List<ServerConfigStartup> configStartupListeners = new ArrayList<ServerConfigStartup>();
|
||||
private List<TransactionEventListener> transactionEventListeners = new ArrayList<TransactionEventListener>();
|
||||
|
||||
/**
|
||||
* By default inserts are included in the change log.
|
||||
*/
|
||||
private boolean changeLogIncludeInserts = true;
|
||||
|
||||
private ChangeLogPrepare changeLogPrepare;
|
||||
|
||||
private ChangeLogListener changeLogListener;
|
||||
|
||||
private ChangeLogRegister changeLogRegister;
|
||||
|
||||
private ReadAuditLogger readAuditLogger;
|
||||
|
||||
private ReadAuditPrepare readAuditPrepare;
|
||||
|
||||
private EncryptKeyManager encryptKeyManager;
|
||||
|
||||
private EncryptDeployManager encryptDeployManager;
|
||||
@@ -294,6 +382,11 @@ public class ServerConfig {
|
||||
private int queryCacheMaxTimeToLive = 60*60*6;
|
||||
private Object objectMapper;
|
||||
|
||||
/**
|
||||
* Set to true if you want eq("someProperty", null) to generate 1=1 rather than "is null" sql expression.
|
||||
*/
|
||||
private boolean expressionEqualsWithNullAsNoop;
|
||||
|
||||
/**
|
||||
* Construct a Server Configuration for programmatically creating an EbeanServer.
|
||||
*/
|
||||
@@ -304,7 +397,7 @@ public class ServerConfig {
|
||||
/**
|
||||
* Return the Jackson JsonFactory to use.
|
||||
* <p>
|
||||
* If not set a default implmentation will be used.
|
||||
* If not set a default implementation will be used.
|
||||
*/
|
||||
public JsonFactory getJsonFactory() {
|
||||
return jsonFactory;
|
||||
@@ -313,7 +406,7 @@ public class ServerConfig {
|
||||
/**
|
||||
* Set the Jackson JsonFactory to use.
|
||||
* <p>
|
||||
* If not set a default implmentation will be used.
|
||||
* If not set a default implementation will be used.
|
||||
*/
|
||||
public void setJsonFactory(JsonFactory jsonFactory) {
|
||||
this.jsonFactory = jsonFactory;
|
||||
@@ -333,6 +426,23 @@ public class ServerConfig {
|
||||
this.jsonDateTime = jsonDateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JSON include mode used when writing JSON.
|
||||
*/
|
||||
public JsonConfig.Include getJsonInclude() {
|
||||
return jsonInclude;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JSON include mode used when writing JSON.
|
||||
* <p>
|
||||
* Set to NON_NULL or NON_EMPTY to suppress nulls or null & empty collections respectively.
|
||||
* </p>
|
||||
*/
|
||||
public void setJsonInclude(JsonConfig.Include jsonInclude) {
|
||||
this.jsonInclude = jsonInclude;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the EbeanServer.
|
||||
*/
|
||||
@@ -411,6 +521,22 @@ public class ServerConfig {
|
||||
this.defaultServer = defaultServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CurrentUserProvider. This is used to populate @WhoCreated, @WhoModified and
|
||||
* support other audit features (who executed a query etc).
|
||||
*/
|
||||
public CurrentUserProvider getCurrentUserProvider() {
|
||||
return currentUserProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the CurrentUserProvider. This is used to populate @WhoCreated, @WhoModified and
|
||||
* support other audit features (who executed a query etc).
|
||||
*/
|
||||
public void setCurrentUserProvider(CurrentUserProvider currentUserProvider) {
|
||||
this.currentUserProvider = currentUserProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the PersistBatch mode to use by default at the transaction level.
|
||||
* <p>
|
||||
@@ -438,7 +564,7 @@ public class ServerConfig {
|
||||
/**
|
||||
* Return the JDBC batch mode to use per save(), delete(), insert() or update() request.
|
||||
* <p>
|
||||
* This makes sense when a save() or delete() etc cascades and executes multiple child statements. The best caase
|
||||
* This makes sense when a save() or delete() cascades and executes multiple child statements. The best case
|
||||
* for this is when saving a master/parent bean this cascade inserts many detail/child beans.
|
||||
* </p>
|
||||
* <p>
|
||||
@@ -556,6 +682,171 @@ public class ServerConfig {
|
||||
this.databaseSequenceBatchSize = databaseSequenceBatchSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ChangeLogPrepare.
|
||||
* <p>
|
||||
* This is used to set user context information to the ChangeSet in the
|
||||
* foreground thread prior to the logging occurring in a background thread.
|
||||
* </p>
|
||||
*/
|
||||
public ChangeLogPrepare getChangeLogPrepare() {
|
||||
return changeLogPrepare;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ChangeLogPrepare.
|
||||
* <p>
|
||||
* This is used to set user context information to the ChangeSet in the
|
||||
* foreground thread prior to the logging occurring in a background thread.
|
||||
* </p>
|
||||
*/
|
||||
public void setChangeLogPrepare(ChangeLogPrepare changeLogPrepare) {
|
||||
this.changeLogPrepare = changeLogPrepare;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ChangeLogListener which actually performs the logging of change sets
|
||||
* in the background.
|
||||
*/
|
||||
public ChangeLogListener getChangeLogListener() {
|
||||
return changeLogListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ChangeLogListener which actually performs the logging of change sets
|
||||
* in the background.
|
||||
*/
|
||||
public void setChangeLogListener(ChangeLogListener changeLogListener) {
|
||||
this.changeLogListener = changeLogListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ChangeLogRegister which controls which ChangeLogFilter is used for each
|
||||
* bean type and in this way provide fine grained control over which persist requests
|
||||
* are included in the change log.
|
||||
*/
|
||||
public ChangeLogRegister getChangeLogRegister() {
|
||||
return changeLogRegister;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ChangeLogRegister which controls which ChangeLogFilter is used for each
|
||||
* bean type and in this way provide fine grained control over which persist requests
|
||||
* are included in the change log.
|
||||
*/
|
||||
public void setChangeLogRegister(ChangeLogRegister changeLogRegister) {
|
||||
this.changeLogRegister = changeLogRegister;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if inserts should be included in the change log by default.
|
||||
*/
|
||||
public boolean isChangeLogIncludeInserts() {
|
||||
return changeLogIncludeInserts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if inserts should be included in the change log by default.
|
||||
*/
|
||||
public void setChangeLogIncludeInserts(boolean changeLogIncludeInserts) {
|
||||
this.changeLogIncludeInserts = changeLogIncludeInserts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ReadAuditLogger to use.
|
||||
*/
|
||||
public ReadAuditLogger getReadAuditLogger() {
|
||||
return readAuditLogger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ReadAuditLogger to use. If not set the default implementation is used
|
||||
* which logs the read events in JSON format to a standard named SLF4J logger
|
||||
* (which can be configured in say logback to log to a separate log file).
|
||||
*/
|
||||
public void setReadAuditLogger(ReadAuditLogger readAuditLogger) {
|
||||
this.readAuditLogger = readAuditLogger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ReadAuditPrepare to use.
|
||||
*/
|
||||
public ReadAuditPrepare getReadAuditPrepare() {
|
||||
return readAuditPrepare;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ReadAuditPrepare to use.
|
||||
* <p>
|
||||
* It is expected that an implementation is used that read user context information
|
||||
* (user id, user ip address etc) and sets it on the ReadEvent bean before it is sent
|
||||
* to the ReadAuditLogger.
|
||||
* </p>
|
||||
*/
|
||||
public void setReadAuditPrepare(ReadAuditPrepare readAuditPrepare) {
|
||||
this.readAuditPrepare = readAuditPrepare;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DB migration configuration.
|
||||
*/
|
||||
public DbMigrationConfig getMigrationConfig() {
|
||||
return migrationConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the DB migration configuration.
|
||||
*/
|
||||
public void setMigrationConfig(DbMigrationConfig migrationConfig) {
|
||||
this.migrationConfig = migrationConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the suffix appended to the base table to derive the view that contains the union
|
||||
* of the base table and the history table in order to support asOf queries.
|
||||
*/
|
||||
public String getAsOfViewSuffix() {
|
||||
return asOfViewSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the suffix appended to the base table to derive the view that contains the union
|
||||
* of the base table and the history table in order to support asOf queries.
|
||||
*/
|
||||
public void setAsOfViewSuffix(String asOfViewSuffix) {
|
||||
this.asOfViewSuffix = asOfViewSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the database column used to support history and 'As of' queries. This column is a timestamp range
|
||||
* or equivalent.
|
||||
*/
|
||||
public String getAsOfSysPeriod() {
|
||||
return asOfSysPeriod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the database column used to support history and 'As of' queries. This column is a timestamp range
|
||||
* or equivalent.
|
||||
*/
|
||||
public void setAsOfSysPeriod(String asOfSysPeriod) {
|
||||
this.asOfSysPeriod = asOfSysPeriod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the history table suffix (defaults to _history).
|
||||
*/
|
||||
public String getHistoryTableSuffix() {
|
||||
return historyTableSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the history table suffix.
|
||||
*/
|
||||
public void setHistoryTableSuffix(String historyTableSuffix) {
|
||||
this.historyTableSuffix = historyTableSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if we are running in a JTA Transaction manager.
|
||||
*/
|
||||
@@ -861,35 +1152,31 @@ public class ServerConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the configuration for the Autofetch feature.
|
||||
* Return the constraint naming convention used in DDL generation.
|
||||
*/
|
||||
public AutofetchConfig getAutofetchConfig() {
|
||||
return autofetchConfig;
|
||||
public DbConstraintNaming getConstraintNaming() {
|
||||
return constraintNaming;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the configuration for the Autofetch feature.
|
||||
* Set the constraint naming convention used in DDL generation.
|
||||
*/
|
||||
public void setAutofetchConfig(AutofetchConfig autofetchConfig) {
|
||||
this.autofetchConfig = autofetchConfig;
|
||||
public void setConstraintNaming(DbConstraintNaming constraintNaming) {
|
||||
this.constraintNaming = constraintNaming;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the PreparedStatementDelegate.
|
||||
* Return the configuration for AutoTune.
|
||||
*/
|
||||
public PstmtDelegate getPstmtDelegate() {
|
||||
return pstmtDelegate;
|
||||
public AutoTuneConfig getAutoTuneConfig() {
|
||||
return autoTuneConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PstmtDelegate which can be used to support JDBC driver specific
|
||||
* features.
|
||||
* <p>
|
||||
* Typically this means Oracle JDBC driver specific workarounds.
|
||||
* </p>
|
||||
* Set the configuration for AutoTune.
|
||||
*/
|
||||
public void setPstmtDelegate(PstmtDelegate pstmtDelegate) {
|
||||
this.pstmtDelegate = pstmtDelegate;
|
||||
public void setAutoTuneConfig(AutoTuneConfig autoTuneConfig) {
|
||||
this.autoTuneConfig = autoTuneConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -955,6 +1242,28 @@ public class ServerConfig {
|
||||
this.autoCommitMode = autoCommitMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if transaction begin should be started with explicit statement.
|
||||
*/
|
||||
public boolean isExplicitTransactionBeginMode() {
|
||||
return explicitTransactionBeginMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if transaction begin should be started with explicit statement.
|
||||
* <p>
|
||||
* This works for H2 and Postgres but not for Oracle - only use this if you first name
|
||||
* is Daryl or you have explicitly talked to Rob about this feature.
|
||||
* </p>
|
||||
* <p>
|
||||
* This is generally not expected to be turned on but instead allow transactions to start
|
||||
* implicitly which is generally the standard approach.
|
||||
* </p>
|
||||
*/
|
||||
public void setExplicitTransactionBeginMode(boolean explicitTransactionBeginMode) {
|
||||
this.explicitTransactionBeginMode = explicitTransactionBeginMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a value used to represent TRUE in the database.
|
||||
* <p>
|
||||
@@ -1174,19 +1483,18 @@ public class ServerConfig {
|
||||
this.dbEncrypt = dbEncrypt;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if UUID should be stored as binary(16) (as opposed to varchar(40)).
|
||||
* Return the DB type used to store UUID.
|
||||
*/
|
||||
public boolean isUuidStoreAsBinary() {
|
||||
return uuidStoreAsBinary;
|
||||
public DbUuid getDbUuid() {
|
||||
return dbUuid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if UUID should be stored as binary(16) (as opposed to varchar(40)).
|
||||
* Set the DB type used to store UUID.
|
||||
*/
|
||||
public void setUuidStoreAsBinary(boolean uuidStoreAsBinary) {
|
||||
this.uuidStoreAsBinary = uuidStoreAsBinary;
|
||||
public void setDbUuid(DbUuid dbUuid) {
|
||||
this.dbUuid = dbUuid;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1227,19 +1535,81 @@ public class ServerConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true to run the DDL generation on startup.
|
||||
* Set to true to generate the "create all" DDL on startup.
|
||||
*
|
||||
* Typically we want this on when we are running tests locally (and often using H2)
|
||||
* and we want to create the full DB schema from scratch to run tests.
|
||||
*/
|
||||
public void setDdlGenerate(boolean ddlGenerate) {
|
||||
this.ddlGenerate = ddlGenerate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true to run the generated DDL on startup.
|
||||
* Set to true to run the generated "create all DDL" on startup.
|
||||
*
|
||||
* Typically we want this on when we are running tests locally (and often using H2)
|
||||
* and we want to create the full DB schema from scratch to run tests.
|
||||
*/
|
||||
public void setDdlRun(boolean ddlRun) {
|
||||
this.ddlRun = ddlRun;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the "drop all ddl" should be skipped.
|
||||
*
|
||||
* Typically we want to do this when using H2 (in memory) as our test database and the drop statements
|
||||
* are not required so skipping the drop table statements etc makes it faster with less noise in the logs.
|
||||
*/
|
||||
public boolean isDdlCreateOnly() {
|
||||
return ddlCreateOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if the "drop all ddl" should be skipped.
|
||||
*
|
||||
* Typically we want to do this when using H2 (in memory) as our test database and the drop statements
|
||||
* are not required so skipping the drop table statements etc makes it faster with less noise in the logs.
|
||||
*/
|
||||
public void setDdlCreateOnly(boolean ddlCreateOnly) {
|
||||
this.ddlCreateOnly = ddlCreateOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return SQL script to execute after the "create all" DDL has been run.
|
||||
* <p>
|
||||
* Typically this is a sql script that inserts test seed data when running tests.
|
||||
* Place a sql script in src/test/resources that inserts test seed data.
|
||||
* </p>
|
||||
*/
|
||||
public String getDdlSeedSql() {
|
||||
return ddlSeedSql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a SQL script to execute after the "create all" DDL has been run.
|
||||
* <p>
|
||||
* Typically this is a sql script that inserts test seed data when running tests.
|
||||
* Place a sql script in src/test/resources that inserts test seed data.
|
||||
* </p>
|
||||
*/
|
||||
public void setDdlSeedSql(String ddlSeedSql) {
|
||||
this.ddlSeedSql = ddlSeedSql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a SQL script to execute before the "create all" DDL has been run.
|
||||
*/
|
||||
public String getDdlInitSql() {
|
||||
return ddlInitSql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a SQL script to execute before the "create all" DDL has been run.
|
||||
*/
|
||||
public void setDdlInitSql(String ddlInitSql) {
|
||||
this.ddlInitSql = ddlInitSql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the DDL should be generated.
|
||||
*/
|
||||
@@ -1426,7 +1796,26 @@ public class ServerConfig {
|
||||
public void setUpdateChangesOnly(boolean updateChangesOnly) {
|
||||
this.updateChangesOnly = updateChangesOnly;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if updates in JDBC batch default to include all properties by default.
|
||||
*/
|
||||
public boolean isUpdateAllPropertiesInBatch() {
|
||||
return updateAllPropertiesInBatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to false if by default updates in JDBC batch should not include all properties.
|
||||
* <p>
|
||||
* This mode can be explicitly set per transaction.
|
||||
* </p>
|
||||
*
|
||||
* @see com.avaje.ebean.Transaction#setUpdateAllLoadedProperties(boolean)
|
||||
*/
|
||||
public void setUpdateAllPropertiesInBatch(boolean updateAllPropertiesInBatch) {
|
||||
this.updateAllPropertiesInBatch = updateAllPropertiesInBatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if updates by default delete missing children when cascading save to a OneToMany or
|
||||
* ManyToMany. When not set this defaults to true.
|
||||
@@ -1541,14 +1930,45 @@ public class ServerConfig {
|
||||
persistControllers.add(beanPersistController);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a BeanPostLoad instance.
|
||||
* <p>
|
||||
* Note alternatively you can use {@link #setPostLoaders(List)} to set
|
||||
* all the BeanPostLoad instances.
|
||||
* </p>
|
||||
*/
|
||||
public void add(BeanPostLoad postLoad) {
|
||||
postLoaders.add(postLoad);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of BeanFindController instances.
|
||||
*/
|
||||
public List<BeanFindController> getFindControllers() {
|
||||
return findControllers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the list of BeanFindController instances.
|
||||
*/
|
||||
public void setFindControllers(List<BeanFindController> findControllers) {
|
||||
this.findControllers = findControllers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of BeanPostLoader instances.
|
||||
*/
|
||||
public List<BeanPostLoad> getPostLoaders() {
|
||||
return postLoaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the list of BeanPostLoader instances.
|
||||
*/
|
||||
public void setPostLoaders(List<BeanPostLoad> postLoaders) {
|
||||
this.postLoaders = postLoaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BeanPersistController instances.
|
||||
*/
|
||||
@@ -1682,6 +2102,22 @@ public class ServerConfig {
|
||||
this.persistenceContextScope = persistenceContextScope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ClassLoadConfig which is used to detect Joda, Java8 types etc and also
|
||||
* create new instances of plugins given a className.
|
||||
*/
|
||||
public ClassLoadConfig getClassLoadConfig() {
|
||||
return classLoadConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ClassLoadConfig which is used to detect Joda, Java8 types etc and also
|
||||
* create new instances of plugins given a className.
|
||||
*/
|
||||
public void setClassLoadConfig(ClassLoadConfig classLoadConfig) {
|
||||
this.classLoadConfig = classLoadConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load settings from ebean.properties.
|
||||
*/
|
||||
@@ -1693,16 +2129,59 @@ public class ServerConfig {
|
||||
* Load the settings from the given properties
|
||||
*/
|
||||
public void loadFromProperties(Properties properties) {
|
||||
// keep the properties used for configuration so that these are available for plugins
|
||||
this.properties = properties;
|
||||
PropertiesWrapper p = new PropertiesWrapper("ebean", name, properties);
|
||||
loadSettings(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load settings from test-ebean.properties and do nothing if the properties is not found.
|
||||
* <p>
|
||||
* This is typically used when test-ebean.properties is put into the test class path and used
|
||||
* to configure Ebean for running tests.
|
||||
* </p>
|
||||
*/
|
||||
public void loadTestProperties() {
|
||||
Properties properties = PropertyMap.testProperties();
|
||||
if (!properties.isEmpty()) {
|
||||
PropertiesWrapper p = new PropertiesWrapper("ebean", name, properties);
|
||||
loadSettings(p);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the properties that we used for configuration and were set via a call to loadFromProperties().
|
||||
*/
|
||||
public Properties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the instance to use (can be null) for the given plugin.
|
||||
*
|
||||
* @param properties the properties
|
||||
* @param pluginType the type of plugin
|
||||
* @param key properties key
|
||||
* @param instance existing instance
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T createInstance(PropertiesWrapper p, Class<T> pluginType, String key) {
|
||||
protected <T> T createInstance(PropertiesWrapper properties, Class<T> pluginType, String key, T instance) {
|
||||
|
||||
String classname = p.get(key, null);
|
||||
return classname == null ? null : (T) ClassUtil.newInstance(classname);
|
||||
if (instance != null) {
|
||||
return instance;
|
||||
}
|
||||
String classname = properties.get(key, null);
|
||||
return createInstance(pluginType, classname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the instance to use (can be null) for the given plugin.
|
||||
* @param pluginType the type of plugin
|
||||
* @param classname the implementation class as per properties
|
||||
*/
|
||||
protected <T> T createInstance(Class<T> pluginType, String classname) {
|
||||
return classname == null ? null : (T) classLoadConfig.newInstance(classname);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1719,8 +2198,8 @@ public class ServerConfig {
|
||||
/**
|
||||
* This is broken out for the same reason as above - preserve existing behaviour but let it be overridden.
|
||||
*/
|
||||
protected void loadAutofetchSettings(PropertiesWrapper p) {
|
||||
autofetchConfig.loadSettings(p);
|
||||
protected void loadAutoTuneSettings(PropertiesWrapper p) {
|
||||
autoTuneConfig.loadSettings(p);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1728,31 +2207,35 @@ public class ServerConfig {
|
||||
*/
|
||||
protected void loadSettings(PropertiesWrapper p) {
|
||||
|
||||
migrationConfig.loadSettings(p);
|
||||
|
||||
namingConvention = createNamingConvention(p, namingConvention);
|
||||
if (namingConvention != null) {
|
||||
namingConvention.loadFromProperties(p);
|
||||
}
|
||||
if (autofetchConfig == null) {
|
||||
autofetchConfig = new AutofetchConfig();
|
||||
if (autoTuneConfig == null) {
|
||||
autoTuneConfig = new AutoTuneConfig();
|
||||
}
|
||||
loadAutofetchSettings(p);
|
||||
loadAutoTuneSettings(p);
|
||||
|
||||
if (dataSourceConfig == null) {
|
||||
dataSourceConfig = new DataSourceConfig();
|
||||
}
|
||||
loadDataSourceSettings(p);
|
||||
|
||||
explicitTransactionBeginMode = p.getBoolean("explicitTransactionBeginMode", explicitTransactionBeginMode);
|
||||
autoCommitMode = p.getBoolean("autoCommitMode", autoCommitMode);
|
||||
useJtaTransactionManager = p.getBoolean("useJtaTransactionManager", useJtaTransactionManager);
|
||||
|
||||
disableClasspathSearch = p.getBoolean("disableClasspathSearch", disableClasspathSearch);
|
||||
databasePlatform = createInstance(p, DatabasePlatform.class, "databasePlatform");
|
||||
encryptKeyManager = createInstance(p, EncryptKeyManager.class, "encryptKeyManager");
|
||||
encryptDeployManager = createInstance(p, EncryptDeployManager.class, "encryptDeployManager");
|
||||
encryptor = createInstance(p, Encryptor.class, "encryptor");
|
||||
dbEncrypt = createInstance(p, DbEncrypt.class, "dbEncrypt");
|
||||
serverCacheFactory = createInstance(p, ServerCacheFactory.class, "serverCacheFactory");
|
||||
serverCacheManager = createInstance(p, ServerCacheManager.class, "serverCacheManager");
|
||||
currentUserProvider = createInstance(p, CurrentUserProvider.class, "currentUserProvider", currentUserProvider);
|
||||
databasePlatform = createInstance(p, DatabasePlatform.class, "databasePlatform", databasePlatform);
|
||||
encryptKeyManager = createInstance(p, EncryptKeyManager.class, "encryptKeyManager", encryptKeyManager);
|
||||
encryptDeployManager = createInstance(p, EncryptDeployManager.class, "encryptDeployManager", encryptDeployManager);
|
||||
encryptor = createInstance(p, Encryptor.class, "encryptor", encryptor);
|
||||
dbEncrypt = createInstance(p, DbEncrypt.class, "dbEncrypt", dbEncrypt);
|
||||
serverCacheFactory = createInstance(p, ServerCacheFactory.class, "serverCacheFactory", serverCacheFactory);
|
||||
serverCacheManager = createInstance(p, ServerCacheManager.class, "serverCacheManager", serverCacheManager);
|
||||
cacheWarmingDelay = p.getInt("cacheWarmingDelay", cacheWarmingDelay);
|
||||
classPathReaderClassName = p.get("classpathreader");
|
||||
|
||||
@@ -1769,6 +2252,7 @@ public class ServerConfig {
|
||||
collectQueryStatsByNode = p.getBoolean("collectQueryStatsByNode", collectQueryStatsByNode);
|
||||
collectQueryOrigins = p.getBoolean("collectQueryOrigins", collectQueryOrigins);
|
||||
|
||||
updateAllPropertiesInBatch = p.getBoolean("updateAllPropertiesInBatch", updateAllPropertiesInBatch);
|
||||
updateChangesOnly = p.getBoolean("updateChangesOnly", updateChangesOnly);
|
||||
|
||||
boolean defaultDeleteMissingChildren = p.getBoolean("defaultDeleteMissingChildren", updatesDeleteMissingChildren);
|
||||
@@ -1784,19 +2268,29 @@ public class ServerConfig {
|
||||
int batchSize = p.getInt("batch.size", persistBatchSize);
|
||||
persistBatchSize = p.getInt("persistBatchSize", batchSize);
|
||||
|
||||
persistenceContextScope = PersistenceContextScope.valueOf(p.get("persistenceContextScope","TRANSACTION"));
|
||||
persistenceContextScope = PersistenceContextScope.valueOf(p.get("persistenceContextScope", "TRANSACTION"));
|
||||
|
||||
changeLogIncludeInserts = p.getBoolean("changeLogIncludeInserts", changeLogIncludeInserts);
|
||||
expressionEqualsWithNullAsNoop = p.getBoolean("expressionEqualsWithNullAsNoop", expressionEqualsWithNullAsNoop);
|
||||
|
||||
asOfViewSuffix = p.get("asOfViewSuffix", asOfViewSuffix);
|
||||
asOfSysPeriod = p.get("asOfSysPeriod", asOfSysPeriod);
|
||||
historyTableSuffix = p.get("historyTableSuffix", historyTableSuffix);
|
||||
dataSourceJndiName = p.get("dataSourceJndiName", dataSourceJndiName);
|
||||
databaseSequenceBatchSize = p.getInt("databaseSequenceBatchSize", databaseSequenceBatchSize);
|
||||
databaseBooleanTrue = p.get("databaseBooleanTrue", databaseBooleanTrue);
|
||||
databaseBooleanFalse = p.get("databaseBooleanFalse", databaseBooleanFalse);
|
||||
databasePlatformName = p.get("databasePlatformName", databasePlatformName);
|
||||
uuidStoreAsBinary = p.getBoolean("uuidStoreAsBinary", uuidStoreAsBinary);
|
||||
dbUuid = p.getEnum(DbUuid.class, "dbuuid", dbUuid);
|
||||
if (p.getBoolean("uuidStoreAsBinary", false)) {
|
||||
dbUuid = DbUuid.BINARY;
|
||||
}
|
||||
localTimeWithNanos = p.getBoolean("localTimeWithNanos", localTimeWithNanos);
|
||||
|
||||
lazyLoadBatchSize = p.getInt("lazyLoadBatchSize", lazyLoadBatchSize);
|
||||
queryBatchSize = p.getInt("queryBatchSize", queryBatchSize);
|
||||
|
||||
jsonInclude = p.getEnum(JsonConfig.Include.class, "jsonInclude", jsonInclude);
|
||||
String jsonDateTimeFormat = p.get("jsonDateTime", null);
|
||||
if (jsonDateTimeFormat != null) {
|
||||
jsonDateTime = JsonConfig.DateTime.valueOf(jsonDateTimeFormat);
|
||||
@@ -1806,13 +2300,16 @@ public class ServerConfig {
|
||||
|
||||
ddlGenerate = p.getBoolean("ddl.generate", ddlGenerate);
|
||||
ddlRun = p.getBoolean("ddl.run", ddlRun);
|
||||
ddlCreateOnly = p.getBoolean("ddl.createOnly", ddlCreateOnly);
|
||||
ddlInitSql = p.get("ddl.initSql", ddlInitSql);
|
||||
ddlSeedSql = p.get("ddl.seedSql", ddlSeedSql);
|
||||
|
||||
classes = getClasses(p);
|
||||
}
|
||||
|
||||
private NamingConvention createNamingConvention(PropertiesWrapper properties, NamingConvention namingConvention) {
|
||||
|
||||
NamingConvention nc = createInstance(properties, NamingConvention.class, "namingconvention");
|
||||
NamingConvention nc = createInstance(properties, NamingConvention.class, "namingconvention", null);
|
||||
return (nc != null) ? nc : namingConvention;
|
||||
}
|
||||
|
||||
@@ -1874,11 +2371,63 @@ public class ServerConfig {
|
||||
return databasePlatform.isDisallowBatchOnCascade() ? PersistBatch.NONE : persistBatchOnCascade;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Jackson ObjectMapper.
|
||||
* <p>
|
||||
* Note that this is not strongly typed as Jackson ObjectMapper is an optional dependency.
|
||||
* </p>
|
||||
*/
|
||||
public Object getObjectMapper() {
|
||||
return objectMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Jackson ObjectMapper.
|
||||
* <p>
|
||||
* Note that this is not strongly typed as Jackson ObjectMapper is an optional dependency.
|
||||
* </p>
|
||||
*/
|
||||
public void setObjectMapper(Object objectMapper) {
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if eq("someProperty", null) should to generate "1=1" rather than "is null" sql expression.
|
||||
*/
|
||||
public boolean isExpressionEqualsWithNullAsNoop() {
|
||||
return expressionEqualsWithNullAsNoop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if you want eq("someProperty", null) to generate "1=1" rather than "is null" sql expression.
|
||||
* <p>
|
||||
* Setting this to true has the effect that eq(propertyName, value), ieq(propertyName, value) and
|
||||
* ne(propertyName, value) have no effect when the value is null. The expression factory adds a NoopExpression
|
||||
* which will add "1=1" into the SQL rather than "is null".
|
||||
* </p>
|
||||
*/
|
||||
public void setExpressionEqualsWithNullAsNoop(boolean expressionEqualsWithNullAsNoop) {
|
||||
this.expressionEqualsWithNullAsNoop = expressionEqualsWithNullAsNoop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify how UUID is stored.
|
||||
*/
|
||||
public enum DbUuid {
|
||||
|
||||
/**
|
||||
* Store using native UUID in H2 and Postgres.
|
||||
*/
|
||||
AUTO,
|
||||
|
||||
/**
|
||||
* Store using DB VARCHAR.
|
||||
*/
|
||||
VARCHAR,
|
||||
|
||||
/**
|
||||
* Store using DB BINARY.
|
||||
*/
|
||||
BINARY
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,23 +3,26 @@ package com.avaje.ebean.config;
|
||||
/**
|
||||
* Converts between Camel Case and Underscore based names for both table and
|
||||
* column names (and is the default naming convention in Ebean).
|
||||
*
|
||||
*
|
||||
* @author emcgreal
|
||||
* @author rbygrave
|
||||
*/
|
||||
public class UnderscoreNamingConvention extends AbstractNamingConvention {
|
||||
|
||||
/** Force toUnderscore to return in upper case. */
|
||||
/**
|
||||
* Force toUnderscore to return in upper case.
|
||||
*/
|
||||
private boolean forceUpperCase = false;
|
||||
|
||||
/** The digits compressed. */
|
||||
/**
|
||||
* The digits compressed.
|
||||
*/
|
||||
private boolean digitsCompressed = true;
|
||||
|
||||
/**
|
||||
* Create with a given sequence format.
|
||||
*
|
||||
* @param sequenceFormat
|
||||
* the sequence format
|
||||
*
|
||||
* @param sequenceFormat the sequence format
|
||||
*/
|
||||
public UnderscoreNamingConvention(String sequenceFormat) {
|
||||
super(sequenceFormat);
|
||||
@@ -34,39 +37,30 @@ public class UnderscoreNamingConvention extends AbstractNamingConvention {
|
||||
|
||||
/**
|
||||
* Returns the last part of the class name.
|
||||
*
|
||||
* @param beanClass
|
||||
* the bean class
|
||||
*
|
||||
*
|
||||
* @param beanClass the bean class
|
||||
* @return the table name from class
|
||||
*/
|
||||
public TableName getTableNameByConvention(Class<?> beanClass) {
|
||||
|
||||
return new TableName(getCatalog(),
|
||||
getSchema(),
|
||||
toUnderscoreFromCamel(beanClass.getSimpleName()));
|
||||
return new TableName(getCatalog(), getSchema(), toUnderscoreFromCamel(beanClass.getSimpleName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts Camel case property name to underscore based column name.
|
||||
*
|
||||
*
|
||||
* @return the column from property
|
||||
*/
|
||||
public String getColumnFromProperty(Class<?> beanClass, String propertyName) {// Field
|
||||
// field)
|
||||
// {
|
||||
public String getColumnFromProperty(Class<?> beanClass, String propertyName) {
|
||||
|
||||
return toUnderscoreFromCamel(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts underscore based column name to Camel case property name.
|
||||
*
|
||||
* @param beanClass
|
||||
* the bean class
|
||||
* @param dbColumnName
|
||||
* the db column name
|
||||
*
|
||||
*
|
||||
* @param beanClass the bean class
|
||||
* @param dbColumnName the db column name
|
||||
* @return the property from column
|
||||
*/
|
||||
public String getPropertyFromColumn(Class<?> beanClass, String dbColumnName) {
|
||||
@@ -110,7 +104,7 @@ public class UnderscoreNamingConvention extends AbstractNamingConvention {
|
||||
protected String toUnderscoreFromCamel(String camelCase) {
|
||||
|
||||
int lastUpper = -1;
|
||||
StringBuffer sb = new StringBuffer();
|
||||
StringBuilder sb = new StringBuilder(camelCase.length()+4);
|
||||
for (int i = 0; i < camelCase.length(); i++) {
|
||||
char c = camelCase.charAt(i);
|
||||
|
||||
@@ -144,16 +138,11 @@ public class UnderscoreNamingConvention extends AbstractNamingConvention {
|
||||
}
|
||||
|
||||
/**
|
||||
* To camel from underscore.
|
||||
*
|
||||
* @param underscore
|
||||
* the underscore
|
||||
*
|
||||
* @return the string
|
||||
* Convert and return the from string from underscore to camel case.
|
||||
*/
|
||||
protected String toCamelFromUnderscore(String underscore) {
|
||||
|
||||
StringBuffer result = new StringBuffer();
|
||||
StringBuilder result = new StringBuilder(underscore.length());
|
||||
String[] vals = underscore.split("_");
|
||||
|
||||
for (int i = 0; i < vals.length; i++) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.sql.Types;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import com.avaje.ebean.BackgroundExecutor;
|
||||
import com.avaje.ebean.dbmigration.ddlgeneration.platform.DB2Ddl;
|
||||
|
||||
/**
|
||||
* DB2 specific platform.
|
||||
@@ -14,10 +15,11 @@ public class DB2Platform extends DatabasePlatform {
|
||||
public DB2Platform() {
|
||||
super();
|
||||
this.name = "db2";
|
||||
|
||||
// only support getGeneratedKeys with non-batch JDBC
|
||||
// so generally use SEQUENCE instead for H2
|
||||
this.maxTableNameLength = 18;
|
||||
this.maxConstraintNameLength = 18;
|
||||
this.sqlLimiter = new Db2SqlLimiter();
|
||||
this.platformDdl = new DB2Ddl(dbTypeMap, dbIdentity);
|
||||
|
||||
this.dbIdentity.setSupportsGetGeneratedKeys(true);
|
||||
this.dbIdentity.setSupportsSequence(true);
|
||||
|
||||
@@ -25,8 +27,6 @@ public class DB2Platform extends DatabasePlatform {
|
||||
dbTypeMap.put(Types.REAL, new DbType("real"));
|
||||
dbTypeMap.put(Types.TINYINT, new DbType("smallint"));
|
||||
dbTypeMap.put(Types.DECIMAL, new DbType("decimal", 15));
|
||||
|
||||
this.dbDdlSyntax.setIdentity("generated by default as identity");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,7 @@ public class DB2SequenceIdGenerator extends SequenceIdGenerator {
|
||||
*/
|
||||
public DB2SequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
|
||||
super(be, ds, seqName, batchSize);
|
||||
this.baseSql = "select nextval for " + seqName;
|
||||
this.baseSql = "values nextval for " + seqName;
|
||||
this.unionBaseSql = " union " + baseSql;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
package com.avaje.ebean.config.dbplatform;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import com.avaje.ebean.BackgroundExecutor;
|
||||
import com.avaje.ebean.Query;
|
||||
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.dbmigration.ddlgeneration.DdlHandler;
|
||||
import com.avaje.ebean.dbmigration.ddlgeneration.platform.PlatformDdl;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
* Database platform specific settings.
|
||||
*/
|
||||
@@ -17,6 +18,7 @@ public class DatabasePlatform {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DatabasePlatform.class);
|
||||
|
||||
|
||||
/**
|
||||
* Behavior used when ending a query only transaction (at read committed isolation level).
|
||||
*/
|
||||
@@ -50,58 +52,63 @@ public class DatabasePlatform {
|
||||
*/
|
||||
protected OnQueryOnly onQueryOnly = OnQueryOnly.ROLLBACK;
|
||||
|
||||
/**
|
||||
* The open quote used by quoted identifiers.
|
||||
/**
|
||||
* The open quote used by quoted identifiers.
|
||||
*/
|
||||
protected String openQuote = "\"";
|
||||
|
||||
/**
|
||||
* The close quote used by quoted identifiers.
|
||||
* The close quote used by quoted identifiers.
|
||||
*/
|
||||
protected String closeQuote = "\"";
|
||||
|
||||
/**
|
||||
* For limit/offset, row_number etc limiting of SQL queries.
|
||||
/**
|
||||
* For limit/offset, row_number etc limiting of SQL queries.
|
||||
*/
|
||||
protected SqlLimiter sqlLimiter = new LimitOffsetSqlLimiter();
|
||||
|
||||
/**
|
||||
* Mapping of JDBC to Database types.
|
||||
/**
|
||||
* Mapping of JDBC to Database types.
|
||||
*/
|
||||
protected DbTypeMap dbTypeMap = new DbTypeMap();
|
||||
|
||||
/**
|
||||
* DB specific DDL syntax.
|
||||
/**
|
||||
* Set to true if the DB has native UUID type support.
|
||||
*/
|
||||
protected DbDdlSyntax dbDdlSyntax = new DbDdlSyntax();
|
||||
protected boolean nativeUuidType;
|
||||
|
||||
/**
|
||||
* Defines DB identity/sequence features.
|
||||
/**
|
||||
* Defines DB identity/sequence features.
|
||||
*/
|
||||
protected DbIdentity dbIdentity = new DbIdentity();
|
||||
|
||||
/**
|
||||
* The JDBC type to map booleans to (by default).
|
||||
/**
|
||||
* The history support for this database platform.
|
||||
*/
|
||||
protected DbHistorySupport historySupport;
|
||||
|
||||
/**
|
||||
* The JDBC type to map booleans to (by default).
|
||||
*/
|
||||
protected int booleanDbType = Types.BOOLEAN;
|
||||
|
||||
/**
|
||||
* The JDBC type to map Blob to.
|
||||
/**
|
||||
* The JDBC type to map Blob to.
|
||||
*/
|
||||
protected int blobDbType = Types.BLOB;
|
||||
|
||||
/**
|
||||
* The JDBC type to map Clob to.
|
||||
/**
|
||||
* The JDBC type to map Clob to.
|
||||
*/
|
||||
protected int clobDbType = Types.CLOB;
|
||||
|
||||
/**
|
||||
* For Oracle treat empty strings as null.
|
||||
/**
|
||||
* For Oracle treat empty strings as null.
|
||||
*/
|
||||
protected boolean treatEmptyStringsAsNull;
|
||||
|
||||
/**
|
||||
* The database platform name.
|
||||
/**
|
||||
* The database platform name.
|
||||
*/
|
||||
protected String name = "generic";
|
||||
|
||||
@@ -120,7 +127,7 @@ public class DatabasePlatform {
|
||||
* The like clause. Can be overridden to disable default escape character.
|
||||
*/
|
||||
protected String likeClause = "like ?";
|
||||
|
||||
|
||||
protected DbEncrypt dbEncrypt;
|
||||
|
||||
protected boolean idInExpandedForm;
|
||||
@@ -140,6 +147,20 @@ public class DatabasePlatform {
|
||||
*/
|
||||
protected boolean disallowBatchOnCascade;
|
||||
|
||||
protected PlatformDdl platformDdl;
|
||||
|
||||
/**
|
||||
* The maximum length of table names - used specifically when derived
|
||||
* default table names for intersection tables.
|
||||
*/
|
||||
protected int maxTableNameLength = 60;
|
||||
|
||||
/**
|
||||
* A value of 60 is a reasonable default for all databases except
|
||||
* Oracle (limited to 30) and DB2 (limited to 18).
|
||||
*/
|
||||
protected int maxConstraintNameLength = 60;
|
||||
|
||||
/**
|
||||
* Instantiates a new database platform.
|
||||
*/
|
||||
@@ -152,13 +173,42 @@ public class DatabasePlatform {
|
||||
* "generic" is returned when no specific database platform has been set or
|
||||
* found.
|
||||
* </p>
|
||||
*
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the maximum table name length.
|
||||
* <p>
|
||||
* This is used when deriving names of intersection tables.
|
||||
* </p>
|
||||
*/
|
||||
public int getMaxTableNameLength() {
|
||||
return maxTableNameLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the maximum constraint name allowed for the platform.
|
||||
*/
|
||||
public int getMaxConstraintNameLength() {
|
||||
return maxConstraintNameLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the platform specific DDL.
|
||||
*/
|
||||
public PlatformDdl getPlatformDdl() {
|
||||
return platformDdl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a DDL handler for generating DDL scripts.
|
||||
*/
|
||||
public DdlHandler createDdlHandler(ServerConfig serverConfig) {
|
||||
return platformDdl.createDdlHandler(serverConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the JDBC driver does not allow additional queries to execute
|
||||
* when a resultSet is being 'streamed' as is the case with findEach() etc.
|
||||
@@ -172,16 +222,12 @@ public class DatabasePlatform {
|
||||
|
||||
/**
|
||||
* Return a DB Sequence based IdGenerator.
|
||||
*
|
||||
* @param be
|
||||
* the BackgroundExecutor that can be used to load the sequence if
|
||||
* desired
|
||||
* @param ds
|
||||
* the DataSource
|
||||
* @param seqName
|
||||
* the name of the sequence
|
||||
* @param batchSize
|
||||
* the number of sequences that should be loaded
|
||||
*
|
||||
* @param be the BackgroundExecutor that can be used to load the sequence if
|
||||
* desired
|
||||
* @param ds the DataSource
|
||||
* @param seqName the name of the sequence
|
||||
* @param batchSize the number of sequences that should be loaded
|
||||
*/
|
||||
public IdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
|
||||
return null;
|
||||
@@ -215,24 +261,36 @@ public class DatabasePlatform {
|
||||
this.dbEncrypt = dbEncrypt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the history support for this database platform.
|
||||
*/
|
||||
public DbHistorySupport getHistorySupport() {
|
||||
return historySupport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the history support for this database platform.
|
||||
*/
|
||||
public void setHistorySupport(DbHistorySupport historySupport) {
|
||||
this.historySupport = historySupport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the DB supports native UUID.
|
||||
*/
|
||||
public boolean isNativeUuidType() {
|
||||
return nativeUuidType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mapping of JDBC to DB types.
|
||||
*
|
||||
*
|
||||
* @return the db type map
|
||||
*/
|
||||
public DbTypeMap getDbTypeMap() {
|
||||
return dbTypeMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DDL syntax for this platform.
|
||||
*
|
||||
* @return the db ddl syntax
|
||||
*/
|
||||
public DbDdlSyntax getDbDdlSyntax() {
|
||||
return dbDdlSyntax;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the column alias prefix.
|
||||
*/
|
||||
@@ -263,7 +321,7 @@ public class DatabasePlatform {
|
||||
|
||||
/**
|
||||
* Return the close quote for quoted identifiers.
|
||||
*
|
||||
*
|
||||
* @return the close quote
|
||||
*/
|
||||
public String getCloseQuote() {
|
||||
@@ -272,7 +330,7 @@ public class DatabasePlatform {
|
||||
|
||||
/**
|
||||
* Return the open quote for quoted identifiers.
|
||||
*
|
||||
*
|
||||
* @return the open quote
|
||||
*/
|
||||
public String getOpenQuote() {
|
||||
@@ -281,7 +339,7 @@ public class DatabasePlatform {
|
||||
|
||||
/**
|
||||
* Return the JDBC type used to store booleans.
|
||||
*
|
||||
*
|
||||
* @return the boolean db type
|
||||
*/
|
||||
public int getBooleanDbType() {
|
||||
@@ -311,7 +369,7 @@ public class DatabasePlatform {
|
||||
|
||||
/**
|
||||
* Return true if empty strings should be treated as null.
|
||||
*
|
||||
*
|
||||
* @return true, if checks if is treat empty strings as null
|
||||
*/
|
||||
public boolean isTreatEmptyStringsAsNull() {
|
||||
@@ -347,7 +405,7 @@ public class DatabasePlatform {
|
||||
|
||||
/**
|
||||
* Return the DB identity/sequence features for this platform.
|
||||
*
|
||||
*
|
||||
* @return the db identity
|
||||
*/
|
||||
public DbIdentity getDbIdentity() {
|
||||
@@ -360,7 +418,7 @@ public class DatabasePlatform {
|
||||
* <p>
|
||||
* Basically add the clauses for limit/offset, rownum, row_number().
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @return the sql limiter
|
||||
*/
|
||||
public SqlLimiter getSqlLimiter() {
|
||||
@@ -369,15 +427,12 @@ public class DatabasePlatform {
|
||||
|
||||
/**
|
||||
* Convert backticks to the platform specific open quote and close quote
|
||||
*
|
||||
* <p>
|
||||
* Specific plugins may implement this method to cater for platform specific
|
||||
* naming rules.
|
||||
* </p>
|
||||
*
|
||||
* @param dbName
|
||||
* the db name
|
||||
*
|
||||
*
|
||||
* @param dbName the db name
|
||||
* @return the string
|
||||
*/
|
||||
public String convertQuotedIdentifiers(String dbName) {
|
||||
@@ -442,22 +497,4 @@ public class DatabasePlatform {
|
||||
return disallowBatchOnCascade;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate and return the create sequence DDL.
|
||||
*/
|
||||
public String ddlCreateSequence(String sequenceName, int initialValue, int allocationSize) {
|
||||
|
||||
StringBuilder sb = new StringBuilder("create sequence ");
|
||||
sb.append(sequenceName);
|
||||
if (initialValue > 1) {
|
||||
sb.append(" start with ").append(initialValue);
|
||||
}
|
||||
if (allocationSize > 0 && allocationSize != 50) {
|
||||
// at this stage ignoring allocationSize 50 as this is the 'default' and
|
||||
// not consistent with the way Ebean batch fetches sequence values
|
||||
sb.append(" increment by ").append(allocationSize);
|
||||
}
|
||||
sb.append(";");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,333 +0,0 @@
|
||||
package com.avaje.ebean.config.dbplatform;
|
||||
|
||||
import com.avaje.ebean.config.TableName;
|
||||
|
||||
/**
|
||||
* Used to support DB specific syntax for DDL generation.
|
||||
*/
|
||||
public class DbDdlSyntax {
|
||||
|
||||
protected boolean renderIndexForFkey = true;
|
||||
|
||||
protected boolean inlinePrimaryKeyConstraint = false;
|
||||
|
||||
protected boolean addOneToOneUniqueContraint = true;
|
||||
|
||||
protected int maxConstraintNameLength = 32;
|
||||
|
||||
protected int columnNameWidth = 25;
|
||||
|
||||
/**
|
||||
* Flag set when we want to disable constraints on each table (rather than globally).
|
||||
*/
|
||||
protected boolean dropKeyConstraints;
|
||||
|
||||
protected String dropTableCascade;
|
||||
protected String dropIfExists;
|
||||
|
||||
protected String newLine = "\n";
|
||||
|
||||
protected String identity = "auto_increment";
|
||||
protected String identitySuffix = "";
|
||||
|
||||
protected String pkPrefix = "pk_";
|
||||
|
||||
protected String disableReferentialIntegrity;
|
||||
protected String enableReferentialIntegrity;
|
||||
|
||||
protected String foreignKeySuffix;
|
||||
|
||||
/**
|
||||
* Return the primary key name for a given bean descriptor.
|
||||
*/
|
||||
public String getPrimaryKeyName(String tableName) {
|
||||
|
||||
String pk = pkPrefix + tableName;
|
||||
if (pk.length() > maxConstraintNameLength) {
|
||||
// need to trim the primary key name
|
||||
pk = pk.substring(0, maxConstraintNameLength);
|
||||
}
|
||||
return pk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the column definition for an identity column.
|
||||
*/
|
||||
public String getIdentityColumnDefn(String columnDefn) {
|
||||
String identity = getIdentity();
|
||||
if (identity != null && identity.length() > 0) {
|
||||
return columnDefn+" "+identity;
|
||||
}
|
||||
return columnDefn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the identity clause for DB's that have identities.
|
||||
*/
|
||||
public String getIdentity() {
|
||||
return identity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the identity clause.
|
||||
*/
|
||||
public void setIdentity(String identity) {
|
||||
this.identity = identity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Typically returns empty string but for SQLite and perhaps others
|
||||
* the Identity/AutoIncrement clause comes after the primary key clause.
|
||||
*/
|
||||
public String getIdentitySuffix() {
|
||||
return identitySuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the identity clause that would appear after the primary key clause.
|
||||
* <p>
|
||||
* Only used for SQLite at this stage.
|
||||
* </p>
|
||||
*/
|
||||
public void setIdentitySuffix(String identitySuffix) {
|
||||
this.identitySuffix = identitySuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the width for padding whitespace after column names.
|
||||
*/
|
||||
public int getColumnNameWidth() {
|
||||
return columnNameWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the amount of padding to write after the column name.
|
||||
*/
|
||||
public void setColumnNameWidth(int columnNameWidth) {
|
||||
this.columnNameWidth = columnNameWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the new line character.
|
||||
*/
|
||||
public String getNewLine() {
|
||||
return newLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the new line character.
|
||||
*/
|
||||
public void setNewLine(String newLine) {
|
||||
this.newLine = newLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the prefix used in naming primary keys.
|
||||
*/
|
||||
public String getPkPrefix() {
|
||||
return pkPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the prefix used in naming primary keys.
|
||||
*/
|
||||
public void setPkPrefix(String pkPrefix) {
|
||||
this.pkPrefix = pkPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DB specific command to disable referential integrity
|
||||
*/
|
||||
public String getDisableReferentialIntegrity() {
|
||||
return disableReferentialIntegrity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the DB specific command to disable referential integrity
|
||||
*/
|
||||
public void setDisableReferentialIntegrity(String disableReferentialIntegrity) {
|
||||
this.disableReferentialIntegrity = disableReferentialIntegrity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the DB specific command to enable referential integrity
|
||||
*/
|
||||
public String getEnableReferentialIntegrity() {
|
||||
return enableReferentialIntegrity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the DB specific command to enable referential integrity
|
||||
*/
|
||||
public void setEnableReferentialIntegrity(String enableReferentialIntegrity) {
|
||||
this.enableReferentialIntegrity = enableReferentialIntegrity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true to is constraints are disabled on each table.
|
||||
*/
|
||||
public boolean isDropKeyConstraints() {
|
||||
return dropKeyConstraints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return some DDL to disable constraints on the given table.
|
||||
*/
|
||||
public String dropKeyConstraintPrefix(String tableName, String fkName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if indexes should be created for the foreign keys.
|
||||
*/
|
||||
public boolean isRenderIndexForFkey() {
|
||||
return renderIndexForFkey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether indexes should be created for the foreign keys.
|
||||
*/
|
||||
public void setRenderIndexForFkey(boolean renderIndexForFkey) {
|
||||
this.renderIndexForFkey = renderIndexForFkey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Typically returns IF EXISTS (if that is supported by the database platform)
|
||||
* or null.
|
||||
*/
|
||||
public String getDropIfExists() {
|
||||
return dropIfExists;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the IF EXISTS clause for dropping tables if that is supported by the
|
||||
* database platform.
|
||||
*/
|
||||
public void setDropIfExists(String dropIfExists) {
|
||||
this.dropIfExists = dropIfExists;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return prefix text that goes before drop table.
|
||||
*/
|
||||
public String dropTablePrefix(String tableName) {
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the cascade option for the drop table command.
|
||||
*/
|
||||
public String getDropTableCascade() {
|
||||
return dropTableCascade;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the cascade option for the drop table command.
|
||||
*/
|
||||
public void setDropTableCascade(String dropTableCascade) {
|
||||
this.dropTableCascade = dropTableCascade;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the foreign key suffix.
|
||||
*/
|
||||
public String getForeignKeySuffix() {
|
||||
return foreignKeySuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the foreign key suffix.
|
||||
*/
|
||||
public void setForeignKeySuffix(String foreignKeySuffix) {
|
||||
this.foreignKeySuffix = foreignKeySuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the maximum length that constraint names can be for this database.
|
||||
*/
|
||||
public int getMaxConstraintNameLength() {
|
||||
return maxConstraintNameLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum length that constraint names can be for this database.
|
||||
*/
|
||||
public void setMaxConstraintNameLength(int maxFkeyLength) {
|
||||
this.maxConstraintNameLength = maxFkeyLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if imported side of OneToOne's should have unique constraints
|
||||
* generated.
|
||||
*/
|
||||
public boolean isAddOneToOneUniqueContraint() {
|
||||
return addOneToOneUniqueContraint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to false for DB's that don't want both a unique and index on the
|
||||
* imported OneToOne.
|
||||
*/
|
||||
public void setAddOneToOneUniqueContraint(boolean addOneToOneUniqueContraint) {
|
||||
this.addOneToOneUniqueContraint = addOneToOneUniqueContraint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if primary key constraints should be inlined when they are a
|
||||
* single column.
|
||||
*/
|
||||
public boolean isInlinePrimaryKeyConstraint() {
|
||||
return inlinePrimaryKeyConstraint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether to inline primary key constraints.
|
||||
*/
|
||||
public void setInlinePrimaryKeyConstraint(boolean inlinePrimaryKeyConstraint) {
|
||||
this.inlinePrimaryKeyConstraint = inlinePrimaryKeyConstraint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and returns a fully index name.
|
||||
*/
|
||||
public String getIndexName(String table, String propName, int ixCount) {
|
||||
|
||||
|
||||
StringBuilder buffer = new StringBuilder(30);
|
||||
buffer.append("ix_").append(TableName.parse(table));
|
||||
buffer.append("_").append(propName);
|
||||
|
||||
addSuffix(buffer, ixCount);
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and returns a fully qualified foreign key constraint name.
|
||||
*/
|
||||
public String getForeignKeyName(String table, String propName, int fkCount) {
|
||||
|
||||
StringBuilder buffer = new StringBuilder(30);
|
||||
buffer.append("fk_").append(TableName.parse(table));
|
||||
buffer.append("_").append(propName);
|
||||
|
||||
addSuffix(buffer, fkCount);
|
||||
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the suffix.
|
||||
*/
|
||||
protected void addSuffix(StringBuilder buffer, int count) {
|
||||
String suffixNr = Integer.toString(count);
|
||||
int suffixLen = suffixNr.length() + 1;
|
||||
|
||||
if (buffer.length() + suffixLen > maxConstraintNameLength) {
|
||||
buffer.setLength(maxConstraintNameLength - suffixLen);
|
||||
}
|
||||
buffer.append("_");
|
||||
buffer.append(suffixNr);
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user