mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
347
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
60a84b7a38 | ||
|
|
fa3e9e6fc6 | ||
|
|
8ca44edf9c | ||
|
|
fcefd94086 | ||
|
|
70e5d57b7e | ||
|
|
cc3b9c9508 | ||
|
|
be49be38d0 | ||
|
|
dca13db945 | ||
|
|
bd318a5d85 | ||
|
|
4c2be2986a | ||
|
|
3d7bebd244 | ||
|
|
e23bbf5f94 | ||
|
|
27b0c33a4b | ||
|
|
53ef159d06 | ||
|
|
a7d778d98b | ||
|
|
19580ff83d | ||
|
|
a79a44c513 | ||
|
|
184b82e1b2 | ||
|
|
04e935acd0 | ||
|
|
142ffe925c | ||
|
|
395505ec0d | ||
|
|
c21a76fa5b | ||
|
|
a2690fdccd | ||
|
|
4039c20462 | ||
|
|
6d43028fba | ||
|
|
efcee7e739 | ||
|
|
523fe6ae54 | ||
|
|
8ec031bfde | ||
|
|
cd938fd659 | ||
|
|
837e296451 | ||
|
|
52b0bd7b7d | ||
|
|
a8cad4f3d9 | ||
|
|
e4cb81cbba | ||
|
|
08cd0aa4b7 | ||
|
|
b565a5843e | ||
|
|
79c96c9ec1 | ||
|
|
b703b683d8 | ||
|
|
456eb3aca9 | ||
|
|
54c35300d4 | ||
|
|
dfc5963e35 | ||
|
|
36777d5a3d | ||
|
|
12b028fc43 | ||
|
|
72b2f30f2d | ||
|
|
1de74ac366 | ||
|
|
07cb243db3 | ||
|
|
9a02618b67 | ||
|
|
801cb6fa73 | ||
|
|
1c8a416de0 | ||
|
|
c30a8c79a2 | ||
|
|
35cb4356c5 | ||
|
|
a73c985315 | ||
|
|
b5fbfbf1b6 | ||
|
|
4471607b2d | ||
|
|
e4c4b0b43d | ||
|
|
d7ffc4bbb5 | ||
|
|
0bb2f104a4 | ||
|
|
ac3ca8113d | ||
|
|
4ec46e3008 | ||
|
|
e9ab0f34f3 | ||
|
|
2143ebc21c | ||
|
|
7dd25344ef | ||
|
|
c381464316 | ||
|
|
a5d5549f2c | ||
|
|
d7d144b908 | ||
|
|
25416a3cda | ||
|
|
e6b0306bde | ||
|
|
2d6ca4bb1e | ||
|
|
99d5f4f01c | ||
|
|
8ea0936da8 | ||
|
|
f8fc94c694 | ||
|
|
bac3fd6874 | ||
|
|
0659d7604c | ||
|
|
a825e50584 | ||
|
|
94f24f054e | ||
|
|
989d82813b | ||
|
|
2e0dba3741 | ||
|
|
56360f0fb3 | ||
|
|
d84f2eea58 | ||
|
|
34dc4375da | ||
|
|
9e186698fe | ||
|
|
0b615a79cc | ||
|
|
6e98486a03 | ||
|
|
b0364f3c42 | ||
|
|
8c47ba89d1 | ||
|
|
8ed871f116 | ||
|
|
f493c7e8cf | ||
|
|
0e596fd87f | ||
|
|
37154cf4d4 | ||
|
|
fe241d8cce | ||
|
|
efaa771bb4 | ||
|
|
4094b1e345 | ||
|
|
8bb9ec0cfe | ||
|
|
a9575048b4 | ||
|
|
86bcfa804b | ||
|
|
b6a3c54e99 | ||
|
|
6753e36327 | ||
|
|
e78ac677f6 | ||
|
|
19d2b04175 | ||
|
|
d1844c9b5a | ||
|
|
93803eade4 | ||
|
|
82fd6dc65f | ||
|
|
ca6171f697 | ||
|
|
5b4ff2627c | ||
|
|
2aa92d63fd | ||
|
|
658b5b7e06 | ||
|
|
4e3cd83e36 | ||
|
|
aa80bc0c10 | ||
|
|
638cfbca5e | ||
|
|
afa9d89cfe | ||
|
|
22a433997e | ||
|
|
b9d8a9c532 | ||
|
|
1f0191b9e4 | ||
|
|
2d78c5c5e8 | ||
|
|
7c54d21760 | ||
|
|
b9a502ca85 | ||
|
|
b622d85292 | ||
|
|
320ffb4a2d | ||
|
|
0292b4b558 | ||
|
|
2c8ae16179 | ||
|
|
381ac58eed | ||
|
|
af9459e41e | ||
|
|
5882169641 | ||
|
|
f694f2946a | ||
|
|
4c0144de61 | ||
|
|
5e70ea5095 | ||
|
|
acb28925f2 | ||
|
|
3d2a68782c | ||
|
|
8c97d4d0fe | ||
|
|
eb7de343a8 | ||
|
|
4ca1645f9f | ||
|
|
d1fe79005c | ||
|
|
015ee44de3 | ||
|
|
714bbadbc0 | ||
|
|
9e811e9aef | ||
|
|
f97dcb60c0 | ||
|
|
1af3d0bcf3 | ||
|
|
01a0cee3c2 | ||
|
|
f26feec3d9 | ||
|
|
65c76cb2c0 | ||
|
|
874427dac1 | ||
|
|
1176c2e97a | ||
|
|
44e0585fb7 | ||
|
|
889c0f12e0 | ||
|
|
0135263dbd | ||
|
|
564194042b | ||
|
|
244d45674a | ||
|
|
4722f10f5e | ||
|
|
3f5140e7f3 | ||
|
|
43dec17d08 | ||
|
|
f1ee45d7d1 | ||
|
|
3263e7bfc3 | ||
|
|
e01f19b3aa | ||
|
|
20f6a659fe | ||
|
|
09fe923770 | ||
|
|
e6f5e42c2d | ||
|
|
010f73fea2 | ||
|
|
5150ecba62 | ||
|
|
978b1dbe02 | ||
|
|
9813703ce5 | ||
|
|
09001e80b5 | ||
|
|
4aa3ca6d95 | ||
|
|
5ec8469ddc | ||
|
|
39099bbcc9 | ||
|
|
cb2ca0de11 | ||
|
|
b25233b0b9 | ||
|
|
743f1b10e3 | ||
|
|
6055a33dc8 | ||
|
|
230d18e48f | ||
|
|
371f50fb4d | ||
|
|
a3be2041c8 | ||
|
|
09a831f2d6 | ||
|
|
27d9e03691 | ||
|
|
5a3c6b9dad | ||
|
|
502eb78ffd | ||
|
|
61d6cccbcb | ||
|
|
761ec584b2 | ||
|
|
144b8c3077 | ||
|
|
79a1b3a024 | ||
|
|
519b75a778 | ||
|
|
1659c526d7 | ||
|
|
93fc7b07a0 | ||
|
|
d7e6feebc2 | ||
|
|
2a6c60c89b | ||
|
|
b569ec97ee | ||
|
|
a3540057b7 | ||
|
|
6b6cf48ae2 | ||
|
|
f09cba3ab5 | ||
|
|
724183f669 | ||
|
|
a40212d41e | ||
|
|
c9ce02c43d | ||
|
|
03c9782d63 | ||
|
|
130e9451f4 | ||
|
|
dce6a3e9e1 | ||
|
|
486044d29b | ||
|
|
934b0f0044 | ||
|
|
2633cd6bfe | ||
|
|
2c81d0df03 | ||
|
|
9ef59e359b | ||
|
|
6561f6f5e7 | ||
|
|
b2e8e628fa | ||
|
|
bbb8d85971 | ||
|
|
14b94ebe12 | ||
|
|
f5f59d90d4 | ||
|
|
ac3f4ca369 | ||
|
|
10133e6040 | ||
|
|
321fb26df3 | ||
|
|
28bd018d1f | ||
|
|
cceb29313b | ||
|
|
530bfa982e | ||
|
|
3cfa636e88 | ||
|
|
a2e8f098cf | ||
|
|
9e42cfd7d7 | ||
|
|
a3c54d4d20 | ||
|
|
1d48e2afb3 | ||
|
|
d84c9dc1a9 | ||
|
|
6165bf5a6c | ||
|
|
712d3ea78f | ||
|
|
9720cd8189 | ||
|
|
bc4d9837c6 | ||
|
|
4a0f8931a0 | ||
|
|
3c8c52ca7f | ||
|
|
d29ef8934d | ||
|
|
a4c3949cfc | ||
|
|
97bbce321d | ||
|
|
0b9d199829 | ||
|
|
3da924b943 | ||
|
|
5ad313d290 | ||
|
|
8565f5f807 | ||
|
|
96e79248dc | ||
|
|
e00e490e73 | ||
|
|
dd95081e63 | ||
|
|
03bd31677a | ||
|
|
4619c56b09 | ||
|
|
c3dc57f0fb | ||
|
|
50ba20289b | ||
|
|
6b73072982 | ||
|
|
6e340bd149 | ||
|
|
65f551650f | ||
|
|
3be3741db6 | ||
|
|
610afd3717 | ||
|
|
4084822d2c | ||
|
|
a2c82263ee | ||
|
|
30f3d542b3 | ||
|
|
56cb2c69aa | ||
|
|
bd1dd43cbf | ||
|
|
5caae29df9 | ||
|
|
9713b607b5 | ||
|
|
0e46558cae | ||
|
|
2386f1034b | ||
|
|
ddf9f5c508 | ||
|
|
559867294f | ||
|
|
bf0c8d8dab | ||
|
|
7077e92cb0 | ||
|
|
035c5570c3 | ||
|
|
0be0fd1e05 | ||
|
|
bdfd380687 | ||
|
|
d1a4c73cd6 | ||
|
|
7133c81fc5 | ||
|
|
c6b4de39e8 | ||
|
|
94f367af70 | ||
|
|
dc6c393300 | ||
|
|
239f3a0a54 | ||
|
|
d3e78ab54e | ||
|
|
c6483535bd | ||
|
|
95bb2a5d56 | ||
|
|
23649ed840 | ||
|
|
3ee4034a76 | ||
|
|
21d377546e | ||
|
|
8c9dccc6a3 | ||
|
|
6fdf681993 | ||
|
|
7e8f413578 | ||
|
|
6705e5a962 | ||
|
|
d9126a936d | ||
|
|
4ee024b1ce | ||
|
|
19491d5ae6 | ||
|
|
db816594c5 | ||
|
|
fa73b7791f | ||
|
|
c61da5b0e5 | ||
|
|
49d724ad65 | ||
|
|
3ee2410a79 | ||
|
|
c2ddc70565 | ||
|
|
2f66e07c25 | ||
|
|
0807569ee2 | ||
|
|
206dec1bf8 | ||
|
|
0e852f5bb5 | ||
|
|
a272fb4e02 | ||
|
|
cbdc6e09aa | ||
|
|
211087f636 | ||
|
|
dca824b431 | ||
|
|
6bcc8eb0f2 | ||
|
|
844df4d5c9 | ||
|
|
6360d5fe1c | ||
|
|
e57a074b68 | ||
|
|
052632239e | ||
|
|
16aa4caceb | ||
|
|
83d84f6079 | ||
|
|
23c278d878 | ||
|
|
7074b0de71 | ||
|
|
2a9b025e88 | ||
|
|
16b3a0b1c1 | ||
|
|
e0c4f73600 | ||
|
|
6eb1947a6e | ||
|
|
2f793c29dc | ||
|
|
326fc221bf | ||
|
|
d49018363c | ||
|
|
2a2a0ad1f4 | ||
|
|
463b03ef7c | ||
|
|
80d39775ba | ||
|
|
92cdd25ca9 | ||
|
|
53680ba53b | ||
|
|
aa85c5fa3b | ||
|
|
a1ce6f8a81 | ||
|
|
7480904792 | ||
|
|
b12cfafc21 | ||
|
|
f07727651e | ||
|
|
6090eaa167 | ||
|
|
40eada4e80 | ||
|
|
2d375b3596 | ||
|
|
d864e2c723 | ||
|
|
e50c372562 | ||
|
|
e2cb033119 | ||
|
|
9620c57f19 | ||
|
|
07cc0fcbb6 | ||
|
|
6d1beb5c03 | ||
|
|
1667107422 | ||
|
|
de5cf1df2c | ||
|
|
a83114ced2 | ||
|
|
d6983422bf | ||
|
|
6d4b3ad84e | ||
|
|
a3df7919b5 | ||
|
|
6f1aa39cc9 | ||
|
|
f18c24c1d1 | ||
|
|
068401c29c | ||
|
|
6fbbd8b107 | ||
|
|
6379bd9e5d | ||
|
|
94d58dfa7c | ||
|
|
035fb80959 | ||
|
|
3b97f77083 | ||
|
|
a7d47202e6 | ||
|
|
199a9d3118 | ||
|
|
5df3ac4b04 | ||
|
|
782f77b688 | ||
|
|
1d570a233e | ||
|
|
4a6b58bd9b | ||
|
|
d64073bef0 | ||
|
|
6d8a9236f8 | ||
|
|
1665b4f2fa |
@@ -17,14 +17,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'zulu'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'zulu'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
|
||||
name: JDK 18-ea
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '30 6 * * 1,3,5'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
java_version: [18-ea]
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'zulu'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
path:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: Build with Maven
|
||||
run: mvn -T 8 test
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: oracle-actions/setup-java@v1
|
||||
with:
|
||||
website: jdk.java.net
|
||||
release: ${{ matrix.java_version }}
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -17,14 +17,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'zulu'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'zulu'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -17,14 +17,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
[](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean)
|
||||
[](https://github.com/ebean-orm/ebean/blob/master/LICENSE)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/multi-jdk-build.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/jdk-18-ea.yml)
|
||||
|
||||
##### Build with database platforms
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/h2database.yml)
|
||||
@@ -12,9 +11,9 @@
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/mariadb.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/oracle.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/sqlserver.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/db2luw.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/yugabyte.yml)
|
||||
|
||||
|
||||
##### Build with Java Early Access versions
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/jdk-ea.yml)
|
||||
[](https://github.com/ebean-orm/ebean-datasource/actions/workflows/jdk-ea.yml)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-clickhouse</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-clickhouse</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.11.0</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-cockroach</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.11.0</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-db2</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-db2</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.11.0</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-h2</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.11.0</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-hana</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-hana</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.11.0</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-mariadb</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-mariadb</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.11.0</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-mysql</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-mysql</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.11.0</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-nuodb</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-nuodb</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.11.0</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-oracle</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-oracle</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.11.0</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-postgres</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.11.0</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-sqlite</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlite</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.11.0</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-sqlserver</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlserver</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.11.0</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-yugabyte</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.11.0</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean (all platforms)</name>
|
||||
@@ -16,31 +16,31 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-joda-time</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-jsonnode</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-mapper</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -53,18 +53,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-all</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.11.0</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>composites</artifactId>
|
||||
|
||||
+11
-8
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean api</name>
|
||||
@@ -90,19 +90,22 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.transaction</groupId>
|
||||
<artifactId>jta</artifactId>
|
||||
<version>1.1</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- JAVAX-DEPENDENCY-START -->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!-- JAVAX-DEPENDENCY-END -->
|
||||
<!-- JAKARTA-DEPENDENCY-START ___
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<version>6.0.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
____ JAKARTA-DEPENDENCY-END -->
|
||||
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
|
||||
@@ -76,9 +76,9 @@ final class DbPrimary {
|
||||
defaultServerName = System.getProperty("db", defaultServerName);
|
||||
defaultServerName = System.getProperty("ebean_db", defaultServerName);
|
||||
if (isEmpty(defaultServerName)) {
|
||||
defaultServerName = Config.get("datasource.default", null);
|
||||
defaultServerName = Config.getOptional("datasource.default").orElse(null);
|
||||
if (isEmpty(defaultServerName)) {
|
||||
defaultServerName = Config.get("ebean.default.datasource", null);
|
||||
defaultServerName = Config.getOptional("ebean.default.datasource").orElse(null);
|
||||
}
|
||||
}
|
||||
if (defaultServerName == null) {
|
||||
|
||||
@@ -30,6 +30,13 @@ public final class Expr {
|
||||
private Expr() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying expression factory.
|
||||
*/
|
||||
public static ExpressionFactory factory() {
|
||||
return DB.expressionFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Equal To - property equal to the given value.
|
||||
*/
|
||||
|
||||
@@ -951,9 +951,12 @@ public interface ExpressionList<T> {
|
||||
ExpressionList<T> gtOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Greater Than or Equal to OR Null - ({@code >= or null }).
|
||||
* Is GREATER THAN if value is non-null and otherwise no expression is added to the query.
|
||||
* <p>
|
||||
* This is effectively a helper method that allows a query to be built in fluid style where some predicates are
|
||||
* effectively optional. We can use <code>gtIfPresent()</code> rather than having a separate if block.
|
||||
*/
|
||||
ExpressionList<T> geOrNull(String propertyName, Object value);
|
||||
ExpressionList<T> gtIfPresent(String propertyName, @Nullable Object value);
|
||||
|
||||
/**
|
||||
* Greater Than or Equal to the result of a sub-query.
|
||||
@@ -966,6 +969,20 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> ge(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Greater Than or Equal to OR Null - ({@code >= or null }).
|
||||
*/
|
||||
ExpressionList<T> geOrNull(String propertyName, Object value);
|
||||
|
||||
|
||||
/**
|
||||
* Is GREATER THAN OR EQUAL TO if value is non-null and otherwise no expression is added to the query.
|
||||
* <p>
|
||||
* This is effectively a helper method that allows a query to be built in fluid style where some predicates are
|
||||
* effectively optional. We can use <code>geIfPresent()</code> rather than having a separate if block.
|
||||
*/
|
||||
ExpressionList<T> geIfPresent(String propertyName, @Nullable Object value);
|
||||
|
||||
/**
|
||||
* Less Than the result of a sub-query.
|
||||
*/
|
||||
@@ -982,9 +999,12 @@ public interface ExpressionList<T> {
|
||||
ExpressionList<T> ltOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Less Than or Equal to OR Null - ({@code <= or null }).
|
||||
* Is LESS THAN if value is non-null and otherwise no expression is added to the query.
|
||||
* <p>
|
||||
* This is effectively a helper method that allows a query to be built in fluid style where some predicates are
|
||||
* effectively optional. We can use <code>ltIfPresent()</code> rather than having a separate if block.
|
||||
*/
|
||||
ExpressionList<T> leOrNull(String propertyName, Object value);
|
||||
ExpressionList<T> ltIfPresent(String propertyName, @Nullable Object value);
|
||||
|
||||
/**
|
||||
* Less Than or Equal to the result of a sub-query.
|
||||
@@ -996,6 +1016,19 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> le(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Less Than or Equal to OR Null - ({@code <= or null }).
|
||||
*/
|
||||
ExpressionList<T> leOrNull(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Is LESS THAN OR EQUAL TO if value is non-null and otherwise no expression is added to the query.
|
||||
* <p>
|
||||
* This is effectively a helper method that allows a query to be built in fluid style where some predicates are
|
||||
* effectively optional. We can use <code>leIfPresent()</code> rather than having a separate if block.
|
||||
*/
|
||||
ExpressionList<T> leIfPresent(String propertyName, @Nullable Object value);
|
||||
|
||||
/**
|
||||
* Is Null - property is null.
|
||||
*/
|
||||
@@ -1730,4 +1763,8 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> endNot();
|
||||
|
||||
/**
|
||||
* Clears the current expression list.
|
||||
*/
|
||||
ExpressionList<T> clear();
|
||||
}
|
||||
|
||||
@@ -231,18 +231,6 @@ public class OrderBy<T> implements Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this order by can be used in select clause.
|
||||
*/
|
||||
public boolean supportsSelect() {
|
||||
for (Property property : list) {
|
||||
if (!property.supportsSelect()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A property and its ascending descending order.
|
||||
*/
|
||||
@@ -403,12 +391,6 @@ public class OrderBy<T> implements Serializable {
|
||||
this.ascending = ascending;
|
||||
}
|
||||
|
||||
/**
|
||||
* Support use in select clause if no collation or nulls ordering.
|
||||
*/
|
||||
boolean supportsSelect() {
|
||||
return nulls == null;
|
||||
}
|
||||
}
|
||||
|
||||
private void parse(String orderByClause) {
|
||||
|
||||
@@ -17,15 +17,32 @@ public interface ProfileLocation {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a new ProfileLocation with a given lineNumber and label.
|
||||
* Create and return a new ProfileLocation with line number.
|
||||
*/
|
||||
static ProfileLocation create(int lineNumber, String label) {
|
||||
return XServiceProvider.profileLocationFactory().create(lineNumber, label);
|
||||
static ProfileLocation createWithLine() {
|
||||
return XServiceProvider.profileLocationFactory().createWithLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a new ProfileLocation with a given lineNumber and label.
|
||||
*/
|
||||
static ProfileLocation create(String label) {
|
||||
return XServiceProvider.profileLocationFactory().create(label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated in favor of {@link #create(String)}.
|
||||
*/
|
||||
@Deprecated
|
||||
static ProfileLocation create(int lineNumber, String label) {
|
||||
return create(label);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated for removal - not used.
|
||||
* Create and return a new ProfileLocation with a given location.
|
||||
*/
|
||||
@Deprecated
|
||||
static ProfileLocation createAt(String location) {
|
||||
return XServiceProvider.profileLocationFactory().createAt(location);
|
||||
}
|
||||
|
||||
@@ -1768,4 +1768,31 @@ public interface Query<T> extends CancelableQuery {
|
||||
*/
|
||||
Query<T> orderById(boolean orderById);
|
||||
|
||||
/**
|
||||
* Type safe query bean properties and expressions (marker interface).
|
||||
* <p>
|
||||
* Implemented by query bean properties and expressions based on those properties.
|
||||
* <p>
|
||||
* The base type determines which {@link StdOperators} can be used on the property.
|
||||
*
|
||||
* @param <T> The property type.
|
||||
*/
|
||||
interface Property<T> {
|
||||
|
||||
/**
|
||||
* Return a property given the expression.
|
||||
*/
|
||||
static <T> Property<T> of(String expression) {
|
||||
return new SimpleProperty<>(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the property in string expression form.
|
||||
* <p>
|
||||
* This is a path to a database column (like "name" or "billingAddress.city") or a function
|
||||
* wrapping a path (like <em>lower(name)</em>, <em>concat(name, '-', billingAddress.city)</em>
|
||||
*/
|
||||
@Override
|
||||
String toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package io.ebean;
|
||||
|
||||
final class SimpleProperty<T> implements Query.Property<T> {
|
||||
|
||||
private final String expression;
|
||||
|
||||
SimpleProperty(String expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return expression;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,332 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.Query.Property;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Standard Operators for use with strongly typed query construction.
|
||||
* <p>
|
||||
* This is currently deemed to be experimental and subject to change.
|
||||
*/
|
||||
@Deprecated(since = "experimental")
|
||||
public final class StdOperators {
|
||||
|
||||
// ---- Functions ---- //
|
||||
|
||||
/**
|
||||
* Sum of the given property.
|
||||
*/
|
||||
public static Property<Number> sum(Property<? extends Number> property) {
|
||||
return Property.of("sum(" + property + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Count of the given property.
|
||||
*/
|
||||
public static Property<Number> count(Property<?> property) {
|
||||
return Property.of("count(" + property + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Average of the given property.
|
||||
*/
|
||||
public static <T> Property<T> avg(Property<T> property) {
|
||||
return Property.of("avg(" + property + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Max of the given property.
|
||||
*/
|
||||
public static <T> Property<T> max(Property<T> property) {
|
||||
return Property.of("max(" + property + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Min of the given property.
|
||||
*/
|
||||
public static <T> Property<T> min(Property<T> property) {
|
||||
return Property.of("min(" + property + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Coalesce of the property and value.
|
||||
*/
|
||||
public static <T> Property<T> coalesce(Property<T> property, Object value) {
|
||||
return Property.of("coalesce(" + property.toString() + "," + sqlValue(value) + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Lower of the given property.
|
||||
*/
|
||||
public static Property<String> lower(Property<String> property) {
|
||||
return Property.of("lower(" + property + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Upper of the given property.
|
||||
*/
|
||||
public static Property<String> upper(Property<String> property) {
|
||||
return Property.of("upper(" + property + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Concat of the given property and values or other properties.
|
||||
*/
|
||||
public static Property<String> concat(Property<?> property, Object... values) {
|
||||
StringBuilder expression = new StringBuilder(50);
|
||||
expression.append("concat(").append(property.toString());
|
||||
for (Object value : values) {
|
||||
expression.append(",").append(sqlConcatString(value));
|
||||
}
|
||||
expression.append(")");
|
||||
return Property.of(expression.toString());
|
||||
}
|
||||
|
||||
private static String sqlConcatString(Object value) {
|
||||
if (value instanceof Property) {
|
||||
return value.toString();
|
||||
} else {
|
||||
return sqlQuote(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows numbers to be unquoted.
|
||||
*/
|
||||
private static String sqlValue(Object value) {
|
||||
if (value instanceof Property || value instanceof Number) {
|
||||
return value.toString();
|
||||
} else {
|
||||
return sqlQuote(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SQL quoted escaping single quotes.
|
||||
*/
|
||||
private static String sqlQuote(Object value) {
|
||||
return "'" + String.valueOf(value).replace("'", "''") + "'";
|
||||
}
|
||||
|
||||
// ---- Operators ---- //
|
||||
|
||||
/**
|
||||
* Equal to - for a property and value.
|
||||
*/
|
||||
public static <T> Expression eq(Property<T> property, T value) {
|
||||
return Expr.eq(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Equal to - for a property and sub-query.
|
||||
*/
|
||||
public static <T> Expression eq(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.in(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Equal to or null - for a property and value.
|
||||
*/
|
||||
public static <T> Expression eqOrNull(Property<T> property, T value) {
|
||||
return Expr.factory().eqOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not equal to - for a property and value.
|
||||
*/
|
||||
public static <T> Expression ne(Property<T> property, T value) {
|
||||
return Expr.ne(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not equal to - for a property and sub-query.
|
||||
*/
|
||||
public static <T> Expression ne(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.ne(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater than - for a property and value.
|
||||
*/
|
||||
public static <T> Expression gt(Property<T> property, T value) {
|
||||
return Expr.gt(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater than - for a property and sub-query.
|
||||
*/
|
||||
public static <T> Expression gt(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.gt(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater than or null - for a property and value.
|
||||
*/
|
||||
public static <T> Expression gtOrNull(Property<T> property, T value) {
|
||||
return Expr.factory().gtOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater than or equal to - for a property and value.
|
||||
*/
|
||||
public static <T> Expression ge(Property<T> property, T value) {
|
||||
return Expr.ge(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater than or equal to - for a property and sub-query.
|
||||
*/
|
||||
public static <T> Expression ge(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.ge(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater than or null - for a property and value.
|
||||
*/
|
||||
public static <T> Expression geOrNull(Property<T> property, T value) {
|
||||
return Expr.factory().geOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Less than - for a property and value.
|
||||
*/
|
||||
public static <T> Expression lt(Property<T> property, T value) {
|
||||
return Expr.lt(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Less than - for a property and sub-query.
|
||||
*/
|
||||
public static <T> Expression lt(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.lt(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Less than or null - for a property and value.
|
||||
*/
|
||||
public static <T> Expression ltOrNull(Property<T> property, T value) {
|
||||
return Expr.factory().ltOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater than or equal to - for a property and value.
|
||||
*/
|
||||
public static <T> Expression le(Property<T> property, T value) {
|
||||
return Expr.le(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater than or equal to - for a property and sub-query.
|
||||
*/
|
||||
public static <T> Expression le(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.le(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater than or equal to or null - for a property and value.
|
||||
*/
|
||||
public static <T> Expression leOrNull(Property<T> property, T value) {
|
||||
return Expr.factory().leOrNull(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* In range - for a property and values.
|
||||
*/
|
||||
public static <T> Expression inRange(Property<T> property, T lowValue, T highValue) {
|
||||
return Expr.factory().inRange(property.toString(), lowValue, highValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* In range - for properties and a value.
|
||||
*/
|
||||
public static <T> Expression inRange(Property<T> lowProperty, Property<T> highProperty, T value) {
|
||||
return Expr.factory().inRangeWith(lowProperty.toString(), highProperty.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* In range - for properties.
|
||||
*/
|
||||
public static <T> Expression inRange(Property<T> lowProperty, Property<T> property, Property<T> highProperty) {
|
||||
return Expr.factory().inRangeWithProperties(lowProperty.toString(), property.toString(), highProperty.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* In - for a given property and collection of values.
|
||||
*/
|
||||
public static <T> Expression in(Property<T> property, Collection<T> value) {
|
||||
return Expr.in(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* In - for a given property and sub-query.
|
||||
*/
|
||||
public static <T> Expression in(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.in(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* In or empty - for a given property and collection of values.
|
||||
*/
|
||||
public static <T> Expression inOrEmpty(Property<T> property, Collection<T> value) {
|
||||
return Expr.inOrEmpty(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not In - for a given property and collection of values.
|
||||
*/
|
||||
public static <T> Expression notIn(Property<T> property, Collection<T> value) {
|
||||
return Expr.factory().notIn(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Not In - for a given property and sub-query.
|
||||
*/
|
||||
public static <T> Expression notIn(Property<T> property, Query<?> subQuery) {
|
||||
return Expr.factory().notIn(property.toString(), subQuery);
|
||||
}
|
||||
|
||||
// ---- String operators ---- //
|
||||
|
||||
/**
|
||||
* Like - for a given property and value.
|
||||
*/
|
||||
public static Expression like(Property<String> property, String value) {
|
||||
return Expr.like(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Case-insensitive Like - for a given property and value.
|
||||
*/
|
||||
public static Expression ilike(Property<String> property, String value) {
|
||||
return Expr.ilike(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts with - for a given property and value.
|
||||
*/
|
||||
public static Expression startsWith(Property<String> property, String value) {
|
||||
return Expr.startsWith(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Case-insensitive starts with - for a given property and value.
|
||||
*/
|
||||
public static Expression istartsWith(Property<String> property, String value) {
|
||||
return Expr.istartsWith(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains - for a given property and value.
|
||||
*/
|
||||
public static Expression contains(Property<String> property, String value) {
|
||||
return Expr.contains(property.toString(), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Case-insensitive contains - for a given property and value.
|
||||
*/
|
||||
public static Expression icontains(Property<String> property, String value) {
|
||||
return Expr.icontains(property.toString(), value);
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ package io.ebean;
|
||||
*
|
||||
* int rows = DB.update(Customer.class)
|
||||
* .set("status", Customer.Status.ACTIVE)
|
||||
* .set("updtime", new Timestamp(System.currentTimeMillis()))
|
||||
* .set("whenUpdated", Instant.now())
|
||||
* .where()
|
||||
* .gt("id", 1000)
|
||||
* .update();
|
||||
@@ -25,6 +25,20 @@ package io.ebean;
|
||||
* update o_customer set status=?, updtime=? where id > ?
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h4>Example: Using query bean</h4>
|
||||
* <pre>{@code
|
||||
*
|
||||
* var cust = QCustomer.alias();
|
||||
*
|
||||
* int rows = new QCustomer()
|
||||
* .id.gt(1000)
|
||||
* .asUpdate()
|
||||
* .set(cust.status, Customer.Status.COMPLETE)
|
||||
* .set(cust.whenUpdated, Instant.now())
|
||||
* .update();
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* Note that if the where() clause contains a join then the SQL update changes to use a
|
||||
* <code> WHERE ID IN () </code> form.
|
||||
@@ -40,7 +54,7 @@ package io.ebean;
|
||||
*
|
||||
* int rows = DB.update(Customer.class)
|
||||
* .set("status", Customer.Status.ACTIVE)
|
||||
* .set("updtime", new Timestamp(System.currentTimeMillis()))
|
||||
* .set("whenUpdated", Instant.now())
|
||||
* .where()
|
||||
* .eq("status", Customer.Status.NEW)
|
||||
* .eq("billingAddress.country", nz)
|
||||
@@ -73,7 +87,7 @@ public interface UpdateQuery<T> {
|
||||
*
|
||||
* int rows = DB.update(Customer.class)
|
||||
* .set("status", Customer.Status.ACTIVE)
|
||||
* .set("updtime", new Timestamp(System.currentTimeMillis()))
|
||||
* .set("whenUpdated", Instant.now())
|
||||
* .where()
|
||||
* .gt("id", 1000)
|
||||
* .update();
|
||||
@@ -85,6 +99,27 @@ public interface UpdateQuery<T> {
|
||||
*/
|
||||
UpdateQuery<T> set(String property, Object value);
|
||||
|
||||
/**
|
||||
* Set the value of a property.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* var cust = QCustomer.alias();
|
||||
*
|
||||
* int rows = new QCustomer()
|
||||
* .id.gt(1000)
|
||||
* .asUpdate()
|
||||
* .set(cust.status, Customer.Status.COMPLETE)
|
||||
* .set(cust.whenUpdated, Instant.now())
|
||||
* .update();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param property The bean property to be set
|
||||
* @param value The value to set the property to
|
||||
*/
|
||||
<P> UpdateQuery<T> set(Query.Property<P> property, P value);
|
||||
|
||||
/**
|
||||
* Set the property to be null.
|
||||
* <p>
|
||||
@@ -102,6 +137,13 @@ public interface UpdateQuery<T> {
|
||||
*/
|
||||
UpdateQuery<T> setNull(String property);
|
||||
|
||||
/**
|
||||
* Set the property to be null.
|
||||
*
|
||||
* @param property The bean property to be set
|
||||
*/
|
||||
UpdateQuery<T> setNull(Query.Property<?> property);
|
||||
|
||||
/**
|
||||
* Set using a property expression that does not need any bind values.
|
||||
* <p>
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebean.bean;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static io.ebean.util.EncodeB64.enc;
|
||||
|
||||
@@ -27,19 +28,26 @@ public final class CallStack implements Serializable, CallOrigin {
|
||||
|
||||
private final String zeroHash;
|
||||
private final String pathHash;
|
||||
private final StackTraceElement[] callStack;
|
||||
private final Object[] callStack;
|
||||
private final int hc;
|
||||
|
||||
public CallStack(StackTraceElement[] callStack, int zeroHash, int pathHash) {
|
||||
public CallStack(Object[] callStack, int zeroHash, int pathHash) {
|
||||
this.callStack = callStack;
|
||||
this.hc = computeHashCode();
|
||||
this.zeroHash = enc(zeroHash);
|
||||
this.pathHash = enc(pathHash);
|
||||
}
|
||||
|
||||
public CallStack(List<StackWalker.StackFrame> frames) {
|
||||
this.callStack = frames.toArray(new Object[0]);
|
||||
this.hc = computeHashCode();
|
||||
this.zeroHash = enc(callStack[0].hashCode());
|
||||
this.pathHash = enc(hc);
|
||||
}
|
||||
|
||||
private int computeHashCode() {
|
||||
int hc = 0;
|
||||
for (StackTraceElement element : callStack) {
|
||||
for (Object element : callStack) {
|
||||
hc = 92821 * hc + element.hashCode();
|
||||
}
|
||||
return hc;
|
||||
|
||||
@@ -24,6 +24,11 @@ public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
this.owner = (EntityBean) ownerBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InterceptReadOnly{" + owner + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityBean getOwner() {
|
||||
return owner;
|
||||
|
||||
@@ -113,6 +113,25 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
this.flags = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InterceptReadWrite{state=" + state +
|
||||
(dirty ? " dirty;" : "") +
|
||||
(forceUpdate ? " forceUpdate;" : "") +
|
||||
(readOnly ? " readOnly;" : "") +
|
||||
(disableLazyLoad ? " disableLazyLoad;" : "") +
|
||||
(lazyLoadFailure ? " lazyLoadFailure;" : "") +
|
||||
(fullyLoadedBean ? " fullyLoadedBean;" : "") +
|
||||
(loadedFromCache ? " loadedFromCache;" : "") +
|
||||
", pc=" + System.identityHashCode(persistenceContext) +
|
||||
", flags=" + Arrays.toString(flags) +
|
||||
(lazyLoadProperty > -1 ? (", lazyLoadProperty=" + lazyLoadProperty) : "") +
|
||||
", loader=" + beanLoader +
|
||||
(ownerId != null ? (", ownerId=" + ownerId) : "") +
|
||||
", owner=" + owner +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityBean getOwner() {
|
||||
return owner;
|
||||
@@ -690,7 +709,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
if (beanLoader == null) {
|
||||
final Database database = DB.byName(ebeanServerName);
|
||||
if (database == null) {
|
||||
throw new PersistenceException("Database [" + ebeanServerName + "] was not found?");
|
||||
throw new PersistenceException(ebeanServerName == null ? "No registered default server" : "Database [" + ebeanServerName + "] is not registered");
|
||||
}
|
||||
// For stand alone reference bean or after deserialisation lazy load
|
||||
// using the ebeanServer. Synchronise only on the bean.
|
||||
@@ -718,14 +737,14 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
}
|
||||
if (lazyLoadFailure) {
|
||||
// failed when batch lazy loaded by another bean in the batch
|
||||
throw new EntityNotFoundException("(Lazy) loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted");
|
||||
throw new EntityNotFoundException("(Lazy) loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted. BeanLoader: " + beanLoader);
|
||||
}
|
||||
if (lazyLoadProperty == -1) {
|
||||
lazyLoadProperty = loadProperty;
|
||||
loader.loadBean(this);
|
||||
if (lazyLoadFailure) {
|
||||
// failed when lazy loading this bean
|
||||
throw new EntityNotFoundException("Lazy loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted.");
|
||||
throw new EntityNotFoundException("Lazy loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted. BeanLoader: " + beanLoader);
|
||||
}
|
||||
// bean should be loaded and intercepting now. setLoaded() has
|
||||
// been called by the lazy loading mechanism
|
||||
|
||||
@@ -29,6 +29,11 @@ public class ServerCacheStatistics {
|
||||
|
||||
protected long evictCount;
|
||||
|
||||
protected long gcCount;
|
||||
protected long idleCount;
|
||||
protected long ttlCount;
|
||||
protected long lruCount;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
//noinspection StringBufferReplaceableByString
|
||||
@@ -43,6 +48,10 @@ public class ServerCacheStatistics {
|
||||
sb.append(" remove:").append(removeCount);
|
||||
sb.append(" clear:").append(clearCount);
|
||||
sb.append(" evict:").append(evictCount);
|
||||
sb.append(" gc:").append(gcCount);
|
||||
sb.append(" idle:").append(idleCount);
|
||||
sb.append(" ttl:").append(ttlCount);
|
||||
sb.append(" lru:").append(lruCount);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@@ -191,4 +200,37 @@ public class ServerCacheStatistics {
|
||||
return evictCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the count of entries removed by the garbage collection.
|
||||
*/
|
||||
public void setGcCount(long gcCount) {
|
||||
this.gcCount = gcCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of entries removed by the garbage collection.
|
||||
*/
|
||||
public long getGcCount() {
|
||||
return gcCount;
|
||||
}
|
||||
|
||||
public void setIdleCount(long idleCount) {
|
||||
this.idleCount = idleCount;
|
||||
}
|
||||
|
||||
public long getIdleCount() {
|
||||
return idleCount;
|
||||
}
|
||||
|
||||
public void setTtlCount(long ttlCount) {
|
||||
this.ttlCount = ttlCount;
|
||||
}
|
||||
|
||||
public long getTtlCount() {
|
||||
return ttlCount;
|
||||
}
|
||||
|
||||
public void setLruCount(long lruCount) {
|
||||
this.lruCount = lruCount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,10 +123,10 @@ public class DatabaseConfig {
|
||||
private boolean loadModuleInfo = true;
|
||||
|
||||
/**
|
||||
* List of interesting classes such as entities, embedded, ScalarTypes,
|
||||
* Listeners, Finders, Controllers etc.
|
||||
* Interesting classes such as entities, embedded, ScalarTypes,
|
||||
* Listeners, Finders, Controllers, AttributeConverters etc.
|
||||
*/
|
||||
private List<Class<?>> classes = new ArrayList<>();
|
||||
private Set<Class<?>> classes = new HashSet<>();
|
||||
|
||||
/**
|
||||
* The packages that are searched for interesting classes. Only used when
|
||||
@@ -2320,8 +2320,7 @@ public class DatabaseConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* Programmatically add classes (typically entities) that this server should
|
||||
* use.
|
||||
* Programmatically add classes (typically entities) that this server should use.
|
||||
* <p>
|
||||
* The class can be an Entity, Embedded type, ScalarType, BeanPersistListener,
|
||||
* BeanFinder or BeanPersistController.
|
||||
@@ -2331,8 +2330,7 @@ public class DatabaseConfig {
|
||||
* <p>
|
||||
* Alternatively the classes can be added via {@link #setClasses(List)}.
|
||||
*
|
||||
* @param cls the entity type (or other type) that should be registered by this
|
||||
* database.
|
||||
* @param cls the entity type (or other type) that should be registered by this database.
|
||||
*/
|
||||
public void addClass(Class<?> cls) {
|
||||
classes.add(cls);
|
||||
@@ -2341,7 +2339,7 @@ public class DatabaseConfig {
|
||||
/**
|
||||
* Register all the classes (typically entity classes).
|
||||
*/
|
||||
public void addAll(List<Class<?>> classList) {
|
||||
public void addAll(Collection<Class<?>> classList) {
|
||||
if (classList != null && !classList.isEmpty()) {
|
||||
classes.addAll(classList);
|
||||
}
|
||||
@@ -2383,15 +2381,26 @@ public class DatabaseConfig {
|
||||
* <p>
|
||||
* Alternatively the classes can contain added via {@link #addClass(Class)}.
|
||||
*/
|
||||
public void setClasses(List<Class<?>> classes) {
|
||||
this.classes = classes;
|
||||
public void setClasses(Collection<Class<?>> classes) {
|
||||
this.classes = new HashSet<>(classes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the classes registered for this database. Typically this includes
|
||||
* Return the classes registered for this database. Typically, this includes
|
||||
* entities and perhaps listeners.
|
||||
*/
|
||||
public List<Class<?>> getClasses() {
|
||||
public Set<Class<?>> classes() {
|
||||
return classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to classes().
|
||||
* <p>
|
||||
* Sorry if returning Set rather than List breaks code but it feels safer to
|
||||
* do that than a subtle change to return a shallow copy which you will not detect.
|
||||
*/
|
||||
@Deprecated
|
||||
public Set<Class<?>> getClasses() {
|
||||
return classes;
|
||||
}
|
||||
|
||||
@@ -2760,8 +2769,6 @@ public class DatabaseConfig {
|
||||
this.classLoadConfig = classLoadConfig;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Load settings from application.properties, application.yaml and other sources.
|
||||
* <p>
|
||||
@@ -2906,7 +2913,7 @@ public class DatabaseConfig {
|
||||
serverCachePlugin = p.createInstance(ServerCachePlugin.class, "serverCachePlugin", serverCachePlugin);
|
||||
|
||||
String packagesProp = p.get("search.packages", p.get("packages", null));
|
||||
packages = getSearchList(packagesProp, packages);
|
||||
packages = searchList(packagesProp, packages);
|
||||
|
||||
skipCacheAfterWrite = p.getBoolean("skipCacheAfterWrite", skipCacheAfterWrite);
|
||||
updateAllPropertiesInBatch = p.getBoolean("updateAllPropertiesInBatch", updateAllPropertiesInBatch);
|
||||
@@ -2982,10 +2989,10 @@ public class DatabaseConfig {
|
||||
tenantCatalogProvider = p.createInstance(TenantCatalogProvider.class, "tenant.catalogProvider", tenantCatalogProvider);
|
||||
tenantSchemaProvider = p.createInstance(TenantSchemaProvider.class, "tenant.schemaProvider", tenantSchemaProvider);
|
||||
tenantPartitionColumn = p.get("tenant.partitionColumn", tenantPartitionColumn);
|
||||
classes = getClasses(p);
|
||||
classes = readClasses(p);
|
||||
|
||||
String mappingsProp = p.get("mappingLocations", null);
|
||||
mappingLocations = getSearchList(mappingsProp, mappingLocations);
|
||||
mappingLocations = searchList(mappingsProp, mappingLocations);
|
||||
}
|
||||
|
||||
private NamingConvention createNamingConvention(PropertiesWrapper properties, NamingConvention namingConvention) {
|
||||
@@ -2999,13 +3006,13 @@ public class DatabaseConfig {
|
||||
* @param properties the properties
|
||||
* @return the classes
|
||||
*/
|
||||
private List<Class<?>> getClasses(PropertiesWrapper properties) {
|
||||
private Set<Class<?>> readClasses(PropertiesWrapper properties) {
|
||||
String classNames = properties.get("classes", null);
|
||||
if (classNames == null) {
|
||||
return classes;
|
||||
}
|
||||
|
||||
List<Class<?>> classList = new ArrayList<>();
|
||||
Set<Class<?>> classList = new HashSet<>();
|
||||
String[] split = StringHelper.splitNames(classNames);
|
||||
for (String cn : split) {
|
||||
if (!"class".equalsIgnoreCase(cn)) {
|
||||
@@ -3020,7 +3027,7 @@ public class DatabaseConfig {
|
||||
return classList;
|
||||
}
|
||||
|
||||
private List<String> getSearchList(String searchNames, List<String> defaultValue) {
|
||||
private List<String> searchList(String searchNames, List<String> defaultValue) {
|
||||
if (searchNames != null) {
|
||||
String[] entries = StringHelper.splitNames(searchNames);
|
||||
List<String> hitList = new ArrayList<>(entries.length);
|
||||
@@ -3399,8 +3406,16 @@ public class DatabaseConfig {
|
||||
* When false we either register entity classes via application code or use classpath
|
||||
* scanning to find and register entity classes.
|
||||
*/
|
||||
public boolean isLoadModuleInfo() {
|
||||
return loadModuleInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated - migrate to isLoadModuleInfo().
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean isAutoLoadModuleInfo() {
|
||||
return loadModuleInfo && classes.isEmpty();
|
||||
return loadModuleInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,9 +13,16 @@ public interface SpiProfileLocationFactory {
|
||||
ProfileLocation create();
|
||||
|
||||
/**
|
||||
* Create a profile location with a line number.
|
||||
* Create a profile location with line numbering.
|
||||
*/
|
||||
ProfileLocation create(int lineNumber, String label);
|
||||
ProfileLocation createWithLine();
|
||||
|
||||
/**
|
||||
* Create with a given label - used only with {@code @Transaction}.
|
||||
*
|
||||
* @param label the label for the transaction
|
||||
*/
|
||||
ProfileLocation create(String label);
|
||||
|
||||
/**
|
||||
* Create a known location.
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package io.ebean.util;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Provides a stack filter that excludes ebean and jdk code.
|
||||
*/
|
||||
public final class StackWalkFilter {
|
||||
|
||||
private static final Filter FILTER = new Filter();
|
||||
|
||||
/**
|
||||
* Return a stack filter that excludes ebean and jdk code.
|
||||
*/
|
||||
public static Predicate<StackWalker.StackFrame> filter() {
|
||||
return FILTER;
|
||||
}
|
||||
|
||||
private static class Filter implements Predicate<StackWalker.StackFrame> {
|
||||
|
||||
@Override
|
||||
public boolean test(StackWalker.StackFrame stackFrame) {
|
||||
return !stackFrame.getClassName().startsWith("io.ebean")
|
||||
&& !stackFrame.getClassName().startsWith("jdk.")
|
||||
&& !stackFrame.getMethodName().startsWith("_ebean_");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
ebean-version: 141
|
||||
ebean-version: 143
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package io.ebean;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
import static io.ebean.StdOperators.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class StdOperatorsTest {
|
||||
|
||||
final Query.Property<Number> amount = Query.Property.of("amount");
|
||||
final Query.Property<String> foo = Query.Property.of("foo");
|
||||
final Query.Property<String> bar = Query.Property.of("bar");
|
||||
|
||||
@Test
|
||||
void testAvg() {
|
||||
assertThat(avg(foo).toString()).isEqualTo("avg(foo)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCount() {
|
||||
assertThat(count(foo).toString()).isEqualTo("count(foo)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMax() {
|
||||
assertThat(max(foo).toString()).isEqualTo("max(foo)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMin() {
|
||||
assertThat(min(foo).toString()).isEqualTo("min(foo)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSum() {
|
||||
assertThat(sum(amount).toString()).isEqualTo("sum(amount)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testLower() {
|
||||
assertThat(lower(foo).toString()).isEqualTo("lower(foo)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpper() {
|
||||
assertThat(upper(foo).toString()).isEqualTo("upper(foo)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConcat() {
|
||||
assertThat(concat(foo, "+").toString()).isEqualTo("concat(foo,'+')");
|
||||
assertThat(concat(foo, 42).toString()).isEqualTo("concat(foo,'42')");
|
||||
assertThat(concat(foo, LocalDate.of(2022, 9, 1)).toString()).isEqualTo("concat(foo,'2022-09-01')");
|
||||
assertThat(concat(foo, bar).toString()).isEqualTo("concat(foo,bar)");
|
||||
assertThat(concat(foo, ":", 42, bar).toString()).isEqualTo("concat(foo,':','42',bar)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCoalesce() {
|
||||
assertThat(coalesce(foo, bar).toString()).isEqualTo("coalesce(foo,bar)");
|
||||
assertThat(coalesce(foo, 42).toString()).isEqualTo("coalesce(foo,42)");
|
||||
assertThat(coalesce(foo, 0).toString()).isEqualTo("coalesce(foo,0)");
|
||||
assertThat(coalesce(foo, "apple").toString()).isEqualTo("coalesce(foo,'apple')");
|
||||
assertThat(coalesce(foo, "banana").toString()).isEqualTo("coalesce(foo,'banana')");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCoalesceWithQuoted() {
|
||||
assertThat(coalesce(foo, "ba'nana").toString()).isEqualTo("coalesce(foo,'ba''nana')");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConcatWithQuoted() {
|
||||
assertThat(concat(foo, "ba'nana").toString()).isEqualTo("concat(foo,'ba''nana')");
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,6 @@ package io.ebean.config;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.ebean.annotation.MutationDetection;
|
||||
import io.ebean.annotation.PersistBatch;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.config.JsonConfig;
|
||||
import io.ebean.config.MatchingNamingConvention;
|
||||
import io.ebean.config.PlatformConfig;
|
||||
import io.ebean.config.dbplatform.IdType;
|
||||
import io.ebean.datasource.DataSourceConfig;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
@@ -93,6 +89,7 @@ class DatabaseConfigTest {
|
||||
assertTrue(config.isDbOffline());
|
||||
assertTrue(config.isAutoReadOnlyDataSource());
|
||||
assertTrue(config.isAutoLoadModuleInfo());
|
||||
assertTrue(config.isLoadModuleInfo());
|
||||
assertTrue(config.skipDataSourceCheck());
|
||||
|
||||
assertTrue(config.isIdGeneratorAutomatic());
|
||||
@@ -165,6 +162,7 @@ class DatabaseConfigTest {
|
||||
assertEquals(MutationDetection.HASH, config.getJsonMutationDetection());
|
||||
assertTrue(config.getPlatformConfig().isCaseSensitiveCollation());
|
||||
assertTrue(config.isAutoLoadModuleInfo());
|
||||
assertTrue(config.isLoadModuleInfo());
|
||||
|
||||
assertFalse(config.isQueryPlanEnable());
|
||||
assertEquals(Long.MAX_VALUE, config.getQueryPlanThresholdMicros());
|
||||
@@ -175,6 +173,7 @@ class DatabaseConfigTest {
|
||||
|
||||
config.setLoadModuleInfo(false);
|
||||
assertFalse(config.isAutoLoadModuleInfo());
|
||||
assertFalse(config.isLoadModuleInfo());
|
||||
config.setAutoPersistUpdates(true);
|
||||
assertTrue(config.isAutoPersistUpdates());
|
||||
config.setSkipDataSourceCheck(true);
|
||||
|
||||
+20
-6
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</parent>
|
||||
<!-- <parent>-->
|
||||
<!-- <groupId>org.avaje</groupId>-->
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-parent-13.11.0</tag>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
|
||||
<name>ebean autotune</name>
|
||||
@@ -26,17 +26,31 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- needed for java 11+ -->
|
||||
<!-- JAVAX-DEPENDENCY-START -->
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jaxb</groupId>
|
||||
<artifactId>jaxb-runtime</artifactId>
|
||||
<version>2.3.6</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- JAVAX-DEPENDENCY-END -->
|
||||
<!-- JAKARTA-DEPENDENCY-START ___
|
||||
<dependency>
|
||||
<groupId>jakarta.xml.bind</groupId>
|
||||
<artifactId>jakarta.xml.bind-api</artifactId>
|
||||
<version>4.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sun.xml.bind</groupId>
|
||||
<artifactId>jaxb-impl</artifactId>
|
||||
<version>4.0.0</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
____ JAKARTA-DEPENDENCY-END -->
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
@@ -55,7 +69,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -70,7 +84,7 @@
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<tiles>
|
||||
<tile>io.ebean.tile:enhancement:13.10.1</tile>
|
||||
<tile>io.ebean.tile:enhancement:13.12.0</tile>
|
||||
</tiles>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
+35
-47
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean bom</name>
|
||||
@@ -89,192 +89,180 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-joda-time</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-jsonnode</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-mapper</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-xml</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-autotune</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>kotlin-querybean-generator</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-redis</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-spring-txn</artifactId>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- platforms -->
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-all</artifactId>
|
||||
<version>13.11.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-clickhouse</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-db2</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-h2</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-hana</artifactId>
|
||||
<version>13.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-hsqldb</artifactId>
|
||||
<version>13.11.0-SNAPSHOT</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-mariadb</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-mysql</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-nuodb</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-oracle</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgres</artifactId>
|
||||
<version>13.11.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-sqlanywhere</artifactId>
|
||||
<version>13.11.0-SNAPSHOT</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-sqlite</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-sqlserver</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
@@ -16,7 +16,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
+8
-8
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core</artifactId>
|
||||
@@ -15,14 +15,14 @@
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-parent-13.11.0</tag>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -46,13 +46,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -143,21 +143,21 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlserver</artifactId>
|
||||
<version>13.11.0</version>
|
||||
<version>13.15.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -9,4 +9,5 @@ public final class CoreLog {
|
||||
|
||||
public static final System.Logger log = AppLog.getLogger("io.ebean.core");
|
||||
public static final System.Logger internal = AppLog.getLogger("io.ebean.internal");
|
||||
public static final System.Logger markedAsDeleted = AppLog.getLogger("io.ebean.MarkedAsDeleted");
|
||||
}
|
||||
|
||||
@@ -6,10 +6,7 @@ import io.ebeaninternal.api.SpiQuery.Mode;
|
||||
import io.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Request for loading ManyToOne and OneToOne relationships.
|
||||
@@ -65,9 +62,9 @@ public final class LoadBeanRequest extends LoadRequest {
|
||||
/**
|
||||
* Return the list of Id values for the beans in the lazy load buffer.
|
||||
*/
|
||||
public List<Object> getIdList() {
|
||||
List<Object> idList = new ArrayList<>();
|
||||
BeanDescriptor<?> desc = loadBuffer.descriptor();
|
||||
public List<Object> ids() {
|
||||
final List<Object> idList = new ArrayList<>(batch.size());
|
||||
final BeanDescriptor<?> desc = loadBuffer.descriptor();
|
||||
for (EntityBeanIntercept ebi : batch) {
|
||||
idList.add(desc.getId(ebi.getOwner()));
|
||||
}
|
||||
@@ -103,7 +100,7 @@ public final class LoadBeanRequest extends LoadRequest {
|
||||
/**
|
||||
* Load the beans into the L2 cache if that is requested and check for load failures due to deletes.
|
||||
*/
|
||||
public void postLoad(List<?> list) {
|
||||
public Result postLoad(List<?> list) {
|
||||
Set<Object> loadedIds = new HashSet<>();
|
||||
BeanDescriptor<?> desc = loadBuffer.descriptor();
|
||||
// collect Ids and maybe load bean cache
|
||||
@@ -114,6 +111,8 @@ public final class LoadBeanRequest extends LoadRequest {
|
||||
desc.cacheBeanPutAll(list);
|
||||
}
|
||||
if (lazyLoadProperty != null) {
|
||||
List<EntityBeanIntercept> missed = new ArrayList<>();
|
||||
Set<Object> missedIds = new HashSet<>();
|
||||
for (EntityBeanIntercept ebi : batch) {
|
||||
// check if the underlying row in DB was deleted. Mark the bean as 'failed' if
|
||||
// necessary but allow processing to continue until it is accessed by client code
|
||||
@@ -121,8 +120,43 @@ public final class LoadBeanRequest extends LoadRequest {
|
||||
if (!loadedIds.contains(id)) {
|
||||
// assume this is logically deleted (hence not found)
|
||||
desc.markAsDeleted(ebi.getOwner());
|
||||
missedIds.add(id);
|
||||
missed.add(ebi);
|
||||
}
|
||||
}
|
||||
return new Result(loadedIds, missedIds, missed);
|
||||
}
|
||||
return EMPTY_RESULT;
|
||||
}
|
||||
|
||||
static final Result EMPTY_RESULT = new Result(Collections.emptySet(),Collections.emptySet(), Collections.emptyList());
|
||||
|
||||
public static class Result {
|
||||
|
||||
private final Set<Object> loadedIds;
|
||||
private final Set<Object> missedIds;
|
||||
private final List<EntityBeanIntercept> missed;
|
||||
|
||||
Result(Set<Object> loadedIds, Set<Object> missedIds, List<EntityBeanIntercept> missed) {
|
||||
this.loadedIds = loadedIds;
|
||||
this.missedIds = missedIds;
|
||||
this.missed = missed;
|
||||
}
|
||||
|
||||
public boolean markedDeleted() {
|
||||
return !missedIds.isEmpty();
|
||||
}
|
||||
|
||||
public Set<Object> missedIds() {
|
||||
return missedIds;
|
||||
}
|
||||
|
||||
public Set<Object> loadedIds() {
|
||||
return loadedIds;
|
||||
}
|
||||
|
||||
public List<EntityBeanIntercept> missed() {
|
||||
return missed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,4 +50,9 @@ public interface LoadContext {
|
||||
* Register a collection for lazy loading.
|
||||
*/
|
||||
void register(String path, BeanPropertyAssocMany<?> many, BeanCollection<?> bc);
|
||||
|
||||
/**
|
||||
* Use soft-references for streaming queries, so unreachable entries can be garbage collected.
|
||||
*/
|
||||
void useReferences(boolean useReferences);
|
||||
}
|
||||
|
||||
@@ -6,16 +6,30 @@ import io.ebean.bean.PersistenceContext;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A buffer of bean collections for batch lazy loading and secondary query loading.
|
||||
*/
|
||||
public interface LoadManyBuffer {
|
||||
|
||||
int getBatchSize();
|
||||
/**
|
||||
* The batch (max) size;
|
||||
*/
|
||||
int batchSize();
|
||||
|
||||
List<BeanCollection<?>> getBatch();
|
||||
/**
|
||||
* The actual size.
|
||||
*/
|
||||
int size();
|
||||
|
||||
/**
|
||||
* Get the <code>i</code>th element from buffer. This can be null.
|
||||
*/
|
||||
BeanCollection<?> get(int i);
|
||||
|
||||
/**
|
||||
* Removes an element from the buffer. This will NOT affect size.
|
||||
*/
|
||||
boolean removeFromBuffer(BeanCollection<?> collection);
|
||||
|
||||
BeanPropertyAssocMany<?> getBeanProperty();
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static java.lang.System.Logger.Level.DEBUG;
|
||||
import static java.lang.System.Logger.Level.INFO;
|
||||
|
||||
/**
|
||||
* Request for loading Associated Many Beans.
|
||||
@@ -19,32 +20,32 @@ import static java.lang.System.Logger.Level.DEBUG;
|
||||
public final class LoadManyRequest extends LoadRequest {
|
||||
|
||||
private static final System.Logger log = CoreLog.log;
|
||||
|
||||
private final List<BeanCollection<?>> batch;
|
||||
private final LoadManyBuffer loadContext;
|
||||
private final boolean onlyIds;
|
||||
private final boolean loadCache;
|
||||
private final BeanCollection<?> originCollection;
|
||||
private boolean originIncluded;
|
||||
|
||||
/**
|
||||
* Construct for lazy loading.
|
||||
*/
|
||||
public LoadManyRequest(LoadManyBuffer loadContext, boolean onlyIds, boolean loadCache) {
|
||||
this(loadContext, null, true, onlyIds, loadCache);
|
||||
public LoadManyRequest(LoadManyBuffer loadContext, boolean onlyIds, boolean loadCache, BeanCollection<?> originCollection) {
|
||||
super(null, true);
|
||||
this.loadContext = loadContext;
|
||||
this.onlyIds = onlyIds;
|
||||
this.loadCache = loadCache;
|
||||
this.originCollection = originCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct for secondary query.
|
||||
*/
|
||||
public LoadManyRequest(LoadManyBuffer loadContext, OrmQueryRequest<?> parentRequest) {
|
||||
this(loadContext, parentRequest, false, false, false);
|
||||
}
|
||||
|
||||
private LoadManyRequest(LoadManyBuffer loadContext, OrmQueryRequest<?> parentRequest, boolean lazy, boolean onlyIds, boolean loadCache) {
|
||||
super(parentRequest, lazy);
|
||||
super(parentRequest, false);
|
||||
this.loadContext = loadContext;
|
||||
this.batch = loadContext.getBatch();
|
||||
this.onlyIds = onlyIds;
|
||||
this.loadCache = loadCache;
|
||||
this.onlyIds = false;
|
||||
this.loadCache = false;
|
||||
this.originCollection = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -59,9 +60,20 @@ public final class LoadManyRequest extends LoadRequest {
|
||||
private List<Object> parentIdList(SpiEbeanServer server) {
|
||||
List<Object> idList = new ArrayList<>();
|
||||
BeanPropertyAssocMany<?> many = many();
|
||||
for (BeanCollection<?> bc : batch) {
|
||||
idList.add(many.parentId(bc.getOwnerBean()));
|
||||
bc.setLoader(server); // don't use the load buffer again
|
||||
for (int i = 0; i < loadContext.size(); i++) {
|
||||
BeanCollection<?> bc = loadContext.get(i);
|
||||
if (bc != null) {
|
||||
if (lazy && !originIncluded && bc == originCollection) {
|
||||
originIncluded = true;
|
||||
}
|
||||
idList.add(many.parentId(bc.getOwnerBean()));
|
||||
bc.setLoader(server); // don't use the load buffer again
|
||||
}
|
||||
}
|
||||
if (originCollection != null && !originIncluded) {
|
||||
CoreLog.log.log(INFO, "Batch lazy loading including origin collection - size:{0}", idList.size());
|
||||
idList.add(many.parentId(originCollection.getOwnerBean()));
|
||||
originCollection.setLoader(server); // don't use the load buffer again
|
||||
}
|
||||
if (many.targetDescriptor().isPadInExpression()) {
|
||||
BindPadding.padIds(idList);
|
||||
@@ -91,7 +103,7 @@ public final class LoadManyRequest extends LoadRequest {
|
||||
query.setPersistenceContext(loadContext.getPersistenceContext());
|
||||
query.setLoadDescription(lazy ? "+lazy" : "+query", description());
|
||||
if (lazy) {
|
||||
query.setLazyLoadBatchSize(loadContext.getBatchSize());
|
||||
query.setLazyLoadBatchSize(loadContext.batchSize());
|
||||
} else {
|
||||
query.setBeanCacheMode(CacheMode.OFF);
|
||||
}
|
||||
@@ -112,15 +124,18 @@ public final class LoadManyRequest extends LoadRequest {
|
||||
BeanPropertyAssocMany<?> many = many();
|
||||
// check for BeanCollection's that where never processed
|
||||
// in the +query or +lazy load due to no rows (predicates)
|
||||
for (BeanCollection<?> bc : batch) {
|
||||
if (bc.checkEmptyLazyLoad()) {
|
||||
if (log.isLoggable(DEBUG)) {
|
||||
EntityBean ownerBean = bc.getOwnerBean();
|
||||
Object parentId = desc.getId(ownerBean);
|
||||
log.log(DEBUG, "BeanCollection after lazy load was empty. type:{0} id:{1} owner:{2}", ownerBean.getClass().getName(), parentId, ownerBean);
|
||||
for (int i = 0; i < loadContext.size(); i++) {
|
||||
BeanCollection<?> bc = loadContext.get(i);
|
||||
if (bc != null) {
|
||||
if (bc.checkEmptyLazyLoad()) {
|
||||
if (log.isLoggable(DEBUG)) {
|
||||
EntityBean ownerBean = bc.getOwnerBean();
|
||||
Object parentId = desc.getId(ownerBean);
|
||||
log.log(DEBUG, "BeanCollection after lazy load was empty. type:{0} id:{1} owner:{2}", ownerBean.getClass().getName(), parentId, ownerBean);
|
||||
}
|
||||
} else if (loadCache && many.isUseCache()) {
|
||||
desc.cacheManyPropPut(many, bc, desc.cacheKeyForBean(bc.getOwnerBean()));
|
||||
}
|
||||
} else if (loadCache && many.isUseCache()) {
|
||||
desc.cacheManyPropPut(many, bc, desc.getId(bc.getOwnerBean()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,18 +10,25 @@ package io.ebeaninternal.api;
|
||||
public interface SpiLogManager {
|
||||
|
||||
/**
|
||||
* Return the SQL logger.
|
||||
* Enable bind logging.
|
||||
*/
|
||||
boolean enableBindLog();
|
||||
|
||||
/**
|
||||
* Logger used for general transactions.
|
||||
*/
|
||||
SpiTxnLogger logger();
|
||||
|
||||
/**
|
||||
* Logger used for read only transactions.
|
||||
*/
|
||||
SpiTxnLogger readOnlyLogger();
|
||||
|
||||
/**
|
||||
* Hmmmm, return the SQL logger for logging truncate statements.
|
||||
* <p>
|
||||
* Maybe we should get rid of this
|
||||
*/
|
||||
SpiLogger sql();
|
||||
|
||||
/**
|
||||
* Return the TXN logger.
|
||||
*/
|
||||
SpiLogger txn();
|
||||
|
||||
/**
|
||||
* Return the Summary logger.
|
||||
*/
|
||||
SpiLogger sum();
|
||||
|
||||
}
|
||||
|
||||
@@ -14,18 +14,9 @@ public interface SpiLogger {
|
||||
*/
|
||||
boolean isDebug();
|
||||
|
||||
/**
|
||||
* Is trace logging enabled.
|
||||
*/
|
||||
boolean isTrace();
|
||||
|
||||
/**
|
||||
* Log a debug level message.
|
||||
*/
|
||||
void debug(String msg);
|
||||
void debug(String msg, Object... args);
|
||||
|
||||
/**
|
||||
* Log a trace level message.
|
||||
*/
|
||||
void trace(String msg);
|
||||
}
|
||||
|
||||
@@ -27,10 +27,6 @@ public interface SpiTransaction extends Transaction {
|
||||
*/
|
||||
String getLabel();
|
||||
|
||||
/**
|
||||
* Return the string prefix with the transaction id and label used in logging.
|
||||
*/
|
||||
String getLogPrefix();
|
||||
|
||||
/**
|
||||
* Return true if generated SQL and Bind values should be logged to the
|
||||
@@ -47,12 +43,17 @@ public interface SpiTransaction extends Transaction {
|
||||
/**
|
||||
* Log a message to the SQL logger.
|
||||
*/
|
||||
void logSql(String msg);
|
||||
void logSql(String msg, Object... args);
|
||||
|
||||
/**
|
||||
* Log a message to the SUMMARY logger.
|
||||
* Log a summary message to the SUMMARY logger.
|
||||
*/
|
||||
void logSummary(String msg);
|
||||
void logSummary(String msg, Object... args);
|
||||
|
||||
/**
|
||||
* Log a transaction message to the transaction logger.
|
||||
*/
|
||||
void logTxn(String msg, Object... args);
|
||||
|
||||
/**
|
||||
* Register a "Deferred Relationship" that requires an additional update later.
|
||||
|
||||
@@ -137,10 +137,6 @@ public abstract class SpiTransactionProxy implements SpiTransaction {
|
||||
transaction.setDocStoreBatchSize(batchSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLogPrefix() {
|
||||
return transaction.getLogPrefix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLogSql() {
|
||||
@@ -153,13 +149,18 @@ public abstract class SpiTransactionProxy implements SpiTransaction {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logSql(String msg) {
|
||||
transaction.logSql(msg);
|
||||
public void logSql(String msg, Object... args) {
|
||||
transaction.logSql(msg, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logSummary(String msg) {
|
||||
transaction.logSummary(msg);
|
||||
public void logSummary(String msg, Object... args) {
|
||||
transaction.logSummary(msg, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logTxn(String msg, Object... args) {
|
||||
transaction.logTxn(msg, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package io.ebeaninternal.api;
|
||||
|
||||
/**
|
||||
* Per Transaction logging of SQL, TXN and Summary messages.
|
||||
*/
|
||||
public interface SpiTxnLogger {
|
||||
|
||||
String id();
|
||||
|
||||
/**
|
||||
* Is debug logging enabled.
|
||||
*/
|
||||
boolean isLogSql();
|
||||
|
||||
/**
|
||||
* Is summary logging enabled.
|
||||
*/
|
||||
boolean isLogSummary();
|
||||
|
||||
/**
|
||||
* Log a SQL message.
|
||||
*/
|
||||
void sql(String msg, Object... args);
|
||||
|
||||
/**
|
||||
* Log a Summary message.
|
||||
*/
|
||||
void sum(String msg, Object... args);
|
||||
|
||||
/**
|
||||
* Log a Transaction message.
|
||||
*/
|
||||
void txn(String msg, Object... args);
|
||||
|
||||
/**
|
||||
* Transaction Committed.
|
||||
*/
|
||||
void notifyCommit();
|
||||
|
||||
/**
|
||||
* Query only transaction completed.
|
||||
*/
|
||||
void notifyQueryOnly();
|
||||
|
||||
/**
|
||||
* Transaction Rolled back.
|
||||
*/
|
||||
void notifyRollback(Throwable cause);
|
||||
}
|
||||
@@ -34,5 +34,5 @@ public interface SpiJsonReader {
|
||||
|
||||
Object readValueUsingObjectMapper(Class<?> propertyType) throws IOException;
|
||||
|
||||
boolean intercept();
|
||||
boolean update();
|
||||
}
|
||||
|
||||
+17
-17
@@ -91,15 +91,15 @@ public final class CacheChangeSet {
|
||||
/**
|
||||
* Add many property remove.
|
||||
*/
|
||||
public <T> void addManyRemove(BeanDescriptor<T> desc, String manyProperty, Object parentId) {
|
||||
many(desc, manyProperty).addRemove(parentId);
|
||||
public <T> void addManyRemove(BeanDescriptor<T> desc, String manyProperty, String parentKey) {
|
||||
many(desc, manyProperty).addRemove(parentKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add many property put.
|
||||
*/
|
||||
public <T> void addManyPut(BeanDescriptor<T> desc, String manyProperty, Object parentId, CachedManyIds entry) {
|
||||
many(desc, manyProperty).addPut(parentId, entry);
|
||||
public <T> void addManyPut(BeanDescriptor<T> desc, String manyProperty, String parentKey, CachedManyIds entry) {
|
||||
many(desc, manyProperty).addPut(parentKey, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -164,8 +164,8 @@ public final class CacheChangeSet {
|
||||
private static final class ManyChange implements CacheChange {
|
||||
|
||||
final ManyKey key;
|
||||
final Set<Object> removes = new HashSet<>();
|
||||
final Map<Object, CachedManyIds> puts = new LinkedHashMap<>();
|
||||
final Set<String> removes = new HashSet<>();
|
||||
final Map<String, CachedManyIds> puts = new LinkedHashMap<>();
|
||||
boolean clear;
|
||||
|
||||
ManyChange(ManyKey key) {
|
||||
@@ -183,17 +183,17 @@ public final class CacheChangeSet {
|
||||
/**
|
||||
* Remove entry for the given parentId.
|
||||
*/
|
||||
void addRemove(Object parentId) {
|
||||
void addRemove(String parentKey) {
|
||||
if (!clear) {
|
||||
removes.add(parentId);
|
||||
removes.add(parentKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Put entry for the given parentId.
|
||||
*/
|
||||
void addPut(Object parentId, CachedManyIds entry) {
|
||||
puts.put(parentId, entry);
|
||||
void addPut(String parentKey, CachedManyIds entry) {
|
||||
puts.put(parentKey, entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -201,11 +201,11 @@ public final class CacheChangeSet {
|
||||
if (clear) {
|
||||
key.cacheClear();
|
||||
} else {
|
||||
for (Map.Entry<Object, CachedManyIds> entry : puts.entrySet()) {
|
||||
for (Map.Entry<String, CachedManyIds> entry : puts.entrySet()) {
|
||||
key.cachePut(entry.getKey(), entry.getValue());
|
||||
}
|
||||
for (Object parentId : removes) {
|
||||
key.cacheRemove(parentId);
|
||||
for (String parentKey : removes) {
|
||||
key.cacheRemove(parentKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -241,12 +241,12 @@ public final class CacheChangeSet {
|
||||
desc.cacheManyPropClear(manyProperty);
|
||||
}
|
||||
|
||||
void cachePut(Object parentId, CachedManyIds entry) {
|
||||
desc.cacheManyPropPut(manyProperty, parentId, entry);
|
||||
void cachePut(String parentKey, CachedManyIds entry) {
|
||||
desc.cacheManyPropPut(manyProperty, parentKey, entry);
|
||||
}
|
||||
|
||||
void cacheRemove(Object parentId) {
|
||||
desc.cacheManyPropRemove(manyProperty, parentId);
|
||||
void cacheRemove(String parentKey) {
|
||||
desc.cacheManyPropRemove(manyProperty, parentKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -130,7 +130,7 @@ final class DefaultCacheHolder {
|
||||
}
|
||||
|
||||
private ServerCacheOptions getQueryOptions(Class<?> cls) {
|
||||
CacheQueryTuning tuning = AnnotationUtil.get(cls, CacheQueryTuning.class);
|
||||
CacheQueryTuning tuning = AnnotationUtil.typeGet(cls, CacheQueryTuning.class);
|
||||
if (tuning != null) {
|
||||
return new ServerCacheOptions(tuning).applyDefaults(queryDefault);
|
||||
}
|
||||
@@ -138,9 +138,9 @@ final class DefaultCacheHolder {
|
||||
}
|
||||
|
||||
private ServerCacheOptions getBeanOptions(Class<?> cls) {
|
||||
Cache cache = cls.getAnnotation(Cache.class);
|
||||
Cache cache = AnnotationUtil.typeGet(cls, Cache.class);
|
||||
boolean nearCache = (cache != null && cache.nearCache());
|
||||
CacheBeanTuning tuning = cls.getAnnotation(CacheBeanTuning.class);
|
||||
CacheBeanTuning tuning = AnnotationUtil.typeGet(cls, CacheBeanTuning.class);
|
||||
if (tuning != null) {
|
||||
return new ServerCacheOptions(nearCache, tuning).applyDefaults(beanDefault);
|
||||
}
|
||||
|
||||
+24
-1
@@ -44,7 +44,10 @@ public class DefaultServerCache implements ServerCache {
|
||||
protected final CountMetric removeCount;
|
||||
protected final CountMetric clearCount;
|
||||
protected final CountMetric evictCount;
|
||||
|
||||
protected final CountMetric gcCount;
|
||||
protected final CountMetric idleCount;
|
||||
protected final CountMetric ttlCount;
|
||||
protected final CountMetric lruCount;
|
||||
protected final String name;
|
||||
protected final String shortName;
|
||||
protected final int maxSize;
|
||||
@@ -55,6 +58,7 @@ public class DefaultServerCache implements ServerCache {
|
||||
protected final ReentrantLock lock = new ReentrantLock();
|
||||
protected final AtomicLong mutationCounter = new AtomicLong();
|
||||
|
||||
|
||||
public DefaultServerCache(DefaultServerCacheConfig config) {
|
||||
this.name = config.getName();
|
||||
this.shortName = config.getShortName();
|
||||
@@ -73,6 +77,11 @@ public class DefaultServerCache implements ServerCache {
|
||||
this.removeCount = factory.createCountMetric(prefix + shortName + ".remove");
|
||||
this.clearCount = factory.createCountMetric(prefix + shortName + ".clear");
|
||||
this.evictCount = factory.createCountMetric(prefix + shortName + ".evict");
|
||||
this.gcCount = factory.createCountMetric(prefix + shortName + ".gc");
|
||||
this.idleCount = factory.createCountMetric(prefix + shortName + ".idle");
|
||||
this.ttlCount = factory.createCountMetric(prefix + shortName + ".ttl");
|
||||
this.lruCount = factory.createCountMetric(prefix + shortName + ".lru");
|
||||
|
||||
}
|
||||
|
||||
public void periodicTrim(BackgroundExecutor executor) {
|
||||
@@ -90,6 +99,10 @@ public class DefaultServerCache implements ServerCache {
|
||||
removeCount.visit(visitor);
|
||||
clearCount.visit(visitor);
|
||||
evictCount.visit(visitor);
|
||||
gcCount.visit(visitor);
|
||||
idleCount.visit(visitor);
|
||||
ttlCount.visit(visitor);
|
||||
lruCount.visit(visitor);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -104,6 +117,10 @@ public class DefaultServerCache implements ServerCache {
|
||||
cacheStats.setRemoveCount(removeCount.get(reset));
|
||||
cacheStats.setClearCount(clearCount.get(reset));
|
||||
cacheStats.setEvictCount(evictCount.get(reset));
|
||||
cacheStats.setGcCount(gcCount.get(reset));
|
||||
cacheStats.setIdleCount(idleCount.get(reset));
|
||||
cacheStats.setTtlCount(ttlCount.get(reset));
|
||||
cacheStats.setLruCount(lruCount.get(reset));
|
||||
return cacheStats;
|
||||
}
|
||||
|
||||
@@ -289,6 +306,12 @@ public class DefaultServerCache implements ServerCache {
|
||||
evictCount.add(trimmedByGC);
|
||||
evictCount.add(trimmedByTTL);
|
||||
evictCount.add(trimmedByLRU);
|
||||
|
||||
gcCount.add(trimmedByGC);
|
||||
idleCount.add(trimmedByIdle);
|
||||
ttlCount.add(trimmedByTTL);
|
||||
lruCount.add(trimmedByLRU);
|
||||
|
||||
if (logger.isLoggable(TRACE)) {
|
||||
long exeMicros = TimeUnit.MICROSECONDS.convert(System.nanoTime() - startNanos, TimeUnit.NANOSECONDS);
|
||||
logger.log(TRACE, "Executed trim of cache {0} in [{1}]millis idle[{2}] timeToLive[{3}] accessTime[{4}] gc[{5}]",
|
||||
|
||||
@@ -4,7 +4,6 @@ import io.ebean.CancelableQuery;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.util.JdbcClose;
|
||||
import io.ebeaninternal.api.*;
|
||||
import io.ebeaninternal.server.util.Str;
|
||||
import io.ebeaninternal.server.persist.Binder;
|
||||
import io.ebeaninternal.server.persist.TrimLogSql;
|
||||
import io.ebeaninternal.server.util.BindParamsParser;
|
||||
@@ -151,7 +150,7 @@ public abstract class AbstractSqlQueryRequest implements CancelableQuery {
|
||||
}
|
||||
if (isLogSql()) {
|
||||
long micros = (System.nanoTime() - startNano) / 1000L;
|
||||
transaction.logSql(Str.add(TrimLogSql.trim(sql), "; --bind(", bindLog, ") --micros(", micros + ")"));
|
||||
transaction.logSql("{0}; --bind({1}) --micros({2})", TrimLogSql.trim(sql), bindLog, micros);
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
|
||||
@@ -14,10 +14,12 @@ import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import io.ebeaninternal.server.transaction.DefaultPersistenceContext;
|
||||
|
||||
import javax.persistence.EntityNotFoundException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.lang.System.Logger.Level.DEBUG;
|
||||
import static java.lang.System.Logger.Level.ERROR;
|
||||
|
||||
/**
|
||||
* Helper to handle lazy loading and refreshing of beans.
|
||||
@@ -72,7 +74,8 @@ final class DefaultBeanLoader {
|
||||
if (ebi.isReadOnly()) {
|
||||
readOnly = Boolean.TRUE;
|
||||
}
|
||||
if (parentDesc.cacheManyPropLoad(many, beanCollection, parentId, readOnly)) {
|
||||
final String parentKey = parentDesc.cacheKey(parentId);
|
||||
if (parentDesc.cacheManyPropLoad(many, beanCollection, parentKey, readOnly)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -113,7 +116,8 @@ final class DefaultBeanLoader {
|
||||
log.log(DEBUG, "BeanCollection after load was empty. Owner:{0}", beanCollection.getOwnerBean());
|
||||
}
|
||||
} else if (useManyIdCache) {
|
||||
parentDesc.cacheManyPropPut(many, beanCollection, parentId);
|
||||
final String parentKey = parentDesc.cacheKey(parentId);
|
||||
parentDesc.cacheManyPropPut(many, beanCollection, parentKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -122,21 +126,28 @@ final class DefaultBeanLoader {
|
||||
* Load a batch of beans for +query or +lazy loading.
|
||||
*/
|
||||
void loadBean(LoadBeanRequest loadRequest) {
|
||||
Set<EntityBeanIntercept> batch = loadRequest.batch();
|
||||
final Set<EntityBeanIntercept> batch = loadRequest.batch();
|
||||
if (batch.isEmpty()) {
|
||||
throw new RuntimeException("Nothing in batch?");
|
||||
}
|
||||
|
||||
List<Object> idList = loadRequest.getIdList();
|
||||
if (idList.isEmpty()) {
|
||||
// everything was loaded from cache
|
||||
final List<Object> ids = loadRequest.ids();
|
||||
if (ids.isEmpty()) {
|
||||
// this should never happen given the batch is not empty
|
||||
CoreLog.internal.log(ERROR, "No Ids when loading Batch buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
SpiQuery<?> query = server.createQuery(loadRequest.beanType());
|
||||
loadRequest.configureQuery(query, idList);
|
||||
List<?> list = executeQuery(loadRequest, query);
|
||||
loadRequest.postLoad(list);
|
||||
final SpiQuery<?> query = server.createQuery(loadRequest.beanType());
|
||||
loadRequest.configureQuery(query, ids);
|
||||
final List<?> list = executeQuery(loadRequest, query);
|
||||
final LoadBeanRequest.Result result = loadRequest.postLoad(list);
|
||||
if (result.markedDeleted() && CoreLog.markedAsDeleted.isLoggable(DEBUG)) {
|
||||
CoreLog.markedAsDeleted.log(DEBUG, "Loaded bean batch {0}", batch);
|
||||
String msg = MessageFormat.format("Loaded bean marked as deleted for {0} ids:{1} missedIds:{2} loadedIds:{3} sql:{4} loadedList:{5} missed:{6}",
|
||||
loadRequest.beanType(), ids, result.missedIds(), result.loadedIds(), query.getGeneratedSql(), list, result.missed());
|
||||
CoreLog.markedAsDeleted.log(DEBUG, msg, new RuntimeException("LoadBeanRequest markedAsDeleted"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+13
-52
@@ -2,17 +2,17 @@ package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebean.bean.CallOrigin;
|
||||
import io.ebean.bean.CallStack;
|
||||
import io.ebean.util.StackWalkFilter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Default CallStackFactory where the Hash function for StackTraceElement includes the line number.
|
||||
*/
|
||||
public final class DefaultCallOriginFactory implements CallOriginFactory {
|
||||
|
||||
private static final int IGNORE_LEADING_ELEMENTS = 5;
|
||||
|
||||
private static final String IO_EBEAN = "io.ebean";
|
||||
final class DefaultCallOriginFactory implements CallOriginFactory {
|
||||
|
||||
private final int maxCallStack;
|
||||
|
||||
@@ -22,57 +22,18 @@ public final class DefaultCallOriginFactory implements CallOriginFactory {
|
||||
|
||||
@Override
|
||||
public CallOrigin createCallOrigin() {
|
||||
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
|
||||
|
||||
// ignore the first 6 as they are always avaje stack elements
|
||||
int startIndex = IGNORE_LEADING_ELEMENTS;
|
||||
|
||||
// find the first non-avaje stackElement
|
||||
for (; startIndex < stackTrace.length; startIndex++) {
|
||||
if (!ignore(stackTrace[startIndex])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int stackLength = stackTrace.length - startIndex;
|
||||
if (stackLength > maxCallStack) {
|
||||
// maximum of maxCallStack stackTrace elements
|
||||
stackLength = maxCallStack;
|
||||
}
|
||||
|
||||
// create the 'interesting' part of the stackTrace
|
||||
StackTraceElement[] finalTrace = new StackTraceElement[stackLength];
|
||||
System.arraycopy(stackTrace, startIndex, finalTrace, 0, stackLength);
|
||||
|
||||
if (stackLength < 1) {
|
||||
final var frames = StackWalker.getInstance().walk(this::filter);
|
||||
if (frames.isEmpty()) {
|
||||
// this should not really happen
|
||||
throw new RuntimeException("StackTraceElement size 0? stack: " + Arrays.toString(stackTrace));
|
||||
throw new RuntimeException("stackFrames filtered to empty for stack: " + Arrays.toString(Thread.currentThread().getStackTrace()));
|
||||
}
|
||||
|
||||
return createCallStack(finalTrace);
|
||||
return new CallStack(frames);
|
||||
}
|
||||
|
||||
private boolean ignore(StackTraceElement element) {
|
||||
if (element.getClassName().startsWith(IO_EBEAN)) {
|
||||
return true;
|
||||
}
|
||||
return element.getMethodName().startsWith("_ebean_");
|
||||
}
|
||||
|
||||
private CallOrigin createCallStack(StackTraceElement[] finalTrace) {
|
||||
return new CallStack(finalTrace, finalTrace[0].hashCode(), pathHash(finalTrace));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the hash code for the path excluding the first element.
|
||||
*/
|
||||
private int pathHash(StackTraceElement[] callStack) {
|
||||
|
||||
int hc = 0;
|
||||
for (int i = 1; i < callStack.length; i++) {
|
||||
hc = 92821 * hc + callStack[i].hashCode();
|
||||
}
|
||||
return hc;
|
||||
private <T> List<StackWalker.StackFrame> filter(Stream<StackWalker.StackFrame> frames) {
|
||||
return frames.filter(StackWalkFilter.filter())
|
||||
.limit(maxCallStack)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ import javax.persistence.PersistenceException;
|
||||
import java.net.URL;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import static java.lang.System.Logger.Level.*;
|
||||
@@ -121,7 +121,7 @@ public final class DefaultContainer implements SpiContainer {
|
||||
configProvider.apply(config);
|
||||
}
|
||||
}
|
||||
if (config.isAutoLoadModuleInfo()) {
|
||||
if (config.isLoadModuleInfo()) {
|
||||
// auto register entity classes
|
||||
boolean found = false;
|
||||
for (EntityClassRegister loader : ServiceLoader.load(EntityClassRegister.class)) {
|
||||
@@ -160,6 +160,8 @@ public final class DefaultContainer implements SpiContainer {
|
||||
*/
|
||||
private BootupClasses bootupClasses(DatabaseConfig config) {
|
||||
BootupClasses bootup = bootupClasses1(config);
|
||||
bootup.addServerConfigStartup(config.getServerConfigStartupListeners());
|
||||
bootup.runServerConfigStartup(config);
|
||||
bootup.addIdGenerators(config.getIdGenerators());
|
||||
bootup.addPersistControllers(config.getPersistControllers());
|
||||
bootup.addPostLoaders(config.getPostLoaders());
|
||||
@@ -167,9 +169,7 @@ public final class DefaultContainer implements SpiContainer {
|
||||
bootup.addFindControllers(config.getFindControllers());
|
||||
bootup.addPersistListeners(config.getPersistListeners());
|
||||
bootup.addQueryAdapters(config.getQueryAdapters());
|
||||
bootup.addServerConfigStartup(config.getServerConfigStartupListeners());
|
||||
bootup.addChangeLogInstances(config);
|
||||
bootup.runServerConfigStartup(config);
|
||||
return bootup;
|
||||
}
|
||||
|
||||
@@ -177,10 +177,10 @@ public final class DefaultContainer implements SpiContainer {
|
||||
* Get the class based entities, scalarTypes, Listeners etc.
|
||||
*/
|
||||
private BootupClasses bootupClasses1(DatabaseConfig config) {
|
||||
List<Class<?>> entityClasses = config.getClasses();
|
||||
if (config.isDisableClasspathSearch() || (entityClasses != null && !entityClasses.isEmpty())) {
|
||||
Set<Class<?>> classes = config.classes();
|
||||
if (config.isDisableClasspathSearch() || (classes != null && !classes.isEmpty())) {
|
||||
// use classes we explicitly added via configuration
|
||||
return new BootupClasses(entityClasses);
|
||||
return new BootupClasses(classes);
|
||||
}
|
||||
return BootupClassPathSearch.search(config);
|
||||
}
|
||||
|
||||
@@ -962,13 +962,15 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
if (transaction == null) {
|
||||
transaction = currentServerTransaction();
|
||||
}
|
||||
query.setDefaultRawSqlIfRequired();
|
||||
if (query.isAutoTunable() && !autoTuneService.tuneQuery(query)) {
|
||||
// use deployment FetchType.LAZY/EAGER annotations
|
||||
// to define the 'default' select clause
|
||||
query.setDefaultSelectClause();
|
||||
if (!query.isRawSql()) {
|
||||
query.setDefaultRawSqlIfRequired();
|
||||
if (query.isAutoTunable() && !autoTuneService.tuneQuery(query)) {
|
||||
// use deployment FetchType.LAZY/EAGER annotations
|
||||
// to define the 'default' select clause
|
||||
query.setDefaultSelectClause();
|
||||
}
|
||||
query.selectAllForLazyLoadProperty();
|
||||
}
|
||||
query.selectAllForLazyLoadProperty();
|
||||
ProfileLocation profileLocation = query.getProfileLocation();
|
||||
if (profileLocation != null) {
|
||||
profileLocation.obtain();
|
||||
@@ -1091,7 +1093,13 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public <T> Set<T> findSet(Query<T> query, Transaction transaction) {
|
||||
SpiOrmQueryRequest request = createQueryRequest(Type.SET, query, transaction);
|
||||
SpiOrmQueryRequest request = buildQueryRequest(Type.SET, query, transaction);
|
||||
request.resetBeanCacheAutoMode(false);
|
||||
if ((transaction == null || !transaction.isSkipCache()) && request.getFromBeanCache()) {
|
||||
// hit bean cache and got all results from cache
|
||||
return request.beanCacheHitsAsSet();
|
||||
}
|
||||
request.prepareQuery();
|
||||
Object result = request.getFromQueryCache();
|
||||
if (result != null) {
|
||||
return (Set<T>) result;
|
||||
@@ -1107,12 +1115,13 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public <K, T> Map<K, T> findMap(Query<T> query, @Nullable Transaction transaction) {
|
||||
SpiOrmQueryRequest request = createQueryRequest(Type.MAP, query, transaction);
|
||||
SpiOrmQueryRequest request = buildQueryRequest(Type.MAP, query, transaction);
|
||||
request.resetBeanCacheAutoMode(false);
|
||||
if ((transaction == null || !transaction.isSkipCache()) && request.getFromBeanCache()) {
|
||||
// hit bean cache and got all results from cache
|
||||
return request.beanCacheHitsAsMap();
|
||||
}
|
||||
request.prepareQuery();
|
||||
Object result = request.getFromQueryCache();
|
||||
if (result != null) {
|
||||
return (Map<K, T>) result;
|
||||
|
||||
@@ -10,7 +10,7 @@ final class NoopCallOriginFactory implements CallOriginFactory {
|
||||
|
||||
private static final StackTraceElement E0 = new StackTraceElement("none", "none", "none", 0);
|
||||
|
||||
private final CallOrigin COMMON = new CallStack(new StackTraceElement[]{E0}, 0, 0);
|
||||
private final CallOrigin COMMON = new CallStack(new Object[]{E0}, 0, 0);
|
||||
|
||||
@Override
|
||||
public CallOrigin createCallOrigin() {
|
||||
|
||||
@@ -229,6 +229,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
persistenceContext.beginIterate();
|
||||
}
|
||||
loadContext = new DLoadContext(this, secondaryQueries);
|
||||
loadContext.useReferences(Type.ITERATE == query.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -515,12 +516,12 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
if (query.getType() == Type.MAP) {
|
||||
mergeCacheHitsToMap(result);
|
||||
} else {
|
||||
mergeCacheHitsToList(result);
|
||||
mergeCacheHitsToCollection(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void mergeCacheHitsToList(BeanCollection<T> result) {
|
||||
private void mergeCacheHitsToCollection(BeanCollection<T> result) {
|
||||
for (T hit : cacheBeans) {
|
||||
result.internalAdd(hit);
|
||||
}
|
||||
@@ -579,6 +580,15 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
return property;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<T> beanCacheHitsAsSet() {
|
||||
OrderBy<T> orderBy = query.getOrderBy();
|
||||
if (orderBy != null && !orderBy.isEmpty()) {
|
||||
beanDescriptor.sort(cacheBeans, orderBy.toStringFormat());
|
||||
}
|
||||
return new LinkedHashSet<>(cacheBeans);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getFromBeanCache() {
|
||||
if (!query.isBeanCacheGet()) {
|
||||
@@ -691,8 +701,8 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
/**
|
||||
* Log the SQL if the logLevel is appropriate.
|
||||
*/
|
||||
public void logSql(String sql) {
|
||||
transaction.logSql(sql);
|
||||
public void logSql(String msg, Object... args) {
|
||||
transaction.logSql(msg, args);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -928,20 +928,20 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
}
|
||||
|
||||
private void logSummaryMessage() {
|
||||
String draft = (beanDescriptor.isDraftable() && !publish) ? "] draft[true]" : "]";
|
||||
String draft = (beanDescriptor.isDraftable() && !publish) ? " draft[true]" : "";
|
||||
String name = beanDescriptor.name();
|
||||
switch (type) {
|
||||
case INSERT:
|
||||
transaction.logSummary("Inserted [" + name + "] [" + (idValue == null ? "" : idValue) + draft);
|
||||
transaction.logSummary("Inserted [{0}] [{1}]{2}", name, (idValue == null ? "" : idValue), draft);
|
||||
break;
|
||||
case UPDATE:
|
||||
transaction.logSummary("Updated [" + name + "] [" + idValue + draft);
|
||||
transaction.logSummary("Updated [{0}] [{1}]{2}", name, idValue , draft);
|
||||
break;
|
||||
case DELETE:
|
||||
transaction.logSummary("Deleted [" + name + "] [" + idValue + draft);
|
||||
transaction.logSummary("Deleted [{0}] [{1}]{2}", name, idValue , draft);
|
||||
break;
|
||||
case DELETE_SOFT:
|
||||
transaction.logSummary("SoftDelete [" + name + "] [" + idValue + draft);
|
||||
transaction.logSummary("SoftDelete [{0}] [{1}]{2}", name, idValue , draft);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
+2
-6
@@ -1,12 +1,8 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebean.CallableSql;
|
||||
import io.ebeaninternal.api.BindParams;
|
||||
import io.ebeaninternal.api.*;
|
||||
import io.ebeaninternal.api.BindParams.Param;
|
||||
import io.ebeaninternal.api.SpiCallableSql;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.api.SpiTransaction;
|
||||
import io.ebeaninternal.api.TransactionEventTable;
|
||||
import io.ebeaninternal.server.persist.PersistExecute;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
@@ -86,7 +82,7 @@ public final class PersistRequestCallableSql extends PersistRequest {
|
||||
persistExecute.collectSqlCall(label, startNanos);
|
||||
}
|
||||
if (transaction.isLogSummary()) {
|
||||
transaction.logSummary("CallableSql label[" + callableSql.getLabel() + "]" + " rows[" + rowCount + "]" + " bind[" + bindLog + "]");
|
||||
transaction.logSummary("CallableSql label[{0}] rows[{1}] bind[{2}]", callableSql.getLabel(), rowCount, bindLog);
|
||||
}
|
||||
|
||||
// register table modifications with the transaction event
|
||||
|
||||
@@ -83,7 +83,7 @@ public final class PersistRequestOrmUpdate extends PersistRequest {
|
||||
OrmUpdateType ormUpdateType = ormUpdate.getOrmUpdateType();
|
||||
String tableName = ormUpdate.getBaseTable();
|
||||
if (transaction.isLogSummary()) {
|
||||
transaction.logSummary(ormUpdateType + " table[" + tableName + "] rows[" + rowCount + "] bind[" + bindLog + "]");
|
||||
transaction.logSummary("{0} table[{1}] rows[{2}] bind[{3}]", ormUpdateType, tableName, rowCount, bindLog);
|
||||
}
|
||||
if (ormUpdate.isNotifyCache()) {
|
||||
// add the modification info to the TransactionEvent
|
||||
|
||||
@@ -3,7 +3,6 @@ package io.ebeaninternal.server.core;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.api.SpiSqlUpdate;
|
||||
import io.ebeaninternal.api.SpiTransaction;
|
||||
import io.ebeaninternal.server.util.Str;
|
||||
import io.ebeaninternal.server.persist.BatchControl;
|
||||
import io.ebeaninternal.server.persist.PersistExecute;
|
||||
import io.ebeaninternal.server.persist.TrimLogSql;
|
||||
@@ -148,7 +147,7 @@ public final class PersistRequestUpdateSql extends PersistRequest {
|
||||
*/
|
||||
public void logSqlBatchBind() {
|
||||
if (transaction.isLogSql()) {
|
||||
transaction.logSql(Str.add(" -- bind(", bindLog, ")"));
|
||||
transaction.logSql(" -- bind({0})", bindLog);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +160,7 @@ public final class PersistRequestUpdateSql extends PersistRequest {
|
||||
persistExecute.collectSqlUpdate(label, startNanos);
|
||||
}
|
||||
if (transaction.isLogSql() && !batchThisRequest) {
|
||||
transaction.logSql(Str.add(TrimLogSql.trim(updateSql.getGeneratedSql()), "; -- bind(", bindLog, ") rows(", String.valueOf(rowCount), ")"));
|
||||
transaction.logSql("{0}; -- bind({1}) rows({2})", TrimLogSql.trim(updateSql.getGeneratedSql()), bindLog, rowCount);
|
||||
}
|
||||
if (updateSql.isAutoTableMod()) {
|
||||
// add the modification info to the TransactionEvent
|
||||
|
||||
@@ -123,7 +123,7 @@ public final class RelationalQueryRequest extends AbstractSqlQueryRequest {
|
||||
public void logSummary() {
|
||||
if (transaction.isLogSummary()) {
|
||||
long micros = (System.nanoTime() - startNano) / 1000L;
|
||||
transaction.logSummary("SqlQuery rows[" + rows + "] micros[" + micros + "] bind[" + bindLog + "]");
|
||||
transaction.logSummary("SqlQuery rows[{0}] micros[{1}] bind[{2}]", rows, micros, bindLog);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -153,6 +153,11 @@ public interface SpiOrmQueryRequest<T> extends BeanQueryRequest<T>, DocQueryRequ
|
||||
*/
|
||||
<K> Map<K,T> beanCacheHitsAsMap();
|
||||
|
||||
/**
|
||||
* Return the bean cache hits for findMap (when all hits / no misses).
|
||||
*/
|
||||
Set<T> beanCacheHitsAsSet();
|
||||
|
||||
/**
|
||||
* Reset Bean cache mode AUTO - require explicit setting for bean cache use with findList().
|
||||
*/
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static java.lang.System.Logger.Level.DEBUG;
|
||||
@@ -79,9 +80,9 @@ public class BootupClasses implements Predicate<Class<?>> {
|
||||
public BootupClasses() {
|
||||
}
|
||||
|
||||
public BootupClasses(List<Class<?>> list) {
|
||||
if (list != null) {
|
||||
for (Class<?> cls : list) {
|
||||
public BootupClasses(Set<Class<?>> classes) {
|
||||
if (classes != null) {
|
||||
for (Class<?> cls : classes) {
|
||||
test(cls);
|
||||
}
|
||||
}
|
||||
@@ -342,8 +343,9 @@ public class BootupClasses implements Predicate<Class<?>> {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private boolean isInterestingInterface(Class<?> cls) {
|
||||
if (Modifier.isAbstract(cls.getModifiers())) {
|
||||
// do not include abstract classes as we can
|
||||
if (Modifier.isAbstract(cls.getModifiers())
|
||||
|| !(Modifier.isPublic(cls.getModifiers()) || Modifier.isProtected(cls.getModifiers()))) {
|
||||
// do not include abstract and non pupbic/protected classes as we can
|
||||
// not instantiate them
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -38,13 +38,10 @@ public final class BeanCollectionUtil {
|
||||
// returns a collection of beans
|
||||
return bc.getActualEntries();
|
||||
}
|
||||
|
||||
if (o instanceof Map<?, ?>) {
|
||||
// yes, we want the entrySet (to set the keys)
|
||||
return ((Map<?, ?>) o).entrySet();
|
||||
|
||||
} else if (o instanceof Collection<?>) {
|
||||
if (o instanceof Collection<?>) {
|
||||
return ((Collection<?>) o);
|
||||
} else if (o instanceof Map<?, ?>) {
|
||||
return ((Map<?, ?>) o).entrySet();
|
||||
}
|
||||
throw new PersistenceException("expecting a Map or Collection but got " + o.getClass().getName());
|
||||
}
|
||||
|
||||
@@ -1202,26 +1202,26 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
/**
|
||||
* Try to load the beanCollection from cache return true if successful.
|
||||
*/
|
||||
public boolean cacheManyPropLoad(BeanPropertyAssocMany<?> many, BeanCollection<?> bc, Object parentId, Boolean readOnly) {
|
||||
return cacheHelp.manyPropLoad(many, bc, parentId, readOnly);
|
||||
public boolean cacheManyPropLoad(BeanPropertyAssocMany<?> many, BeanCollection<?> bc, String parentKey, Boolean readOnly) {
|
||||
return cacheHelp.manyPropLoad(many, bc, parentKey, readOnly);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put the beanCollection into the cache.
|
||||
*/
|
||||
public void cacheManyPropPut(BeanPropertyAssocMany<?> many, BeanCollection<?> bc, Object parentId) {
|
||||
cacheHelp.manyPropPut(many, bc, parentId);
|
||||
public void cacheManyPropPut(BeanPropertyAssocMany<?> many, BeanCollection<?> bc, String parentKey) {
|
||||
cacheHelp.manyPropPut(many, bc, parentKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the bean collection entry in the cache.
|
||||
*/
|
||||
public void cacheManyPropPut(String name, Object parentId, CachedManyIds entry) {
|
||||
cacheHelp.cachePutManyIds(parentId, name, entry);
|
||||
public void cacheManyPropPut(String name, String parentKey, CachedManyIds entry) {
|
||||
cacheHelp.cachePutManyIds(name, parentKey, entry);
|
||||
}
|
||||
|
||||
public void cacheManyPropRemove(String propertyName, Object parentId) {
|
||||
cacheHelp.manyPropRemove(propertyName, parentId);
|
||||
public void cacheManyPropRemove(String propertyName, String parentKey) {
|
||||
cacheHelp.manyPropRemove(propertyName, parentKey);
|
||||
}
|
||||
|
||||
public void cacheManyPropClear(String propertyName) {
|
||||
@@ -2096,7 +2096,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
/**
|
||||
* Return the cache key for the given bean (based on id value).
|
||||
*/
|
||||
String cacheKeyForBean(EntityBean bean) {
|
||||
public String cacheKeyForBean(EntityBean bean) {
|
||||
return cacheKey(idProperty.getValue(bean));
|
||||
}
|
||||
|
||||
@@ -2112,11 +2112,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
return getId((EntityBean) bean);
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public Object beanId(T bean) {
|
||||
// return getId((EntityBean) bean);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Return the Id value for the bean with embeddedId beans converted into maps.
|
||||
* <p>
|
||||
|
||||
+19
-19
@@ -226,13 +226,12 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
queryCache.put(id, entry);
|
||||
}
|
||||
|
||||
|
||||
void manyPropRemove(String propertyName, Object parentId) {
|
||||
void manyPropRemove(String propertyName, String parentKey) {
|
||||
ServerCache collectionIdsCache = cacheManager.getCollectionIdsCache(beanType, propertyName);
|
||||
if (manyLog.isLoggable(TRACE)) {
|
||||
manyLog.log(TRACE, " REMOVE {0}({1}).{2}", cacheName, parentId, propertyName);
|
||||
manyLog.log(TRACE, " REMOVE {0}({1}).{2}", cacheName, parentKey, propertyName);
|
||||
}
|
||||
collectionIdsCache.remove(parentId);
|
||||
collectionIdsCache.remove(parentKey);
|
||||
}
|
||||
|
||||
void manyPropClear(String propertyName) {
|
||||
@@ -246,15 +245,15 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
/**
|
||||
* Return the CachedManyIds for a given bean many property. Returns null if not in the cache.
|
||||
*/
|
||||
private CachedManyIds manyPropGet(Object parentId, String propertyName) {
|
||||
private CachedManyIds manyPropGet(String propertyName, String parentKey) {
|
||||
ServerCache collectionIdsCache = cacheManager.getCollectionIdsCache(beanType, propertyName);
|
||||
CachedManyIds entry = (CachedManyIds) collectionIdsCache.get(parentId);
|
||||
CachedManyIds entry = (CachedManyIds) collectionIdsCache.get(parentKey);
|
||||
if (entry == null) {
|
||||
if (manyLog.isLoggable(TRACE)) {
|
||||
manyLog.log(TRACE, " GET {0}({1}).{2} - cache miss", cacheName, parentId, propertyName);
|
||||
manyLog.log(TRACE, " GET {0}({1}).{2} - cache miss", cacheName, parentKey, propertyName);
|
||||
}
|
||||
} else if (manyLog.isLoggable(DEBUG)) {
|
||||
manyLog.log(DEBUG, " GET {0}({1}).{2} - hit", cacheName, parentId, propertyName);
|
||||
manyLog.log(DEBUG, " GET {0}({1}).{2} - hit", cacheName, parentKey, propertyName);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
@@ -262,12 +261,12 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
/**
|
||||
* Try to load the bean collection from cache return true if successful.
|
||||
*/
|
||||
boolean manyPropLoad(BeanPropertyAssocMany<?> many, BeanCollection<?> bc, Object parentId, Boolean readOnly) {
|
||||
boolean manyPropLoad(BeanPropertyAssocMany<?> many, BeanCollection<?> bc, String parentKey, Boolean readOnly) {
|
||||
if (many.isElementCollection()) {
|
||||
// held as part of the bean cache so skip
|
||||
return false;
|
||||
}
|
||||
CachedManyIds entry = manyPropGet(parentId, many.name());
|
||||
CachedManyIds entry = manyPropGet(many.name(), parentKey);
|
||||
if (entry == null) {
|
||||
// not in cache so return unsuccessful
|
||||
return false;
|
||||
@@ -293,9 +292,9 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
/**
|
||||
* Put the beanCollection into the cache.
|
||||
*/
|
||||
void manyPropPut(BeanPropertyAssocMany<?> many, Object details, Object parentId) {
|
||||
void manyPropPut(BeanPropertyAssocMany<?> many, Object details, String parentKey) {
|
||||
if (many.isElementCollection()) {
|
||||
CachedBeanData data = (CachedBeanData) beanCache.get(parentId);
|
||||
CachedBeanData data = (CachedBeanData) beanCache.get(parentKey);
|
||||
if (data != null) {
|
||||
try {
|
||||
// add as JSON to bean cache
|
||||
@@ -305,9 +304,9 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
|
||||
CachedBeanData newData = data.update(changes, data.getVersion());
|
||||
if (beanLog.isLoggable(DEBUG)) {
|
||||
beanLog.log(DEBUG, " UPDATE {0}({1}) changes:{2}", cacheName, parentId, changes);
|
||||
beanLog.log(DEBUG, " UPDATE {0}({1}) changes:{2}", cacheName, parentKey, changes);
|
||||
}
|
||||
beanCache.put(parentId, newData);
|
||||
beanCache.put(parentKey, newData);
|
||||
} catch (IOException e) {
|
||||
log.log(ERROR, "Error updating L2 cache", e);
|
||||
}
|
||||
@@ -315,17 +314,17 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
} else {
|
||||
CachedManyIds entry = createManyIds(many, details);
|
||||
if (entry != null) {
|
||||
cachePutManyIds(parentId, many.name(), entry);
|
||||
cachePutManyIds(many.name(), parentKey, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cachePutManyIds(Object parentId, String manyName, CachedManyIds entry) {
|
||||
void cachePutManyIds(String manyName, String parentKey, CachedManyIds entry) {
|
||||
ServerCache collectionIdsCache = cacheManager.getCollectionIdsCache(beanType, manyName);
|
||||
if (manyLog.isLoggable(DEBUG)) {
|
||||
manyLog.log(DEBUG, " PUT {0}({1}).{2} - ids:{3}", cacheName, parentId, manyName, entry);
|
||||
manyLog.log(DEBUG, " PUT {0}({1}).{2} - ids:{3}", cacheName, parentKey, manyName, entry);
|
||||
}
|
||||
collectionIdsCache.put(parentId, entry);
|
||||
collectionIdsCache.put(parentKey, entry);
|
||||
}
|
||||
|
||||
private CachedManyIds createManyIds(BeanPropertyAssocMany<?> many, Object details) {
|
||||
@@ -828,7 +827,8 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
Object details = many.getValue(updateRequest.entityBean());
|
||||
CachedManyIds entry = createManyIds(many, details);
|
||||
if (entry != null) {
|
||||
changeSet.addManyPut(desc, many.name(), id, entry);
|
||||
final String parentKey = desc.cacheKey(id);
|
||||
changeSet.addManyPut(desc, many.name(), parentKey, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +133,12 @@ final class BeanDescriptorJsonHelp<T> {
|
||||
String key = parser.getCurrentName();
|
||||
BeanProperty p = desc.beanProperty(key);
|
||||
if (p != null) {
|
||||
p.jsonRead(readJson, bean);
|
||||
if (p.isVersion() && readJson.update() ) {
|
||||
// skip version prop during update
|
||||
p.jsonRead(readJson);
|
||||
} else {
|
||||
p.jsonRead(readJson, bean);
|
||||
}
|
||||
} else {
|
||||
// read an unmapped property
|
||||
if (unmappedProperties == null) {
|
||||
|
||||
@@ -20,9 +20,9 @@ import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
import io.ebeaninternal.api.json.SpiJsonReader;
|
||||
import io.ebeaninternal.api.json.SpiJsonWriter;
|
||||
import io.ebeaninternal.server.bind.DataBind;
|
||||
import io.ebeaninternal.server.core.EncryptAlias;
|
||||
import io.ebeaninternal.server.core.InternString;
|
||||
import io.ebeaninternal.server.bind.DataBind;
|
||||
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedProperty;
|
||||
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedWhenCreated;
|
||||
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedWhenModified;
|
||||
@@ -65,7 +65,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
/**
|
||||
* Flag to mark this is the id property.
|
||||
*/
|
||||
private final boolean id;
|
||||
protected final boolean id;
|
||||
private final boolean importedPrimaryKey;
|
||||
/**
|
||||
* Flag to make this as a dummy property for unidirecitonal relationships.
|
||||
@@ -1408,15 +1408,20 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
}
|
||||
|
||||
public void jsonRead(SpiJsonReader ctx, EntityBean bean) throws IOException {
|
||||
Object objValue = jsonRead(ctx);
|
||||
if (jsonDeserialize) {
|
||||
if (ctx.update()) {
|
||||
setValueIntercept(bean, objValue);
|
||||
} else {
|
||||
setValue(bean, objValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Object jsonRead(SpiJsonReader ctx) throws IOException {
|
||||
JsonToken event = ctx.nextToken();
|
||||
if (JsonToken.VALUE_NULL == event) {
|
||||
if (jsonDeserialize) {
|
||||
if (ctx.intercept()) {
|
||||
setValueIntercept(bean, null);
|
||||
} else {
|
||||
setValue(bean, null);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
// expect to read non-null json value
|
||||
Object objValue;
|
||||
@@ -1433,13 +1438,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
CoreLog.log.log(ERROR, msg, e);
|
||||
}
|
||||
}
|
||||
if (jsonDeserialize) {
|
||||
if (ctx.intercept()) {
|
||||
setValueIntercept(bean, objValue);
|
||||
} else {
|
||||
setValue(bean, objValue);
|
||||
}
|
||||
}
|
||||
return objValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ package io.ebeaninternal.server.deploy;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import io.ebean.SqlUpdate;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.bean.BeanCollection;
|
||||
@@ -27,6 +29,7 @@ import java.io.StringWriter;
|
||||
import java.util.*;
|
||||
|
||||
import static java.lang.System.Logger.Level.ERROR;
|
||||
import static java.lang.System.Logger.Level.WARNING;
|
||||
|
||||
/**
|
||||
* Property mapped to a List Set or Map.
|
||||
@@ -937,7 +940,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
if (elementDescriptor != null) {
|
||||
elementDescriptor.jsonWriteMapEntry(ctx, entry);
|
||||
} else {
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean)entry.getValue());
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean) entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1003,7 +1006,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
if (JsonToken.VALUE_NULL == event) {
|
||||
return null;
|
||||
}
|
||||
return jsonReadCollection(ctx, null);
|
||||
return jsonReadCollection(ctx, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1016,15 +1019,16 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
/**
|
||||
* Read the collection (JSON Array) containing entity beans.
|
||||
*/
|
||||
public Object jsonReadCollection(SpiJsonReader readJson, EntityBean parentBean) throws IOException {
|
||||
public Object jsonReadCollection(SpiJsonReader readJson, EntityBean parentBean, Object targets) throws IOException {
|
||||
if (elementDescriptor != null && elementDescriptor.isJsonReadCollection()) {
|
||||
return elementDescriptor.jsonReadCollection(readJson, parentBean);
|
||||
}
|
||||
BeanCollection<?> collection = createEmpty(parentBean);
|
||||
BeanCollectionAdd add = beanCollectionAdd(collection);
|
||||
Map<Object, T> existingBeans = extractBeans(targets);
|
||||
do {
|
||||
// CHECKME: Update existing list entry here?
|
||||
EntityBean detailBean = (EntityBean) targetDescriptor.jsonRead(readJson, name, null);
|
||||
|
||||
EntityBean detailBean = getDetailBean(readJson, existingBeans);
|
||||
if (detailBean == null) {
|
||||
// read the entire array
|
||||
break;
|
||||
@@ -1039,6 +1043,63 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
return collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find bean in the target collection and reuse it for JSON update.
|
||||
*/
|
||||
private EntityBean getDetailBean(SpiJsonReader readJson, Map<Object, T> targets) throws IOException {
|
||||
BeanProperty idProperty = targetDescriptor.idProperty();
|
||||
if (targets == null || idProperty == null) {
|
||||
return (EntityBean) targetDescriptor.jsonRead(readJson, name, null);
|
||||
} else {
|
||||
JsonToken token = readJson.parser().nextToken();
|
||||
if (JsonToken.VALUE_NULL == token || JsonToken.END_ARRAY == token) {
|
||||
return null;
|
||||
}
|
||||
// extract the id. We have to buffer the JSON;
|
||||
ObjectNode node = readJson.mapper().readTree(readJson.parser());
|
||||
SpiJsonReader jsonReader = readJson.forJson(node.traverse());
|
||||
JsonNode idNode = node.get(idProperty.name());
|
||||
Object id = idNode == null ? null : idProperty.jsonRead(readJson.forJson(idNode.traverse()));
|
||||
return (EntityBean) targetDescriptor.jsonRead(jsonReader, name, targets.get(id));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract beans, that are currently in the target collection. (targets can be a List/Set/Map)
|
||||
*/
|
||||
private Map<Object, T> extractBeans(Object targets) {
|
||||
Collection<T> beans;
|
||||
|
||||
if (targets == null) {
|
||||
return null;
|
||||
} else if (targets instanceof Map) {
|
||||
if (((Map<?, T>) targets).isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
beans = ((Map<?, T>) targets).values();
|
||||
} else if (targets instanceof Collection) {
|
||||
if (((Collection<?>) targets).isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
beans = (Collection<T>) targets;
|
||||
} else {
|
||||
CoreLog.log.log(WARNING, "Found non collection value " + targets.getClass().getSimpleName());
|
||||
return null;
|
||||
}
|
||||
|
||||
BeanProperty idProp = targetDescriptor.idProperty();
|
||||
Map<Object, T> ret = new HashMap<>();
|
||||
for (T bean : beans) {
|
||||
if (bean instanceof EntityBean) {
|
||||
Object id = idProp.getValue((EntityBean) bean);
|
||||
if (id != null) {
|
||||
ret.put(id, bean);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret.isEmpty() ? null : ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind all the property values to the SqlUpdate.
|
||||
*/
|
||||
|
||||
+3
-3
@@ -50,10 +50,10 @@ class BeanPropertyAssocManyJsonHelp {
|
||||
if (JsonToken.START_ARRAY != event && JsonToken.START_OBJECT != event) {
|
||||
throw new JsonParseException(parser, "Unexpected token " + event + " - expecting start array or object");
|
||||
}
|
||||
if (readJson.intercept()) {
|
||||
many.setValueIntercept(parentBean, many.jsonReadCollection(readJson, parentBean));
|
||||
if (readJson.update()) {
|
||||
many.setValueIntercept(parentBean, many.jsonReadCollection(readJson, parentBean, many.value(parentBean)));
|
||||
} else {
|
||||
many.setValue(parentBean, many.jsonReadCollection(readJson, parentBean));
|
||||
many.setValue(parentBean, many.jsonReadCollection(readJson, parentBean, null));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -197,7 +197,8 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
if (assocBean != null) {
|
||||
Object parentId = targetDescriptor.id(assocBean);
|
||||
if (parentId != null) {
|
||||
changeSet.addManyRemove(targetDescriptor, relationshipProperty.name(), parentId);
|
||||
final String parentKey = targetDescriptor.cacheKey(parentId);
|
||||
changeSet.addManyRemove(targetDescriptor, relationshipProperty.name(), parentKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -655,7 +656,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
@Override
|
||||
public void setValue(EntityBean bean, Object value) {
|
||||
super.setValue(bean, value);
|
||||
if (embedded && value instanceof EntityBean) {
|
||||
if (!id && embedded && value instanceof EntityBean) {
|
||||
setEmbeddedOwner(bean, value);
|
||||
}
|
||||
}
|
||||
@@ -663,7 +664,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
@Override
|
||||
public void setValueIntercept(EntityBean bean, Object value) {
|
||||
super.setValueIntercept(bean, value);
|
||||
if (embedded && value instanceof EntityBean) {
|
||||
if (!id && embedded && value instanceof EntityBean) {
|
||||
setEmbeddedOwner(bean, value);
|
||||
}
|
||||
}
|
||||
@@ -675,8 +676,10 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
Object emb = getValue(owner);
|
||||
if (emb != null) {
|
||||
EntityBean embeddedBean = (EntityBean) emb;
|
||||
embeddedBean._ebean_getIntercept().setEmbeddedOwner(owner, propertyIndex);
|
||||
targetDescriptor.setAllLoaded(embeddedBean);
|
||||
if (!id) {
|
||||
embeddedBean._ebean_getIntercept().setEmbeddedOwner(owner, propertyIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -784,9 +787,10 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
@Override
|
||||
public void jsonRead(SpiJsonReader readJson, EntityBean bean) throws IOException {
|
||||
if (jsonDeserialize && targetDescriptor != null) {
|
||||
T target = (T) value(bean);
|
||||
// CHECKME: may we skip reading the object from the json stream?
|
||||
T target = readJson.update() ? (T) value(bean) : null;
|
||||
T assocBean = targetDescriptor.jsonRead(readJson, name, target);
|
||||
if (readJson.intercept()) {
|
||||
if (readJson.update()) {
|
||||
setValueIntercept(bean, assocBean);
|
||||
} else {
|
||||
setValue(bean, assocBean);
|
||||
@@ -794,6 +798,11 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonRead(SpiJsonReader readJson) throws IOException {
|
||||
return targetDescriptor.jsonRead(readJson, name, null);
|
||||
}
|
||||
|
||||
public boolean isReference(Object detailBean) {
|
||||
EntityBean eb = (EntityBean) detailBean;
|
||||
return targetDescriptor.isReference(eb._ebean_getIntercept());
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ public final class BeanPropertySimpleCollection<T> extends BeanPropertyAssocMany
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonReadCollection(SpiJsonReader readJson, EntityBean parentBean) throws IOException {
|
||||
public Object jsonReadCollection(SpiJsonReader readJson, EntityBean parentBean, Object collectionValue) throws IOException {
|
||||
return elementDescriptor.jsonReadCollection(readJson, parentBean);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,10 +465,9 @@ final class AnnotationFields extends AnnotationParser {
|
||||
if (!gen.generator().isEmpty()) {
|
||||
// use a custom IdGenerator
|
||||
PlatformIdGenerator idGenerator = generatedPropFactory.getIdGenerator(gen.generator());
|
||||
if (idGenerator == null) {
|
||||
throw new IllegalStateException("No custom IdGenerator registered with name " + gen.generator());
|
||||
if (idGenerator != null) {
|
||||
descriptor.setCustomIdGenerator(idGenerator);
|
||||
}
|
||||
descriptor.setCustomIdGenerator(idGenerator);
|
||||
} else if (prop.getPropertyType().equals(UUID.class)) {
|
||||
descriptor.setUuidGenerator();
|
||||
}
|
||||
|
||||
+7
-8
@@ -9,8 +9,7 @@ import io.ebeaninternal.server.deploy.ManyType;
|
||||
import io.ebeaninternal.server.deploy.meta.*;
|
||||
import io.ebeaninternal.server.type.TypeManager;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.persistence.Transient;
|
||||
import javax.persistence.*;
|
||||
import java.lang.reflect.*;
|
||||
|
||||
import static java.lang.System.Logger.Level.*;
|
||||
@@ -105,20 +104,18 @@ public final class DeployCreateProperties {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private DeployBeanProperty createManyType(DeployBeanDescriptor<?> desc, Class<?> targetType, ManyType manyType) {
|
||||
try {
|
||||
ScalarType<?> scalarType = typeManager.type(targetType);
|
||||
if (scalarType != null) {
|
||||
return new DeployBeanPropertySimpleCollection(desc, targetType, manyType);
|
||||
return new DeployBeanPropertySimpleCollection<>(desc, targetType, manyType);
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
CoreLog.internal.log(DEBUG, "expected non-scalar type {0}", e.getMessage());
|
||||
}
|
||||
return new DeployBeanPropertyAssocMany(desc, targetType, manyType);
|
||||
return new DeployBeanPropertyAssocMany<>(desc, targetType, manyType);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private DeployBeanProperty createProp(DeployBeanDescriptor<?> desc, Field field) {
|
||||
Class<?> propertyType = field.getType();
|
||||
if (isSpecialScalarType(field)) {
|
||||
@@ -149,9 +146,11 @@ public final class DeployCreateProperties {
|
||||
// return with no ScalarType (still support JSON features)
|
||||
return new DeployBeanProperty(desc, propertyType, null, null);
|
||||
}
|
||||
if (AnnotationUtil.has(field, Convert.class)) {
|
||||
throw new IllegalStateException("No AttributeConverter registered for type " + propertyType + " at " + desc.getFullName() + "." + field.getName());
|
||||
}
|
||||
try {
|
||||
return new DeployBeanPropertyAssocOne(desc, propertyType);
|
||||
|
||||
return new DeployBeanPropertyAssocOne<>(desc, propertyType);
|
||||
} catch (Exception e) {
|
||||
CoreLog.log.log(ERROR, "Error with " + desc + " field:" + field.getName(), e);
|
||||
return null;
|
||||
|
||||
+26
@@ -903,6 +903,16 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return add(expr.geOrNull(propertyName, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> gtIfPresent(String propertyName, @Nullable Object value) {
|
||||
return value == null ? this : add(expr.gt(propertyName, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> geIfPresent(String propertyName, @Nullable Object value) {
|
||||
return value == null ? this : add(expr.ge(propertyName, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> icontains(String propertyName, String value) {
|
||||
return add(expr.icontains(propertyName, value));
|
||||
@@ -1061,6 +1071,16 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return add(expr.leOrNull(propertyName, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> ltIfPresent(String propertyName, @Nullable Object value) {
|
||||
return value == null ? this : add(expr.lt(propertyName, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> leIfPresent(String propertyName, @Nullable Object value) {
|
||||
return value == null ? this : add(expr.le(propertyName, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> not(Expression exp) {
|
||||
return add(expr.not(exp));
|
||||
@@ -1268,4 +1288,10 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> clear() {
|
||||
list.clear();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -677,6 +677,16 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
|
||||
return exprList.geOrNull(propertyName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> gtIfPresent(String propertyName, @Nullable Object value) {
|
||||
return value == null ? this : exprList.gt(propertyName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> geIfPresent(String propertyName, @Nullable Object value) {
|
||||
return value == null ? this : exprList.ge(propertyName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> having() {
|
||||
throw new IllegalStateException("having() not allowed on Junction expression list");
|
||||
@@ -837,6 +847,16 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
|
||||
return exprList.leOrNull(propertyName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> ltIfPresent(String propertyName, @Nullable Object value) {
|
||||
return value == null ? this : exprList.lt(propertyName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> leIfPresent(String propertyName, @Nullable Object value) {
|
||||
return value == null ? this : exprList.le(propertyName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> ne(String propertyName, Query<?> subQuery) {
|
||||
return exprList.ne(propertyName, subQuery);
|
||||
@@ -1068,4 +1088,9 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> clear() {
|
||||
return exprList.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,13 +32,13 @@ public final class ReadJson implements SpiJsonReader {
|
||||
private final Object objectMapper;
|
||||
private final PersistenceContext persistenceContext;
|
||||
private final LoadContext loadContext;
|
||||
private final boolean intercept;
|
||||
private final boolean update;
|
||||
private final boolean enableLazyLoading;
|
||||
|
||||
/**
|
||||
* Construct with parser and readOptions.
|
||||
*/
|
||||
public ReadJson(BeanDescriptor<?> desc, JsonParser parser, JsonReadOptions readOptions, Object objectMapper, boolean intercept) {
|
||||
public ReadJson(BeanDescriptor<?> desc, JsonParser parser, JsonReadOptions readOptions, Object objectMapper, boolean update) {
|
||||
this.rootDesc = desc;
|
||||
this.parser = parser;
|
||||
this.objectMapper = objectMapper;
|
||||
@@ -48,7 +48,7 @@ public final class ReadJson implements SpiJsonReader {
|
||||
// only create visitorMap, pathStack if needed ...
|
||||
this.visitorMap = (readOptions == null) ? null : readOptions.getVisitorMap();
|
||||
this.pathStack = (visitorMap == null && loadContext == null) ? null : new PathStack();
|
||||
this.intercept = intercept;
|
||||
this.update = update;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,7 +62,7 @@ public final class ReadJson implements SpiJsonReader {
|
||||
this.objectMapper = source.objectMapper;
|
||||
this.persistenceContext = source.persistenceContext;
|
||||
this.loadContext = source.loadContext;
|
||||
this.intercept = source.intercept;
|
||||
this.update = source.update;
|
||||
this.enableLazyLoading = source.enableLazyLoading;
|
||||
}
|
||||
|
||||
@@ -213,10 +213,10 @@ public final class ReadJson implements SpiJsonReader {
|
||||
}
|
||||
|
||||
/**
|
||||
* Do we have to set values via intercept or not.
|
||||
* Do we update an existing bean? This meeans we have to set values via intercept and handle collections.
|
||||
*/
|
||||
@Override
|
||||
public boolean intercept() {
|
||||
return intercept;
|
||||
public boolean update() {
|
||||
return update;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,6 +125,11 @@ final class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext
|
||||
this.batch = new HashSet<>(Math.max((int) (batchSize/.75f) + 1, 16));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LoadBuffer@" + hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock lock() {
|
||||
bufferLock.lock();
|
||||
@@ -186,6 +191,9 @@ final class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext
|
||||
|
||||
@Override
|
||||
public void loadBean(EntityBeanIntercept ebi) {
|
||||
assert bufferLock.isHeldByCurrentThread();
|
||||
assert bufferLock.isLocked();
|
||||
|
||||
// A lock is effectively held by EntityBeanIntercept.loadBean()
|
||||
if (context.desc.lazyLoadMany(ebi, context)) {
|
||||
// lazy load property was a Many
|
||||
|
||||
@@ -58,6 +58,7 @@ public final class DLoadContext implements LoadContext {
|
||||
private final ProfilingListener profilingListener;
|
||||
private final Map<String, ObjectGraphNode> nodePathMap = new HashMap<>();
|
||||
private final PersistenceContext persistenceContext;
|
||||
boolean useReferences;
|
||||
private List<OrmQueryProperties> secQuery;
|
||||
private Object tenantId;
|
||||
|
||||
@@ -118,7 +119,6 @@ public final class DLoadContext implements LoadContext {
|
||||
this.origin = null;
|
||||
this.relativePath = null;
|
||||
}
|
||||
|
||||
// initialise rootBeanContext after origin and relativePath have been set
|
||||
this.rootBeanContext = new DLoadBeanContext(this, rootDescriptor, null, null);
|
||||
registerSecondaryQueries(secondaryQueries);
|
||||
@@ -156,6 +156,11 @@ public final class DLoadContext implements LoadContext {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void useReferences(boolean useReferences) {
|
||||
this.useReferences = useReferences;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the load context at this path with OrmQueryProperties which is
|
||||
* used to build the appropriate query for +query or +lazy loading.
|
||||
|
||||
+130
-25
@@ -14,7 +14,10 @@ import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import io.ebeaninternal.server.querydefn.OrmQueryProperties;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@@ -38,7 +41,7 @@ final class DLoadManyContext extends DLoadBaseContext implements LoadManyContext
|
||||
}
|
||||
|
||||
private LoadBuffer createBuffer(int size) {
|
||||
LoadBuffer buffer = new LoadBuffer(this, size);
|
||||
LoadBuffer buffer = parent.useReferences ? new LoadBufferWeakRef(this, size) : new LoadBufferHardRef(this, size);
|
||||
if (bufferList != null) {
|
||||
bufferList.add(buffer);
|
||||
}
|
||||
@@ -94,7 +97,7 @@ final class DLoadManyContext extends DLoadBaseContext implements LoadManyContext
|
||||
try {
|
||||
if (bufferList != null) {
|
||||
for (LoadBuffer loadBuffer : bufferList) {
|
||||
if (!loadBuffer.list.isEmpty()) {
|
||||
if (loadBuffer.size() > 0) {
|
||||
LoadManyRequest req = new LoadManyRequest(loadBuffer, parentRequest);
|
||||
parent.getEbeanServer().loadMany(req);
|
||||
}
|
||||
@@ -115,13 +118,12 @@ final class DLoadManyContext extends DLoadBaseContext implements LoadManyContext
|
||||
* A buffer for batch loading bean collections on a given path.
|
||||
* Supports batch lazy loading and secondary query loading.
|
||||
*/
|
||||
static class LoadBuffer implements BeanCollectionLoader, LoadManyBuffer {
|
||||
static abstract class LoadBuffer implements BeanCollectionLoader, LoadManyBuffer {
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
private final PersistenceContext persistenceContext;
|
||||
private final DLoadManyContext context;
|
||||
private final int batchSize;
|
||||
private final List<BeanCollection<?>> list;
|
||||
final int batchSize;
|
||||
|
||||
LoadBuffer(DLoadManyContext context, int batchSize) {
|
||||
this.context = context;
|
||||
@@ -129,7 +131,6 @@ final class DLoadManyContext extends DLoadBaseContext implements LoadManyContext
|
||||
// case it changes as part of a findIterate etc
|
||||
this.persistenceContext = context.getPersistenceContext();
|
||||
this.batchSize = batchSize;
|
||||
this.list = new ArrayList<>(batchSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -138,7 +139,7 @@ final class DLoadManyContext extends DLoadBaseContext implements LoadManyContext
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBatchSize() {
|
||||
public int batchSize() {
|
||||
return batchSize;
|
||||
}
|
||||
|
||||
@@ -146,20 +147,15 @@ final class DLoadManyContext extends DLoadBaseContext implements LoadManyContext
|
||||
* Return true if the buffer is full.
|
||||
*/
|
||||
public boolean isFull() {
|
||||
return batchSize == list.size();
|
||||
return batchSize() == size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the buffer is full.
|
||||
*/
|
||||
public void add(BeanCollection<?> bc) {
|
||||
list.add(bc);
|
||||
}
|
||||
public abstract void add(BeanCollection<?> bc);
|
||||
|
||||
@Override
|
||||
public List<BeanCollection<?>> getBatch() {
|
||||
return list;
|
||||
}
|
||||
abstract void clear();
|
||||
|
||||
@Override
|
||||
public BeanPropertyAssocMany<?> getBeanProperty() {
|
||||
@@ -205,27 +201,136 @@ final class DLoadManyContext extends DLoadBaseContext implements LoadManyContext
|
||||
EntityBean ownerBean = bc.getOwnerBean();
|
||||
BeanDescriptor<?> parentDesc = context.desc.descriptor(ownerBean.getClass());
|
||||
Object parentId = parentDesc.getId(ownerBean);
|
||||
if (parentDesc.cacheManyPropLoad(context.property, bc, parentId, context.parent.isReadOnly())) {
|
||||
final String parentKey = parentDesc.cacheKey(parentId);
|
||||
if (parentDesc.cacheManyPropLoad(context.property, bc, parentKey, context.parent.isReadOnly())) {
|
||||
// we loaded the bean collection from cache so remove it from the buffer
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
// find it using instance equality - avoiding equals() and potential deadlock issue
|
||||
if (list.get(i) == bc) {
|
||||
list.remove(i);
|
||||
bc.setLoader(context.parent.getEbeanServer());
|
||||
return;
|
||||
}
|
||||
if (removeFromBuffer(bc)) {
|
||||
bc.setLoader(context.parent.getEbeanServer());
|
||||
}
|
||||
// find it using instance equality - avoiding equals() and potential deadlock issue
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
context.parent.getEbeanServer().loadMany(new LoadManyRequest(this, onlyIds, useCache));
|
||||
context.parent.getEbeanServer().loadMany(new LoadManyRequest(this, onlyIds, useCache, bc));
|
||||
// clear the buffer as all entries have been loaded
|
||||
list.clear();
|
||||
clear();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class LoadBufferHardRef extends LoadBuffer {
|
||||
private final BeanCollection<?>[] list;
|
||||
|
||||
private int size;
|
||||
|
||||
LoadBufferHardRef(DLoadManyContext context, int batchSize) {
|
||||
super(context, batchSize);
|
||||
this.list = new BeanCollection<?>[batchSize];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the buffer is full.
|
||||
*/
|
||||
@Override
|
||||
public void add(BeanCollection<?> bc) {
|
||||
list[size++] = bc;
|
||||
}
|
||||
|
||||
@Override
|
||||
void clear() {
|
||||
Arrays.fill(list, null);
|
||||
size = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollection<?> get(int i) {
|
||||
return list[i];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeFromBuffer(BeanCollection<?> collection) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
// find it using instance equality - avoiding equals() and potential deadlock issue
|
||||
if (list[i] == collection) {
|
||||
list[i] = null;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This load buffer uses weak references, so unreachable beanCollections will drop out from the buffer.
|
||||
*/
|
||||
static class LoadBufferWeakRef extends LoadBuffer {
|
||||
private final Reference<BeanCollection<?>>[] list;
|
||||
|
||||
private int size;
|
||||
|
||||
LoadBufferWeakRef(DLoadManyContext context, int batchSize) {
|
||||
super(context, batchSize);
|
||||
this.list = new Reference[batchSize];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the buffer is full.
|
||||
*/
|
||||
@Override
|
||||
public void add(BeanCollection<?> bc) {
|
||||
list[size++] = new WeakReference<>(bc);
|
||||
}
|
||||
|
||||
@Override
|
||||
void clear() {
|
||||
Arrays.fill(list, null);
|
||||
size = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollection<?> get(int i) {
|
||||
Reference<BeanCollection<?>> ref = list[i];
|
||||
if (ref == null) {
|
||||
return null;
|
||||
}
|
||||
BeanCollection<?> bc = ref.get();
|
||||
if (bc == null) {
|
||||
// remove dead references
|
||||
list[i] = null;
|
||||
}
|
||||
return bc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeFromBuffer(BeanCollection<?> collection) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (list[i] != null) {
|
||||
BeanCollection<?> bc = list[i].get();
|
||||
if (bc == null) {
|
||||
// remove dead references
|
||||
list[i] = null;
|
||||
}
|
||||
// find it using instance equality - avoiding equals() and potential deadlock issue
|
||||
if (bc == collection) {
|
||||
list[i] = null;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,22 +2,30 @@ package io.ebeaninternal.server.logger;
|
||||
|
||||
import io.ebeaninternal.api.SpiLogManager;
|
||||
import io.ebeaninternal.api.SpiLogger;
|
||||
import io.ebeaninternal.api.SpiTxnLogger;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public final class DLogManager implements SpiLogManager {
|
||||
|
||||
private final SpiLogger sql;
|
||||
private final SpiLogger summary;
|
||||
private final SpiLogger txn;
|
||||
private final boolean useIds;
|
||||
private final AtomicLong counter = new AtomicLong(1000);
|
||||
private final DTxnLogger readOnly;
|
||||
|
||||
public DLogManager(SpiLogger sql, SpiLogger summary, SpiLogger txn) {
|
||||
this.sql = sql;
|
||||
this.summary = summary;
|
||||
this.txn = txn;
|
||||
this.useIds = txn.isDebug();
|
||||
this.readOnly = new DTxnLogger(null, sql, summary, txn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiLogger txn() {
|
||||
return txn;
|
||||
public boolean enableBindLog() {
|
||||
return sql.isDebug();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -26,8 +34,13 @@ public final class DLogManager implements SpiLogManager {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiLogger sum() {
|
||||
return summary;
|
||||
public SpiTxnLogger logger() {
|
||||
String id = useIds ? Long.toString(counter.incrementAndGet()) : "";
|
||||
return new DTxnLogger(id, sql, summary, txn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiTxnLogger readOnlyLogger() {
|
||||
return readOnly;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user