mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
396
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef8d9c7eb0 | ||
|
|
a464c763d0 | ||
|
|
d4d1e571d3 | ||
|
|
92e85e32a2 | ||
|
|
ff1b01e5ca | ||
|
|
327f25c568 | ||
|
|
00a1324c52 | ||
|
|
75b9df942c | ||
|
|
946b390037 | ||
|
|
3a1e1e23f5 | ||
|
|
d9ea465102 | ||
|
|
3bc7f061eb | ||
|
|
0bc07d38b2 | ||
|
|
79f6d6d0f0 | ||
|
|
782e41098d | ||
|
|
0225fddf6d | ||
|
|
be3e08018e | ||
|
|
c9204eed3f | ||
|
|
edb6a0ebe2 | ||
|
|
826b507b77 | ||
|
|
8ad8f47c6b | ||
|
|
5944777a13 | ||
|
|
05a1b0d64e | ||
|
|
4d62958645 | ||
|
|
610a8b2df6 | ||
|
|
5b8bb41598 | ||
|
|
9e16d955ae | ||
|
|
197bb0509a | ||
|
|
5536aeb829 | ||
|
|
d629fb2dbd | ||
|
|
10c01574d2 | ||
|
|
cfad20c8e1 | ||
|
|
0ea375b4fc | ||
|
|
71fce1b4c5 | ||
|
|
db60065389 | ||
|
|
d3a765a532 | ||
|
|
fd4be0ca59 | ||
|
|
267a81b792 | ||
|
|
1615beadd1 | ||
|
|
a3e5c3de72 | ||
|
|
267b1b7303 | ||
|
|
c902caed24 | ||
|
|
662666e1a4 | ||
|
|
394f245e33 | ||
|
|
89da952b15 | ||
|
|
d927b8c2c2 | ||
|
|
6867c4568c | ||
|
|
e0e572a8b4 | ||
|
|
3c7555de36 | ||
|
|
75662aac5c | ||
|
|
e4ddcbd40a | ||
|
|
a8f390c3b7 | ||
|
|
f1b196cf2e | ||
|
|
04675ea76b | ||
|
|
8e44ad71e8 | ||
|
|
febd56c9c0 | ||
|
|
0d3649853a | ||
|
|
beed67567a | ||
|
|
0fe0803374 | ||
|
|
5fd7aca3d9 | ||
|
|
348fecddf7 | ||
|
|
b333449d84 | ||
|
|
87a97c2889 | ||
|
|
790147e42d | ||
|
|
3a93abaa7f | ||
|
|
1049d951d9 | ||
|
|
c3bdac5271 | ||
|
|
9bcba0b80d | ||
|
|
1529a2f12b | ||
|
|
b41b6da40e | ||
|
|
4285cbaeb2 | ||
|
|
26fd7c5498 | ||
|
|
6ec4e4b965 | ||
|
|
e3a20a351d | ||
|
|
9b8f7be98f | ||
|
|
61f5442e3b | ||
|
|
c5acd31da4 | ||
|
|
49fde7654e | ||
|
|
05338531ed | ||
|
|
eb4d906814 | ||
|
|
2a96a59deb | ||
|
|
f571da5154 | ||
|
|
ffad9abeef | ||
|
|
e8df81d78a | ||
|
|
ed19a96801 | ||
|
|
6d27e30b88 | ||
|
|
52aa1a2d91 | ||
|
|
ddbd816f6d | ||
|
|
00940c2b31 | ||
|
|
708ec64893 | ||
|
|
d0dd2d8203 | ||
|
|
faa921ac27 | ||
|
|
f2a99c7b01 | ||
|
|
b6ea9df444 | ||
|
|
e6cde5862d | ||
|
|
dec927bf9a | ||
|
|
ae41471c74 | ||
|
|
843d9d2700 | ||
|
|
475fd38be5 | ||
|
|
b88e4a35f8 | ||
|
|
c82f3783f0 | ||
|
|
bf99f9d08d | ||
|
|
f30c3869b6 | ||
|
|
3b32e4c018 | ||
|
|
e0669e9a9f | ||
|
|
95b1488aed | ||
|
|
897a97d415 | ||
|
|
1d71f617c2 | ||
|
|
1ca5789112 | ||
|
|
70ec8a3891 | ||
|
|
2dfa9d2e77 | ||
|
|
29a5a13dd9 | ||
|
|
7a3494ebd9 | ||
|
|
915bf29eaf | ||
|
|
dad4837b50 | ||
|
|
8fa8c687e9 | ||
|
|
aff54f5cf7 | ||
|
|
fa0336a404 | ||
|
|
7ccea9ff7e | ||
|
|
c2e4f862bc | ||
|
|
36bda117a6 | ||
|
|
08838770e9 | ||
|
|
137a7950ff | ||
|
|
e3980a14a2 | ||
|
|
ca9f48d019 | ||
|
|
e83e6b0f8f | ||
|
|
7d18329c18 | ||
|
|
c6fa60f28c | ||
|
|
3ab7ebe5e6 | ||
|
|
48e875714b | ||
|
|
5ba93ed927 | ||
|
|
9974102f1a | ||
|
|
ba27e09179 | ||
|
|
90066eee0c | ||
|
|
53c8827a52 | ||
|
|
3bb6f0ca65 | ||
|
|
6e5eb6b963 | ||
|
|
7bea0d0eb2 | ||
|
|
5a07a54544 | ||
|
|
684508b7ea | ||
|
|
ab72fd97b9 | ||
|
|
8486415249 | ||
|
|
6a74b84b8c | ||
|
|
999be3e0a7 | ||
|
|
a656b55526 | ||
|
|
dabb1451e9 | ||
|
|
cde00650ca | ||
|
|
6b96bea480 | ||
|
|
a731bfdfaf | ||
|
|
0ee153d6bc | ||
|
|
cb89b903fd | ||
|
|
a93e2e05c5 | ||
|
|
05ad6da7e6 | ||
|
|
0d3ea9626c | ||
|
|
b8b83c2ec8 | ||
|
|
d05dfae1d7 | ||
|
|
d0fcd4a13a | ||
|
|
b02adeccc1 | ||
|
|
b3f110b7a5 | ||
|
|
daf0ba67a4 | ||
|
|
cf3499f0e4 | ||
|
|
a72cbaf243 | ||
|
|
9ea2811aa3 | ||
|
|
0abef7396f | ||
|
|
101d9e85ef | ||
|
|
7a3be45efd | ||
|
|
f4d92eed18 | ||
|
|
db6f2cba75 | ||
|
|
6f694eb6ca | ||
|
|
539633c963 | ||
|
|
8e05956f6b | ||
|
|
94951a5476 | ||
|
|
2cd769d00f | ||
|
|
389f2bcd2f | ||
|
|
1ba259d15d | ||
|
|
4899f23773 | ||
|
|
771e9ff069 | ||
|
|
7d27c06483 | ||
|
|
d6a8643fe4 | ||
|
|
97c714d945 | ||
|
|
57f6668b37 | ||
|
|
9d506b4397 | ||
|
|
5a12cc58d1 | ||
|
|
f7c83411c2 | ||
|
|
a02fee7de0 | ||
|
|
170e323ee9 | ||
|
|
4555f3da51 | ||
|
|
376b3a9f13 | ||
|
|
43af5343a4 | ||
|
|
886f539fc4 | ||
|
|
1035d74113 | ||
|
|
26a4feb5ba | ||
|
|
a1c0e21234 | ||
|
|
cbe133dd68 | ||
|
|
4b1fe063b0 | ||
|
|
15f1bd310b | ||
|
|
6e3e9bd4f7 | ||
|
|
fddcc64741 | ||
|
|
ed917c55f1 | ||
|
|
17fed0ebd8 | ||
|
|
2dcd17830a | ||
|
|
a412873da6 | ||
|
|
7f5370c709 | ||
|
|
9470a1376c | ||
|
|
7f5b65cf45 | ||
|
|
6d0f5aea82 | ||
|
|
530a75b591 | ||
|
|
13cfaba0c8 | ||
|
|
1fa92efb63 | ||
|
|
bc477c64cb | ||
|
|
804098149e | ||
|
|
567ad92050 | ||
|
|
3a84cb8623 | ||
|
|
b4ddbe38ee | ||
|
|
01722b334b | ||
|
|
0a780523cf | ||
|
|
f2e04d9fbf | ||
|
|
4b8565e7c7 | ||
|
|
1359d534d5 | ||
|
|
94ae513d85 | ||
|
|
d58c56484e | ||
|
|
75a27fa2d6 | ||
|
|
cc1c08cd34 | ||
|
|
029cde12db | ||
|
|
b33914ab2f | ||
|
|
d571a6c354 | ||
|
|
95b19569e4 | ||
|
|
a9560c6664 | ||
|
|
235822bcb2 | ||
|
|
5a024ea19f | ||
|
|
399f8b92fa | ||
|
|
be93263015 | ||
|
|
b4fe4ec8b9 | ||
|
|
8c9f5f4a22 | ||
|
|
953f8054e6 | ||
|
|
aadb791980 | ||
|
|
7430f97c9c | ||
|
|
ba21eeaadb | ||
|
|
c0e827ffda | ||
|
|
3b30708dfc | ||
|
|
9f9184ac6a | ||
|
|
5845f94303 | ||
|
|
dd824ffe52 | ||
|
|
e5d29afa4c | ||
|
|
5ae5e408e3 | ||
|
|
90f6d0707f | ||
|
|
0310601e31 | ||
|
|
015dd00b8e | ||
|
|
6d978add29 | ||
|
|
e529232f76 | ||
|
|
d982ac73b7 | ||
|
|
ddaff81b9c | ||
|
|
1d11666945 | ||
|
|
223e5160dc | ||
|
|
64605b5090 | ||
|
|
425124d8f7 | ||
|
|
6af8968280 | ||
|
|
a9bee03ba7 | ||
|
|
302cc426bd | ||
|
|
44462e3513 | ||
|
|
b748c598a1 | ||
|
|
dbac184b4c | ||
|
|
29c5916203 | ||
|
|
827315a11d | ||
|
|
14ef8f6e0d | ||
|
|
5b63434f13 | ||
|
|
3e8cc87f01 | ||
|
|
190b4ef588 | ||
|
|
4a20c9eb99 | ||
|
|
d8c2b3d583 | ||
|
|
48c8f5e2ca | ||
|
|
69a753fc4f | ||
|
|
b9ba6b2db5 | ||
|
|
7a6071ac9a | ||
|
|
404b167bcc | ||
|
|
7278db56ea | ||
|
|
1dc5ecc81f | ||
|
|
c39661e2c2 | ||
|
|
a702bbb5ee | ||
|
|
1982027300 | ||
|
|
2e1a6eec04 | ||
|
|
e5f37e638c | ||
|
|
7ffea8e922 | ||
|
|
315640df6b | ||
|
|
78a647a72e | ||
|
|
7ffd2f1886 | ||
|
|
0087eabb4e | ||
|
|
5f0731f975 | ||
|
|
85e31899b9 | ||
|
|
3337541ac4 | ||
|
|
b123b06f4d | ||
|
|
17df5a2c16 | ||
|
|
e13aaefee1 | ||
|
|
09ce693da2 | ||
|
|
17f7be72f4 | ||
|
|
23061473c7 | ||
|
|
0944b87283 | ||
|
|
86768dfe4d | ||
|
|
ffdafc796b | ||
|
|
5466c6a350 | ||
|
|
7e0ac5a73a | ||
|
|
008e1849a2 | ||
|
|
dcf60a3d1c | ||
|
|
774cab327d | ||
|
|
2f824c99ea | ||
|
|
1a54fc12ad | ||
|
|
a1d6b280bc | ||
|
|
fa561e5197 | ||
|
|
4a8231a6cc | ||
|
|
5cb486c745 | ||
|
|
dd26dc342d | ||
|
|
7733e9382c | ||
|
|
bc6d2fb3be | ||
|
|
a9dbc036e9 | ||
|
|
8d29a3a575 | ||
|
|
4158ac4665 | ||
|
|
ddab6e65b7 | ||
|
|
bbede04a56 | ||
|
|
9df96b0294 | ||
|
|
6a6b6b8200 | ||
|
|
e26e093680 | ||
|
|
fc107115c6 | ||
|
|
0139ad891e | ||
|
|
4f70c09690 | ||
|
|
df8ae18bf6 | ||
|
|
8edaabf755 | ||
|
|
25eea42211 | ||
|
|
263f6cdeba | ||
|
|
38f1967e60 | ||
|
|
6eb8eb0dd2 | ||
|
|
1165d857d8 | ||
|
|
874c2f5231 | ||
|
|
88ab852855 | ||
|
|
b577331524 | ||
|
|
ec45fc1c86 | ||
|
|
e65876e8ed | ||
|
|
5453037172 | ||
|
|
9b116c9bf6 | ||
|
|
82862deccc | ||
|
|
1c83bbe0b0 | ||
|
|
f16f34f35f | ||
|
|
38bc5b2fea | ||
|
|
356dc5eb19 | ||
|
|
c5779133bc | ||
|
|
b8b6311348 | ||
|
|
8eed983fbb | ||
|
|
7cfecb83a9 | ||
|
|
e92939a34d | ||
|
|
408b982eb3 | ||
|
|
dd7e7711a8 | ||
|
|
5a3f7853a6 | ||
|
|
01847e44de | ||
|
|
0cf9f0bf58 | ||
|
|
b01b44af10 | ||
|
|
8d85000970 | ||
|
|
e7f9c63502 | ||
|
|
eb21b41fba | ||
|
|
3dc6c567a0 | ||
|
|
18eed47306 | ||
|
|
9ddf1333ed | ||
|
|
73896d375f | ||
|
|
3f645211a6 | ||
|
|
451e2fa93c | ||
|
|
2ff3b0acb7 | ||
|
|
42594533da | ||
|
|
678494f331 | ||
|
|
361df6732a | ||
|
|
c3320f4a0b | ||
|
|
c411d9a665 | ||
|
|
8ea2c31076 | ||
|
|
254b0df16b | ||
|
|
c0f4451d20 | ||
|
|
6c544a2835 | ||
|
|
227d18bbf0 | ||
|
|
18cdd2ed7a | ||
|
|
91d1fb8cea | ||
|
|
058021f8d0 | ||
|
|
f4d270e8b5 | ||
|
|
7b8052c097 | ||
|
|
68b7deba9d | ||
|
|
860aad11ce | ||
|
|
65e924feaa | ||
|
|
6cc5e83b01 | ||
|
|
752d5d4782 | ||
|
|
20fdbfc972 | ||
|
|
bd01dfd29a | ||
|
|
6a9b5944a3 | ||
|
|
6e31de6f2e | ||
|
|
5fddc37037 | ||
|
|
f830662cce | ||
|
|
84ac737ceb | ||
|
|
483f0398b2 | ||
|
|
c67e66c0ca | ||
|
|
b60f9201a9 | ||
|
|
3fe521c53a | ||
|
|
091b5fbf26 |
@@ -31,6 +31,10 @@ jobs:
|
||||
path:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: Maven version
|
||||
run: mvn --version
|
||||
# - name: Maven single test
|
||||
# run: mvn --batch-mode clean verify -Dtest="io.ebeaninternal.server.core.DefaultServer_getReferenceTest" -DfailIfNoTests=false
|
||||
- name: Build with Maven
|
||||
run: mvn package
|
||||
run: mvn clean package
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
name: DB2 LUW
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '10 8 * * 2,5'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
java_version: [11]
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
path:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: db2
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-db2.properties
|
||||
@@ -0,0 +1,41 @@
|
||||
|
||||
name: H2Database
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '10 1 * * *'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
java_version: [11]
|
||||
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: Maven version
|
||||
run: mvn --version
|
||||
- name: H2Database
|
||||
run: mvn clean package
|
||||
|
||||
@@ -3,8 +3,8 @@ name: JDK 18-ea
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
# schedule:
|
||||
# - cron: '30 6 * * *'
|
||||
schedule:
|
||||
- cron: '30 6 * * 1,3,5'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
|
||||
name: JDK EA
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '39 6 * * 1,3,5'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
java_version: [17,18,19,loom,valhalla,metropolis,panama]
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- 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
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
path:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: Build with Maven
|
||||
run: mvn package
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
|
||||
name: MariaDB 10.6
|
||||
name: MariaDB
|
||||
|
||||
on: [workflow_dispatch]
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '10 7 * * 1,4'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
+12
-6
@@ -1,5 +1,5 @@
|
||||
|
||||
name: Multi-database platform test
|
||||
name: Multi-database platform
|
||||
|
||||
on: [workflow_dispatch]
|
||||
|
||||
@@ -31,15 +31,21 @@ jobs:
|
||||
path:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: h2
|
||||
- name: h2database
|
||||
run: mvn clean test
|
||||
- name: postgres
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-postgres.properties
|
||||
- name: mysql
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-mysql.properties
|
||||
- name: sqlserver 2019
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-sqlserver19.properties
|
||||
- name: sqlserver 2017
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-sqlserver17.properties
|
||||
- name: mariadb
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-mariadb.properties
|
||||
- name: yugabyte
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-yugabyte.properties
|
||||
- name: sqlserver
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-sqlserver17.properties
|
||||
# - name: sqlserver19
|
||||
# run: mvn clean test -Dprops.file=testconfig/ebean-sqlserver19.properties
|
||||
# - name: db2
|
||||
# run: mvn clean test -Dprops.file=testconfig/ebean-db2.properties
|
||||
# - name: oracle
|
||||
# run: mvn clean test -Dprops.file=testconfig/ebean-oracle.properties
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
name: Oracle18
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '10 6 * * 1,4'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
java_version: [11]
|
||||
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: oracle
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-oracle.properties
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
name: SqlServer 2019 latest
|
||||
name: SqlServer 2019
|
||||
|
||||
on: [workflow_dispatch]
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
|
||||
name: SqlServer 2017 latest
|
||||
name: SqlServer
|
||||
|
||||
on: [workflow_dispatch]
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '10 7 * * 2,5'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -31,7 +34,5 @@ jobs:
|
||||
path:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
# - name: sqlserver 2019 latest
|
||||
# run: mvn clean test -Dprops.file=testconfig/ebean-sqlserver.properties
|
||||
- name: sqlserver 2017 latest
|
||||
- name: sqlserver 2017
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-sqlserver17.properties
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
name: Yugabyte
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '10 3 * * *'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
java_version: [11]
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
path:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: yugabyte
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-yugabyte.properties
|
||||
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2012 Authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
EbeanORM
|
||||
|
||||
Copyright 2012 Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -4,10 +4,12 @@
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/multi-jdk-build.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/jdk-18-ea.yml)
|
||||
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/h2database.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/postgres.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/mysql.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/mariadb-10.6.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/sqlserver-2017-latest.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/mariadb.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/sqlserver.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/yugabyte.yml)
|
||||
|
||||
# Sponsors
|
||||
<table>
|
||||
@@ -49,6 +51,3 @@ Goto [https://ebean.io/docs/](https://ebean.io/docs/)
|
||||
|
||||
[Maven central - all related projects](http://search.maven.org/#search%7Cga%7C1%7Cebean "maven central all related projects")
|
||||
|
||||
## Other versions
|
||||
* [](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean-agent) - ebean-agent
|
||||
* [](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean-maven-plugin) - ebean-maven-plugin
|
||||
|
||||
+5
-5
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean api</name>
|
||||
@@ -27,7 +27,7 @@
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>avaje-config</artifactId>
|
||||
<version>1.5</version>
|
||||
<version>1.7</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
@@ -49,7 +49,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-annotation</artifactId>
|
||||
<version>7.3</version>
|
||||
<version>7.6</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -85,7 +85,7 @@
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>1.4.199</version>
|
||||
<version>${h2database.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>1.0</version>
|
||||
<version>1.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean api</name>
|
||||
<description>ebean api</description>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!--
|
||||
Projects are expected to explicit depend on version
|
||||
of slf4j that they want to use
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.30</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>avaje-config</artifactId>
|
||||
<version>1.5</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
Class retention Nonnull and Nullable annotations
|
||||
to assist with IDE auto-completion with Ebean API
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>avaje-lang</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>persistence-api</artifactId>
|
||||
<version>2.2.5</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-annotation</artifactId>
|
||||
<version>7.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-types</artifactId>
|
||||
<version>2.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-datasource-api</artifactId>
|
||||
<version>${ebean-datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Jackson core used internally by Ebean -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- provided scope for JsonNode support -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Provided scope so that the H2HistoryTrigger can live in Ebean core
|
||||
and not require a separate module for it -->
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>1.4.199</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.transaction</groupId>
|
||||
<artifactId>jta</artifactId>
|
||||
<version>1.1</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.repaint.maven</groupId>
|
||||
<artifactId>tiles-maven-plugin</artifactId>
|
||||
<version>2.24</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<tiles>
|
||||
<tile>io.avaje.tile:moditech-module:1.0</tile>
|
||||
</tiles>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebean;
|
||||
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -23,10 +24,10 @@ public interface ScriptRunner {
|
||||
/**
|
||||
* Run a script given the resource path (that should start with "/").
|
||||
*/
|
||||
void run(String path);
|
||||
void run(String resourcePath);
|
||||
|
||||
/**
|
||||
* Run a script given the resource path (that should start with "/") and place holders.
|
||||
* Run a script given the resource path (that should start with "/") and place-holders.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -38,7 +39,7 @@ public interface ScriptRunner {
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
void run(String path, Map<String, String> placeholderMap);
|
||||
void run(String resourcePath, Map<String, String> placeholderMap);
|
||||
|
||||
/**
|
||||
* Run a DDL or SQL script given the resource.
|
||||
@@ -46,10 +47,20 @@ public interface ScriptRunner {
|
||||
void run(URL resource);
|
||||
|
||||
/**
|
||||
* Run a DDL or SQL script given the resource and place holders.
|
||||
* Run a DDL or SQL script given the resource and place-holders.
|
||||
*/
|
||||
void run(URL resource, Map<String, String> placeholderMap);
|
||||
|
||||
/**
|
||||
* Run a DDL or SQL script given the file.
|
||||
*/
|
||||
void run(Path file);
|
||||
|
||||
/**
|
||||
* Run a DDL or SQL script given the file and place-holders.
|
||||
*/
|
||||
void run(Path file, Map<String, String> placeholderMap);
|
||||
|
||||
/**
|
||||
* Run the raw provided DDL or SQL script.
|
||||
*
|
||||
|
||||
@@ -98,4 +98,14 @@ public class Version<T> {
|
||||
public Map<String, ValuePair> getDiff() {
|
||||
return diff;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Version{" +
|
||||
"bean=" + bean +
|
||||
", start=" + start +
|
||||
", end=" + end +
|
||||
", diff=" + diff +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,7 +360,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* Return true if the entity should be updated.
|
||||
*/
|
||||
public boolean isUpdate() {
|
||||
return forceUpdate || state == STATE_LOADED;
|
||||
return forceUpdate || state == STATE_LOADED || state == STATE_REFERENCE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -829,7 +829,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
/**
|
||||
* Load the bean when it is a reference.
|
||||
*/
|
||||
protected void loadBean(int loadProperty) {
|
||||
void loadBean(int loadProperty) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (beanLoader == null) {
|
||||
@@ -886,7 +886,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* Helper method to check if two objects are equal.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
protected static boolean notEqual(Object obj1, Object obj2) {
|
||||
static boolean notEqual(Object obj1, Object obj2) {
|
||||
if (obj1 == null) {
|
||||
return (obj2 != null);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package io.ebean.config;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* BackgroundExecutorWrapper that can be used to wrap tasks that are sent to background (i.e. another thread).
|
||||
* It should copy all necessary thread-local variables. See {@link MdcBackgroundExecutorWrapper} for implementation details.
|
||||
*
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*/
|
||||
public interface BackgroundExecutorWrapper {
|
||||
|
||||
/**
|
||||
* Wrap the task with MDC context if defined.
|
||||
*/
|
||||
<T> Callable<T> wrap(Callable<T> task);
|
||||
|
||||
/**
|
||||
* Wrap the task with MDC context if defined.
|
||||
*/
|
||||
Runnable wrap(Runnable task);
|
||||
|
||||
/**
|
||||
* Combines two wrappers by nesting them.
|
||||
*/
|
||||
default BackgroundExecutorWrapper with(BackgroundExecutorWrapper inner) {
|
||||
return new BackgroundExecutorWrapper() {
|
||||
|
||||
@Override
|
||||
public Runnable wrap(Runnable task) {
|
||||
return BackgroundExecutorWrapper.this.wrap(inner.wrap(task));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Callable<T> wrap(Callable<T> task) {
|
||||
return BackgroundExecutorWrapper.this.wrap(inner.wrap(task));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -371,6 +371,33 @@ public class DatabaseConfig {
|
||||
*/
|
||||
private String uuidStateFile;
|
||||
|
||||
/**
|
||||
* The node id (=mac address) for Version 1 UUIDs. There are several options:
|
||||
* <ul>
|
||||
* <li><code>null</code> (default) The generator tries to get the hardwarwe MAC
|
||||
* address. If this fails, it will fall back to 'generate' mode.</li>
|
||||
* <li><code>"generate"</code> Hardware detection is skipped. It generates a
|
||||
* random identifier and tries to persist this to the state file. This nodeId
|
||||
* will be reused on next start. If persisting to the state file will fail also,
|
||||
* it will fall back to 'random' mode.<br>
|
||||
* This mode is good, if the MAC address is not reliable, e.g. if you run
|
||||
* multiple ebean instances on the same machine.</li>
|
||||
* <li><code>"random"</code> In this mode, a random node id is generated on each
|
||||
* start. No stateFile is used. it will generate a new nodeId on each
|
||||
* application start.<br>
|
||||
* This mode is good, if you have no write access to save the state file.</li>
|
||||
* <li><code>"xx-xx-xx-xx-xx-xx"</code> When an explicit nodeId is specified,
|
||||
* this one is used.</li>
|
||||
* </ul>
|
||||
* Note: It is possible that multiple servers are sharing the same state file as
|
||||
* long as they are in the <b>same</b> JVM/ClassLoader scope. In this case it is
|
||||
* recommended to use the same uuidNodeId configuration.
|
||||
*
|
||||
* If you have multiple servers in different JVMs, do <b>not</b> share the state
|
||||
* files!
|
||||
*/
|
||||
private String uuidNodeId;
|
||||
|
||||
/**
|
||||
* The clock used for setting the timestamps (e.g. @UpdatedTimestamp) on objects.
|
||||
*/
|
||||
@@ -418,6 +445,7 @@ public class DatabaseConfig {
|
||||
|
||||
private int backgroundExecutorSchedulePoolSize = 1;
|
||||
private int backgroundExecutorShutdownSecs = 30;
|
||||
private BackgroundExecutorWrapper backgroundExecutorWrapper = new MdcBackgroundExecutorWrapper();
|
||||
|
||||
// defaults for the L2 bean caching
|
||||
|
||||
@@ -1436,6 +1464,20 @@ public class DatabaseConfig {
|
||||
this.backgroundExecutorShutdownSecs = backgroundExecutorShutdownSecs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the background executor wrapper.
|
||||
*/
|
||||
public BackgroundExecutorWrapper getBackgroundExecutorWrapper() {
|
||||
return backgroundExecutorWrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the background executor wrapper. The wrapper is used when a task is sent to background and should copy the thread-locals.
|
||||
*/
|
||||
public void setBackgroundExecutorWrapper(BackgroundExecutorWrapper backgroundExecutorWrapper) {
|
||||
this.backgroundExecutorWrapper = backgroundExecutorWrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the L2 cache default max size.
|
||||
*/
|
||||
@@ -2019,6 +2061,20 @@ public class DatabaseConfig {
|
||||
public void setUuidStateFile(String uuidStateFile) {
|
||||
this.uuidStateFile = uuidStateFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the V1-UUID-NodeId
|
||||
*/
|
||||
public String getUuidNodeId() {
|
||||
return uuidNodeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the V1-UUID-NodeId.
|
||||
*/
|
||||
public void setUuidNodeId(String uuidNodeId) {
|
||||
this.uuidNodeId = uuidNodeId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if LocalTime should be persisted with nanos precision.
|
||||
@@ -2843,6 +2899,7 @@ public class DatabaseConfig {
|
||||
|
||||
backgroundExecutorSchedulePoolSize = p.getInt("backgroundExecutorSchedulePoolSize", backgroundExecutorSchedulePoolSize);
|
||||
backgroundExecutorShutdownSecs = p.getInt("backgroundExecutorShutdownSecs", backgroundExecutorShutdownSecs);
|
||||
backgroundExecutorWrapper = p.createInstance(BackgroundExecutorWrapper.class, "backgroundExecutorWrapper", backgroundExecutorWrapper);
|
||||
disableClasspathSearch = p.getBoolean("disableClasspathSearch", disableClasspathSearch);
|
||||
currentUserProvider = p.createInstance(CurrentUserProvider.class, "currentUserProvider", currentUserProvider);
|
||||
databasePlatform = p.createInstance(DatabasePlatform.class, "databasePlatform", databasePlatform);
|
||||
@@ -2888,6 +2945,7 @@ public class DatabaseConfig {
|
||||
|
||||
uuidVersion = p.getEnum(UuidVersion.class, "uuidVersion", uuidVersion);
|
||||
uuidStateFile = p.get("uuidStateFile", uuidStateFile);
|
||||
uuidNodeId = p.get("uuidNodeId", uuidNodeId);
|
||||
|
||||
localTimeWithNanos = p.getBoolean("localTimeWithNanos", localTimeWithNanos);
|
||||
jodaLocalTimeMode = p.get("jodaLocalTimeMode", jodaLocalTimeMode);
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package io.ebean.config;
|
||||
|
||||
import org.slf4j.MDC;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* Propagates MDC context for tasks executed in the background.
|
||||
*/
|
||||
public final class MdcBackgroundExecutorWrapper implements BackgroundExecutorWrapper {
|
||||
|
||||
/**
|
||||
* Wrap the task with MDC context if defined.
|
||||
*/
|
||||
@Override
|
||||
public <T> Callable<T> wrap(Callable<T> task) {
|
||||
final Map<String, String> map = MDC.getCopyOfContextMap();
|
||||
if (map == null) {
|
||||
return task;
|
||||
} else {
|
||||
return () -> {
|
||||
MDC.setContextMap(map);
|
||||
try {
|
||||
return task.call();
|
||||
} finally {
|
||||
MDC.clear();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the task with MDC context if defined.
|
||||
*/
|
||||
@Override
|
||||
public Runnable wrap(Runnable task) {
|
||||
final Map<String, String> map = MDC.getCopyOfContextMap();
|
||||
if (map == null) {
|
||||
return task;
|
||||
} else {
|
||||
return () -> {
|
||||
MDC.setContextMap(map);
|
||||
try {
|
||||
task.run();
|
||||
} finally {
|
||||
MDC.clear();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,6 +66,8 @@ public class PlatformConfig {
|
||||
|
||||
private boolean caseSensitiveCollation = true;
|
||||
|
||||
private boolean useMigrationStoredProcedures = false;
|
||||
|
||||
/**
|
||||
* Modify the default mapping of standard types such as default precision for DECIMAL etc.
|
||||
*/
|
||||
@@ -90,6 +92,7 @@ public class PlatformConfig {
|
||||
this.geometrySRID = platformConfig.geometrySRID;
|
||||
this.dbUuid = platformConfig.dbUuid;
|
||||
this.caseSensitiveCollation = platformConfig.caseSensitiveCollation;
|
||||
this.useMigrationStoredProcedures = platformConfig.useMigrationStoredProcedures;
|
||||
this.allQuotedIdentifiers = platformConfig.allQuotedIdentifiers;
|
||||
this.databaseInetAddressVarchar = platformConfig.databaseInetAddressVarchar;
|
||||
this.customDbTypeMappings = platformConfig.customDbTypeMappings;
|
||||
@@ -142,6 +145,20 @@ public class PlatformConfig {
|
||||
this.caseSensitiveCollation = caseSensitiveCollation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if force use of helper stored procedures for migrations.
|
||||
*/
|
||||
public boolean isUseMigrationStoredProcedures() {
|
||||
return useMigrationStoredProcedures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set true to force use of helper stored procedures for migrations.
|
||||
*/
|
||||
public void setUseMigrationStoredProcedures(boolean useMigrationStoredProcedures) {
|
||||
this.useMigrationStoredProcedures = useMigrationStoredProcedures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if Postgres FOR UPDATE should use the NO KEY option.
|
||||
*/
|
||||
@@ -317,6 +334,7 @@ public class PlatformConfig {
|
||||
databaseBooleanFalse = p.get("databaseBooleanFalse", databaseBooleanFalse);
|
||||
databaseInetAddressVarchar = p.getBoolean("databaseInetAddressVarchar", databaseInetAddressVarchar);
|
||||
caseSensitiveCollation = p.getBoolean("caseSensitiveCollation", caseSensitiveCollation);
|
||||
useMigrationStoredProcedures = p.getBoolean("useMigrationStoredProcedures", useMigrationStoredProcedures);
|
||||
|
||||
DbUuid dbUuid = p.getEnum(DbUuid.class, "dbuuid", null);
|
||||
if (dbUuid != null) {
|
||||
|
||||
@@ -7,13 +7,10 @@ public class BasicSqlAnsiLimiter implements BasicSqlLimiter {
|
||||
|
||||
@Override
|
||||
public String limit(String dbSql, int firstRow, int maxRows) {
|
||||
|
||||
StringBuilder sb = new StringBuilder(50 + dbSql.length());
|
||||
|
||||
sb.append(dbSql);
|
||||
if (firstRow > 0) {
|
||||
sb.append(" ").append("offset");
|
||||
sb.append(" ").append(firstRow).append(" rows");
|
||||
sb.append(" offset ").append(firstRow).append(" rows");
|
||||
}
|
||||
if (maxRows > 0) {
|
||||
sb.append(" fetch next ").append(maxRows).append(" rows only");
|
||||
|
||||
@@ -15,6 +15,7 @@ import javax.persistence.PersistenceException;
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
@@ -53,6 +54,17 @@ public class DatabasePlatform {
|
||||
|
||||
protected boolean supportsSavepointId = true;
|
||||
|
||||
protected boolean useMigrationStoredProcedures = false;
|
||||
|
||||
/**
|
||||
* Can we use native java time API objects in
|
||||
* {@link ResultSet#getObject(int, Class)} and
|
||||
* {@link PreparedStatement#setObject(int, Object)}.
|
||||
*
|
||||
* Not all drivers (DB2 e.g.) will support this.
|
||||
*/
|
||||
protected boolean supportsNativeJavaTime = true;
|
||||
|
||||
/**
|
||||
* The behaviour used when ending a read only transaction at read committed isolation level.
|
||||
*/
|
||||
@@ -202,6 +214,8 @@ public class DatabasePlatform {
|
||||
*/
|
||||
protected PersistBatch persistBatchOnCascade = PersistBatch.ALL;
|
||||
|
||||
protected int maxInBinding;
|
||||
|
||||
/**
|
||||
* The maximum length of table names - used specifically when derived
|
||||
* default table names for intersection tables.
|
||||
@@ -237,6 +251,7 @@ public class DatabasePlatform {
|
||||
public void configure(PlatformConfig config) {
|
||||
this.sequenceBatchSize = config.getDatabaseSequenceBatchSize();
|
||||
this.caseSensitiveCollation = config.isCaseSensitiveCollation();
|
||||
this.useMigrationStoredProcedures = config.isUseMigrationStoredProcedures();
|
||||
configureIdType(config.getIdType());
|
||||
configure(config, config.isAllQuotedIdentifiers());
|
||||
}
|
||||
@@ -343,6 +358,13 @@ public class DatabasePlatform {
|
||||
return supportsSavepointId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if migrations should use stored procedures.
|
||||
*/
|
||||
public boolean isUseMigrationStoredProcedures() {
|
||||
return useMigrationStoredProcedures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the platform supports LIMIT with sql update.
|
||||
*/
|
||||
@@ -350,6 +372,13 @@ public class DatabasePlatform {
|
||||
return inlineSqlUpdateLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the maximum number of bind values this database platform allows or zero for no limit.
|
||||
*/
|
||||
public int getMaxInBinding() {
|
||||
return maxInBinding;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the maximum table name length.
|
||||
* <p>
|
||||
@@ -573,11 +602,8 @@ public class DatabasePlatform {
|
||||
this.supportsResultSetConcurrencyModeUpdatable = supportsResultSetConcurrencyModeUpdatable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normally not needed - overridden in CockroachPlatform.
|
||||
*/
|
||||
public boolean isDdlAutoCommit() {
|
||||
return false;
|
||||
public void setUseMigrationStoredProcedures(final boolean useMigrationStoredProcedures) {
|
||||
this.useMigrationStoredProcedures = useMigrationStoredProcedures;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -813,4 +839,8 @@ public class DatabasePlatform {
|
||||
protected void escapeLikeCharacter(char ch, StringBuilder sb) {
|
||||
sb.append(likeEscapeChar).append(ch);
|
||||
}
|
||||
|
||||
public boolean supportsNativeJavaTime() {
|
||||
return supportsNativeJavaTime;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,14 +31,39 @@ public class SqlCodeTranslator implements SqlExceptionTranslator {
|
||||
this.map = Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceException translate(String message, SQLException e) {
|
||||
|
||||
private DataErrorType getErrorType(SQLException e) {
|
||||
DataErrorType errorType = map.get(e.getSQLState());
|
||||
if (errorType == null) {
|
||||
// fall back to error code
|
||||
errorType = map.get(String.valueOf(e.getErrorCode()));
|
||||
}
|
||||
return errorType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceException translate(String message, SQLException e) {
|
||||
|
||||
DataErrorType errorType = getErrorType(e);
|
||||
// for DB2 we must inspect the sql exception chain to determine which
|
||||
// persistence error occurred in a batch execution. We also concatenate
|
||||
// the error messages to improve error analysis.
|
||||
SQLException chain = e.getNextException();
|
||||
if (chain != null) {
|
||||
StringBuilder sb = new StringBuilder(message);
|
||||
int i = 1;
|
||||
while (chain != null && i < 100000) { // prevents from endless loop
|
||||
sb.append("\n\t#").append(i++).append(": ").append(chain.getMessage());
|
||||
if (errorType == null) {
|
||||
errorType = getErrorType(chain);
|
||||
if (errorType != null) {
|
||||
sb.append(" (causing error)"); // mark the line, where we found a matching error code
|
||||
}
|
||||
}
|
||||
chain = chain.getNextException();
|
||||
}
|
||||
message = sb.toString();
|
||||
}
|
||||
|
||||
if (errorType != null) {
|
||||
switch (errorType) {
|
||||
case AcquireLock:
|
||||
|
||||
@@ -18,6 +18,8 @@ public class ClickHousePlatform extends DatabasePlatform {
|
||||
//this.exceptionTranslator =
|
||||
this.nativeUuidType = true;
|
||||
this.dbDefaultValue.setNow("now()");
|
||||
this.dbDefaultValue.setFalse("0");
|
||||
this.dbDefaultValue.setTrue("1");
|
||||
|
||||
this.dbIdentity.setIdType(IdType.IDENTITY);
|
||||
this.dbIdentity.setSupportsGetGeneratedKeys(false);
|
||||
|
||||
+1
-12
@@ -11,18 +11,7 @@ public class CockroachPlatform extends PostgresPlatform {
|
||||
public CockroachPlatform() {
|
||||
super();
|
||||
this.platform = Platform.COCKROACH;
|
||||
// no like escape clause supported
|
||||
this.likeSpecialCharacters = new char[]{'%', '_'};
|
||||
this.likeClauseRaw = "like ?";
|
||||
this.likeClauseEscaped = "like ?";
|
||||
}
|
||||
|
||||
/**
|
||||
* Needs a commit after create index such that alter table add foreign key ... succeeds.
|
||||
*/
|
||||
@Override
|
||||
public boolean isDdlAutoCommit() {
|
||||
return true;
|
||||
this.historySupport = null; // not yet implemented in DDL
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-9
@@ -1,7 +1,6 @@
|
||||
package io.ebean.config.dbplatform.db2;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.annotation.PersistBatch;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
@@ -15,21 +14,19 @@ import java.sql.Types;
|
||||
/**
|
||||
* DB2 specific platform.
|
||||
*/
|
||||
public class DB2Platform extends DatabasePlatform {
|
||||
public abstract class BaseDB2Platform extends DatabasePlatform {
|
||||
|
||||
public DB2Platform() {
|
||||
public BaseDB2Platform() {
|
||||
super();
|
||||
this.platform = Platform.DB2;
|
||||
// Note: DB2 (at least LUW supports length up to 128)
|
||||
// TOOD: Check if we need to introduce a new platform (DB2_LUW_11 ?)
|
||||
this.maxTableNameLength = 18;
|
||||
this.maxConstraintNameLength = 18;
|
||||
this.supportsNativeJavaTime = false;
|
||||
this.truncateTable = "truncate table %s reuse storage ignore delete triggers immediate";
|
||||
this.likeClauseRaw = "like ?";
|
||||
this.sqlLimiter = new Db2SqlLimiter();
|
||||
|
||||
this.dbIdentity.setSupportsGetGeneratedKeys(true);
|
||||
this.dbIdentity.setSupportsSequence(true);
|
||||
|
||||
this.idInExpandedForm = true; // Db2 does not support (a,b) in ((?,?),(?,?))
|
||||
this.exceptionTranslator =
|
||||
new SqlErrorCodes()
|
||||
.addAcquireLock("40001","57033") // key -911/-913
|
||||
@@ -39,13 +36,13 @@ public class DB2Platform extends DatabasePlatform {
|
||||
.addDataIntegrity("23502","23503","23504","23511","23512","23511","42917","23515")
|
||||
.build();
|
||||
|
||||
historySupport = new DB2HistorySupport();
|
||||
booleanDbType = Types.BOOLEAN;
|
||||
dbTypeMap.put(DbType.TINYINT, new DbPlatformType("smallint", false));
|
||||
dbTypeMap.put(DbType.INTEGER, new DbPlatformType("integer", false));
|
||||
dbTypeMap.put(DbType.BIGINT, new DbPlatformType("bigint", false));
|
||||
dbTypeMap.put(DbType.REAL, new DbPlatformType("real"));
|
||||
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("decimal", 16, 3));
|
||||
persistBatchOnCascade = PersistBatch.NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -0,0 +1,39 @@
|
||||
package io.ebean.config.dbplatform.db2;
|
||||
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.config.dbplatform.DbType;
|
||||
import io.ebean.config.dbplatform.SqlErrorCodes;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
/**
|
||||
* DB2 specific platform for i Series.
|
||||
*
|
||||
* @author Cédric Sougné
|
||||
*/
|
||||
public class DB2ForIPlatform extends BaseDB2Platform {
|
||||
|
||||
public DB2ForIPlatform() {
|
||||
super();
|
||||
this.platform = Platform.DB2FORI;
|
||||
// Note: IBM i from 7.1 allow up to to 128
|
||||
// TODO: Check if we need to introduce older platform (DB2ForI_6 ? but older
|
||||
// documentation is not anymore published on ibm.com),
|
||||
this.maxTableNameLength = 128;
|
||||
this.maxConstraintNameLength = 128;
|
||||
|
||||
this.dbIdentity.setSupportsIdentity(true);
|
||||
|
||||
this.exceptionTranslator = new SqlErrorCodes().addAcquireLock("57033") // key -913
|
||||
.addDuplicateKey("23505") // -803
|
||||
// .addDataIntegrity("-407","-530","-531","-532","-543","-544","-545","-603","-667")
|
||||
// we need SQLState, not code:
|
||||
// https://www.ibm.com/support/knowledgecenter/en/SSEPEK_10.0.0/codes/src/tpc/db2z_n.html
|
||||
.addDataIntegrity("23502", "23503", "23504", "23507", "23511", "23512", "23513", "42917", "23515")
|
||||
.build();
|
||||
|
||||
booleanDbType = Types.SMALLINT;
|
||||
dbTypeMap.put(DbType.BOOLEAN, new DbPlatformType("smallint default 0"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package io.ebean.config.dbplatform.db2;
|
||||
|
||||
import io.ebean.config.dbplatform.DbStandardHistorySupport;
|
||||
|
||||
/**
|
||||
* DB2 based history support.
|
||||
*/
|
||||
public class DB2HistorySupport extends DbStandardHistorySupport {
|
||||
|
||||
@Override
|
||||
public String getAsOfViewSuffix(String asOfViewSuffix) {
|
||||
return " for system_time as of ?";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersionsBetweenSuffix(String asOfViewSuffix) {
|
||||
return " for system_time between ? and ?";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSysPeriodLower(String tableAlias, String sysPeriod) {
|
||||
return tableAlias + "." + sysPeriod + "_start";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSysPeriodUpper(String tableAlias, String sysPeriod) {
|
||||
return tableAlias + "." + sysPeriod + "_end";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package io.ebean.config.dbplatform.db2;
|
||||
|
||||
import io.ebean.annotation.PersistBatch;
|
||||
import io.ebean.annotation.Platform;
|
||||
|
||||
/**
|
||||
* DB2 specific platform for older DB2 versions. This platform is here for
|
||||
* compatibility reasons. It uses a length limit of 18 chars for table and
|
||||
* constraint names. Newer DB2 versions will support up to 128. It is strongly
|
||||
* recommended to migrate to db2luw/DB2ForI or db2zos platform.
|
||||
*/
|
||||
public class DB2LegacyPlatform extends BaseDB2Platform {
|
||||
public DB2LegacyPlatform() {
|
||||
super();
|
||||
this.platform = Platform.DB2;
|
||||
// Note: DB2 (at least LUW supports length up to 128)
|
||||
// TOOD: Check if we need to introduce a new platform (DB2_LUW_11 ?)
|
||||
this.maxTableNameLength = 18;
|
||||
this.maxConstraintNameLength = 18;
|
||||
this.persistBatchOnCascade = PersistBatch.NONE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package io.ebean.config.dbplatform.db2;
|
||||
|
||||
import io.ebean.annotation.Platform;
|
||||
|
||||
/**
|
||||
* DB2 platform for Linux/Unix/Windows.
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*
|
||||
*/
|
||||
public class DB2LuwPlatform extends BaseDB2Platform {
|
||||
public DB2LuwPlatform() {
|
||||
super();
|
||||
this.platform = Platform.DB2LUW;
|
||||
this.maxTableNameLength = 128;
|
||||
this.maxConstraintNameLength = 128;
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ public class DB2SequenceIdGenerator extends SequenceBatchIdGenerator {
|
||||
public DB2SequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
|
||||
super(be, ds, seqName, batchSize);
|
||||
this.baseSql = "values nextval for " + seqName;
|
||||
this.unionBaseSql = " union " + baseSql;
|
||||
this.unionBaseSql = ", nextval for " + seqName;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package io.ebean.config.dbplatform.db2;
|
||||
|
||||
import io.ebean.annotation.Platform;
|
||||
|
||||
/**
|
||||
* DB2 platform for z/OS.
|
||||
* Note: This platform is currently not tested!
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*
|
||||
*/
|
||||
public class DB2ZosPlatform extends BaseDB2Platform {
|
||||
public DB2ZosPlatform() {
|
||||
super();
|
||||
this.platform = Platform.DB2ZOS;
|
||||
this.maxTableNameLength = 128;
|
||||
this.maxConstraintNameLength = 128;
|
||||
}
|
||||
}
|
||||
@@ -15,10 +15,13 @@ public class Db2SqlLimiter implements SqlLimiter {
|
||||
sb.append("distinct ");
|
||||
}
|
||||
sb.append(request.getDbSql());
|
||||
|
||||
int firstRow = request.getFirstRow();
|
||||
if (firstRow > 0) {
|
||||
sb.append(" offset ").append(firstRow).append(" rows");
|
||||
}
|
||||
int maxRows = request.getMaxRows();
|
||||
if (maxRows > 0) {
|
||||
sb.append(" ").append(NEW_LINE).append("FETCH FIRST ").append(maxRows).append(" ROWS ONLY");
|
||||
sb.append(" fetch next ").append(maxRows).append(" rows only");
|
||||
}
|
||||
|
||||
String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
@@ -76,7 +77,7 @@ public class H2HistoryTrigger implements Trigger {
|
||||
public void fire(Connection connection, Object[] oldRow, Object[] newRow) throws SQLException {
|
||||
if (oldRow != null) {
|
||||
// a delete or update event
|
||||
Timestamp now = new Timestamp(System.currentTimeMillis());
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
oldRow[effectEndPosition] = now;
|
||||
if (newRow != null) {
|
||||
// update event. Set the effective start timestamp to now.
|
||||
|
||||
@@ -39,6 +39,7 @@ public class H2Platform extends DatabasePlatform {
|
||||
this.dbIdentity.setSupportsIdentity(true);
|
||||
|
||||
dbTypeMap.put(DbType.UUID, new DbPlatformType("uuid", false));
|
||||
dbTypeMap.put(DbType.INTEGER, new DbPlatformType("integer", false));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,13 +18,12 @@ public class H2SequenceIdGenerator extends SequenceBatchIdGenerator {
|
||||
*/
|
||||
public H2SequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
|
||||
super(be, ds, seqName, batchSize);
|
||||
this.baseSql = "select " + seqName + ".nextval";
|
||||
this.baseSql = "select nextval('" + seqName + "')";
|
||||
this.unionBaseSql = " union " + baseSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSql(int batchSize) {
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(baseSql);
|
||||
for (int i = 1; i < batchSize; i++) {
|
||||
|
||||
@@ -92,4 +92,8 @@ public class HanaPlatform extends DatabasePlatform {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUseMigrationStoredProcedures() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package io.ebean.config.dbplatform.mariadb;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.dbplatform.PlatformIdGenerator;
|
||||
import io.ebean.config.dbplatform.mysql.BaseMySqlPlatform;
|
||||
|
||||
/**
|
||||
@@ -11,6 +15,14 @@ public class MariaDbPlatform extends BaseMySqlPlatform {
|
||||
public MariaDbPlatform() {
|
||||
super();
|
||||
this.platform = Platform.MARIADB;
|
||||
this.sequenceBatchMode = false;
|
||||
this.historySupport = new MariaDbHistorySupport();
|
||||
this.dbIdentity.setSupportsSequence(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int stepSize, String seqName) {
|
||||
return new MariaDbSequence(be, ds, seqName, stepSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package io.ebean.config.dbplatform.mariadb;
|
||||
|
||||
import io.ebean.BackgroundExecutor;
|
||||
import io.ebean.config.dbplatform.SequenceStepIdGenerator;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
public class MariaDbSequence extends SequenceStepIdGenerator {
|
||||
|
||||
private final String nextSql;
|
||||
|
||||
/**
|
||||
* Construct where batchSize is the sequence step size.
|
||||
*/
|
||||
public MariaDbSequence(BackgroundExecutor be, DataSource ds, String seqName, int stepSize) {
|
||||
super(be, ds, seqName, stepSize);
|
||||
this.nextSql = "select next value for " + seqName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSql(int batchSize) {
|
||||
return nextSql;
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ public class Oracle11Platform extends OraclePlatform {
|
||||
public Oracle11Platform() {
|
||||
super();
|
||||
this.platform = Platform.ORACLE11;
|
||||
this.columnAliasPrefix = "c";
|
||||
this.sqlLimiter = new OracleRownumSqlLimiter();
|
||||
this.basicSqlLimiter = new OracleRownumBasicLimiter();
|
||||
dbIdentity.setIdType(IdType.SEQUENCE);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package io.ebean.config.dbplatform.oracle;
|
||||
|
||||
/**
|
||||
* Oracle 12 platform using column alias.
|
||||
*/
|
||||
public class Oracle12Platform extends OraclePlatform {
|
||||
|
||||
public Oracle12Platform() {
|
||||
super();
|
||||
//this.platform = Platform.ORACLE12;
|
||||
this.columnAliasPrefix = "c";
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,8 @@ public class OraclePlatform extends DatabasePlatform {
|
||||
public OraclePlatform() {
|
||||
super();
|
||||
this.platform = Platform.ORACLE;
|
||||
this.columnAliasPrefix = "c";
|
||||
this.supportsDeleteTableAlias = true;
|
||||
this.maxInBinding = 1000;
|
||||
this.maxTableNameLength = 30;
|
||||
this.maxConstraintNameLength = 30;
|
||||
this.dbEncrypt = new OracleDbEncrypt();
|
||||
@@ -35,11 +35,9 @@ public class OraclePlatform extends DatabasePlatform {
|
||||
dbIdentity.setSupportsSequence(true);
|
||||
dbIdentity.setSupportsIdentity(true);
|
||||
dbIdentity.setSupportsGetGeneratedKeys(true);
|
||||
|
||||
this.dbDefaultValue.setFalse("0");
|
||||
this.dbDefaultValue.setTrue("1");
|
||||
this.dbDefaultValue.setNow("current_timestamp");
|
||||
|
||||
this.treatEmptyStringsAsNull = true;
|
||||
this.likeClauseRaw = "like ?";
|
||||
|
||||
@@ -56,7 +54,6 @@ public class OraclePlatform extends DatabasePlatform {
|
||||
|
||||
booleanDbType = Types.INTEGER;
|
||||
dbTypeMap.put(DbType.BOOLEAN, new DbPlatformType("number(1)"));
|
||||
|
||||
dbTypeMap.put(DbType.INTEGER, new DbPlatformType("number", 10));
|
||||
dbTypeMap.put(DbType.BIGINT, new DbPlatformType("number", 19));
|
||||
dbTypeMap.put(DbType.REAL, new DbPlatformType("number", 19, 4));
|
||||
@@ -65,12 +62,10 @@ public class OraclePlatform extends DatabasePlatform {
|
||||
dbTypeMap.put(DbType.TINYINT, new DbPlatformType("number", 3));
|
||||
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("number", 16, 3));
|
||||
dbTypeMap.put(DbType.VARCHAR, new DbPlatformType("varchar2", 255));
|
||||
|
||||
dbTypeMap.put(DbType.LONGVARBINARY, new DbPlatformType("blob"));
|
||||
dbTypeMap.put(DbType.LONGVARCHAR, new DbPlatformType("clob"));
|
||||
dbTypeMap.put(DbType.VARBINARY, new DbPlatformType("raw", 255));
|
||||
dbTypeMap.put(DbType.BINARY, new DbPlatformType("raw", 255));
|
||||
|
||||
dbTypeMap.put(DbType.TIME, new DbPlatformType("timestamp"));
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -27,6 +27,7 @@ abstract class SqlServerBasePlatform extends DatabasePlatform {
|
||||
// SQL Server unless we are using sequences
|
||||
this.dbEncrypt = new SqlServerDbEncrypt();
|
||||
this.persistBatchOnCascade = PersistBatch.NONE;
|
||||
this.maxInBinding = 2000;
|
||||
this.idInExpandedForm = true;
|
||||
this.selectCountWithAlias = true;
|
||||
this.selectCountWithColumnAlias = true;
|
||||
@@ -119,4 +120,9 @@ abstract class SqlServerBasePlatform extends DatabasePlatform {
|
||||
// for update are hints on from clause of base table
|
||||
return sql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUseMigrationStoredProcedures() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package io.ebean.config.dbplatform.yugabyte;
|
||||
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.dbplatform.postgres.PostgresPlatform;
|
||||
|
||||
public class YugabytePlaform extends PostgresPlatform {
|
||||
|
||||
public YugabytePlaform() {
|
||||
super();
|
||||
this.platform = Platform.YUGABYTE;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package io.ebean.plugin;
|
||||
|
||||
import io.ebean.bean.EntityBean;
|
||||
|
||||
/**
|
||||
* Errorhandler to handle load errors and may be recover correct value.
|
||||
*
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface LoadErrorHandler {
|
||||
void handleLoadError(EntityBean bean, Property prop, String fullName, Exception e);
|
||||
}
|
||||
@@ -18,7 +18,7 @@ import java.util.Locale;
|
||||
* try {
|
||||
* File f = new File("src/test/resources/test1.csv");
|
||||
*
|
||||
* FileReader reader = new FileReader(f);
|
||||
* FileReader reader = new FileReader(f, encoding);
|
||||
*
|
||||
* CsvReader<Customer> csvReader = DB.createCsvReader(Customer.class);
|
||||
*
|
||||
|
||||
@@ -71,6 +71,20 @@ public class AnnotationUtil {
|
||||
return typeGet(clazz, annotation) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an element is annotated with an annotation of given type searching meta-annotations.
|
||||
*/
|
||||
public static boolean metaHas(AnnotatedElement element, Class<?> annotationType) {
|
||||
return !metaFindAll(element, annotationType).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all the annotations of a given type searching meta-annotations.
|
||||
*/
|
||||
public static Set<Annotation> metaFindAll(AnnotatedElement element, Class<?> annotationType) {
|
||||
return metaFindAllFor(element, Collections.singleton(annotationType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all the annotations for the filter searching meta-annotations.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package io.ebean.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Utilities for IO. It uses UTF-8 as encoding when reading/writing and uses
|
||||
* buffered IO for better performance.
|
||||
*/
|
||||
public class IOUtils {
|
||||
|
||||
/**
|
||||
* Read from stream as UTF-8.
|
||||
*/
|
||||
public static BufferedReader newReader(InputStream is) {
|
||||
return new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from file as UTF-8.
|
||||
*/
|
||||
public static BufferedReader newReader(File file) throws FileNotFoundException {
|
||||
return newReader(new FileInputStream(file));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write to stream as UTF-8
|
||||
*/
|
||||
public static BufferedWriter newWriter(OutputStream os) {
|
||||
return new BufferedWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Write to file as UTF-8
|
||||
*/
|
||||
public static BufferedWriter newWriter(File file) throws FileNotFoundException {
|
||||
return newWriter(new FileOutputStream(file));
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package io.ebean.util;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</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-12.13.2</tag>
|
||||
<tag>ebean-parent-12.16.0</tag>
|
||||
</scm>
|
||||
|
||||
<name>ebean autotune</name>
|
||||
@@ -26,7 +26,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jaxb</groupId>
|
||||
<artifactId>jaxb-runtime</artifactId>
|
||||
<version>2.3.2</version>
|
||||
<version>2.3.6</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>1.0</version>
|
||||
<version>1.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<tiles>
|
||||
<tile>io.ebean.tile:enhancement:12.11.3</tile>
|
||||
<tile>io.ebean.tile:enhancement:12.15.0</tile>
|
||||
<tile>io.avaje.tile:moditech-module:1.0</tile>
|
||||
</tiles>
|
||||
</configuration>
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
<!-- <parent>-->
|
||||
<!-- <groupId>org.avaje</groupId>-->
|
||||
<!-- <artifactId>java8-oss</artifactId>-->
|
||||
<!-- <version>2.2</version>-->
|
||||
<!-- </parent>-->
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
|
||||
<name>ebean autotune</name>
|
||||
<description>ebean automatic query tuning module</description>
|
||||
<artifactId>ebean-autotune</artifactId>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- needed for java 11+ -->
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jaxb</groupId>
|
||||
<artifactId>jaxb-runtime</artifactId>
|
||||
<version>2.3.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-datasource</artifactId>
|
||||
<version>${ebean-datasource.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.repaint.maven</groupId>
|
||||
<artifactId>tiles-maven-plugin</artifactId>
|
||||
<version>2.24</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<tiles>
|
||||
<tile>io.ebean.tile:enhancement:12.11.3</tile>
|
||||
<tile>io.avaje.tile:moditech-module:1.0</tile>
|
||||
</tiles>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
+15
-15
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean bom</name>
|
||||
@@ -71,88 +71,88 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-xml</artifactId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-autotune</artifactId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>kotlin-querybean-generator</artifactId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis</artifactId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-redis</artifactId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean bom</name>
|
||||
<description>ebean bill of materials pom</description>
|
||||
<artifactId>ebean-bom</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- dependencies external to this ebean.git build -->
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-runner</artifactId>
|
||||
<version>${ebean-ddl-runner.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration-auto</artifactId>
|
||||
<version>${ebean-migration-auto.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>${ebean-migration.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-datasource-api</artifactId>
|
||||
<version>${ebean-datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-datasource</artifactId>
|
||||
<version>${ebean-datasource.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-agent</artifactId>
|
||||
<version>${ebean-agent.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-maven-plugin</artifactId>
|
||||
<version>${ebean-maven-plugin.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test-docker</artifactId>
|
||||
<version>${ebean-test-docker.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- modules -->
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-xml</artifactId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-autotune</artifactId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>kotlin-querybean-generator</artifactId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis</artifactId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-redis</artifactId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</dependencyManagement>
|
||||
|
||||
</project>
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
@@ -16,7 +16,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<name>ebean core type</name>
|
||||
<description>ebean scalar types api</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.repaint.maven</groupId>
|
||||
<artifactId>tiles-maven-plugin</artifactId>
|
||||
<version>2.24</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<tiles>
|
||||
<tile>io.avaje.tile:moditech-module:1.0</tile>
|
||||
</tiles>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -47,6 +47,8 @@ public interface DataReader {
|
||||
|
||||
Object getObject() throws SQLException;
|
||||
|
||||
<T> T getObject(Class<T> cls) throws SQLException;
|
||||
|
||||
InputStream getBinaryStream() throws SQLException;
|
||||
|
||||
/**
|
||||
|
||||
+10
-10
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core</artifactId>
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-parent-12.13.2</tag>
|
||||
<tag>ebean-parent-12.16.0</tag>
|
||||
</scm>
|
||||
|
||||
<dependencies>
|
||||
@@ -23,7 +23,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-runner</artifactId>
|
||||
<version>1.2</version>
|
||||
<version>${ebean-ddl-runner.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,25 +35,25 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration-auto</artifactId>
|
||||
<version>1.1</version>
|
||||
<version>${ebean-migration-auto.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>12.13.2</version>
|
||||
<version>12.16.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -78,7 +78,7 @@
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>1.4.199</version>
|
||||
<version>${h2database.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.2.24</version>
|
||||
<version>42.3.3</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>1.0</version>
|
||||
<version>1.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -1,247 +0,0 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>ebean core</name>
|
||||
<description>ebean core module</description>
|
||||
<url>https://ebean.io/</url>
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>HEAD</tag>
|
||||
</scm>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-runner</artifactId>
|
||||
<version>1.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>classpath-scanner</artifactId>
|
||||
<version>6.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration-auto</artifactId>
|
||||
<version>1.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>12.13.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.antlr</groupId>
|
||||
<artifactId>antlr4-runtime</artifactId>
|
||||
<version>4.8-1</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
Class retention Nonnull and Nullable annotations
|
||||
to assist with IDE auto-completion with Ebean API
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>avaje-jsr305-x</artifactId>
|
||||
<version>1.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Provided scope so that the H2HistoryTrigger can live in Ebean core
|
||||
and not require a separate module for it -->
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>1.4.199</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.transaction</groupId>
|
||||
<artifactId>javax.transaction-api</artifactId>
|
||||
<version>1.3</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- validation annotations Size etc -->
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<version>2.0.1.Final</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>jakarta.validation</groupId>
|
||||
<artifactId>jakarta.validation-api</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
<version>2.9.7</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>javax.annotation</groupId>-->
|
||||
<!-- <artifactId>javax.annotation-api</artifactId>-->
|
||||
<!-- <version>1.3.2</version>-->
|
||||
<!-- <optional>true</optional>-->
|
||||
<!-- </dependency>-->
|
||||
|
||||
<!-- Jackson core used internally by Ebean -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Provided scope for Postgres JSON/JSONB support -->
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.2.24</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- Test scope -->
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-datasource</artifactId>
|
||||
<version>${ebean-datasource.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-maven-plugin</artifactId>
|
||||
<version>${ebean-maven-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>test</id>
|
||||
<phase>process-test-classes</phase>
|
||||
<configuration>
|
||||
<transformArgs>debug=0</transformArgs>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>testEnhance</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0-M4</version>
|
||||
<configuration>
|
||||
<useSystemClassLoader>false</useSystemClassLoader>
|
||||
<trimStackTrace>false</trimStackTrace>
|
||||
<failIfNoTests>false</failIfNoTests>
|
||||
<includes>
|
||||
<include>**/Test*.java</include>
|
||||
<include>**/*Test.java</include>
|
||||
<include>**/*Tests.java</include>
|
||||
</includes>
|
||||
<systemProperties>
|
||||
<property>
|
||||
<!-- transfer datasource.default parameter -->
|
||||
<name>datasource.default</name>
|
||||
<value>${datasource.default}</value>
|
||||
</property>
|
||||
<property>
|
||||
<!-- transfer dbClockDelta parameter -->
|
||||
<name>dbClockDelta</name>
|
||||
<value>${dbClockDelta}</value>
|
||||
</property>
|
||||
</systemProperties>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>3.1.1</version>
|
||||
<configuration>
|
||||
<doctitle>Ebean 12</doctitle>
|
||||
<overview>src/main/java/io/ebean/overview.html</overview>
|
||||
<excludePackageNames>io.ebeaninternal.*:io.ebeanservice:io.ebean.common:io.ebean.bean:io.ebean.service:io.ebean.metric:io.ebean.util:io.ebean.config.properties:io.ebean.config.dbplatform</excludePackageNames>
|
||||
<linksource>true</linksource>
|
||||
<overview>src/main/java/com/avaje/ebean/overview.html</overview>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-javadocs</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>io.repaint.maven</groupId>
|
||||
<artifactId>tiles-maven-plugin</artifactId>
|
||||
<version>2.24</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<tiles>
|
||||
<tile>io.avaje.tile:moditech-module:1.0</tile>
|
||||
</tiles>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -167,6 +167,7 @@ public final class BindParams implements Serializable {
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void setParameter(int position, Object value) {
|
||||
assert value != null : "use setNullParameter";
|
||||
Param p = getParam(position);
|
||||
if (value instanceof Collection) {
|
||||
// use of postgres ANY with positioned parameter
|
||||
@@ -218,6 +219,7 @@ public final class BindParams implements Serializable {
|
||||
* Set a named In parameter that is not null.
|
||||
*/
|
||||
public Param setParameter(String name, Object value) {
|
||||
assert value != null : "use setNullParameter";
|
||||
Param p = getParam(name);
|
||||
p.setInValue(value);
|
||||
return p;
|
||||
|
||||
@@ -4,7 +4,7 @@ import io.ebean.bean.EntityBeanIntercept;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A buffer of beans for batch lazy loading and secondary query loading.
|
||||
@@ -13,7 +13,7 @@ public interface LoadBeanBuffer {
|
||||
|
||||
int batchSize();
|
||||
|
||||
List<EntityBeanIntercept> batch();
|
||||
Set<EntityBeanIntercept> batch();
|
||||
|
||||
BeanDescriptor<?> descriptor();
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ import java.util.Set;
|
||||
*/
|
||||
public final class LoadBeanRequest extends LoadRequest {
|
||||
|
||||
private final List<EntityBeanIntercept> batch;
|
||||
private final Set<EntityBeanIntercept> batch;
|
||||
private final LoadBeanBuffer loadBuffer;
|
||||
private final String lazyLoadProperty;
|
||||
private final boolean loadCache;
|
||||
@@ -58,7 +58,7 @@ public final class LoadBeanRequest extends LoadRequest {
|
||||
/**
|
||||
* Return the batch of beans to actually load.
|
||||
*/
|
||||
public List<EntityBeanIntercept> batch() {
|
||||
public Set<EntityBeanIntercept> batch() {
|
||||
return batch;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,6 @@ package io.ebeaninternal.api;
|
||||
import io.ebean.*;
|
||||
import io.ebean.bean.BeanCollectionLoader;
|
||||
import io.ebean.bean.CallOrigin;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.event.readaudit.ReadAuditLogger;
|
||||
import io.ebean.event.readaudit.ReadAuditPrepare;
|
||||
import io.ebean.meta.MetricVisitor;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.api;
|
||||
|
||||
import io.ebean.meta.QueryPlanRequest;
|
||||
import io.ebeaninternal.server.type.bindcapture.BindCapture;
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,6 @@ import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import io.ebean.event.changelog.BeanChange;
|
||||
import io.ebean.event.changelog.ChangeSet;
|
||||
import io.ebean.event.changelog.ChangeType;
|
||||
import io.ebean.text.json.JsonContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
|
||||
@@ -15,8 +15,6 @@ import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
/**
|
||||
* Wraps the objects involved in executing a SQL / Relational Query.
|
||||
*/
|
||||
|
||||
@@ -5,7 +5,6 @@ import io.avaje.classpath.scanner.ClassPathScannerFactory;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
|
||||
@@ -3,20 +3,20 @@ package io.ebeaninternal.server.core;
|
||||
import io.ebean.ScriptRunner;
|
||||
import io.ebean.ddlrunner.DdlRunner;
|
||||
import io.ebean.ddlrunner.ScriptTransform;
|
||||
import io.ebean.util.IOUtils;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.util.UrlHelper;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.LineNumberReader;
|
||||
import java.io.Reader;
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
final class DScriptRunner implements ScriptRunner {
|
||||
|
||||
private static final String NEWLINE = "\n";
|
||||
@@ -30,8 +30,8 @@ final class DScriptRunner implements ScriptRunner {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(String path) {
|
||||
run(path, null);
|
||||
public void run(String resourcePath) {
|
||||
run(resourcePath, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -49,26 +49,42 @@ final class DScriptRunner implements ScriptRunner {
|
||||
run(resource, null, placeholderMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(Path file) {
|
||||
run(file, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(Path file, Map<String, String> placeholderMap) {
|
||||
requireNonNull(file);
|
||||
String scriptName = file.toFile().getName();
|
||||
String content = fileContent(file);
|
||||
runScript(content, scriptName, placeholderMap, false);
|
||||
}
|
||||
|
||||
private void run(URL resource, String scriptName, Map<String, String> placeholderMap) {
|
||||
if (resource == null) {
|
||||
throw new IllegalArgumentException("resource is null?");
|
||||
}
|
||||
requireNonNull(resource);
|
||||
if (scriptName == null) {
|
||||
scriptName = resource.getFile();
|
||||
}
|
||||
|
||||
String content = content(resource);
|
||||
runScript(content, scriptName, placeholderMap, false);
|
||||
}
|
||||
|
||||
private String content(URL resource) {
|
||||
if (resource == null) {
|
||||
throw new IllegalArgumentException("resource is null?");
|
||||
private String fileContent(Path file) {
|
||||
try (InputStream inputStream = new FileInputStream(file.toFile());
|
||||
Reader reader = IOUtils.newReader(inputStream)) {
|
||||
return readContent(reader);
|
||||
} catch (IOException e) {
|
||||
throw new PersistenceException("Failed to read script content", e);
|
||||
}
|
||||
}
|
||||
|
||||
try (InputStream inputStream = UrlHelper.openNoCache(resource)) {
|
||||
return readContent(new InputStreamReader(inputStream));
|
||||
|
||||
private String content(URL resource) {
|
||||
requireNonNull(resource);
|
||||
try (InputStream inputStream = UrlHelper.openNoCache(resource);
|
||||
Reader reader = IOUtils.newReader(inputStream)) {
|
||||
return readContent(reader);
|
||||
} catch (IOException e) {
|
||||
throw new PersistenceException("Failed to read script content", e);
|
||||
}
|
||||
@@ -84,14 +100,15 @@ final class DScriptRunner implements ScriptRunner {
|
||||
*/
|
||||
private void runScript(String content, String scriptName, Map<String, String> placeholderMap, boolean useAutoCommit) {
|
||||
try {
|
||||
if (placeholderMap != null) {
|
||||
if (placeholderMap != null && !placeholderMap.isEmpty()) {
|
||||
content = ScriptTransform.build(null, placeholderMap).transform(content);
|
||||
}
|
||||
|
||||
try (Connection connection = obtainConnection()) {
|
||||
DdlRunner runner = new DdlRunner(useAutoCommit, scriptName, platformName);
|
||||
runner.runAll(content, connection);
|
||||
connection.commit();
|
||||
if (!connection.getAutoCommit()) {
|
||||
connection.commit();
|
||||
}
|
||||
runner.runNonTransactional(connection);
|
||||
}
|
||||
|
||||
@@ -109,7 +126,6 @@ final class DScriptRunner implements ScriptRunner {
|
||||
}
|
||||
|
||||
private String readContent(Reader reader) throws IOException {
|
||||
|
||||
StringBuilder buf = new StringBuilder();
|
||||
try (LineNumberReader lineReader = new LineNumberReader(reader)) {
|
||||
String line;
|
||||
|
||||
+39
-12
@@ -4,7 +4,10 @@ import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.config.dbplatform.clickhouse.ClickHousePlatform;
|
||||
import io.ebean.config.dbplatform.cockroach.CockroachPlatform;
|
||||
import io.ebean.config.dbplatform.db2.DB2Platform;
|
||||
import io.ebean.config.dbplatform.db2.DB2ForIPlatform;
|
||||
import io.ebean.config.dbplatform.db2.DB2LegacyPlatform;
|
||||
import io.ebean.config.dbplatform.db2.DB2LuwPlatform;
|
||||
import io.ebean.config.dbplatform.db2.DB2ZosPlatform;
|
||||
import io.ebean.config.dbplatform.h2.H2Platform;
|
||||
import io.ebean.config.dbplatform.hana.HanaPlatform;
|
||||
import io.ebean.config.dbplatform.hsqldb.HsqldbPlatform;
|
||||
@@ -13,6 +16,7 @@ import io.ebean.config.dbplatform.mysql.MySql55Platform;
|
||||
import io.ebean.config.dbplatform.mysql.MySqlPlatform;
|
||||
import io.ebean.config.dbplatform.nuodb.NuoDbPlatform;
|
||||
import io.ebean.config.dbplatform.oracle.Oracle11Platform;
|
||||
import io.ebean.config.dbplatform.oracle.Oracle12Platform;
|
||||
import io.ebean.config.dbplatform.oracle.OraclePlatform;
|
||||
import io.ebean.config.dbplatform.postgres.Postgres9Platform;
|
||||
import io.ebean.config.dbplatform.postgres.PostgresPlatform;
|
||||
@@ -20,16 +24,14 @@ import io.ebean.config.dbplatform.sqlanywhere.SqlAnywherePlatform;
|
||||
import io.ebean.config.dbplatform.sqlite.SQLitePlatform;
|
||||
import io.ebean.config.dbplatform.sqlserver.SqlServer16Platform;
|
||||
import io.ebean.config.dbplatform.sqlserver.SqlServer17Platform;
|
||||
import io.ebean.config.dbplatform.yugabyte.YugabytePlaform;
|
||||
import io.ebeaninternal.api.CoreLog;
|
||||
import io.ebeaninternal.api.DbOffline;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.*;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Create a DatabasePlatform from the configuration.
|
||||
@@ -87,6 +89,9 @@ public class DatabasePlatformFactory {
|
||||
if (dbName.equals("oracle11") || dbName.equals("oracle10") || dbName.equals("oracle9")) {
|
||||
return new Oracle11Platform();
|
||||
}
|
||||
if (dbName.equals("oracle12")) {
|
||||
return new Oracle12Platform();
|
||||
}
|
||||
if (dbName.equals("oracle")) {
|
||||
return new OraclePlatform();
|
||||
}
|
||||
@@ -103,7 +108,19 @@ public class DatabasePlatformFactory {
|
||||
return new SqlAnywherePlatform();
|
||||
}
|
||||
if (dbName.equals("db2")) {
|
||||
return new DB2Platform();
|
||||
throw new IllegalArgumentException("Please choose the more specific db2luw/db2zos/db2fori platform. Refer to issue #2514 for details");
|
||||
}
|
||||
if (dbName.equals("db2legacy")) {
|
||||
return new DB2LegacyPlatform();
|
||||
}
|
||||
if (dbName.equals("db2zos")) {
|
||||
return new DB2ZosPlatform();
|
||||
}
|
||||
if (dbName.equals("db2fori")) {
|
||||
return new DB2ForIPlatform();
|
||||
}
|
||||
if (dbName.equals("db2luw")) {
|
||||
return new DB2LuwPlatform();
|
||||
}
|
||||
if (dbName.equals("clickhouse")) {
|
||||
return new ClickHousePlatform();
|
||||
@@ -149,7 +166,8 @@ public class DatabasePlatformFactory {
|
||||
} else if (dbProductName.contains("hsql database engine")) {
|
||||
return new HsqldbPlatform();
|
||||
} else if (dbProductName.contains("postgres")) {
|
||||
return readPostgres(connection, majorVersion);
|
||||
String productVersion = metaData.getDatabaseProductVersion().toLowerCase(Locale.ENGLISH);
|
||||
return readPostgres(connection, majorVersion, productVersion);
|
||||
} else if (dbProductName.contains("mariadb")) {
|
||||
return new MariaDbPlatform();
|
||||
} else if (dbProductName.contains("mysql")) {
|
||||
@@ -159,7 +177,7 @@ public class DatabasePlatformFactory {
|
||||
} else if (dbProductName.contains("sqlite")) {
|
||||
return new SQLitePlatform();
|
||||
} else if (dbProductName.contains("db2")) {
|
||||
return new DB2Platform();
|
||||
throw new IllegalArgumentException("For DB2 please explicitly choose either db2legacy/db2luw/db2zos/db2fori platform. Refer to issue #2514 for details");
|
||||
} else if (dbProductName.contains("sql anywhere")) {
|
||||
return new SqlAnywherePlatform();
|
||||
} else if (dbProductName.contains("hdb")) {
|
||||
@@ -173,7 +191,13 @@ public class DatabasePlatformFactory {
|
||||
}
|
||||
|
||||
private DatabasePlatform oracleVersion(int majorVersion) {
|
||||
return majorVersion < 12 ? new Oracle11Platform() : new OraclePlatform();
|
||||
if (majorVersion < 12) {
|
||||
return new Oracle11Platform();
|
||||
}
|
||||
if (majorVersion < 13) {
|
||||
return new Oracle12Platform();
|
||||
}
|
||||
return new OraclePlatform();
|
||||
}
|
||||
|
||||
private DatabasePlatform mysqlVersion(int majorVersion, int minorVersion) {
|
||||
@@ -186,11 +210,14 @@ public class DatabasePlatformFactory {
|
||||
/**
|
||||
* Use a select version() query as it could be Postgres or CockroachDB.
|
||||
*/
|
||||
private static DatabasePlatform readPostgres(Connection connection, int majorVersion) {
|
||||
private static DatabasePlatform readPostgres(Connection connection, int majorVersion, String productVersion) {
|
||||
if (productVersion.contains("-yb-")) {
|
||||
return new YugabytePlaform();
|
||||
}
|
||||
try (PreparedStatement statement = connection.prepareStatement("select version() as \"version\"")) {
|
||||
try (ResultSet resultSet = statement.executeQuery()) {
|
||||
if (resultSet.next()) {
|
||||
String productVersion = resultSet.getString("version").toLowerCase();
|
||||
productVersion = resultSet.getString("version").toLowerCase();
|
||||
if (productVersion.contains("cockroach")) {
|
||||
return new CockroachPlatform();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebean.CacheMode;
|
||||
import io.ebean.ExpressionList;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
@@ -17,6 +16,7 @@ import org.slf4j.Logger;
|
||||
|
||||
import javax.persistence.EntityNotFoundException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Helper to handle lazy loading and refreshing of beans.
|
||||
@@ -39,14 +39,14 @@ final class DefaultBeanLoader {
|
||||
}
|
||||
|
||||
void loadMany(BeanCollection<?> bc, boolean onlyIds) {
|
||||
loadManyInternal(bc.getOwnerBean(), bc.getPropertyName(), null, false, onlyIds);
|
||||
loadManyInternal(bc.getOwnerBean(), bc.getPropertyName(), false, onlyIds);
|
||||
}
|
||||
|
||||
void refreshMany(EntityBean parentBean, String propertyName) {
|
||||
loadManyInternal(parentBean, propertyName, null, true, false);
|
||||
loadManyInternal(parentBean, propertyName, true, false);
|
||||
}
|
||||
|
||||
private void loadManyInternal(EntityBean parentBean, String propertyName, Transaction t, boolean refresh, boolean onlyIds) {
|
||||
private void loadManyInternal(EntityBean parentBean, String propertyName, boolean refresh, boolean onlyIds) {
|
||||
EntityBeanIntercept ebi = parentBean._ebean_getIntercept();
|
||||
PersistenceContext pc = ebi.getPersistenceContext();
|
||||
BeanDescriptor<?> parentDesc = server.descriptor(parentBean.getClass());
|
||||
@@ -105,7 +105,7 @@ final class DefaultBeanLoader {
|
||||
query.setReadOnly(true);
|
||||
}
|
||||
|
||||
server.findOne(query, t);
|
||||
server.findOne(query, null);
|
||||
if (beanCollection != null) {
|
||||
if (beanCollection.checkEmptyLazyLoad()) {
|
||||
if (log.isDebugEnabled()) {
|
||||
@@ -121,7 +121,7 @@ final class DefaultBeanLoader {
|
||||
* Load a batch of beans for +query or +lazy loading.
|
||||
*/
|
||||
void loadBean(LoadBeanRequest loadRequest) {
|
||||
List<EntityBeanIntercept> batch = loadRequest.batch();
|
||||
Set<EntityBeanIntercept> batch = loadRequest.batch();
|
||||
if (batch.isEmpty()) {
|
||||
throw new RuntimeException("Nothing in batch?");
|
||||
}
|
||||
@@ -199,7 +199,7 @@ final class DefaultBeanLoader {
|
||||
query.setLazyLoadProperty(ebi.getLazyLoadProperty());
|
||||
if (draft) {
|
||||
query.asDraft();
|
||||
} else {
|
||||
} else if (mode == SpiQuery.Mode.LAZYLOAD_BEAN) {
|
||||
query.setIncludeSoftDeletes();
|
||||
}
|
||||
if (embeddedOwnerIndex > -1) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.ebeaninternal.server.core;
|
||||
|
||||
import io.ebean.config.BackgroundExecutorWrapper;
|
||||
import io.ebean.config.ContainerConfig;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.config.DatabaseConfigProvider;
|
||||
@@ -67,7 +68,8 @@ public final class DefaultContainer implements SpiContainer {
|
||||
String namePrefix = "ebean-" + config.getName();
|
||||
int schedulePoolSize = config.getBackgroundExecutorSchedulePoolSize();
|
||||
int shutdownSecs = config.getBackgroundExecutorShutdownSecs();
|
||||
return new DefaultBackgroundExecutor(schedulePoolSize, shutdownSecs, namePrefix);
|
||||
BackgroundExecutorWrapper wrapper = config.getBackgroundExecutorWrapper();
|
||||
return new DefaultBackgroundExecutor(schedulePoolSize, shutdownSecs, namePrefix, wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -373,7 +373,9 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
migrationRunner.setDefaultDbSchema(dbSchema);
|
||||
}
|
||||
migrationRunner.setName(config.getName());
|
||||
migrationRunner.setPlatform(config.getDatabasePlatform().getPlatform().base().name().toLowerCase());
|
||||
Platform platform = config.getDatabasePlatform().getPlatform();
|
||||
migrationRunner.setBasePlatform(platform.base().name().toLowerCase());
|
||||
migrationRunner.setPlatform(platform.name().toLowerCase());
|
||||
migrationRunner.loadProperties(config.getProperties());
|
||||
migrationRunner.run(config.getDataSource());
|
||||
}
|
||||
@@ -613,6 +615,10 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
try (Connection connection = dataSource().getConnection()) {
|
||||
for (String table : tables) {
|
||||
executeSql(connection, databasePlatform.truncateStatement(table));
|
||||
if (databasePlatform.getPlatform().base() == Platform.DB2) {
|
||||
// DB2 requires commit after each truncate statement
|
||||
connection.commit();
|
||||
}
|
||||
}
|
||||
connection.commit();
|
||||
} catch (SQLException e) {
|
||||
|
||||
@@ -99,7 +99,6 @@ final class InitDataSource {
|
||||
if (config.getDatabasePlatformName() == null) {
|
||||
throw new PersistenceException("You MUST specify a DatabasePlatformName on DatabaseConfig when offline");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
attachAlert(dsConfig);
|
||||
|
||||
@@ -280,7 +280,7 @@ public final class InternalConfiguration {
|
||||
|
||||
private MultiValueBind createMultiValueBind(Platform platform) {
|
||||
// only Postgres at this stage
|
||||
if (platform.base() == Platform.POSTGRES) {
|
||||
if (platform.base() == Platform.POSTGRES || platform.base() == Platform.YUGABYTE || platform.base() == Platform.COCKROACH) {
|
||||
return new PostgresMultiValueBind();
|
||||
}
|
||||
return new MultiValueBind();
|
||||
|
||||
@@ -40,6 +40,9 @@ public final class PersistDeferredRelationship {
|
||||
|
||||
// bind the set clause for the importedId
|
||||
int pos = importedId.bind(1, sqlUpdate, assocBean);
|
||||
if (pos == -1) {
|
||||
return; // could not bind: TODO: should we log/throw an error?
|
||||
}
|
||||
// bind the where clause for the bean
|
||||
Object[] idValues = beanDescriptor.idBinder().getIdValues(bean);
|
||||
for (int j = 0; j < idValues.length; j++) {
|
||||
|
||||
+20
-2
@@ -3,6 +3,7 @@ package io.ebeaninternal.server.deploy;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebeaninternal.server.query.SqlJoinType;
|
||||
import io.ebeaninternal.server.query.SqlTreeJoin;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
@@ -60,11 +61,28 @@ final class AssocOneHelpRefInherit extends AssocOneHelp {
|
||||
return ref;
|
||||
}
|
||||
|
||||
@Override
|
||||
void appendFrom(DbSqlContext ctx, SqlJoinType joinType) {
|
||||
// add join to support the discriminator column
|
||||
String relativePrefix = ctx.getRelativePrefix(property.name);
|
||||
property.tableJoin.addJoin(joinType, relativePrefix, ctx);
|
||||
ctx.addExtraJoin(new Extra(relativePrefix, joinType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra join to support the discriminator column.
|
||||
*/
|
||||
final class Extra implements SqlTreeJoin {
|
||||
final String relativePrefix;
|
||||
final SqlJoinType joinType;
|
||||
Extra(String relativePrefix, SqlJoinType joinType) {
|
||||
this.relativePrefix = relativePrefix;
|
||||
this.joinType = joinType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addJoin(DbSqlContext ctx) {
|
||||
// add join to support the discriminator column *IF* join is not already present
|
||||
property.tableJoin.addJoin(joinType, relativePrefix, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -86,6 +86,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
private final ConcurrentHashMap<String, ElPropertyDeploy> elDeployCache = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<String, ElComparator<T>> comparatorCache = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<String, STreeProperty> dynamicProperty = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<String, Map<String,String>> pathMaps = new ConcurrentHashMap<>();
|
||||
|
||||
private final Map<String, SpiRawSql> namedRawSql;
|
||||
private final Map<String, String> namedQuery;
|
||||
private final boolean multiValueSupported;
|
||||
@@ -1308,8 +1310,8 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
* Hit the bean cache trying to load a list/batch of entities.
|
||||
* Return the set of entities that were successfully loaded from L2 cache.
|
||||
*/
|
||||
public Set<EntityBeanIntercept> cacheBeanLoadAll(List<EntityBeanIntercept> list, PersistenceContext persistenceContext, int lazyLoadProperty, String propertyName) {
|
||||
return cacheHelp.beanCacheLoadAll(list, persistenceContext, lazyLoadProperty, propertyName);
|
||||
public Set<EntityBeanIntercept> cacheBeanLoadAll(Set<EntityBeanIntercept> batch, PersistenceContext persistenceContext, int lazyLoadProperty, String propertyName) {
|
||||
return cacheHelp.beanCacheLoadAll(batch, persistenceContext, lazyLoadProperty, propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2775,6 +2777,22 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
return draftableElement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> pathMap(String prefix) {
|
||||
return pathMaps.computeIfAbsent(prefix, s -> {
|
||||
HashMap<String, String> m = new HashMap<>();
|
||||
for (STreePropertyAssocMany many : propsMany()) {
|
||||
String name = many.name();
|
||||
m.put(name, prefix + "." + name);
|
||||
}
|
||||
for (STreePropertyAssocOne one : propsOne()) {
|
||||
String name = one.name();
|
||||
m.put(name, prefix + "." + name);
|
||||
}
|
||||
return m.isEmpty() ? Collections.emptyMap() : m;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmbeddedPath(String propertyPath) {
|
||||
ElPropertyDeploy elProp = elPropertyDeploy(propertyPath);
|
||||
|
||||
+2
-3
@@ -693,9 +693,9 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
/**
|
||||
* Load a batch of entities from L2 bean cache checking the lazy loaded property is loaded.
|
||||
*/
|
||||
Set<EntityBeanIntercept> beanCacheLoadAll(List<EntityBeanIntercept> list, PersistenceContext context, int lazyLoadProperty, String propertyName) {
|
||||
Set<EntityBeanIntercept> beanCacheLoadAll(Set<EntityBeanIntercept> batch, PersistenceContext context, int lazyLoadProperty, String propertyName) {
|
||||
Map<Object, EntityBeanIntercept> ebis = new HashMap<>();
|
||||
for (EntityBeanIntercept ebi : list) {
|
||||
for (EntityBeanIntercept ebi : batch) {
|
||||
ebis.put(desc.cacheKeyForBean(ebi.getOwner()), ebi);
|
||||
}
|
||||
|
||||
@@ -716,7 +716,6 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
if (beanLog.isTraceEnabled()) {
|
||||
beanLog.trace(" load {}({}) - cache miss on property({})", cacheName, key, propertyName);
|
||||
}
|
||||
iterator.remove();
|
||||
} else {
|
||||
CachedBeanDataToBean.load(desc, ebi.getOwner(), cacheData, context);
|
||||
loaded.add(ebi);
|
||||
|
||||
@@ -992,6 +992,9 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
*/
|
||||
public String renderDbType(DbPlatformType dbType, boolean strict) {
|
||||
if (dbColumnDefn != null) {
|
||||
if (dbColumnDefn.endsWith(";")) {
|
||||
return dbColumnDefn + dbType.renderType(dbLength, dbScale, strict);
|
||||
}
|
||||
return dbColumnDefn;
|
||||
}
|
||||
return dbType.renderType(dbLength, dbScale, strict);
|
||||
@@ -1161,6 +1164,26 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
return lob;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this <code>isLob()</code> or the type will effectively map to a lob.
|
||||
*/
|
||||
@Override
|
||||
public boolean isDbLob() {
|
||||
if (lob) {
|
||||
return true;
|
||||
}
|
||||
switch (dbType) {
|
||||
case DbPlatformType.JSON:
|
||||
case DbPlatformType.JSONB:
|
||||
return dbLength == 0; // must be analog to DbPlatformTypeMapping.lookup
|
||||
case DbPlatformType.JSONBlob:
|
||||
case DbPlatformType.JSONClob:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isLobType(int type) {
|
||||
switch (type) {
|
||||
case Types.CLOB:
|
||||
|
||||
@@ -226,7 +226,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
*/
|
||||
@Override
|
||||
public void addBeanToCollectionWithCreate(EntityBean parentBean, EntityBean detailBean, boolean withCheck) {
|
||||
BeanCollection<?> bc = (BeanCollection<?>) super.getValue(parentBean);
|
||||
BeanCollection<?> bc = beanCollection(parentBean);
|
||||
if (bc == null) {
|
||||
bc = help.createEmpty(parentBean);
|
||||
setValue(parentBean, bc);
|
||||
@@ -234,6 +234,15 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
help.add(bc, detailBean, withCheck);
|
||||
}
|
||||
|
||||
private BeanCollection<?> beanCollection(EntityBean parentBean) {
|
||||
try {
|
||||
return (BeanCollection<?>) super.getValue(parentBean);
|
||||
} catch (ClassCastException e) {
|
||||
// fetching element collection, ok for now
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is considered 'empty' from a save perspective.
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebeaninternal.server.deploy;
|
||||
|
||||
import io.ebeaninternal.server.query.SqlJoinType;
|
||||
import io.ebeaninternal.server.query.SqlTreeJoin;
|
||||
|
||||
/**
|
||||
* Used to provide context during sql construction.
|
||||
@@ -133,4 +134,13 @@ public interface DbSqlContext {
|
||||
*/
|
||||
void appendFromForUpdate();
|
||||
|
||||
/**
|
||||
* Delay adding an extra join to support inheritance discriminator in projection (IF required).
|
||||
*/
|
||||
void addExtraJoin(SqlTreeJoin treeJoin);
|
||||
|
||||
/**
|
||||
* Add extra joins *IF* required to support inheritance discriminator in projection.
|
||||
*/
|
||||
void flushExtraJoins();
|
||||
}
|
||||
|
||||
+5
@@ -62,4 +62,9 @@ class DynamicPropertyAggregationFormula extends DynamicPropertyBase {
|
||||
ctx.appendParseSelect(parsedFormula, alias);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDbLob() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -85,6 +85,9 @@ public final class ImportedIdEmbedded implements ImportedId {
|
||||
for (ImportedIdSimple anImported : imported) {
|
||||
if (anImported.owner.isUpdateable()) {
|
||||
Object scalarValue = anImported.foreignProperty.getValue(embedded);
|
||||
if (scalarValue == null) {
|
||||
return -1; // could not bind
|
||||
}
|
||||
update.setParameter(pos++, scalarValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,6 +151,9 @@ public final class ImportedIdSimple implements ImportedId, Comparable<ImportedId
|
||||
@Override
|
||||
public int bind(int position, SqlUpdate update, EntityBean bean) {
|
||||
Object value = getIdValue(bean);
|
||||
if (value == null) {
|
||||
return -1; // could not bind
|
||||
}
|
||||
update.setParameter(position, value);
|
||||
return ++position;
|
||||
}
|
||||
|
||||
+1
-1
@@ -775,7 +775,7 @@ public class DeployBeanDescriptor<T> {
|
||||
this.identityMode.setIdType(IdType.EXTERNAL);
|
||||
switch (config.getUuidVersion()) {
|
||||
case VERSION1:
|
||||
this.idGenerator = UuidV1IdGenerator.getInstance(config.getUuidStateFile());
|
||||
this.idGenerator = UuidV1IdGenerator.getInstance(config.getUuidStateFile(), config.getUuidNodeId());
|
||||
break;
|
||||
case VERSION1RND:
|
||||
this.idGenerator = UuidV1RndIdGenerator.INSTANCE;
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
package io.ebeaninternal.server.deploy.parse;
|
||||
|
||||
import io.ebean.annotation.Aggregation;
|
||||
import io.ebean.annotation.Avg;
|
||||
import io.ebean.annotation.DbMigration;
|
||||
import io.ebean.annotation.Index;
|
||||
import io.ebean.annotation.Indices;
|
||||
import io.ebean.annotation.Max;
|
||||
import io.ebean.annotation.Min;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.annotation.Sum;
|
||||
import io.ebean.config.NamingConvention;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
import io.ebean.util.AnnotationUtil;
|
||||
@@ -20,7 +15,6 @@ import javax.persistence.JoinColumns;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import io.ebeaninternal.server.deploy.InheritInfo;
|
||||
import io.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
|
||||
import javax.persistence.DiscriminatorColumn;
|
||||
import javax.persistence.DiscriminatorType;
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
import javax.persistence.Inheritance;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -105,8 +106,11 @@ public final class DeployInherit {
|
||||
if (da != null) {
|
||||
// lowercase the discriminator column for RawSql and JSON
|
||||
info.setColumnName(da.name().toLowerCase());
|
||||
info.setColumnType(da.discriminatorType());
|
||||
info.setColumnLength(da.length());
|
||||
DiscriminatorType discriminatorType = da.discriminatorType();
|
||||
info.setColumnType(discriminatorType);
|
||||
if (discriminatorType == DiscriminatorType.STRING) {
|
||||
info.setColumnLength(da.length());
|
||||
}
|
||||
info.setColumnDefn(da.columnDefinition());
|
||||
}
|
||||
if (!info.isAbstract()) {
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package io.ebeaninternal.server.executor;
|
||||
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* A "CachedThreadPool" based on Daemon threads.
|
||||
* <p>
|
||||
* The Threads are created as needed and once idle live for 60 seconds.
|
||||
*/
|
||||
final class DaemonExecutorService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DaemonExecutorService.class);
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(false);
|
||||
private final String namePrefix;
|
||||
private final int shutdownWaitSeconds;
|
||||
private final ExecutorService service;
|
||||
|
||||
DaemonExecutorService(int shutdownWaitSeconds, String namePrefix) {
|
||||
this.service = Executors.newCachedThreadPool(new DaemonThreadFactory(namePrefix));
|
||||
this.shutdownWaitSeconds = shutdownWaitSeconds;
|
||||
this.namePrefix = namePrefix;
|
||||
}
|
||||
|
||||
<T> Future<T> submit(Callable<T> task) {
|
||||
return service.submit(task);
|
||||
}
|
||||
|
||||
Future<?> submit(Runnable task) {
|
||||
return service.submit(task);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown this thread pool nicely if possible.
|
||||
* <p>
|
||||
* This will wait a maximum of 20 seconds before terminating any threads still working.
|
||||
*/
|
||||
void shutdown() {
|
||||
lock.lock();
|
||||
try {
|
||||
if (service.isShutdown()) {
|
||||
logger.debug("DaemonExecutorService[{}] already shut down", namePrefix);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
logger.debug("DaemonExecutorService[{}] shutting down...", namePrefix);
|
||||
service.shutdown();
|
||||
if (!service.awaitTermination(shutdownWaitSeconds, TimeUnit.SECONDS)) {
|
||||
logger.info("DaemonExecutorService[{}] shut down timeout exceeded. Terminating running threads.", namePrefix);
|
||||
service.shutdownNow();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("Error during shutdown of DaemonThreadPool[" + namePrefix + "]", e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+69
-41
@@ -1,15 +1,13 @@
|
||||
package io.ebeaninternal.server.executor;
|
||||
|
||||
import io.avaje.lang.NonNullApi;
|
||||
import io.ebean.config.BackgroundExecutorWrapper;
|
||||
import io.ebeaninternal.api.SpiBackgroundExecutor;
|
||||
import org.slf4j.MDC;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The default implementation of the BackgroundExecutor.
|
||||
@@ -17,56 +15,81 @@ import java.util.concurrent.TimeUnit;
|
||||
@NonNullApi
|
||||
public final class DefaultBackgroundExecutor implements SpiBackgroundExecutor {
|
||||
|
||||
private final ScheduledExecutorService executor;
|
||||
private static final Logger log = LoggerFactory.getLogger("io.ebean.BackgroundExecutor");
|
||||
|
||||
private final ScheduledExecutorService schedulePool;
|
||||
private final DaemonExecutorService pool;
|
||||
private final BackgroundExecutorWrapper wrapper;
|
||||
|
||||
/**
|
||||
* Construct the default implementation of BackgroundExecutor.
|
||||
*/
|
||||
public DefaultBackgroundExecutor(int schedulePoolSize, int shutdownWaitSeconds, String namePrefix) {
|
||||
this.executor = new DaemonScheduleThreadPool(schedulePoolSize, shutdownWaitSeconds, namePrefix);
|
||||
public DefaultBackgroundExecutor(int schedulePoolSize, int shutdownWaitSeconds, String namePrefix, BackgroundExecutorWrapper wrapper) {
|
||||
this.schedulePool = new DaemonScheduleThreadPool(schedulePoolSize, shutdownWaitSeconds, namePrefix + "-periodic-");
|
||||
this.pool = new DaemonExecutorService(shutdownWaitSeconds, namePrefix);
|
||||
this.wrapper = wrapper;
|
||||
log.debug("Created backgroundExecutor {} (schedulePoolSize={}, shutdownWaitSeconds={})", namePrefix, schedulePoolSize, shutdownWaitSeconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the task with MDC context if defined.
|
||||
*/
|
||||
<T> Callable<T> wrapMDC(Callable<T> task) {
|
||||
final Map<String, String> map = MDC.getCopyOfContextMap();
|
||||
if (map == null) {
|
||||
<T> Callable<T> wrap(Callable<T> task) {
|
||||
if (wrapper == null) {
|
||||
return task;
|
||||
} else {
|
||||
return () -> {
|
||||
MDC.setContextMap(map);
|
||||
try {
|
||||
return task.call();
|
||||
} finally {
|
||||
MDC.clear();
|
||||
}
|
||||
};
|
||||
return wrapper.wrap(task);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the task with MDC context if defined.
|
||||
*/
|
||||
Runnable wrapMDC(Runnable task) {
|
||||
final Map<String, String> map = MDC.getCopyOfContextMap();
|
||||
if (map == null) {
|
||||
Runnable wrap(Runnable task) {
|
||||
if (wrapper == null) {
|
||||
return task;
|
||||
} else {
|
||||
return () -> {
|
||||
MDC.setContextMap(map);
|
||||
try {
|
||||
return wrapper.wrap(task);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decorates a runnable by adding an exception handler and some timing metrics.
|
||||
* This is used in methods that accepts a <code>Runnable</code> and return
|
||||
* either <code>void</code> or <code>ScheduledFuture</code>, as there is
|
||||
* normally no Future.get() call.
|
||||
*
|
||||
* Note: When submitting a <code>Callable</code>, you must check
|
||||
* <code>Future.get()</code> for exceptions.
|
||||
*/
|
||||
private Runnable logExceptions(Runnable task) {
|
||||
long queued = System.nanoTime();
|
||||
log.trace("Queued {}", task);
|
||||
return () -> {
|
||||
try {
|
||||
if (log.isTraceEnabled()) {
|
||||
long start = System.nanoTime();
|
||||
log.trace("Start {} (delay time {} us)", task, (start - queued) / 1000L);
|
||||
task.run();
|
||||
log.trace("Stop {} (exec time {} us)", task, (System.nanoTime() - start) / 1000L);
|
||||
} else {
|
||||
task.run();
|
||||
} finally {
|
||||
MDC.clear();
|
||||
}
|
||||
};
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
// log any exception here. Note they will not bubble up to the calling user
|
||||
// unless Future.get() is checked. (Which is almost never done on scheduled
|
||||
// background executions)
|
||||
log.error("Error while executing the task {}", task, t);
|
||||
throw t;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Future<T> submit(Callable<T> task) {
|
||||
return executor.submit(wrapMDC(task));
|
||||
// Note: No "logExceptions" as we expect Future.get() by the invoker
|
||||
return pool.submit(wrap(task));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,47 +97,52 @@ public final class DefaultBackgroundExecutor implements SpiBackgroundExecutor {
|
||||
*/
|
||||
@Override
|
||||
public Future<?> submit(Runnable task) {
|
||||
return executor.submit(wrapMDC(task));
|
||||
return pool.submit(wrap(task));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void execute(Runnable task) {
|
||||
submit(task);
|
||||
submit(logExceptions(task));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executePeriodically(Runnable task, long delay, TimeUnit unit) {
|
||||
executor.scheduleWithFixedDelay(wrapMDC(task), delay, delay, unit);
|
||||
schedulePool.scheduleWithFixedDelay(wrap(logExceptions(task)), delay, delay, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executePeriodically(Runnable task, long initialDelay, long delay, TimeUnit unit) {
|
||||
executor.scheduleWithFixedDelay(wrapMDC(task), initialDelay, delay, unit);
|
||||
schedulePool.scheduleWithFixedDelay(wrap(logExceptions(task)), initialDelay, delay, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long initialDelay, long delay, TimeUnit unit) {
|
||||
return executor.scheduleWithFixedDelay(wrapMDC(task), initialDelay, delay, unit);
|
||||
return schedulePool.scheduleWithFixedDelay(wrap(logExceptions(task)), initialDelay, delay, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long initialDelay, long delay, TimeUnit unit) {
|
||||
return executor.scheduleAtFixedRate(wrapMDC(task), initialDelay, delay, unit);
|
||||
return schedulePool.scheduleAtFixedRate(wrap(logExceptions(task)), initialDelay, delay, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScheduledFuture<?> schedule(Runnable task, long delay, TimeUnit unit) {
|
||||
return executor.schedule(wrapMDC(task), delay, unit);
|
||||
return schedulePool.schedule(wrap(logExceptions(task)), delay, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <V> ScheduledFuture<V> schedule(Callable<V> task, long delay, TimeUnit unit) {
|
||||
return executor.schedule(wrapMDC(task), delay, unit);
|
||||
// Note: No "logExceptions" as we expect Future.get() by the invoker
|
||||
return schedulePool.schedule(wrap(task), delay, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
executor.shutdown();
|
||||
log.trace("BackgroundExecutor shutting down");
|
||||
schedulePool.shutdown();
|
||||
pool.shutdown();
|
||||
log.debug("BackgroundExecutor stopped");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package io.ebeaninternal.server.expression.platform;
|
||||
|
||||
/**
|
||||
* DB2 handling of platform specific expressions. ARRAY expressions not supported.
|
||||
*/
|
||||
final class Db2DbExpression extends BasicDbExpression {
|
||||
|
||||
@Override
|
||||
public String concat(String property0, String separator, String property1, String suffix) {
|
||||
return concatOperator(property0, separator, property1, suffix);
|
||||
}
|
||||
|
||||
}
|
||||
+5
-6
@@ -10,23 +10,22 @@ public final class DbExpressionHandlerFactory {
|
||||
* Create and return the appropriate platform specific handing of expressions.
|
||||
*/
|
||||
public static DbExpressionHandler from(DatabasePlatform databasePlatform) {
|
||||
Platform platform = databasePlatform.getPlatform();
|
||||
Platform platform = databasePlatform.getPlatform().base();
|
||||
switch (platform) {
|
||||
case H2:
|
||||
return new H2DbExpression();
|
||||
case POSTGRES:
|
||||
case POSTGRES9:
|
||||
case YUGABYTE:
|
||||
case COCKROACH:
|
||||
return new PostgresDbExpression();
|
||||
case MARIADB:
|
||||
return new MariaDbExpression();
|
||||
case MYSQL55:
|
||||
case MYSQL:
|
||||
return new MySqlDbExpression();
|
||||
case ORACLE:
|
||||
case ORACLE11:
|
||||
return new OracleDbExpression();
|
||||
case SQLSERVER16:
|
||||
case SQLSERVER17:
|
||||
case DB2:
|
||||
return new Db2DbExpression();
|
||||
case SQLSERVER:
|
||||
return new SqlServerDbExpression();
|
||||
case HANA:
|
||||
|
||||
+2
-1
@@ -10,6 +10,7 @@ final class H2DbExpression extends BasicDbExpression {
|
||||
|
||||
@Override
|
||||
public void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
|
||||
bitwiseFunction(request, propName, operator, compare);
|
||||
String funcName = functionName(operator);
|
||||
request.append(funcName).append("(").append(propName).append(", cast(? as long)) ").append(compare).append(" cast(? as long)");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
* It extends the UuidV1RndIdGenerator so that it can generate rfc4122 compliant Type 1 UUIDs.
|
||||
*
|
||||
* This generator produces real Type 1 UUIDs (best for sqlserver) - You should use this generator only,
|
||||
* if you can guarantee, that mac addess is uniqe.
|
||||
* if you can guarantee, that mac addess is uniqe or specify 'ebean.uuidNodeId' in your config file.
|
||||
*
|
||||
*/
|
||||
public class UuidV1IdGenerator extends UuidV1RndIdGenerator {
|
||||
|
||||
@@ -25,38 +26,36 @@ public class UuidV1IdGenerator extends UuidV1RndIdGenerator {
|
||||
/**
|
||||
* Returns an instance for given file.
|
||||
*/
|
||||
public static UuidV1IdGenerator getInstance(String file) {
|
||||
return INSTANCES.computeIfAbsent(new File(file), UuidV1IdGenerator::new);
|
||||
public static UuidV1IdGenerator getInstance(String file, String nodeId) {
|
||||
return getInstance(new File(file), nodeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance for given file.
|
||||
*/
|
||||
public static UuidV1IdGenerator getInstance(File file) {
|
||||
return INSTANCES.computeIfAbsent(file, UuidV1IdGenerator::new);
|
||||
public static UuidV1IdGenerator getInstance(File file, String nodeId) {
|
||||
return INSTANCES.computeIfAbsent(file, f ->new UuidV1IdGenerator(f, nodeId == null ? null : nodeId.toLowerCase()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an alternative node id - set with the 'ebean.uuid.nodeId' system property.
|
||||
*/
|
||||
private static byte[] getAlternativeNodeId() {
|
||||
private static byte[] parseAlternativeNodeId(String altNodeId) {
|
||||
String[] components = altNodeId.split("-");
|
||||
if (components.length != 6) {
|
||||
throw new IllegalArgumentException(altNodeId + " is invalid. Expected format: xx-xx-xx-xx-xx-xx");
|
||||
}
|
||||
try {
|
||||
String altNodeId = System.getProperty("ebean.uuid.nodeId");
|
||||
if (altNodeId != null) {
|
||||
String[] components = altNodeId.split("-");
|
||||
if (components.length != 5) {
|
||||
throw new IllegalArgumentException("Invalid nodeId string: " + altNodeId);
|
||||
}
|
||||
byte[] nodeId = new byte[6];
|
||||
for (int i=0; i<5; i++) {
|
||||
nodeId[i] = Byte.decode("0x"+components[i]).byteValue();
|
||||
}
|
||||
return nodeId;
|
||||
byte[] nodeId = new byte[6];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
// do not use Byte.parseByte
|
||||
// https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6259307
|
||||
nodeId[i] = (byte) Integer.parseInt(components[i], 16);
|
||||
}
|
||||
} catch (SecurityException se) {
|
||||
// ignore
|
||||
return nodeId;
|
||||
} catch (IllegalArgumentException iae) {
|
||||
throw new IllegalArgumentException(altNodeId + " is invalid.", iae);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,43 +107,85 @@ public class UuidV1IdGenerator extends UuidV1RndIdGenerator {
|
||||
* Creates a new instance of UuidGenerator. Note that there should not be more
|
||||
* than one instance per stateFile.
|
||||
*/
|
||||
private UuidV1IdGenerator(final File stateFile) {
|
||||
private UuidV1IdGenerator(final File stateFile, String altNodeId) {
|
||||
super();
|
||||
this.stateFile = stateFile;
|
||||
try {
|
||||
// See, if there is an alternative MAC address set.
|
||||
nodeId = getAlternativeNodeId();
|
||||
if (nodeId != null) {
|
||||
log.info("Using alternative MAC {} to generate Type 1 UUIDs", getNodeIdentifier());
|
||||
if (altNodeId == null) {
|
||||
// using hardware mode
|
||||
tryHardwareId();
|
||||
} else if (altNodeId.equals("generate")) {
|
||||
tryGenerateMode();
|
||||
} else if (altNodeId.equals("random")) {
|
||||
useRandomMode();
|
||||
} else {
|
||||
nodeId = getHardwareId();
|
||||
log.info("Using MAC {} to generate Type 1 UUIDs", getNodeIdentifier());
|
||||
// See, if there is an alternative MAC address set.
|
||||
nodeId = parseAlternativeNodeId(altNodeId);
|
||||
restoreState();
|
||||
log.info("Explicitly using ID {} to generate Type 1 UUIDs", getNodeIdentifier());
|
||||
}
|
||||
if (nodeId == null) {
|
||||
canSaveState = false;
|
||||
// RFC 4.5 use random portion for node
|
||||
nodeId = super.getNodeIdBytes();
|
||||
log.error("Have to fall back to random node identifier {} (Reason: No suitable network interface found)", getNodeIdentifier());
|
||||
UUID uuid = nextId(null);
|
||||
long ts = timeStamp.get();
|
||||
ts -= UUID_EPOCH_OFFSET;
|
||||
ts /= MILLIS_TO_UUID;
|
||||
|
||||
} else {
|
||||
boolean flag = restoreState();
|
||||
UUID uuid = nextId(null);
|
||||
long ts = timeStamp.get();
|
||||
ts -= UUID_EPOCH_OFFSET;
|
||||
ts /= MILLIS_TO_UUID;
|
||||
|
||||
saveState();
|
||||
log.debug("RestoreState: {}, ClockSeq {}, Timestamp {}, uuid {}, stateFile: {})", flag, clockSeq.get(),
|
||||
new Date(ts), uuid, stateFile);
|
||||
}
|
||||
saveState();
|
||||
log.debug("Saved state: clockSeq {}, timestamp {}, uuid {}, stateFile: {})", clockSeq.get(), new Date(ts), uuid, stateFile);
|
||||
} catch (IOException e) {
|
||||
canSaveState = false;
|
||||
log.error("There was a problem while detecting the nodeId. Falling back to random mode. Try using to specify 'ebean.uuidNodeId' property", e);
|
||||
useRandomMode();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to initialize the generator by retrieving the MAC address from
|
||||
* hardware. If there is no suitable network interface found, it will fall back
|
||||
* to "generate" mode.
|
||||
*
|
||||
* @throws IOException if state file is not readable or tryGenerateMode also
|
||||
* fails.
|
||||
*/
|
||||
private void tryHardwareId() throws IOException {
|
||||
try {
|
||||
nodeId = getHardwareId();
|
||||
} catch (IOException e) {
|
||||
log.error("Error while reading MAC address. Fall back to 'generate' mode", e);
|
||||
tryGenerateMode();
|
||||
}
|
||||
|
||||
if (nodeId != null) {
|
||||
restoreState();
|
||||
log.info("Using MAC {} to generate Type 1 UUIDs", getNodeIdentifier());
|
||||
return;
|
||||
}
|
||||
log.warn("No suitable network interface found. Fall back to 'generate' mode");
|
||||
tryGenerateMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries the "generate" mode. A nodeId is generated once and saved to the state
|
||||
* file
|
||||
*/
|
||||
private void tryGenerateMode() throws IOException {
|
||||
if (restoreState()) {
|
||||
log.info("Using recently generated nodeId {} to generate Type 1 UUIDs", getNodeIdentifier());
|
||||
} else {
|
||||
// RFC 4.5 use random portion for node
|
||||
nodeId = super.getNodeIdBytes();
|
||||
log.error("Have to fall back to random node identifier {} (Reason: {} )", getNodeIdentifier(), e.getMessage());
|
||||
log.info("Using a newly generated nodeId {} to generate Type 1 UUIDs", getNodeIdentifier());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Random mode. A nodeId is generated every start up. no state file is
|
||||
* maintained. This should always work.
|
||||
*/
|
||||
private void useRandomMode() {
|
||||
canSaveState = false;
|
||||
nodeId = super.getNodeIdBytes();
|
||||
log.info("Explicitly using a new random ID {} to generate Type 1 UUIDs", getNodeIdentifier());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Node-identifier (=MAC address) as string
|
||||
*/
|
||||
@@ -164,22 +205,38 @@ public class UuidV1IdGenerator extends UuidV1RndIdGenerator {
|
||||
*/
|
||||
private boolean restoreState() throws IOException {
|
||||
Properties prop = new Properties();
|
||||
if (stateFile.exists()) {
|
||||
try (InputStream is = new FileInputStream(stateFile)) {
|
||||
prop.load(is);
|
||||
}
|
||||
if (!stateFile.exists()) {
|
||||
log.debug("State file '{}' does not exist", stateFile);
|
||||
return false;
|
||||
}
|
||||
if (getNodeIdentifier().equals(prop.getProperty("nodeId"))) {
|
||||
try {
|
||||
Integer seq = Integer.valueOf(prop.getProperty("clockSeq")) & 0x3FFF;
|
||||
Long ts = Long.valueOf(prop.getProperty("timeStamp"));
|
||||
clockSeq.set(seq);
|
||||
timeStamp.set(ts);
|
||||
log.debug("Restored state from '{}'", stateFile);
|
||||
return true;
|
||||
} catch (NumberFormatException nfe) {
|
||||
// nop
|
||||
try (InputStream is = new FileInputStream(stateFile)) {
|
||||
prop.load(is);
|
||||
}
|
||||
|
||||
String propNodeId = prop.getProperty("nodeId");
|
||||
if (propNodeId == null || propNodeId.isEmpty()) {
|
||||
log.warn("State file '{}' is incomplete", stateFile);
|
||||
return false; // we cannot restore
|
||||
}
|
||||
try {
|
||||
if (nodeId == null) {
|
||||
nodeId = parseAlternativeNodeId(propNodeId);
|
||||
} else if (!getNodeIdentifier().equals(propNodeId)) {
|
||||
log.warn(
|
||||
"The nodeId in the state file '{}' has changed from {} to {}. "
|
||||
+ "This can happen when MAC address changes or when two containers share the same state file",
|
||||
stateFile, propNodeId, getNodeIdentifier());
|
||||
return false;
|
||||
}
|
||||
Integer seq = Integer.valueOf(prop.getProperty("clockSeq")) & 0x3FFF;
|
||||
Long ts = Long.valueOf(prop.getProperty("timeStamp"));
|
||||
clockSeq.set(seq);
|
||||
timeStamp.set(ts);
|
||||
log.debug("State successfully restored: {}", prop);
|
||||
return true;
|
||||
|
||||
} catch (IllegalArgumentException nfe) {
|
||||
log.error("State file '{}' is corrupt", stateFile, nfe);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
+15
-14
@@ -15,6 +15,7 @@ import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import io.ebeaninternal.server.querydefn.OrmQueryProperties;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
@@ -66,7 +67,7 @@ final class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext
|
||||
}
|
||||
}
|
||||
|
||||
protected void register(EntityBeanIntercept ebi) {
|
||||
void register(EntityBeanIntercept ebi) {
|
||||
if (currentBuffer.isFull()) {
|
||||
currentBuffer = createBuffer(batchSize);
|
||||
}
|
||||
@@ -91,7 +92,7 @@ final class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext
|
||||
try {
|
||||
if (bufferList != null) {
|
||||
for (LoadBuffer loadBuffer : bufferList) {
|
||||
if (!loadBuffer.list.isEmpty()) {
|
||||
if (!loadBuffer.batch.isEmpty()) {
|
||||
parent.getEbeanServer().loadBean(new LoadBeanRequest(loadBuffer, parentRequest));
|
||||
}
|
||||
if (forEach) {
|
||||
@@ -115,13 +116,13 @@ final class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext
|
||||
private final ReentrantLock bufferLock = new ReentrantLock();
|
||||
private final DLoadBeanContext context;
|
||||
private final int batchSize;
|
||||
private final List<EntityBeanIntercept> list;
|
||||
private final Set<EntityBeanIntercept> batch;
|
||||
private PersistenceContext persistenceContext;
|
||||
|
||||
LoadBuffer(DLoadBeanContext context, int batchSize) {
|
||||
this.context = context;
|
||||
this.batchSize = batchSize;
|
||||
this.list = new ArrayList<>(batchSize);
|
||||
this.batch = new HashSet<>(Math.max((int) (batchSize/.75f) + 1, 16));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -139,7 +140,7 @@ final class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext
|
||||
* Return true if the buffer is full.
|
||||
*/
|
||||
public boolean isFull() {
|
||||
return batchSize == list.size();
|
||||
return batchSize == batch.size();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,12 +151,12 @@ final class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext
|
||||
// get persistenceContext from first loaded bean into the buffer
|
||||
persistenceContext = ebi.getPersistenceContext();
|
||||
}
|
||||
list.add(ebi);
|
||||
batch.add(ebi);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EntityBeanIntercept> batch() {
|
||||
return list;
|
||||
public Set<EntityBeanIntercept> batch() {
|
||||
return batch;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -190,13 +191,13 @@ final class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext
|
||||
// lazy load property was a Many
|
||||
return;
|
||||
}
|
||||
if (list.isEmpty()) {
|
||||
if (!batch.contains(ebi)) {
|
||||
// re-add to the batch and lazy load from DB skipping l2 cache
|
||||
list.add(ebi);
|
||||
batch.add(ebi);
|
||||
} else if (context.hitCache) {
|
||||
Set<EntityBeanIntercept> hits = context.desc.cacheBeanLoadAll(list, persistenceContext, ebi.getLazyLoadPropertyIndex(), ebi.getLazyLoadProperty());
|
||||
list.removeAll(hits);
|
||||
if (list.isEmpty() || hits.contains(ebi)) {
|
||||
Set<EntityBeanIntercept> hits = context.desc.cacheBeanLoadAll(batch, persistenceContext, ebi.getLazyLoadPropertyIndex(), ebi.getLazyLoadProperty());
|
||||
batch.removeAll(hits);
|
||||
if (batch.isEmpty() || hits.contains(ebi)) {
|
||||
// successfully hit the L2 cache so don't invoke DB lazy loading
|
||||
return;
|
||||
}
|
||||
@@ -204,7 +205,7 @@ final class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext
|
||||
|
||||
LoadBeanRequest req = new LoadBeanRequest(this, ebi, context.hitCache);
|
||||
context.desc.ebeanServer().loadBean(req);
|
||||
list.clear();
|
||||
batch.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,18 +21,12 @@ import java.util.List;
|
||||
*/
|
||||
public final class BatchedPstmt implements SpiProfileTransactionEvent {
|
||||
|
||||
/**
|
||||
* The underlying statement.
|
||||
*/
|
||||
private static final DB2GetKeys DB2_HACK = new DB2GetKeys();
|
||||
|
||||
private PreparedStatement pstmt;
|
||||
|
||||
/**
|
||||
* True if an insert that uses generated keys.
|
||||
*/
|
||||
private final boolean isGenKeys;
|
||||
|
||||
/**
|
||||
* The list of BatchPostExecute used to perform post processing.
|
||||
* The list of BatchPostExecute used to perform post-processing.
|
||||
*/
|
||||
private final List<BatchPostExecute> list = new ArrayList<>();
|
||||
private final String sql;
|
||||
@@ -170,12 +164,14 @@ public final class BatchedPstmt implements SpiProfileTransactionEvent {
|
||||
}
|
||||
|
||||
private void getGeneratedKeys() throws SQLException {
|
||||
if (DB2_HACK.getGeneratedKeys(pstmt, list)) {
|
||||
return;
|
||||
}
|
||||
int index = 0;
|
||||
try (ResultSet rset = pstmt.getGeneratedKeys()) {
|
||||
while (rset.next()) {
|
||||
Object idValue = rset.getObject(1);
|
||||
list.get(index).setGeneratedKey(idValue);
|
||||
index++;
|
||||
list.get(index++).setGeneratedKey(idValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package io.ebeaninternal.server.persist;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Horrible DB2 hack.
|
||||
*/
|
||||
final class DB2GetKeys {
|
||||
|
||||
private static Class<? extends PreparedStatement> DB2_PREPARED_STATEMENT;
|
||||
private static Method GET_DB_GENERATED_KEYS;
|
||||
|
||||
static {
|
||||
try {
|
||||
DB2_PREPARED_STATEMENT = (Class<? extends PreparedStatement>) Class.forName("com.ibm.db2.jcc.DB2PreparedStatement");
|
||||
GET_DB_GENERATED_KEYS = DB2_PREPARED_STATEMENT.getDeclaredMethod("getDBGeneratedKeys");
|
||||
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException cnf) {
|
||||
// NOP
|
||||
}
|
||||
}
|
||||
|
||||
static boolean getGeneratedKeys(PreparedStatement pstmt, List<BatchPostExecute> list) throws SQLException {
|
||||
if (DB2_PREPARED_STATEMENT != null) {
|
||||
PreparedStatement db2Stmt = null;
|
||||
if (DB2_PREPARED_STATEMENT.isInstance(pstmt)) {
|
||||
db2Stmt = pstmt;
|
||||
} else if (pstmt.isWrapperFor(DB2_PREPARED_STATEMENT)) {
|
||||
db2Stmt = pstmt.unwrap(DB2_PREPARED_STATEMENT);
|
||||
}
|
||||
if (db2Stmt != null) {
|
||||
// WTF: https://stackoverflow.com/questions/41725492/how-to-get-auto-generated-keys-of-batch-insert-statement
|
||||
ResultSet[] result;
|
||||
try {
|
||||
result = (ResultSet[]) GET_DB_GENERATED_KEYS.invoke(db2Stmt);
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
|
||||
throw new SQLException("Could not get generated keys for DB2", e);
|
||||
}
|
||||
int index = 0;
|
||||
for (ResultSet resultSet : result) {
|
||||
while (resultSet.next()) {
|
||||
Object idValue = resultSet.getObject(1);
|
||||
list.get(index++).setGeneratedKey(idValue);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -41,15 +41,15 @@ public final class DefaultPersister implements Persister {
|
||||
* Actually does the persisting work.
|
||||
*/
|
||||
private final PersistExecute persistExecute;
|
||||
|
||||
private final SpiEbeanServer server;
|
||||
|
||||
private final BeanDescriptorManager beanDescriptorManager;
|
||||
private final int maxInBinding;
|
||||
|
||||
public DefaultPersister(SpiEbeanServer server, Binder binder, BeanDescriptorManager descMgr) {
|
||||
this.server = server;
|
||||
this.beanDescriptorManager = descMgr;
|
||||
this.persistExecute = new DefaultPersistExecute(binder, server.config().getPersistBatchSize());
|
||||
this.maxInBinding = server.databasePlatform().getMaxInBinding();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,8 +81,7 @@ public final class DefaultPersister implements Persister {
|
||||
int rc = request.executeOrQueue();
|
||||
request.commitTransIfRequired();
|
||||
return rc;
|
||||
|
||||
} catch (RuntimeException e) {
|
||||
} catch (Throwable e) {
|
||||
request.rollbackTransIfRequired();
|
||||
throw e;
|
||||
} finally {
|
||||
@@ -333,6 +332,13 @@ public final class DefaultPersister implements Persister {
|
||||
* Recursively delete the bean. This calls back to the EbeanServer.
|
||||
*/
|
||||
private int deleteRecurse(EntityBean detailBean, Transaction t, DeleteMode deleteMode) {
|
||||
return deleteRequest(createDeleteCascade(detailBean, t, deleteMode.persistType()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete without being a cascade.
|
||||
*/
|
||||
private int delete(EntityBean detailBean, Transaction t, DeleteMode deleteMode) {
|
||||
return deleteRequest(createDeleteRequest(detailBean, t, deleteMode.persistType()));
|
||||
}
|
||||
|
||||
@@ -376,8 +382,7 @@ public final class DefaultPersister implements Persister {
|
||||
req.resetDepth();
|
||||
req.commitTransIfRequired();
|
||||
req.flushBatchOnCascade();
|
||||
|
||||
} catch (RuntimeException ex) {
|
||||
} catch (Throwable ex) {
|
||||
req.rollbackTransIfRequired();
|
||||
throw ex;
|
||||
} finally {
|
||||
@@ -413,8 +418,7 @@ public final class DefaultPersister implements Persister {
|
||||
req.resetDepth();
|
||||
req.commitTransIfRequired();
|
||||
req.flushBatchOnCascade();
|
||||
|
||||
} catch (RuntimeException ex) {
|
||||
} catch (Throwable ex) {
|
||||
req.rollbackTransIfRequired();
|
||||
throw ex;
|
||||
} finally {
|
||||
@@ -552,7 +556,7 @@ public final class DefaultPersister implements Persister {
|
||||
req.flushBatchOnCascade();
|
||||
return rows;
|
||||
|
||||
} catch (RuntimeException ex) {
|
||||
} catch (Throwable ex) {
|
||||
req.rollbackTransIfRequired();
|
||||
throw ex;
|
||||
} finally {
|
||||
@@ -560,7 +564,7 @@ public final class DefaultPersister implements Persister {
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteList(List<?> beanList, SpiTransaction t, DeleteMode deleteMode, boolean children) {
|
||||
private void deleteCascade(List<?> beanList, SpiTransaction t, DeleteMode deleteMode, boolean children) {
|
||||
if (children) {
|
||||
t.depth(-1);
|
||||
t.checkBatchEscalationOnCollection();
|
||||
@@ -604,7 +608,7 @@ public final class DefaultPersister implements Persister {
|
||||
for (Object id : ids) {
|
||||
EntityBean bean = descriptor.createEntityBean();
|
||||
descriptor.convertSetId(id, bean);
|
||||
int rowCount = deleteRecurse(bean, transaction, deleteMode);
|
||||
int rowCount = delete(bean, transaction, deleteMode);
|
||||
if (rowCount == -1) {
|
||||
total = -1;
|
||||
} else if (total != -1) {
|
||||
@@ -642,6 +646,20 @@ public final class DefaultPersister implements Persister {
|
||||
* Delete by Id or a List of Id's.
|
||||
*/
|
||||
private int delete(BeanDescriptor<?> descriptor, Object id, List<Object> idList, Transaction transaction, DeleteMode deleteMode) {
|
||||
int rows = 0;
|
||||
if (maxInBinding > 0) {
|
||||
// SqlServer has a 2100 parameter limit, so delete max 2000 ids at once
|
||||
// this gives space up to 100 more query parameters.
|
||||
while (idList != null && idList.size() > maxInBinding) {
|
||||
rows += deleteBatch(descriptor, id, idList.subList(0, maxInBinding), transaction, deleteMode);
|
||||
idList = idList.subList(maxInBinding, idList.size());
|
||||
}
|
||||
}
|
||||
rows += deleteBatch(descriptor, id, idList, transaction, deleteMode);
|
||||
return rows;
|
||||
}
|
||||
|
||||
private int deleteBatch(BeanDescriptor<?> descriptor, Object id, List<Object> idList, Transaction transaction, DeleteMode deleteMode) {
|
||||
SpiTransaction t = (SpiTransaction) transaction;
|
||||
if (t.isPersistCascade()) {
|
||||
BeanPropertyAssocOne<?>[] propImportDelete = descriptor.propertiesOneImportedDelete();
|
||||
@@ -656,7 +674,7 @@ public final class DefaultPersister implements Persister {
|
||||
t.logSummary("-- DeleteById of " + descriptor.name() + " ids[" + idList + "] requires fetch of foreign key values");
|
||||
}
|
||||
List<?> beanList = server.findList(q, t);
|
||||
deleteList(beanList, t, deleteMode, false);
|
||||
deleteCascade(beanList, t, deleteMode, false);
|
||||
return beanList.size();
|
||||
|
||||
} else {
|
||||
@@ -994,6 +1012,8 @@ public final class DefaultPersister implements Persister {
|
||||
executeSqlUpdate(sqlDelete, t);
|
||||
|
||||
} else {
|
||||
// TODO: Review first checking if many property is loaded and using the loaded beans
|
||||
// ... and only using findIdsByParentId() when the many property isn't loaded
|
||||
// Delete recurse using the Id values of the children
|
||||
Object parentId = desc.getId(parentBean);
|
||||
List<Object> idsByParentId = many.findIdsByParentId(parentId, null, t, excludeDetailIds, deleteMode.isHard());
|
||||
@@ -1017,7 +1037,7 @@ public final class DefaultPersister implements Persister {
|
||||
for (Object id : childIds) {
|
||||
refList.add(targetDesc.createReference(id, null));
|
||||
}
|
||||
deleteList(refList, t, deleteMode, true);
|
||||
deleteCascade(refList, t, deleteMode, true);
|
||||
} else {
|
||||
// perform delete by statement if possible
|
||||
delete(targetDesc, null, childIds, t, deleteMode);
|
||||
@@ -1157,6 +1177,10 @@ public final class DefaultPersister implements Persister {
|
||||
return createDeleteRequest(bean, t, type, Flags.ZERO);
|
||||
}
|
||||
|
||||
private <T> PersistRequestBean<T> createDeleteCascade(EntityBean bean, Transaction t, Type type) {
|
||||
return createDeleteRequest(bean, t, type, Flags.RECURSE);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private <T> PersistRequestBean<T> createDeleteRequest(Object bean, Transaction t, PersistRequest.Type type, int flags) {
|
||||
BeanManager<T> mgr = beanManager(bean.getClass());
|
||||
@@ -1167,7 +1191,7 @@ public final class DefaultPersister implements Persister {
|
||||
type = Type.DELETE_SOFT;
|
||||
}
|
||||
|
||||
PersistRequestBean<T> request = new PersistRequestBean<>(server, (T)bean, null, mgr, (SpiTransaction) t, persistExecute, type, flags);
|
||||
PersistRequestBean<T> request = new PersistRequestBean<>(server, (T) bean, null, mgr, (SpiTransaction) t, persistExecute, type, flags);
|
||||
request.initForSoftDelete();
|
||||
return request;
|
||||
}
|
||||
@@ -1186,7 +1210,7 @@ public final class DefaultPersister implements Persister {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> BeanManager<T> beanManager(Class<?> cls) {
|
||||
BeanManager<T> mgr = (BeanManager<T>)beanDescriptorManager.beanManager(cls);
|
||||
BeanManager<T> mgr = (BeanManager<T>) beanDescriptorManager.beanManager(cls);
|
||||
if (mgr == null) {
|
||||
throw new PersistenceException(errNotRegistered(cls));
|
||||
}
|
||||
|
||||
@@ -13,11 +13,8 @@ import io.ebeaninternal.server.persist.dmlbind.BindableList;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import static io.ebean.annotation.Platform.MARIADB;
|
||||
import static io.ebean.annotation.Platform.MYSQL;
|
||||
|
||||
/**
|
||||
* Meta data for insert handler. The meta data is for a particular bean type. It
|
||||
* Metadata for insert handler. The metadata is for a particular bean type. It
|
||||
* is considered immutable and is thread safe.
|
||||
*/
|
||||
final class InsertMeta {
|
||||
@@ -153,31 +150,25 @@ final class InsertMeta {
|
||||
private String genSql(boolean nullId, String table, boolean draftTable) {
|
||||
GenerateDmlRequest request = new GenerateDmlRequest();
|
||||
request.setInsertSetMode();
|
||||
|
||||
request.append("insert into ").append(table);
|
||||
if (nullId && noColumnsForInsert(draftTable)) {
|
||||
return request.append(defaultValues()).toString();
|
||||
}
|
||||
|
||||
request.append(" (");
|
||||
if (!nullId) {
|
||||
id.dmlAppend(request);
|
||||
}
|
||||
|
||||
if (shadowFKey != null) {
|
||||
shadowFKey.dmlAppend(request);
|
||||
}
|
||||
|
||||
if (discriminator != null) {
|
||||
discriminator.dmlAppend(request);
|
||||
}
|
||||
|
||||
if (draftTable) {
|
||||
all.dmlAppend(request);
|
||||
} else {
|
||||
allExcludeDraftOnly.dmlAppend(request);
|
||||
}
|
||||
|
||||
request.append(") values (");
|
||||
request.append(request.getInsertBindBuffer());
|
||||
request.append(")");
|
||||
@@ -185,7 +176,16 @@ final class InsertMeta {
|
||||
}
|
||||
|
||||
private String defaultValues() {
|
||||
return platform.base() == MYSQL || platform.base() == MARIADB ? " values (default)" : " default values";
|
||||
switch (platform.base()) {
|
||||
case MYSQL:
|
||||
case MARIADB:
|
||||
case ORACLE:
|
||||
return " values (default)";
|
||||
case DB2:
|
||||
return " (" + id.getIdentityColumn() + ") values (default)";
|
||||
default:
|
||||
return " default values";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user