mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
109
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
714bbadbc0 | ||
|
|
9e811e9aef | ||
|
|
f97dcb60c0 | ||
|
|
65c76cb2c0 | ||
|
|
874427dac1 | ||
|
|
1176c2e97a | ||
|
|
44e0585fb7 | ||
|
|
889c0f12e0 | ||
|
|
0135263dbd | ||
|
|
564194042b | ||
|
|
244d45674a | ||
|
|
4722f10f5e | ||
|
|
3f5140e7f3 | ||
|
|
43dec17d08 | ||
|
|
f1ee45d7d1 | ||
|
|
3263e7bfc3 | ||
|
|
e01f19b3aa | ||
|
|
20f6a659fe | ||
|
|
09fe923770 | ||
|
|
e6f5e42c2d | ||
|
|
5150ecba62 | ||
|
|
978b1dbe02 | ||
|
|
9813703ce5 | ||
|
|
09001e80b5 | ||
|
|
4aa3ca6d95 | ||
|
|
5ec8469ddc | ||
|
|
39099bbcc9 | ||
|
|
cb2ca0de11 | ||
|
|
b25233b0b9 | ||
|
|
743f1b10e3 | ||
|
|
371f50fb4d | ||
|
|
a3be2041c8 | ||
|
|
09a831f2d6 | ||
|
|
27d9e03691 | ||
|
|
5a3c6b9dad | ||
|
|
502eb78ffd | ||
|
|
761ec584b2 | ||
|
|
144b8c3077 | ||
|
|
79a1b3a024 | ||
|
|
519b75a778 | ||
|
|
1659c526d7 | ||
|
|
93fc7b07a0 | ||
|
|
d7e6feebc2 | ||
|
|
2a6c60c89b | ||
|
|
b569ec97ee | ||
|
|
6b6cf48ae2 | ||
|
|
f09cba3ab5 | ||
|
|
724183f669 | ||
|
|
a40212d41e | ||
|
|
c9ce02c43d | ||
|
|
03c9782d63 | ||
|
|
130e9451f4 | ||
|
|
dce6a3e9e1 | ||
|
|
486044d29b | ||
|
|
934b0f0044 | ||
|
|
2633cd6bfe | ||
|
|
2c81d0df03 | ||
|
|
9ef59e359b | ||
|
|
6561f6f5e7 | ||
|
|
b2e8e628fa | ||
|
|
bbb8d85971 | ||
|
|
14b94ebe12 | ||
|
|
f5f59d90d4 | ||
|
|
ac3f4ca369 | ||
|
|
10133e6040 | ||
|
|
321fb26df3 | ||
|
|
28bd018d1f | ||
|
|
cceb29313b | ||
|
|
530bfa982e | ||
|
|
3cfa636e88 | ||
|
|
a2e8f098cf | ||
|
|
9e42cfd7d7 | ||
|
|
a3c54d4d20 | ||
|
|
1d48e2afb3 | ||
|
|
d84c9dc1a9 | ||
|
|
6165bf5a6c | ||
|
|
712d3ea78f | ||
|
|
96e3c95c29 | ||
|
|
e6e25b979f | ||
|
|
50fd0f6b1a | ||
|
|
0e9b83a1ce | ||
|
|
d2f629e7bb | ||
|
|
e290f68b29 | ||
|
|
a17e62b491 | ||
|
|
928db1f0f6 | ||
|
|
c317092dc5 | ||
|
|
95512d4851 | ||
|
|
62ed5a9f2b | ||
|
|
37ba0b63e4 | ||
|
|
22a5bd9b9d | ||
|
|
45529958ef | ||
|
|
7aa64f47c8 | ||
|
|
919adf331a | ||
|
|
9f229e3cc2 | ||
|
|
3277fe81a1 | ||
|
|
6c6ec3663a | ||
|
|
0461580d1c | ||
|
|
75dbb58c85 | ||
|
|
808f69cac1 | ||
|
|
974953a376 | ||
|
|
f85a367e98 | ||
|
|
87a3c58d93 | ||
|
|
1d1aea77d0 | ||
|
|
2a02935cee | ||
|
|
fd2e5c0fc7 | ||
|
|
6d6b07bf87 | ||
|
|
2cac3cd0bb | ||
|
|
d56098dbf0 | ||
|
|
359f8b41fe |
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-clickhouse</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,18 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-clickhouse</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.10.2</tag>
|
||||
<tag>ebean-parent-13.11.4</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-cockroach</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,18 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.10.2</tag>
|
||||
<tag>ebean-parent-13.11.4</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-db2</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,18 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-db2</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.10.2</tag>
|
||||
<tag>ebean-parent-13.11.4</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-h2</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,18 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.10.2</tag>
|
||||
<tag>ebean-parent-13.11.4</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-hana</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,18 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-hana</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.10.2</tag>
|
||||
<tag>ebean-parent-13.11.4</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-mariadb</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,18 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-mariadb</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.10.2</tag>
|
||||
<tag>ebean-parent-13.11.4</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-mysql</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,18 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-mysql</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.10.2</tag>
|
||||
<tag>ebean-parent-13.11.4</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-nuodb</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,18 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-nuodb</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.10.2</tag>
|
||||
<tag>ebean-parent-13.11.4</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-oracle</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,18 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-oracle</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.10.2</tag>
|
||||
<tag>ebean-parent-13.11.4</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-postgres</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,18 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.10.2</tag>
|
||||
<tag>ebean-parent-13.11.4</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-sqlite</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,18 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlite</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.10.2</tag>
|
||||
<tag>ebean-parent-13.11.4</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-sqlserver</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,18 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlserver</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.10.2</tag>
|
||||
<tag>ebean-parent-13.11.4</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean-yugabyte</name>
|
||||
@@ -16,13 +16,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -35,18 +35,18 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.10.2</tag>
|
||||
<tag>ebean-parent-13.11.4</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>composites</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean (all platforms)</name>
|
||||
@@ -16,31 +16,31 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-joda-time</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-jsonnode</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-mapper</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -53,18 +53,18 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-all</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<scm>
|
||||
<tag>ebean-parent-13.10.2</tag>
|
||||
<tag>ebean-parent-13.11.4</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>composites</artifactId>
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean api</name>
|
||||
@@ -29,7 +29,7 @@
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>avaje-config</artifactId>
|
||||
<version>2.2</version>
|
||||
<version>2.4</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
|
||||
@@ -1730,4 +1730,8 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> endNot();
|
||||
|
||||
/**
|
||||
* Clears the current expression list.
|
||||
*/
|
||||
ExpressionList<T> clear();
|
||||
}
|
||||
|
||||
@@ -231,18 +231,6 @@ public class OrderBy<T> implements Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this order by can be used in select clause.
|
||||
*/
|
||||
public boolean supportsSelect() {
|
||||
for (Property property : list) {
|
||||
if (!property.supportsSelect()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A property and its ascending descending order.
|
||||
*/
|
||||
@@ -403,12 +391,6 @@ public class OrderBy<T> implements Serializable {
|
||||
this.ascending = ascending;
|
||||
}
|
||||
|
||||
/**
|
||||
* Support use in select clause if no collation or nulls ordering.
|
||||
*/
|
||||
boolean supportsSelect() {
|
||||
return nulls == null;
|
||||
}
|
||||
}
|
||||
|
||||
private void parse(String orderByClause) {
|
||||
|
||||
@@ -725,7 +725,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
loader.loadBean(this);
|
||||
if (lazyLoadFailure) {
|
||||
// failed when lazy loading this bean
|
||||
throw new EntityNotFoundException("Lazy loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted.");
|
||||
throw new EntityNotFoundException("Lazy loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted. BeanLoader: " + beanLoader);
|
||||
}
|
||||
// bean should be loaded and intercepting now. setLoaded() has
|
||||
// been called by the lazy loading mechanism
|
||||
|
||||
+5
-10
@@ -1,20 +1,16 @@
|
||||
package io.ebean.platform.db2;
|
||||
package io.ebean.config.dbplatform;
|
||||
|
||||
import io.ebean.config.dbplatform.SqlLimitRequest;
|
||||
import io.ebean.config.dbplatform.SqlLimitResponse;
|
||||
import io.ebean.config.dbplatform.SqlLimiter;
|
||||
|
||||
public class Db2SqlLimiter implements SqlLimiter {
|
||||
public final class AnsiSqlRowsLimiter implements SqlLimiter {
|
||||
|
||||
@Override
|
||||
public SqlLimitResponse limit(SqlLimitRequest request) {
|
||||
|
||||
StringBuilder sb = new StringBuilder(512);
|
||||
String dbSql = request.getDbSql();
|
||||
StringBuilder sb = new StringBuilder(50 + dbSql.length());
|
||||
sb.append("select ");
|
||||
if (request.isDistinct()) {
|
||||
sb.append("distinct ");
|
||||
}
|
||||
sb.append(request.getDbSql());
|
||||
sb.append(dbSql);
|
||||
int firstRow = request.getFirstRow();
|
||||
if (firstRow > 0) {
|
||||
sb.append(" offset ").append(firstRow).append(" rows");
|
||||
@@ -23,7 +19,6 @@ public class Db2SqlLimiter implements SqlLimiter {
|
||||
if (maxRows > 0) {
|
||||
sb.append(" fetch next ").append(maxRows).append(" rows only");
|
||||
}
|
||||
|
||||
String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
|
||||
return new SqlLimitResponse(sql);
|
||||
}
|
||||
@@ -3,42 +3,25 @@ package io.ebean.config.dbplatform;
|
||||
/**
|
||||
* Adds LIMIT OFFSET clauses to a SQL query.
|
||||
*/
|
||||
public class LimitOffsetSqlLimiter implements SqlLimiter {
|
||||
|
||||
/**
|
||||
* LIMIT keyword.
|
||||
*/
|
||||
private static final String LIMIT = "limit";
|
||||
|
||||
/**
|
||||
* OFFSET keyword.
|
||||
*/
|
||||
private static final String OFFSET = "offset";
|
||||
public final class LimitOffsetSqlLimiter implements SqlLimiter {
|
||||
|
||||
@Override
|
||||
public SqlLimitResponse limit(SqlLimitRequest request) {
|
||||
|
||||
String dbSql = request.getDbSql();
|
||||
|
||||
StringBuilder sb = new StringBuilder(50 + dbSql.length());
|
||||
sb.append("select ");
|
||||
if (request.isDistinct()) {
|
||||
sb.append("distinct ");
|
||||
}
|
||||
|
||||
sb.append(dbSql);
|
||||
|
||||
int firstRow = request.getFirstRow();
|
||||
int maxRows = request.getMaxRows();
|
||||
|
||||
if (maxRows > 0 || firstRow > 0) {
|
||||
sb.append(" ").append(LIMIT).append(" ").append(maxRows);
|
||||
if (firstRow > 0) {
|
||||
sb.append(" ").append(OFFSET).append(" ");
|
||||
sb.append(firstRow);
|
||||
}
|
||||
if (maxRows > 0) {
|
||||
sb.append(" limit ").append(maxRows);
|
||||
}
|
||||
int firstRow = request.getFirstRow();
|
||||
if (firstRow > 0) {
|
||||
sb.append(" offset ").append(firstRow);
|
||||
}
|
||||
|
||||
String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
|
||||
return new SqlLimitResponse(sql);
|
||||
}
|
||||
|
||||
@@ -5,14 +5,6 @@ package io.ebean.config.dbplatform;
|
||||
*/
|
||||
public interface SqlLimiter {
|
||||
|
||||
/**
|
||||
* the new line character used.
|
||||
* <p>
|
||||
* Note that this is removed for logging sql to the transaction log.
|
||||
* </p>
|
||||
*/
|
||||
char NEW_LINE = '\n';
|
||||
|
||||
/**
|
||||
* Add the SQL limiting statements around the query.
|
||||
*/
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
<!-- <parent>-->
|
||||
<!-- <groupId>org.avaje</groupId>-->
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-parent-13.10.2</tag>
|
||||
<tag>ebean-parent-13.11.4</tag>
|
||||
</scm>
|
||||
|
||||
<name>ebean autotune</name>
|
||||
@@ -26,7 +26,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
+30
-48
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean bom</name>
|
||||
@@ -89,192 +89,174 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-joda-time</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-jsonnode</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-mapper</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-xml</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-autotune</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>kotlin-querybean-generator</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-redis</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- platforms -->
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-all</artifactId>
|
||||
<version>13.10.2-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-clickhouse</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-db2</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-h2</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-hana</artifactId>
|
||||
<version>13.10.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-hsqldb</artifactId>
|
||||
<version>13.10.2-SNAPSHOT</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-mariadb</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-mysql</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-nuodb</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-oracle</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgres</artifactId>
|
||||
<version>13.10.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-sqlanywhere</artifactId>
|
||||
<version>13.10.2-SNAPSHOT</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-sqlite</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-sqlserver</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
@@ -16,7 +16,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -30,7 +30,7 @@
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.4.1</version>
|
||||
<version>42.4.3</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
|
||||
+9
-9
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-core</artifactId>
|
||||
@@ -15,14 +15,14 @@
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-parent-13.10.2</tag>
|
||||
<tag>ebean-parent-13.11.4</tag>
|
||||
</scm>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -46,13 +46,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -135,7 +135,7 @@
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.5.0</version>
|
||||
<version>42.5.1</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
@@ -143,21 +143,21 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlserver</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -9,4 +9,5 @@ public final class CoreLog {
|
||||
|
||||
public static final System.Logger log = AppLog.getLogger("io.ebean.core");
|
||||
public static final System.Logger internal = AppLog.getLogger("io.ebean.internal");
|
||||
public static final System.Logger markedAsDeleted = AppLog.getLogger("io.ebean.MarkedAsDeleted");
|
||||
}
|
||||
|
||||
@@ -6,10 +6,7 @@ import io.ebeaninternal.api.SpiQuery.Mode;
|
||||
import io.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Request for loading ManyToOne and OneToOne relationships.
|
||||
@@ -103,7 +100,7 @@ public final class LoadBeanRequest extends LoadRequest {
|
||||
/**
|
||||
* Load the beans into the L2 cache if that is requested and check for load failures due to deletes.
|
||||
*/
|
||||
public void postLoad(List<?> list) {
|
||||
public Result postLoad(List<?> list) {
|
||||
Set<Object> loadedIds = new HashSet<>();
|
||||
BeanDescriptor<?> desc = loadBuffer.descriptor();
|
||||
// collect Ids and maybe load bean cache
|
||||
@@ -114,6 +111,7 @@ public final class LoadBeanRequest extends LoadRequest {
|
||||
desc.cacheBeanPutAll(list);
|
||||
}
|
||||
if (lazyLoadProperty != null) {
|
||||
Set<Object> missedIds = new HashSet<>();
|
||||
for (EntityBeanIntercept ebi : batch) {
|
||||
// check if the underlying row in DB was deleted. Mark the bean as 'failed' if
|
||||
// necessary but allow processing to continue until it is accessed by client code
|
||||
@@ -121,8 +119,36 @@ public final class LoadBeanRequest extends LoadRequest {
|
||||
if (!loadedIds.contains(id)) {
|
||||
// assume this is logically deleted (hence not found)
|
||||
desc.markAsDeleted(ebi.getOwner());
|
||||
missedIds.add(id);
|
||||
}
|
||||
}
|
||||
return new Result(loadedIds, missedIds);
|
||||
}
|
||||
return EMPTY_RESULT;
|
||||
}
|
||||
|
||||
static final Result EMPTY_RESULT = new Result(Collections.emptySet(),Collections.emptySet());
|
||||
|
||||
public static class Result {
|
||||
|
||||
private final Set<Object> loadedIds;
|
||||
private final Set<Object> missedIds;
|
||||
|
||||
Result(Set<Object> loadedIds, Set<Object> missedIds) {
|
||||
this.loadedIds = loadedIds;
|
||||
this.missedIds = missedIds;
|
||||
}
|
||||
|
||||
public boolean markedDeleted() {
|
||||
return !missedIds.isEmpty();
|
||||
}
|
||||
|
||||
public Set<Object> missedIds() {
|
||||
return missedIds;
|
||||
}
|
||||
|
||||
public Set<Object> loadedIds() {
|
||||
return loadedIds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ public final class LoadManyRequest extends LoadRequest {
|
||||
log.log(DEBUG, "BeanCollection after lazy load was empty. type:{0} id:{1} owner:{2}", ownerBean.getClass().getName(), parentId, ownerBean);
|
||||
}
|
||||
} else if (loadCache && many.isUseCache()) {
|
||||
desc.cacheManyPropPut(many, bc, desc.getId(bc.getOwnerBean()));
|
||||
desc.cacheManyPropPut(many, bc, desc.cacheKeyForBean(bc.getOwnerBean()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+17
-17
@@ -91,15 +91,15 @@ public final class CacheChangeSet {
|
||||
/**
|
||||
* Add many property remove.
|
||||
*/
|
||||
public <T> void addManyRemove(BeanDescriptor<T> desc, String manyProperty, Object parentId) {
|
||||
many(desc, manyProperty).addRemove(parentId);
|
||||
public <T> void addManyRemove(BeanDescriptor<T> desc, String manyProperty, String parentKey) {
|
||||
many(desc, manyProperty).addRemove(parentKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add many property put.
|
||||
*/
|
||||
public <T> void addManyPut(BeanDescriptor<T> desc, String manyProperty, Object parentId, CachedManyIds entry) {
|
||||
many(desc, manyProperty).addPut(parentId, entry);
|
||||
public <T> void addManyPut(BeanDescriptor<T> desc, String manyProperty, String parentKey, CachedManyIds entry) {
|
||||
many(desc, manyProperty).addPut(parentKey, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -164,8 +164,8 @@ public final class CacheChangeSet {
|
||||
private static final class ManyChange implements CacheChange {
|
||||
|
||||
final ManyKey key;
|
||||
final Set<Object> removes = new HashSet<>();
|
||||
final Map<Object, CachedManyIds> puts = new LinkedHashMap<>();
|
||||
final Set<String> removes = new HashSet<>();
|
||||
final Map<String, CachedManyIds> puts = new LinkedHashMap<>();
|
||||
boolean clear;
|
||||
|
||||
ManyChange(ManyKey key) {
|
||||
@@ -183,17 +183,17 @@ public final class CacheChangeSet {
|
||||
/**
|
||||
* Remove entry for the given parentId.
|
||||
*/
|
||||
void addRemove(Object parentId) {
|
||||
void addRemove(String parentKey) {
|
||||
if (!clear) {
|
||||
removes.add(parentId);
|
||||
removes.add(parentKey);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Put entry for the given parentId.
|
||||
*/
|
||||
void addPut(Object parentId, CachedManyIds entry) {
|
||||
puts.put(parentId, entry);
|
||||
void addPut(String parentKey, CachedManyIds entry) {
|
||||
puts.put(parentKey, entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -201,11 +201,11 @@ public final class CacheChangeSet {
|
||||
if (clear) {
|
||||
key.cacheClear();
|
||||
} else {
|
||||
for (Map.Entry<Object, CachedManyIds> entry : puts.entrySet()) {
|
||||
for (Map.Entry<String, CachedManyIds> entry : puts.entrySet()) {
|
||||
key.cachePut(entry.getKey(), entry.getValue());
|
||||
}
|
||||
for (Object parentId : removes) {
|
||||
key.cacheRemove(parentId);
|
||||
for (String parentKey : removes) {
|
||||
key.cacheRemove(parentKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -241,12 +241,12 @@ public final class CacheChangeSet {
|
||||
desc.cacheManyPropClear(manyProperty);
|
||||
}
|
||||
|
||||
void cachePut(Object parentId, CachedManyIds entry) {
|
||||
desc.cacheManyPropPut(manyProperty, parentId, entry);
|
||||
void cachePut(String parentKey, CachedManyIds entry) {
|
||||
desc.cacheManyPropPut(manyProperty, parentKey, entry);
|
||||
}
|
||||
|
||||
void cacheRemove(Object parentId) {
|
||||
desc.cacheManyPropRemove(manyProperty, parentId);
|
||||
void cacheRemove(String parentKey) {
|
||||
desc.cacheManyPropRemove(manyProperty, parentKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -130,7 +130,7 @@ final class DefaultCacheHolder {
|
||||
}
|
||||
|
||||
private ServerCacheOptions getQueryOptions(Class<?> cls) {
|
||||
CacheQueryTuning tuning = AnnotationUtil.get(cls, CacheQueryTuning.class);
|
||||
CacheQueryTuning tuning = AnnotationUtil.typeGet(cls, CacheQueryTuning.class);
|
||||
if (tuning != null) {
|
||||
return new ServerCacheOptions(tuning).applyDefaults(queryDefault);
|
||||
}
|
||||
@@ -138,9 +138,9 @@ final class DefaultCacheHolder {
|
||||
}
|
||||
|
||||
private ServerCacheOptions getBeanOptions(Class<?> cls) {
|
||||
Cache cache = cls.getAnnotation(Cache.class);
|
||||
Cache cache = AnnotationUtil.typeGet(cls, Cache.class);
|
||||
boolean nearCache = (cache != null && cache.nearCache());
|
||||
CacheBeanTuning tuning = cls.getAnnotation(CacheBeanTuning.class);
|
||||
CacheBeanTuning tuning = AnnotationUtil.typeGet(cls, CacheBeanTuning.class);
|
||||
if (tuning != null) {
|
||||
return new ServerCacheOptions(nearCache, tuning).applyDefaults(beanDefault);
|
||||
}
|
||||
|
||||
@@ -14,10 +14,11 @@ import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import io.ebeaninternal.server.transaction.DefaultPersistenceContext;
|
||||
|
||||
import javax.persistence.EntityNotFoundException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.lang.System.Logger.Level.DEBUG;
|
||||
import static java.lang.System.Logger.Level.*;
|
||||
|
||||
/**
|
||||
* Helper to handle lazy loading and refreshing of beans.
|
||||
@@ -72,7 +73,8 @@ final class DefaultBeanLoader {
|
||||
if (ebi.isReadOnly()) {
|
||||
readOnly = Boolean.TRUE;
|
||||
}
|
||||
if (parentDesc.cacheManyPropLoad(many, beanCollection, parentId, readOnly)) {
|
||||
final String parentKey = parentDesc.cacheKey(parentId);
|
||||
if (parentDesc.cacheManyPropLoad(many, beanCollection, parentKey, readOnly)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -113,7 +115,8 @@ final class DefaultBeanLoader {
|
||||
log.log(DEBUG, "BeanCollection after load was empty. Owner:{0}", beanCollection.getOwnerBean());
|
||||
}
|
||||
} else if (useManyIdCache) {
|
||||
parentDesc.cacheManyPropPut(many, beanCollection, parentId);
|
||||
final String parentKey = parentDesc.cacheKey(parentId);
|
||||
parentDesc.cacheManyPropPut(many, beanCollection, parentKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,8 +138,12 @@ final class DefaultBeanLoader {
|
||||
|
||||
SpiQuery<?> query = server.createQuery(loadRequest.beanType());
|
||||
loadRequest.configureQuery(query, idList);
|
||||
List<?> list = executeQuery(loadRequest, query);
|
||||
loadRequest.postLoad(list);
|
||||
final List<?> list = executeQuery(loadRequest, query);
|
||||
final LoadBeanRequest.Result result = loadRequest.postLoad(list);
|
||||
if (result.markedDeleted() && CoreLog.markedAsDeleted.isLoggable(DEBUG)) {
|
||||
String msg = MessageFormat.format("Loaded bean marked as deleted for {0} missedIds:{1} loadedIds:{2} sql:{3} list:{4}", loadRequest.beanType(), result.missedIds(), result.loadedIds(), query.getGeneratedSql(), list);
|
||||
CoreLog.markedAsDeleted.log(DEBUG, msg, new RuntimeException("LoadBeanRequest markedAsDeleted"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -160,6 +160,8 @@ public final class DefaultContainer implements SpiContainer {
|
||||
*/
|
||||
private BootupClasses bootupClasses(DatabaseConfig config) {
|
||||
BootupClasses bootup = bootupClasses1(config);
|
||||
bootup.addServerConfigStartup(config.getServerConfigStartupListeners());
|
||||
bootup.runServerConfigStartup(config);
|
||||
bootup.addIdGenerators(config.getIdGenerators());
|
||||
bootup.addPersistControllers(config.getPersistControllers());
|
||||
bootup.addPostLoaders(config.getPostLoaders());
|
||||
@@ -167,9 +169,7 @@ public final class DefaultContainer implements SpiContainer {
|
||||
bootup.addFindControllers(config.getFindControllers());
|
||||
bootup.addPersistListeners(config.getPersistListeners());
|
||||
bootup.addQueryAdapters(config.getQueryAdapters());
|
||||
bootup.addServerConfigStartup(config.getServerConfigStartupListeners());
|
||||
bootup.addChangeLogInstances(config);
|
||||
bootup.runServerConfigStartup(config);
|
||||
return bootup;
|
||||
}
|
||||
|
||||
|
||||
@@ -1091,7 +1091,13 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public <T> Set<T> findSet(Query<T> query, Transaction transaction) {
|
||||
SpiOrmQueryRequest request = createQueryRequest(Type.SET, query, transaction);
|
||||
SpiOrmQueryRequest request = buildQueryRequest(Type.SET, query, transaction);
|
||||
request.resetBeanCacheAutoMode(false);
|
||||
if ((transaction == null || !transaction.isSkipCache()) && request.getFromBeanCache()) {
|
||||
// hit bean cache and got all results from cache
|
||||
return request.beanCacheHitsAsSet();
|
||||
}
|
||||
request.prepareQuery();
|
||||
Object result = request.getFromQueryCache();
|
||||
if (result != null) {
|
||||
return (Set<T>) result;
|
||||
@@ -1107,12 +1113,13 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public <K, T> Map<K, T> findMap(Query<T> query, @Nullable Transaction transaction) {
|
||||
SpiOrmQueryRequest request = createQueryRequest(Type.MAP, query, transaction);
|
||||
SpiOrmQueryRequest request = buildQueryRequest(Type.MAP, query, transaction);
|
||||
request.resetBeanCacheAutoMode(false);
|
||||
if ((transaction == null || !transaction.isSkipCache()) && request.getFromBeanCache()) {
|
||||
// hit bean cache and got all results from cache
|
||||
return request.beanCacheHitsAsMap();
|
||||
}
|
||||
request.prepareQuery();
|
||||
Object result = request.getFromQueryCache();
|
||||
if (result != null) {
|
||||
return (Map<K, T>) result;
|
||||
|
||||
@@ -515,12 +515,12 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
if (query.getType() == Type.MAP) {
|
||||
mergeCacheHitsToMap(result);
|
||||
} else {
|
||||
mergeCacheHitsToList(result);
|
||||
mergeCacheHitsToCollection(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void mergeCacheHitsToList(BeanCollection<T> result) {
|
||||
private void mergeCacheHitsToCollection(BeanCollection<T> result) {
|
||||
for (T hit : cacheBeans) {
|
||||
result.internalAdd(hit);
|
||||
}
|
||||
@@ -579,6 +579,15 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
return property;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<T> beanCacheHitsAsSet() {
|
||||
OrderBy<T> orderBy = query.getOrderBy();
|
||||
if (orderBy != null && !orderBy.isEmpty()) {
|
||||
beanDescriptor.sort(cacheBeans, orderBy.toStringFormat());
|
||||
}
|
||||
return new LinkedHashSet<>(cacheBeans);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getFromBeanCache() {
|
||||
if (!query.isBeanCacheGet()) {
|
||||
|
||||
@@ -153,6 +153,11 @@ public interface SpiOrmQueryRequest<T> extends BeanQueryRequest<T>, DocQueryRequ
|
||||
*/
|
||||
<K> Map<K,T> beanCacheHitsAsMap();
|
||||
|
||||
/**
|
||||
* Return the bean cache hits for findMap (when all hits / no misses).
|
||||
*/
|
||||
Set<T> beanCacheHitsAsSet();
|
||||
|
||||
/**
|
||||
* Reset Bean cache mode AUTO - require explicit setting for bean cache use with findList().
|
||||
*/
|
||||
|
||||
@@ -342,8 +342,9 @@ public class BootupClasses implements Predicate<Class<?>> {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private boolean isInterestingInterface(Class<?> cls) {
|
||||
if (Modifier.isAbstract(cls.getModifiers())) {
|
||||
// do not include abstract classes as we can
|
||||
if (Modifier.isAbstract(cls.getModifiers())
|
||||
|| !(Modifier.isPublic(cls.getModifiers()) || Modifier.isProtected(cls.getModifiers()))) {
|
||||
// do not include abstract and non pupbic/protected classes as we can
|
||||
// not instantiate them
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -38,13 +38,10 @@ public final class BeanCollectionUtil {
|
||||
// returns a collection of beans
|
||||
return bc.getActualEntries();
|
||||
}
|
||||
|
||||
if (o instanceof Map<?, ?>) {
|
||||
// yes, we want the entrySet (to set the keys)
|
||||
return ((Map<?, ?>) o).entrySet();
|
||||
|
||||
} else if (o instanceof Collection<?>) {
|
||||
if (o instanceof Collection<?>) {
|
||||
return ((Collection<?>) o);
|
||||
} else if (o instanceof Map<?, ?>) {
|
||||
return ((Map<?, ?>) o).entrySet();
|
||||
}
|
||||
throw new PersistenceException("expecting a Map or Collection but got " + o.getClass().getName());
|
||||
}
|
||||
|
||||
@@ -1202,26 +1202,26 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
/**
|
||||
* Try to load the beanCollection from cache return true if successful.
|
||||
*/
|
||||
public boolean cacheManyPropLoad(BeanPropertyAssocMany<?> many, BeanCollection<?> bc, Object parentId, Boolean readOnly) {
|
||||
return cacheHelp.manyPropLoad(many, bc, parentId, readOnly);
|
||||
public boolean cacheManyPropLoad(BeanPropertyAssocMany<?> many, BeanCollection<?> bc, String parentKey, Boolean readOnly) {
|
||||
return cacheHelp.manyPropLoad(many, bc, parentKey, readOnly);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put the beanCollection into the cache.
|
||||
*/
|
||||
public void cacheManyPropPut(BeanPropertyAssocMany<?> many, BeanCollection<?> bc, Object parentId) {
|
||||
cacheHelp.manyPropPut(many, bc, parentId);
|
||||
public void cacheManyPropPut(BeanPropertyAssocMany<?> many, BeanCollection<?> bc, String parentKey) {
|
||||
cacheHelp.manyPropPut(many, bc, parentKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the bean collection entry in the cache.
|
||||
*/
|
||||
public void cacheManyPropPut(String name, Object parentId, CachedManyIds entry) {
|
||||
cacheHelp.cachePutManyIds(parentId, name, entry);
|
||||
public void cacheManyPropPut(String name, String parentKey, CachedManyIds entry) {
|
||||
cacheHelp.cachePutManyIds(name, parentKey, entry);
|
||||
}
|
||||
|
||||
public void cacheManyPropRemove(String propertyName, Object parentId) {
|
||||
cacheHelp.manyPropRemove(propertyName, parentId);
|
||||
public void cacheManyPropRemove(String propertyName, String parentKey) {
|
||||
cacheHelp.manyPropRemove(propertyName, parentKey);
|
||||
}
|
||||
|
||||
public void cacheManyPropClear(String propertyName) {
|
||||
@@ -2096,7 +2096,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
/**
|
||||
* Return the cache key for the given bean (based on id value).
|
||||
*/
|
||||
String cacheKeyForBean(EntityBean bean) {
|
||||
public String cacheKeyForBean(EntityBean bean) {
|
||||
return cacheKey(idProperty.getValue(bean));
|
||||
}
|
||||
|
||||
@@ -2112,11 +2112,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
return getId((EntityBean) bean);
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public Object beanId(T bean) {
|
||||
// return getId((EntityBean) bean);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Return the Id value for the bean with embeddedId beans converted into maps.
|
||||
* <p>
|
||||
|
||||
+19
-19
@@ -226,13 +226,12 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
queryCache.put(id, entry);
|
||||
}
|
||||
|
||||
|
||||
void manyPropRemove(String propertyName, Object parentId) {
|
||||
void manyPropRemove(String propertyName, String parentKey) {
|
||||
ServerCache collectionIdsCache = cacheManager.getCollectionIdsCache(beanType, propertyName);
|
||||
if (manyLog.isLoggable(TRACE)) {
|
||||
manyLog.log(TRACE, " REMOVE {0}({1}).{2}", cacheName, parentId, propertyName);
|
||||
manyLog.log(TRACE, " REMOVE {0}({1}).{2}", cacheName, parentKey, propertyName);
|
||||
}
|
||||
collectionIdsCache.remove(parentId);
|
||||
collectionIdsCache.remove(parentKey);
|
||||
}
|
||||
|
||||
void manyPropClear(String propertyName) {
|
||||
@@ -246,15 +245,15 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
/**
|
||||
* Return the CachedManyIds for a given bean many property. Returns null if not in the cache.
|
||||
*/
|
||||
private CachedManyIds manyPropGet(Object parentId, String propertyName) {
|
||||
private CachedManyIds manyPropGet(String propertyName, String parentKey) {
|
||||
ServerCache collectionIdsCache = cacheManager.getCollectionIdsCache(beanType, propertyName);
|
||||
CachedManyIds entry = (CachedManyIds) collectionIdsCache.get(parentId);
|
||||
CachedManyIds entry = (CachedManyIds) collectionIdsCache.get(parentKey);
|
||||
if (entry == null) {
|
||||
if (manyLog.isLoggable(TRACE)) {
|
||||
manyLog.log(TRACE, " GET {0}({1}).{2} - cache miss", cacheName, parentId, propertyName);
|
||||
manyLog.log(TRACE, " GET {0}({1}).{2} - cache miss", cacheName, parentKey, propertyName);
|
||||
}
|
||||
} else if (manyLog.isLoggable(DEBUG)) {
|
||||
manyLog.log(DEBUG, " GET {0}({1}).{2} - hit", cacheName, parentId, propertyName);
|
||||
manyLog.log(DEBUG, " GET {0}({1}).{2} - hit", cacheName, parentKey, propertyName);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
@@ -262,12 +261,12 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
/**
|
||||
* Try to load the bean collection from cache return true if successful.
|
||||
*/
|
||||
boolean manyPropLoad(BeanPropertyAssocMany<?> many, BeanCollection<?> bc, Object parentId, Boolean readOnly) {
|
||||
boolean manyPropLoad(BeanPropertyAssocMany<?> many, BeanCollection<?> bc, String parentKey, Boolean readOnly) {
|
||||
if (many.isElementCollection()) {
|
||||
// held as part of the bean cache so skip
|
||||
return false;
|
||||
}
|
||||
CachedManyIds entry = manyPropGet(parentId, many.name());
|
||||
CachedManyIds entry = manyPropGet(many.name(), parentKey);
|
||||
if (entry == null) {
|
||||
// not in cache so return unsuccessful
|
||||
return false;
|
||||
@@ -293,9 +292,9 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
/**
|
||||
* Put the beanCollection into the cache.
|
||||
*/
|
||||
void manyPropPut(BeanPropertyAssocMany<?> many, Object details, Object parentId) {
|
||||
void manyPropPut(BeanPropertyAssocMany<?> many, Object details, String parentKey) {
|
||||
if (many.isElementCollection()) {
|
||||
CachedBeanData data = (CachedBeanData) beanCache.get(parentId);
|
||||
CachedBeanData data = (CachedBeanData) beanCache.get(parentKey);
|
||||
if (data != null) {
|
||||
try {
|
||||
// add as JSON to bean cache
|
||||
@@ -305,9 +304,9 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
|
||||
CachedBeanData newData = data.update(changes, data.getVersion());
|
||||
if (beanLog.isLoggable(DEBUG)) {
|
||||
beanLog.log(DEBUG, " UPDATE {0}({1}) changes:{2}", cacheName, parentId, changes);
|
||||
beanLog.log(DEBUG, " UPDATE {0}({1}) changes:{2}", cacheName, parentKey, changes);
|
||||
}
|
||||
beanCache.put(parentId, newData);
|
||||
beanCache.put(parentKey, newData);
|
||||
} catch (IOException e) {
|
||||
log.log(ERROR, "Error updating L2 cache", e);
|
||||
}
|
||||
@@ -315,17 +314,17 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
} else {
|
||||
CachedManyIds entry = createManyIds(many, details);
|
||||
if (entry != null) {
|
||||
cachePutManyIds(parentId, many.name(), entry);
|
||||
cachePutManyIds(many.name(), parentKey, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cachePutManyIds(Object parentId, String manyName, CachedManyIds entry) {
|
||||
void cachePutManyIds(String manyName, String parentKey, CachedManyIds entry) {
|
||||
ServerCache collectionIdsCache = cacheManager.getCollectionIdsCache(beanType, manyName);
|
||||
if (manyLog.isLoggable(DEBUG)) {
|
||||
manyLog.log(DEBUG, " PUT {0}({1}).{2} - ids:{3}", cacheName, parentId, manyName, entry);
|
||||
manyLog.log(DEBUG, " PUT {0}({1}).{2} - ids:{3}", cacheName, parentKey, manyName, entry);
|
||||
}
|
||||
collectionIdsCache.put(parentId, entry);
|
||||
collectionIdsCache.put(parentKey, entry);
|
||||
}
|
||||
|
||||
private CachedManyIds createManyIds(BeanPropertyAssocMany<?> many, Object details) {
|
||||
@@ -828,7 +827,8 @@ final class BeanDescriptorCacheHelp<T> {
|
||||
Object details = many.getValue(updateRequest.entityBean());
|
||||
CachedManyIds entry = createManyIds(many, details);
|
||||
if (entry != null) {
|
||||
changeSet.addManyPut(desc, many.name(), id, entry);
|
||||
final String parentKey = desc.cacheKey(id);
|
||||
changeSet.addManyPut(desc, many.name(), parentKey, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
|
||||
/**
|
||||
* Flag to mark this is the id property.
|
||||
*/
|
||||
private final boolean id;
|
||||
protected final boolean id;
|
||||
private final boolean importedPrimaryKey;
|
||||
/**
|
||||
* Flag to make this as a dummy property for unidirecitonal relationships.
|
||||
|
||||
@@ -197,7 +197,8 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
if (assocBean != null) {
|
||||
Object parentId = targetDescriptor.id(assocBean);
|
||||
if (parentId != null) {
|
||||
changeSet.addManyRemove(targetDescriptor, relationshipProperty.name(), parentId);
|
||||
final String parentKey = targetDescriptor.cacheKey(parentId);
|
||||
changeSet.addManyRemove(targetDescriptor, relationshipProperty.name(), parentKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -655,7 +656,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
@Override
|
||||
public void setValue(EntityBean bean, Object value) {
|
||||
super.setValue(bean, value);
|
||||
if (embedded && value instanceof EntityBean) {
|
||||
if (!id && embedded && value instanceof EntityBean) {
|
||||
setEmbeddedOwner(bean, value);
|
||||
}
|
||||
}
|
||||
@@ -663,7 +664,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
@Override
|
||||
public void setValueIntercept(EntityBean bean, Object value) {
|
||||
super.setValueIntercept(bean, value);
|
||||
if (embedded && value instanceof EntityBean) {
|
||||
if (!id && embedded && value instanceof EntityBean) {
|
||||
setEmbeddedOwner(bean, value);
|
||||
}
|
||||
}
|
||||
@@ -675,8 +676,10 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
Object emb = getValue(owner);
|
||||
if (emb != null) {
|
||||
EntityBean embeddedBean = (EntityBean) emb;
|
||||
embeddedBean._ebean_getIntercept().setEmbeddedOwner(owner, propertyIndex);
|
||||
targetDescriptor.setAllLoaded(embeddedBean);
|
||||
if (!id) {
|
||||
embeddedBean._ebean_getIntercept().setEmbeddedOwner(owner, propertyIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1123,7 +1123,7 @@ public class DeployBeanProperty {
|
||||
|
||||
private boolean matchPlatform(Platform[] platforms, Platform match) {
|
||||
for (Platform platform : platforms) {
|
||||
if (platform == match) {
|
||||
if (platform == match || platform == match.base()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,10 +465,9 @@ final class AnnotationFields extends AnnotationParser {
|
||||
if (!gen.generator().isEmpty()) {
|
||||
// use a custom IdGenerator
|
||||
PlatformIdGenerator idGenerator = generatedPropFactory.getIdGenerator(gen.generator());
|
||||
if (idGenerator == null) {
|
||||
throw new IllegalStateException("No custom IdGenerator registered with name " + gen.generator());
|
||||
if (idGenerator != null) {
|
||||
descriptor.setCustomIdGenerator(idGenerator);
|
||||
}
|
||||
descriptor.setCustomIdGenerator(idGenerator);
|
||||
} else if (prop.getPropertyType().equals(UUID.class)) {
|
||||
descriptor.setUuidGenerator();
|
||||
}
|
||||
|
||||
@@ -1268,4 +1268,10 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> clear() {
|
||||
list.clear();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1068,4 +1068,9 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> clear() {
|
||||
return exprList.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,7 +205,8 @@ final class DLoadManyContext extends DLoadBaseContext implements LoadManyContext
|
||||
EntityBean ownerBean = bc.getOwnerBean();
|
||||
BeanDescriptor<?> parentDesc = context.desc.descriptor(ownerBean.getClass());
|
||||
Object parentId = parentDesc.getId(ownerBean);
|
||||
if (parentDesc.cacheManyPropLoad(context.property, bc, parentId, context.parent.isReadOnly())) {
|
||||
final String parentKey = parentDesc.cacheKey(parentId);
|
||||
if (parentDesc.cacheManyPropLoad(context.property, bc, parentKey, context.parent.isReadOnly())) {
|
||||
// we loaded the bean collection from cache so remove it from the buffer
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
// find it using instance equality - avoiding equals() and potential deadlock issue
|
||||
|
||||
@@ -861,7 +861,7 @@ public final class DefaultPersister implements Persister {
|
||||
SpiTransaction t = request.transaction();
|
||||
EntityBean orphanForRemoval = request.importedOrphanForRemoval();
|
||||
if (orphanForRemoval != null) {
|
||||
delete(orphanForRemoval, request.transaction(), true);
|
||||
delete(orphanForRemoval, request.transaction(), false);
|
||||
}
|
||||
|
||||
// exported ones with cascade save
|
||||
@@ -1079,7 +1079,7 @@ public final class DefaultPersister implements Persister {
|
||||
private void deleteOrphan(PersistRequestBean<?> request, BeanPropertyAssocOne<?> prop) {
|
||||
Object origValue = request.getOrigValue(prop);
|
||||
if (origValue instanceof EntityBean) {
|
||||
delete((EntityBean) origValue, request.transaction(), true);
|
||||
delete((EntityBean) origValue, request.transaction(), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,8 +35,9 @@ final class SaveManyBeans extends SaveManyBase {
|
||||
private final boolean untouchedBeanCollection;
|
||||
private final Collection<?> collection;
|
||||
private final boolean hasOrderColumn;
|
||||
private final boolean forcedUpdate;
|
||||
private int sortOrder;
|
||||
private boolean insertAllChildren;
|
||||
private boolean forceOrphanRemoval;
|
||||
|
||||
SaveManyBeans(DefaultPersister persister, boolean insertedParent, BeanPropertyAssocMany<?> many, EntityBean parentBean, PersistRequestBean<?> request) {
|
||||
super(persister, insertedParent, many, parentBean, request);
|
||||
@@ -49,6 +50,7 @@ final class SaveManyBeans extends SaveManyBase {
|
||||
this.untouchedBeanCollection = untouchedBeanCollection();
|
||||
this.collection = cascade ? BeanCollectionUtil.getActualEntries(value) : null;
|
||||
this.hasOrderColumn = many.hasOrderColumn();
|
||||
this.forcedUpdate = request.isForcedUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,10 +129,8 @@ final class SaveManyBeans extends SaveManyBase {
|
||||
targetDescriptor.preAllocateIds(collection.size());
|
||||
}
|
||||
if (forcedUpdateOrphanRemoval()) {
|
||||
// collect the Id's (to exclude from deleteManyDetails)
|
||||
List<Object> detailIds = collectIds(collection, targetDescriptor, isMap);
|
||||
// deleting missing children - children not in our collected detailIds
|
||||
persister.deleteManyDetails(transaction, many.descriptor(), parentBean, many, detailIds, deleteMode);
|
||||
// deleting orphans, anything not in our detailsIds
|
||||
persister.deleteManyDetails(transaction, many.descriptor(), parentBean, many, detailIds(), deleteMode);
|
||||
}
|
||||
transaction.depth(+1);
|
||||
saveAllBeans(orderColumn);
|
||||
@@ -141,7 +141,7 @@ final class SaveManyBeans extends SaveManyBase {
|
||||
}
|
||||
|
||||
private boolean forcedUpdateOrphanRemoval() {
|
||||
return !insertedParent && many.isOrphanRemoval() && request.isForcedUpdate();
|
||||
return !insertedParent && many.isOrphanRemoval() && (forceOrphanRemoval || forcedUpdate);
|
||||
}
|
||||
|
||||
private void saveAllBeans(final BeanProperty orderColumn) {
|
||||
@@ -177,10 +177,6 @@ final class SaveManyBeans extends SaveManyBase {
|
||||
skipSavingThisBean = false;
|
||||
// set the parent bean to detailBean
|
||||
many.setJoinValuesToChild(parentBean, detail, mapKeyValue);
|
||||
} else if (insertAllChildren) {
|
||||
ebi.setNew();
|
||||
skipSavingThisBean = false;
|
||||
many.setJoinValuesToChild(parentBean, detail, mapKeyValue);
|
||||
} else {
|
||||
skipSavingThisBean = saveRecurseSkippable;
|
||||
}
|
||||
@@ -215,12 +211,10 @@ final class SaveManyBeans extends SaveManyBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect the Id values of the details to remove 'missing children' for stateless updates.
|
||||
* Return the Id values of beans we know are being updated (any others are orphans)
|
||||
*/
|
||||
private List<Object> collectIds(Collection<?> collection, BeanDescriptor<?> targetDescriptor, boolean isMap) {
|
||||
List<Object> detailIds = new ArrayList<>();
|
||||
// stateless update with deleteMissingChildren so first
|
||||
// collect the Id values to remove the 'missing children'
|
||||
private List<Object> detailIds() {
|
||||
final var detailIds = new ArrayList<>();
|
||||
for (Object detailBean : collection) {
|
||||
if (isMap) {
|
||||
detailBean = ((Map.Entry<?, ?>) detailBean).getValue();
|
||||
@@ -228,8 +222,10 @@ final class SaveManyBeans extends SaveManyBase {
|
||||
if (detailBean instanceof EntityBean) {
|
||||
Object id = targetDescriptor.id(detailBean);
|
||||
if (!isNullOrZero(id)) {
|
||||
// remember the Id (other details not in the collection) will be removed
|
||||
detailIds.add(id);
|
||||
if (forcedUpdate || !((EntityBean) detailBean)._ebean_getIntercept().isNew()) {
|
||||
// Id of bean that will be updated, exclude it from orphan removal
|
||||
detailIds.add(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -261,8 +257,7 @@ final class SaveManyBeans extends SaveManyBase {
|
||||
}
|
||||
|
||||
private void saveAssocManyIntersection(boolean queue) {
|
||||
boolean forcedUpdate = request.isForcedUpdate();
|
||||
boolean vanillaCollection = !(value instanceof BeanCollection<?>);
|
||||
final boolean vanillaCollection = !(value instanceof BeanCollection<?>);
|
||||
if (vanillaCollection || forcedUpdate) {
|
||||
// delete all intersection rows and then treat all
|
||||
// beans in the collection as additions
|
||||
@@ -321,7 +316,7 @@ final class SaveManyBeans extends SaveManyBase {
|
||||
CoreLog.log.log(System.Logger.Level.WARNING, m);
|
||||
} else {
|
||||
if (!many.hasImportedId(otherBean)) {
|
||||
throw new PersistenceException("ManyToMany bean " + otherBean + " does not have an Id value.");
|
||||
throw new PersistenceException("ManyToMany bean does not have an Id value? " + otherBean);
|
||||
} else {
|
||||
// build a intersection row for 'insert'
|
||||
IntersectionRow intRow = many.buildManyToManyMapBean(parentBean, otherBean, publish);
|
||||
@@ -344,10 +339,7 @@ final class SaveManyBeans extends SaveManyBase {
|
||||
return;
|
||||
}
|
||||
if (!(value instanceof BeanCollection<?>)) {
|
||||
if (!forcedUpdateOrphanRemoval() && (!insertedParent && cascade && isChangedProperty())) {
|
||||
persister.addToFlushQueue(many.deleteByParentId(request.beanId(), null), transaction, 0);
|
||||
insertAllChildren = true;
|
||||
}
|
||||
forceOrphanRemoval = !insertedParent && isChangedProperty();
|
||||
} else {
|
||||
BeanCollection<?> c = (BeanCollection<?>) value;
|
||||
Set<?> modifyRemovals = c.getModifyRemovals();
|
||||
@@ -359,7 +351,9 @@ final class SaveManyBeans extends SaveManyBase {
|
||||
if (!hasOrderColumn) {
|
||||
c.modifyReset();
|
||||
}
|
||||
if (modifyRemovals != null && !modifyRemovals.isEmpty()) {
|
||||
if (modifyRemovals == null || modifyRemovals.isEmpty()) {
|
||||
forceOrphanRemoval = !insertedParent && isChangedProperty();
|
||||
} else {
|
||||
for (Object removedBean : modifyRemovals) {
|
||||
if (removedBean instanceof EntityBean) {
|
||||
EntityBean eb = (EntityBean) removedBean;
|
||||
|
||||
@@ -585,16 +585,11 @@ final class CQueryBuilder {
|
||||
}
|
||||
if (distinct && dbOrderBy != null) {
|
||||
// add the orderBy columns to the select clause (due to distinct)
|
||||
final OrderBy<?> orderBy = query.getOrderBy();
|
||||
if (orderBy != null && orderBy.supportsSelect()) {
|
||||
String trimmed = DbOrderByTrim.trim(dbOrderBy);
|
||||
if (query.isSingleAttribute() && select.selectSql().startsWith(trimmed)) {
|
||||
// NOP, already in SQL
|
||||
// TODO: what to do if we select("id").orderBy("prop,id")?
|
||||
// Can we live with a query like "select t0.id, t0.prop, t0.id from"
|
||||
// or should we elliminate the second "t0.id" from select
|
||||
} else {
|
||||
sb.append(", ").append(trimmed);
|
||||
String[] tokens = DbOrderByTrim.trim(dbOrderBy).split(",");
|
||||
for (String token : tokens) {
|
||||
token = token.trim();
|
||||
if (!DbOrderByTrim.contains(select.selectSql(), token)) {
|
||||
sb.append(", ").append(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -643,7 +638,7 @@ final class CQueryBuilder {
|
||||
private void appendHistoryAsOfPredicate() {
|
||||
if (query.isAsOfBaseTable()) {
|
||||
query.incrementAsOfTableCount();
|
||||
if (!historySupport.isStandardsBased()){
|
||||
if (!historySupport.isStandardsBased()) {
|
||||
appendAndOrWhere();
|
||||
sb.append(historySupport.asOfPredicate(request.baseTableAlias()));
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import java.util.regex.Pattern;
|
||||
|
||||
final class DbOrderByTrim {
|
||||
|
||||
private static final Pattern orderByTrim = Pattern.compile("(?i) asc\\b| desc\\b|\\b nulls first\\b|\\b nulls last\\b");
|
||||
private static final Pattern orderByTrim = Pattern.compile("(?i) asc\\b| desc\\b| nulls first\\b| nulls last\\b");
|
||||
|
||||
/**
|
||||
* Convert the dbOrderBy clause to be safe for adding to select or distinct on.
|
||||
@@ -14,4 +14,21 @@ final class DbOrderByTrim {
|
||||
return orderByTrim.matcher(dbOrderBy).replaceAll("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks, if <code>sql</code> contains the <code>column</code>.
|
||||
* <p>
|
||||
* SQL is normally comma separated: "t0.id, t1.id, t2.name"
|
||||
*/
|
||||
static boolean contains(String sql, String column) {
|
||||
if (sql.endsWith(column)) { // simplest way. sql ends with the column
|
||||
return true;
|
||||
} else if (sql.contains(column)) {
|
||||
// We need to check, if it is really the correct column,
|
||||
// sql="t0.name_short, t0.name_long" will match on column="t0.name"
|
||||
return sql.contains(column + ",");
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ public final class SqlTreeBuilder {
|
||||
String[] split = idCols.split(",");
|
||||
for (String col : split) {
|
||||
col = col.trim();
|
||||
if (!dbOrderBy.contains(col)) {
|
||||
if (!DbOrderByTrim.contains(dbOrderBy, col)) {
|
||||
sb.append(", ").append(col);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebean.core.type.ScalarDataReader;
|
||||
import io.ebeaninternal.api.CoreLog;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
import io.ebeaninternal.api.SpiQuery.Mode;
|
||||
import io.ebeaninternal.server.deploy.DbReadContext;
|
||||
@@ -14,6 +15,8 @@ import io.ebeaninternal.server.deploy.id.IdBinder;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.lang.System.Logger.Level.DEBUG;
|
||||
|
||||
/**
|
||||
* Normal bean included in the query.
|
||||
*/
|
||||
@@ -211,6 +214,9 @@ class SqlTreeLoadBean implements SqlTreeLoad {
|
||||
contextBean = ((STreePropertyAssocOne)nodeBeanProp).valueAsEntityBean(parentBean);
|
||||
if (contextBean != null) {
|
||||
desc.markAsDeleted(contextBean);
|
||||
if (CoreLog.markedAsDeleted.isLoggable(DEBUG)) {
|
||||
CoreLog.markedAsDeleted.log(DEBUG, contextBean + " contextBean markedAsDeleted", new RuntimeException(contextBean + " contextBean markedAsDeleted"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -99,6 +99,14 @@ public class DefaultExpressionListTest extends BaseExpressionTest {
|
||||
.isSameByBind(spi(exp().eq("a", 10).eq("b", 20)))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isSameWithClear() {
|
||||
DefaultExpressionList<?> exp1 = spi(exp().eq("a", 10).eq("b", 20).clear().eq("c", 30));
|
||||
DefaultExpressionList<?> exp2 = spi(exp().eq("c", 30));
|
||||
same(exp1, exp2);
|
||||
assertThat(exp1.isSameByBind(exp2)).isTrue();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
void copy() {
|
||||
|
||||
@@ -64,4 +64,11 @@ public class DbOrderByTrimTest {
|
||||
assertEquals("foo", DbOrderByTrim.trim("foo desc nulls last"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void trim_nulls_withAggFunction() {
|
||||
assertEquals("min(customer)", DbOrderByTrim.trim("min(customer) asc nulls last"));
|
||||
assertEquals("foo,min(customer)", DbOrderByTrim.trim("foo,min(customer) asc nulls last"));
|
||||
assertEquals("bar,min(customer)", DbOrderByTrim.trim("bar desc,min(customer) asc nulls last"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-csv-reader</artifactId>
|
||||
@@ -14,21 +14,21 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean ddl generation</name>
|
||||
@@ -28,14 +28,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-all</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.ebeaninternal.dbmigration.model;
|
||||
|
||||
import io.ebeaninternal.dbmigration.ddlgeneration.platform.DdlHelp;
|
||||
import io.ebeaninternal.dbmigration.migration.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -125,6 +126,21 @@ public class ModelDiff {
|
||||
// search for tables that are no longer used
|
||||
for (MTable existingTable : baseModel.getTables().values()) {
|
||||
if (!newTables.containsKey(existingTable.getName())) {
|
||||
// Compounded foreign keys used in many-to-many mapping tables
|
||||
existingTable.getCompoundKeys().forEach(it -> addAlterForeignKey(it.dropForeignKey(existingTable.getName())));
|
||||
// Foreign keys through direct mapping (oneToMany)
|
||||
existingTable.allColumns().stream()
|
||||
.filter(it -> it.getForeignKeyIndex() != null)
|
||||
.map(it -> {
|
||||
AlterForeignKey fk = new AlterForeignKey();
|
||||
fk.setName(it.getForeignKeyName());
|
||||
fk.setIndexName(it.getForeignKeyIndex());
|
||||
fk.setColumnNames(DdlHelp.DROP_FOREIGN_KEY);
|
||||
fk.setTableName(existingTable.getName());
|
||||
return fk;
|
||||
})
|
||||
.forEach(applyChanges::add);
|
||||
|
||||
addDropTable(existingTable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean external mapping api</name>
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-parent-13.10.2</tag>
|
||||
<tag>ebean-parent-13.11.4</tag>
|
||||
</scm>
|
||||
|
||||
<name>ebean external mapping xml</name>
|
||||
@@ -21,7 +21,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-externalmapping-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -54,21 +54,21 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-jackson-jsonnode</artifactId>
|
||||
@@ -14,7 +14,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core-type</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2-SNAPSHOT</version>
|
||||
<version>13.11.4-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-kotlin</artifactId>
|
||||
@@ -28,7 +28,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2-SNAPSHOT</version>
|
||||
<version>13.11.4-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>13.10.2-SNAPSHOT</version>
|
||||
<version>13.11.4-SNAPSHOT</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean postgis</name>
|
||||
@@ -22,14 +22,14 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- provided scope -->
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.5.0</version>
|
||||
<version>42.5.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean querybean</name>
|
||||
@@ -17,7 +17,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -63,21 +63,21 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ package org.example.domain;
|
||||
import io.ebean.annotation.DbArray;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -16,7 +18,11 @@ import java.util.Map;
|
||||
public class Contact extends BaseModel {
|
||||
|
||||
@DbArray
|
||||
List<String> phoneNumbers = new ArrayList<>();
|
||||
List<@Size(max=20) String> phoneNumbers = new ArrayList<>();
|
||||
|
||||
@ElementCollection
|
||||
@Size(max=10)
|
||||
List<@Size(max=20) String> paths;
|
||||
|
||||
@Column(length = 50)
|
||||
String firstName;
|
||||
@@ -36,7 +42,7 @@ public class Contact extends BaseModel {
|
||||
Customer customer;
|
||||
|
||||
@OneToMany(mappedBy = "contact")
|
||||
List<ContactNote> notes;
|
||||
List<@NotNull ContactNote> notes;
|
||||
|
||||
@OneToMany(cascade = CascadeType.PERSIST)
|
||||
@MapKey(name = "key")
|
||||
|
||||
@@ -857,10 +857,20 @@ public class QCustomerTest {
|
||||
cust.setName("testFetchByScalarValue");
|
||||
cust.setPhoneNumber(new PhoneNumber("+18005555555"));
|
||||
cust.save();
|
||||
assertThat(new QCustomer()
|
||||
|
||||
var customer = new QCustomer()
|
||||
.name.eq("testFetchByScalarValue")
|
||||
.phoneNumber.eq(new PhoneNumber("+18005555555"))
|
||||
.findOne()).isNotNull();
|
||||
.findOne();
|
||||
|
||||
assertThat(customer).isNotNull();
|
||||
|
||||
var customers = new QCustomer()
|
||||
.name.eq("testFetchByScalarValue")
|
||||
.phoneNumber.eq(new PhoneNumber("+18005555555"))
|
||||
.findList();
|
||||
|
||||
assertThat(customers).hasSize(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ datasource.default=h2
|
||||
|
||||
datasource.h2.username=sa
|
||||
datasource.h2.password=
|
||||
datasource.h2.url=jdbc:h2:mem:tests;NON_KEYWORDS=KEY
|
||||
datasource.h2.url=jdbc:h2:mem:tests;NON_KEYWORDS=KEY,VALUE
|
||||
|
||||
datasource.pg.username=sa
|
||||
datasource.pg.password=
|
||||
datasource.pg.url=jdbc:h2:mem:tests;NON_KEYWORDS=KEY
|
||||
datasource.pg.url=jdbc:h2:mem:tests;NON_KEYWORDS=KEY,VALUE
|
||||
|
||||
+6
-6
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ebean-redis</artifactId>
|
||||
@@ -22,35 +22,35 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-test</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.domain;
|
||||
|
||||
import io.ebean.Model;
|
||||
import io.ebean.annotation.Cache;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
@Cache
|
||||
@Entity
|
||||
public class UChild extends Model {
|
||||
|
||||
@Id
|
||||
long id;
|
||||
|
||||
String name;
|
||||
|
||||
@ManyToOne
|
||||
final UParent parent;
|
||||
|
||||
public UChild(UParent parent, String name) {
|
||||
this.parent = parent;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public long id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.domain;
|
||||
|
||||
import io.ebean.Model;
|
||||
import io.ebean.annotation.Cache;
|
||||
import io.ebean.annotation.CacheBeanTuning;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@Cache(enableQueryCache = true)
|
||||
@CacheBeanTuning(maxSecsToLive = 1)
|
||||
@Entity
|
||||
public class UParent extends Model {
|
||||
|
||||
@Id
|
||||
private UUID id;
|
||||
|
||||
private String name;
|
||||
|
||||
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL)
|
||||
private final List<UChild> children = new ArrayList<>();
|
||||
|
||||
public UParent(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public UUID id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<UChild> children() {
|
||||
return children;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@ import io.ebean.cache.ServerCache;
|
||||
import io.ebean.cache.ServerCacheStatistics;
|
||||
import org.domain.Person;
|
||||
import org.domain.RCust;
|
||||
import org.domain.UChild;
|
||||
import org.domain.UParent;
|
||||
import org.domain.query.QPerson;
|
||||
import org.domain.query.QRCust;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -19,6 +21,32 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class IntegrationTest {
|
||||
|
||||
@Test
|
||||
void uuid_getPut() {
|
||||
UParent b0 = new UParent("b0");
|
||||
b0.children().add(new UChild(b0,"b0c0"));
|
||||
b0.children().add(new UChild(b0,"b0c1"));
|
||||
b0.save();
|
||||
|
||||
ServerCache beanCache = DB.cacheManager().beanCache(UParent.class);
|
||||
beanCache.clear();
|
||||
beanCache.statistics(true);
|
||||
|
||||
UParent found0 = DB.find(UParent.class, b0.id());
|
||||
assertThat(found0.name()).isEqualTo("b0");
|
||||
|
||||
List<UChild> children = found0.children();
|
||||
assertThat(children).hasSize(2);
|
||||
|
||||
UParent found1 = DB.find(UParent.class, b0.id());
|
||||
assertThat(found1.name()).isEqualTo("b0");
|
||||
|
||||
DB.delete(found1);
|
||||
|
||||
ServerCacheStatistics stats1 = beanCache.statistics(true);
|
||||
assertThat(stats1.getHitCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void mget_when_emptyCollectionOfIds() {
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ ebean:
|
||||
dumpMetricsOnShutdown: true
|
||||
dumpMetricsOptions: sql,hash,loc
|
||||
test:
|
||||
registerTestTenantProvider: false
|
||||
redis: latest
|
||||
# shutdown: stop # stop | remove
|
||||
platform: h2 # h2, postgres, mysql, oracle, sqlserver, sqlite
|
||||
|
||||
+9
-9
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean test</name>
|
||||
@@ -28,20 +28,20 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-ddl-generator</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -105,28 +105,28 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-joda-time</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-jsonnode</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-mapper</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-all</artifactId>
|
||||
<version>13.10.2</version>
|
||||
<version>13.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -183,7 +183,7 @@
|
||||
<dependency>
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>42.5.0</version>
|
||||
<version>42.5.1</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.checkerframework</groupId>
|
||||
|
||||
@@ -25,7 +25,7 @@ class YugabyteSetup implements PlatformSetup {
|
||||
if (!config.isUseDocker()) {
|
||||
return new Properties();
|
||||
}
|
||||
config.setDockerVersion("2.11.2.0-b89");
|
||||
config.setDockerVersion("2.16.0.1-b7");
|
||||
config.setExtensions("pgcrypto");
|
||||
return config.getDockerProperties();
|
||||
}
|
||||
|
||||
@@ -38,8 +38,10 @@ public class ProviderAutoConfig {
|
||||
|
||||
CurrentTenantProvider tenantProvider = config.getCurrentTenantProvider();
|
||||
if (tenantProvider == null) {
|
||||
providerSetFlag += 2;
|
||||
config.setCurrentTenantProvider(new WhoTenantProvider());
|
||||
if (Boolean.parseBoolean(properties.getProperty("ebean.test.registerTestTenantProvider", "true"))) {
|
||||
providerSetFlag += 2;
|
||||
config.setCurrentTenantProvider(new WhoTenantProvider());
|
||||
}
|
||||
}
|
||||
|
||||
EncryptKeyManager keyManager = config.getEncryptKeyManager();
|
||||
|
||||
@@ -236,7 +236,95 @@ public class DtoQuery2Test extends BaseTestCase {
|
||||
assertThat(stats).hasSize(2);
|
||||
|
||||
log.info("stats " + stats);
|
||||
}
|
||||
|
||||
@Test
|
||||
void dto_mapping_columnsWithUnderscores() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
List<DCustCamelCols0> list = server().findDto(DCustCamelCols0.class,
|
||||
"select id as num_with, name as name_for_me from o_customer")
|
||||
.findList();
|
||||
|
||||
assertThat(list).isNotEmpty();
|
||||
for (DCustCamelCols0 dto : list) {
|
||||
assertThat(dto.getNumWith()).isGreaterThan(0);
|
||||
assertThat(dto.getNameForMe()).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void dto_mapping_columnsWithNoUnderscores() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
List<DCustCamelCols0> list = server().findDto(DCustCamelCols0.class,
|
||||
"select id as numwith, name as nameforme from o_customer")
|
||||
.findList();
|
||||
|
||||
assertThat(list).isNotEmpty();
|
||||
for (DCustCamelCols0 dto : list) {
|
||||
assertThat(dto.getNumWith()).isGreaterThan(0);
|
||||
assertThat(dto.getNameForMe()).isNotNull();
|
||||
}
|
||||
|
||||
// mapping is case-insensitive
|
||||
List<DCustCamelCols0> list2 = server().findDto(DCustCamelCols0.class,
|
||||
"select id as numWith, name as nameForMe from o_customer")
|
||||
.findList();
|
||||
|
||||
assertThat(list2).isNotEmpty();
|
||||
for (DCustCamelCols0 dto : list2) {
|
||||
assertThat(dto.getNumWith()).isGreaterThan(0);
|
||||
assertThat(dto.getNameForMe()).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void dto_mapping_propertyNamesCaseInsensitive() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
List<DCustCamelCols2> list = server().findDto(DCustCamelCols2.class,
|
||||
"select id as numwith, name as nameforme from o_customer")
|
||||
.findList();
|
||||
|
||||
assertThat(list).isNotEmpty();
|
||||
for (DCustCamelCols2 dto : list) {
|
||||
assertThat(dto.getNumWITH()).isGreaterThan(0);
|
||||
assertThat(dto.getNameFORMe()).isNotNull();
|
||||
}
|
||||
|
||||
// mapping is case-insensitive
|
||||
List<DCustCamelCols2> list2 = server().findDto(DCustCamelCols2.class,
|
||||
"select id as numWith, name as nameForMe from o_customer")
|
||||
.findList();
|
||||
|
||||
assertThat(list2).isNotEmpty();
|
||||
for (DCustCamelCols2 dto : list2) {
|
||||
assertThat(dto.getNumWITH()).isGreaterThan(0);
|
||||
assertThat(dto.getNameFORMe()).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void dto_mapping_columnsUsingNestedSql() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
String sql
|
||||
= "select num_with, name_for_me from ( "
|
||||
// we don't CARE what the nested SQL is in that the jdbc metaData
|
||||
// for the column names/labels comes from the top most select
|
||||
+ " select id as num_with, name as name_for_me from o_customer "
|
||||
+ ") a";
|
||||
|
||||
List<DCustCamelCols0> list = server().findDto(DCustCamelCols0.class,
|
||||
sql)
|
||||
.findList();
|
||||
|
||||
assertThat(list).isNotEmpty();
|
||||
for (DCustCamelCols0 dto : list) {
|
||||
assertThat(dto.getNumWith()).isGreaterThan(0);
|
||||
assertThat(dto.getNameForMe()).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -478,4 +566,52 @@ public class DtoQuery2Test extends BaseTestCase {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
public static class DCustCamelCols0 {
|
||||
|
||||
Integer numWith;
|
||||
String nameForMe;
|
||||
|
||||
public Integer getNumWith() {
|
||||
return numWith;
|
||||
}
|
||||
|
||||
public DCustCamelCols0 setNumWith(Integer numWith) {
|
||||
this.numWith = numWith;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getNameForMe() {
|
||||
return nameForMe;
|
||||
}
|
||||
|
||||
public DCustCamelCols0 setNameForMe(String nameForMe) {
|
||||
this.nameForMe = nameForMe;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class DCustCamelCols2 {
|
||||
|
||||
Integer numWITH;
|
||||
String nameFORMe;
|
||||
|
||||
public Integer getNumWITH() {
|
||||
return numWITH;
|
||||
}
|
||||
|
||||
public DCustCamelCols2 setNumWITH(Integer numWITH) {
|
||||
this.numWITH = numWITH;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getNameFORMe() {
|
||||
return nameFORMe;
|
||||
}
|
||||
|
||||
public DCustCamelCols2 setNameFORMe(String nameFORMe) {
|
||||
this.nameFORMe = nameFORMe;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import org.tests.model.basic.ECustomId;
|
||||
import org.tests.model.controller.FindControllerMain;
|
||||
import org.tests.model.controller.SoftRefA;
|
||||
import org.tests.model.controller.SoftRefB;
|
||||
import org.tests.model.controller.TestBeanFindController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
+3
-2
@@ -1,16 +1,17 @@
|
||||
package org.tests.model.controller;
|
||||
package io.ebean.xtest.event;
|
||||
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.event.BeanFindController;
|
||||
import io.ebean.event.BeanQueryRequest;
|
||||
import io.ebean.plugin.BeanType;
|
||||
import org.tests.model.controller.FindControllerMain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class TestBeanFindController implements BeanFindController {
|
||||
class TestBeanFindController implements BeanFindController {
|
||||
|
||||
@Override
|
||||
public boolean isRegisterFor(final Class<?> cls) {
|
||||
@@ -0,0 +1,48 @@
|
||||
package misc.migration.v1_0;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Test-model referencing two other tables, which gets dropped for migration test in order to check for correct table drop
|
||||
* procedure (first drop foreign keys, then the tables).
|
||||
*
|
||||
* @author Jonas Pöhler, FOCONIS AG
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "drop_main")
|
||||
public class DropMain {
|
||||
|
||||
@Id
|
||||
Integer id;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "parent")
|
||||
List<DropRefOne> refsOne;
|
||||
|
||||
@ManyToMany(cascade = CascadeType.ALL)
|
||||
List<DropRefMany> refsMany;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public List<DropRefOne> getRefsOne() {
|
||||
return refsOne;
|
||||
}
|
||||
|
||||
public void setRefsOne(List<DropRefOne> refsOne) {
|
||||
this.refsOne = refsOne;
|
||||
}
|
||||
|
||||
public List<DropRefMany> getRefsMany() {
|
||||
return refsMany;
|
||||
}
|
||||
|
||||
public void setRefsMany(List<DropRefMany> refsMany) {
|
||||
this.refsMany = refsMany;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package misc.migration.v1_0;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name = "drop_ref_many")
|
||||
public class DropRefMany {
|
||||
|
||||
@Id
|
||||
Integer id;
|
||||
|
||||
@ManyToMany(cascade = {}, mappedBy = "refsMany")
|
||||
List<DropMain> parents;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public List<DropMain> getParents() {
|
||||
return parents;
|
||||
}
|
||||
|
||||
public void setParents(List<DropMain> parents) {
|
||||
this.parents = parents;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package misc.migration.v1_0;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "drop_ref_one")
|
||||
public class DropRefOne {
|
||||
|
||||
@Id
|
||||
Integer id;
|
||||
|
||||
@ManyToOne(cascade = {})
|
||||
DropMain parent;
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public DropMain getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public void setParent(DropMain parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
package org.tests.basic;
|
||||
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.xtest.IgnorePlatform;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.model.basic.Order;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
@@ -22,6 +24,7 @@ public class TestLimitQuery extends BaseTestCase {
|
||||
rob();
|
||||
}
|
||||
|
||||
@IgnorePlatform({Platform.MYSQL, Platform.MARIADB})
|
||||
@Test
|
||||
public void testMaxRowsZeroWithFirstRow() {
|
||||
|
||||
@@ -40,7 +43,7 @@ public class TestLimitQuery extends BaseTestCase {
|
||||
String sql = query.getGeneratedSql();
|
||||
if (isH2()) {
|
||||
assertThat(sql).contains("offset 3");
|
||||
assertThat(sql).contains("limit 0");
|
||||
assertThat(sql).doesNotContain("limit");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package org.tests.basic;
|
||||
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.QueryIterator;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import io.ebeaninternal.api.SpiPersistenceContext;
|
||||
import io.ebeaninternal.api.SpiTransaction;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
@@ -12,15 +15,17 @@ import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.Order;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.WeakHashMap;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Entity;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class TestPersistenceContext extends BaseTestCase {
|
||||
public class TestPersistenceContext extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
void testReload() {
|
||||
@@ -191,29 +196,135 @@ class TestPersistenceContext extends BaseTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Disabled // run manually
|
||||
@Test
|
||||
void testPcScopes_with_findEachFindList() {
|
||||
for (int i = 0; i < 5000; i++) {
|
||||
Customer c = new Customer();
|
||||
c.setName("Customer #" + i);
|
||||
DB.save(c);
|
||||
Order o = new Order();
|
||||
o.setCustomer(c);
|
||||
DB.save(o);
|
||||
@Embeddable
|
||||
public static class TmId {
|
||||
private final UUID id1;
|
||||
private final UUID id2;
|
||||
|
||||
public TmId(UUID id1, UUID id2) {
|
||||
this.id1 = id1;
|
||||
this.id2 = id2;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
try (Transaction txn = DB.beginTransaction()) {
|
||||
List<Customer> customers = new ArrayList<>();
|
||||
DB.find(Customer.class).select("id").findEach(customers::add);
|
||||
SpiPersistenceContext pc = ((SpiTransaction) txn).getPersistenceContext();
|
||||
assertThat(pc.toString()).contains("Customer=size:5000 (5000 weak)");
|
||||
customers.clear();
|
||||
customers = DB.find(Customer.class).select("id").findList();
|
||||
public UUID getId1() {
|
||||
return id1;
|
||||
}
|
||||
|
||||
assertThat(pc.toString()).contains("Customer=size:5000"); // We expect ALWAYS 5000 entries in the PC
|
||||
}
|
||||
public UUID getId2() {
|
||||
return id2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
TmId tmId = (TmId) o;
|
||||
return Objects.equals(id1, tmId.id1) && Objects.equals(id2, tmId.id2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id1, id2);
|
||||
}
|
||||
}
|
||||
|
||||
@Entity
|
||||
// @Cache(enableQueryCache = true, enableBeanCache = false)
|
||||
public static class TestModel2 {
|
||||
|
||||
@EmbeddedId
|
||||
private TmId id;
|
||||
@Size(max = 255)
|
||||
private String someData;
|
||||
|
||||
public String getSomeData() {
|
||||
return someData;
|
||||
}
|
||||
|
||||
public void setSomeData(String someData) {
|
||||
this.someData = someData;
|
||||
}
|
||||
|
||||
public TmId getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(TmId id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
void initDb() {
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setName("h2-batch");
|
||||
config.loadFromProperties();
|
||||
config.setDdlExtra(false);
|
||||
config.getDataSourceConfig().setUsername("sa");
|
||||
config.getDataSourceConfig().setPassword("sa");
|
||||
config.getDataSourceConfig().setUrl("jdbc:h2:file:./testsFile3;DB_CLOSE_ON_EXIT=FALSE;NON_KEYWORDS=KEY,VALUE");
|
||||
config.addClass(TestModel2.class);
|
||||
config.addClass(TmId.class);
|
||||
DatabaseFactory.create(config);
|
||||
|
||||
String base = "x".repeat(240);
|
||||
// 10 mio TestModel - each needs about 1/4 kbytes -> 2,5 GB in total
|
||||
List<TestModel2> batch = new ArrayList<>();
|
||||
for (int i = 0; i < 1_000_000; i++) {
|
||||
TestModel2 m = new TestModel2();
|
||||
TmId id = new TmId(UUID.randomUUID(), UUID.randomUUID());
|
||||
m.setId(id);
|
||||
m.setSomeData(base + i); // ensure we have not duplicates
|
||||
batch.add(m);
|
||||
if (i % 1000 == 0) {
|
||||
DB.saveAll(batch);
|
||||
batch.clear();
|
||||
}
|
||||
if (i % 100000 == 0) {
|
||||
System.out.println(i);
|
||||
}
|
||||
}
|
||||
DB.saveAll(batch);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled
|
||||
void testFindEachFindList() {
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setName("h2-batch");
|
||||
config.loadFromProperties();
|
||||
config.setDdlRun(false);
|
||||
config.getDataSourceConfig().setUsername("sa");
|
||||
config.getDataSourceConfig().setPassword("sa");
|
||||
config.getDataSourceConfig().setUrl("jdbc:h2:file:./testsFile3;DB_CLOSE_ON_EXIT=FALSE;NON_KEYWORDS=KEY,VALUE");
|
||||
config.addClass(TestModel2.class);
|
||||
config.addClass(TmId.class);
|
||||
DatabaseFactory.create(config);
|
||||
|
||||
AtomicInteger i = new AtomicInteger();
|
||||
System.out.println("Doing findEach");
|
||||
DB.find(TestModel2.class).select("*").findEach(c -> {
|
||||
i.incrementAndGet();
|
||||
});
|
||||
System.out.println("Read " + i + " entries");
|
||||
|
||||
i.set(0);
|
||||
System.out.println("Doing findStream");
|
||||
DB.find(TestModel2.class).select("*").findStream().forEach(c -> i.incrementAndGet());
|
||||
System.out.println("Read " + i + " entries");
|
||||
|
||||
i.set(0);
|
||||
System.out.println("Doing findIterate");
|
||||
QueryIterator<TestModel2> iter = DB.find(TestModel2.class).select("*").findIterate();
|
||||
while (iter.hasNext()) {
|
||||
iter.next();
|
||||
i.incrementAndGet();
|
||||
}
|
||||
System.out.println("Read " + i + " entries");
|
||||
|
||||
System.out.println("Doing FindList, will hold all entries in memory. Expect OOM with -Xmx100m.");
|
||||
List<TestModel2> lst = DB.find(TestModel2.class).select("*").findList();
|
||||
System.out.println("Read " + lst.size() + " entries");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import io.ebean.xtest.BaseTestCase;
|
||||
import io.ebean.xtest.ForPlatform;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.test.LoggedSql;
|
||||
import io.ebean.xtest.IgnorePlatform;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.EBasic;
|
||||
@@ -19,7 +20,6 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
public class TestQueryForUpdate extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
@ForPlatform({Platform.H2, Platform.ORACLE, Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL, Platform.MARIADB})
|
||||
public void testForUpdate() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
@@ -35,13 +35,35 @@ public class TestQueryForUpdate extends BaseTestCase {
|
||||
|
||||
if (isSqlServer()) {
|
||||
assertThat(sqlOf(query)).contains("with (updlock)");
|
||||
} else {
|
||||
} else if (!isDb2()){
|
||||
assertThat(sqlOf(query)).contains("for update");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@ForPlatform({ Platform.H2, Platform.ORACLE, Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL, Platform.MARIADB})
|
||||
public void testForUpdate_withLimit() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
Query<Customer> query;
|
||||
try (final Transaction transaction = DB.beginTransaction()) {
|
||||
query = DB.find(Customer.class)
|
||||
.forUpdate()
|
||||
.setMaxRows(3)
|
||||
.order().desc("id");
|
||||
|
||||
query.findList();
|
||||
}
|
||||
|
||||
if (isSqlServer()) {
|
||||
assertThat(sqlOf(query)).contains("with (updlock)");
|
||||
} else if (!isOracle() && !isDb2()) {
|
||||
// Oracle does not support FOR UPDATE with FETCH
|
||||
assertThat(sqlOf(query)).contains("for update");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@ForPlatform({Platform.H2, Platform.ORACLE, Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL, Platform.MARIADB})
|
||||
public void testForUpdate_when_alreadyInPCAsReference() {
|
||||
ResetBasicData.reset();
|
||||
Order o0 = DB.find(Order.class).orderBy("id").setMaxRows(1).findOne();
|
||||
@@ -75,7 +97,7 @@ public class TestQueryForUpdate extends BaseTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
@ForPlatform({ Platform.H2, Platform.ORACLE, Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL, Platform.MARIADB})
|
||||
@ForPlatform({Platform.H2, Platform.ORACLE, Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL, Platform.MARIADB})
|
||||
public void testForUpdate_when_alreadyInPCAsReference_usingLock() {
|
||||
ResetBasicData.reset();
|
||||
Order o0 = DB.find(Order.class).orderBy("id").setMaxRows(1).findOne();
|
||||
@@ -110,7 +132,7 @@ public class TestQueryForUpdate extends BaseTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
@ForPlatform({ Platform.H2, Platform.ORACLE, Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL, Platform.MARIADB})
|
||||
@ForPlatform({Platform.H2, Platform.ORACLE, Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL, Platform.MARIADB})
|
||||
public void testForUpdate_when_alreadyInPC() {
|
||||
|
||||
EBasic basic = new EBasic("test PC cache");
|
||||
@@ -124,7 +146,7 @@ public class TestQueryForUpdate extends BaseTestCase {
|
||||
assertThat(basic0).isNotNull();
|
||||
|
||||
EBasic basic1 = DB.find(EBasic.class)
|
||||
.setId( basic.getId())
|
||||
.setId(basic.getId())
|
||||
.forUpdate()
|
||||
.findOne();
|
||||
|
||||
|
||||
+120
-3
@@ -1,11 +1,12 @@
|
||||
package org.tests.cache;
|
||||
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.cache.ServerCache;
|
||||
import io.ebean.cache.ServerCacheStatistics;
|
||||
import io.ebean.test.LoggedSql;
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -15,6 +16,7 @@ import org.tests.model.basic.OCachedBean;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -54,10 +56,51 @@ public class TestBeanCache extends BaseTestCase {
|
||||
assertThat(sql).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void idsInFindMap() {
|
||||
|
||||
List<OCachedBean> beans = createBeans(Arrays.asList("m0", "m1", "m2", "m3", "m4", "m5", "m6"));
|
||||
List<Long> ids = beans.stream().map(OCachedBean::getId).collect(Collectors.toList());
|
||||
beanCache.clear();
|
||||
beanCache.statistics(true);
|
||||
Query<OCachedBean> query = DB.find(OCachedBean.class).setUseCache(true);
|
||||
|
||||
// Test findIds
|
||||
LoggedSql.start();
|
||||
query.copy()
|
||||
.where().idIn(ids.subList(0, 1))
|
||||
.findMap(); // cache key is: 3/d[{/c1000}]/w[List[IdIn[?1],]]
|
||||
if (isPostgresCompatible()) {
|
||||
assertThat(LoggedSql.stop().get(0)).contains("t0.id = any(?)");
|
||||
} else {
|
||||
assertThat(LoggedSql.stop().get(0)).contains("in (?)");
|
||||
}
|
||||
|
||||
LoggedSql.start();
|
||||
query.copy()
|
||||
.where().idIn(ids.subList(0, 4))
|
||||
.findMap(); // cache key is: 3/d[{/c1000}]/w[List[IdIn[?5],]]
|
||||
if (isPostgresCompatible()) {
|
||||
assertThat(LoggedSql.stop().get(0)).contains("t0.id = any(?)");
|
||||
} else {
|
||||
assertThat(LoggedSql.stop().get(0)).contains("in (?,?,?,?,?)");
|
||||
}
|
||||
|
||||
LoggedSql.start();
|
||||
query.copy()
|
||||
.where().idIn(ids.subList(2, 6))
|
||||
.findMap(); // same cache key as above and same SQL above
|
||||
if (isPostgresCompatible()) {
|
||||
assertThat(LoggedSql.stop().get(0)).contains("t0.id = any(?)");
|
||||
} else {
|
||||
assertThat(LoggedSql.stop().get(0)).contains("in (?,?,?,?,?)");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void idsIn_explicitCache_expect_cachePut() {
|
||||
|
||||
List<OCachedBean> beans = createBeans(Arrays.asList("k0","k1"));
|
||||
List<OCachedBean> beans = createBeans(Arrays.asList("k0", "k1"));
|
||||
List<Long> ids = beans.stream().map(OCachedBean::getId).collect(Collectors.toList());
|
||||
|
||||
beanCache.clear();
|
||||
@@ -157,6 +200,80 @@ public class TestBeanCache extends BaseTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindSet() {
|
||||
|
||||
List<OCachedBean> beans = createBeans(Arrays.asList("z0", "z1", "z2"));
|
||||
List<Long> ids = beans.stream().map(OCachedBean::getId).collect(Collectors.toList());
|
||||
|
||||
beanCache.clear();
|
||||
beanCache.statistics(true);
|
||||
|
||||
LoggedSql.start();
|
||||
|
||||
log.info("All misses (0 of 3) ...");
|
||||
Set<OCachedBean> set = DB.find(OCachedBean.class)
|
||||
.where().idIn(ids)
|
||||
.setUseCache(true)
|
||||
.findSet();
|
||||
|
||||
assertThat(set).hasSize(3);
|
||||
assertBeanCacheHitMiss(0, 3);
|
||||
List<String> sql = LoggedSql.collect();
|
||||
assertThat(sql).hasSize(1);
|
||||
if (isH2()) {
|
||||
assertSql(sql.get(0)).contains("from o_cached_bean t0 where t0.id in (?,?,?,?,?)");
|
||||
}
|
||||
|
||||
log.info("All hits (3 of 3) ...");
|
||||
set = DB.find(OCachedBean.class)
|
||||
.where().idIn(ids)
|
||||
.setUseCache(true)
|
||||
.findSet();
|
||||
|
||||
assertBeanCacheHitMiss(3, 0);
|
||||
assertThat(set).hasSize(3);
|
||||
sql = LoggedSql.collect();
|
||||
assertThat(sql).hasSize(0); // no misses
|
||||
|
||||
// remove a bean so that we get a "partial" hit (2 out of 3 in cache)
|
||||
beanCache.remove(beans.get(0).getId().toString());
|
||||
|
||||
log.info("Partial hits (2 of 3) ...");
|
||||
set = DB.find(OCachedBean.class)
|
||||
.where().idIn(ids)
|
||||
.setUseCache(true)
|
||||
.findSet();
|
||||
|
||||
assertBeanCacheHitMiss(2, 1);
|
||||
assertThat(set).hasSize(3);
|
||||
sql = LoggedSql.collect();
|
||||
assertThat(sql).hasSize(1);
|
||||
if (isH2()) {
|
||||
// fetch the miss from DB
|
||||
assertSql(sql.get(0)).contains("from o_cached_bean t0 where t0.id in (?)");
|
||||
}
|
||||
|
||||
// remove beans so that we get a "partial" hit (1 out of 3 in cache)
|
||||
beanCache.remove(beans.get(1).getId().toString());
|
||||
beanCache.remove(beans.get(2).getId().toString());
|
||||
|
||||
log.info("Partial hits (1 of 3) ...");
|
||||
set = DB.find(OCachedBean.class)
|
||||
.where().idIn(ids)
|
||||
.setUseCache(true)
|
||||
.findSet();
|
||||
|
||||
assertBeanCacheHitMiss(1, 2);
|
||||
assertThat(set).hasSize(3);
|
||||
sql = LoggedSql.stop();
|
||||
assertThat(sql).hasSize(1);
|
||||
if (isH2()) {
|
||||
// fetch the misses from DB
|
||||
assertSql(sql.get(0)).contains("from o_cached_bean t0 where t0.id in (?,?,?,?,?)");
|
||||
}
|
||||
}
|
||||
|
||||
private void assertBeanCacheHitMiss(int hitCount, int missCount) {
|
||||
ServerCacheStatistics statistics = beanCache.statistics(true);
|
||||
assertThat(statistics.getHitCount()).isEqualTo(hitCount);
|
||||
@@ -183,7 +300,7 @@ public class TestBeanCache extends BaseTestCase {
|
||||
|
||||
Country country = DB.find(Country.class)
|
||||
.where()
|
||||
.eq("name","NotValid")
|
||||
.eq("name", "NotValid")
|
||||
.findOne();
|
||||
|
||||
assertThat(country).isNull();
|
||||
|
||||
@@ -14,13 +14,12 @@ import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class TestCacheCollectionIds extends BaseTestCase {
|
||||
class TestCacheCollectionIds extends BaseTestCase {
|
||||
|
||||
private ServerCacheManager cacheManager = DB.cacheManager();
|
||||
private final ServerCacheManager cacheManager = DB.cacheManager();
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
void test() {
|
||||
ResetBasicData.reset();
|
||||
awaitL2Cache();
|
||||
|
||||
@@ -75,7 +74,6 @@ public class TestCacheCollectionIds extends BaseTestCase {
|
||||
}
|
||||
|
||||
private int fetchCustomer(Integer id) {
|
||||
|
||||
Customer customer2 = DB.find(Customer.class, id);
|
||||
|
||||
List<Contact> contacts2 = customer2.getContacts();
|
||||
@@ -91,7 +89,7 @@ public class TestCacheCollectionIds extends BaseTestCase {
|
||||
* When updating a ManyToMany relations also the collection cache must be updated.
|
||||
*/
|
||||
@Test
|
||||
public void testUpdatingCollectionCacheForManyToManyRelations() {
|
||||
void testUpdatingCollectionCacheForManyToManyRelations() {
|
||||
// arrange
|
||||
ResetBasicData.reset();
|
||||
|
||||
@@ -107,7 +105,7 @@ public class TestCacheCollectionIds extends BaseTestCase {
|
||||
dummyToLoad.getCountries().size();
|
||||
|
||||
ServerCache cachedBeanCountriesCache = cacheManager.collectionIdsCache(OCachedBean.class, "countries");
|
||||
CachedManyIds cachedManyIds = (CachedManyIds) cachedBeanCountriesCache.get(cachedBean.getId());
|
||||
CachedManyIds cachedManyIds = (CachedManyIds) cachedBeanCountriesCache.get(String.valueOf(cachedBean.getId()));
|
||||
|
||||
// confirm the starting data and cache entry
|
||||
assertEquals(2, dummyToLoad.getCountries().size());
|
||||
@@ -124,7 +122,7 @@ public class TestCacheCollectionIds extends BaseTestCase {
|
||||
|
||||
// Get the data to assert/check against
|
||||
OCachedBean result = DB.find(OCachedBean.class, cachedBean.getId());
|
||||
cachedManyIds = (CachedManyIds) cachedBeanCountriesCache.get(result.getId());
|
||||
cachedManyIds = (CachedManyIds) cachedBeanCountriesCache.get(String.valueOf(result.getId()));
|
||||
|
||||
// assert that data and cache both show correct data
|
||||
assertEquals(1, result.getCountries().size());
|
||||
@@ -134,7 +132,7 @@ public class TestCacheCollectionIds extends BaseTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangingCollectionByEditingConnectedCachedBean() {
|
||||
void testChangingCollectionByEditingConnectedCachedBean() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
OCachedBean cachedBean = new OCachedBean();
|
||||
@@ -174,7 +172,7 @@ public class TestCacheCollectionIds extends BaseTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangingCollectionByEditingConnectedNotCachedBean() {
|
||||
void testChangingCollectionByEditingConnectedNotCachedBean() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
OCachedBean cachedBean = new OCachedBean();
|
||||
@@ -213,13 +211,12 @@ public class TestCacheCollectionIds extends BaseTestCase {
|
||||
DB.delete(cachedBean);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* When updating a ManyToMany relations also the collection cache must be updated.
|
||||
* Alternate to above test where in this case the bean is dirty - loadedBean.setName("goodbye");.
|
||||
*/
|
||||
@Test
|
||||
public void testUpdatingCollectionCacheForManyToManyRelationsWithUpdatedBean() {
|
||||
void testUpdatingCollectionCacheForManyToManyRelationsWithUpdatedBean() {
|
||||
// arrange
|
||||
ResetBasicData.reset();
|
||||
|
||||
@@ -235,7 +232,7 @@ public class TestCacheCollectionIds extends BaseTestCase {
|
||||
dummyToLoad.getCountries().size();
|
||||
|
||||
ServerCache cachedBeanCountriesCache = cacheManager.collectionIdsCache(OCachedBean.class, "countries");
|
||||
CachedManyIds cachedManyIds = (CachedManyIds) cachedBeanCountriesCache.get(cachedBean.getId());
|
||||
CachedManyIds cachedManyIds = (CachedManyIds) cachedBeanCountriesCache.get(String.valueOf(cachedBean.getId()));
|
||||
|
||||
// confirm the starting data and cache entry
|
||||
assertEquals(2, dummyToLoad.getCountries().size());
|
||||
@@ -253,7 +250,7 @@ public class TestCacheCollectionIds extends BaseTestCase {
|
||||
|
||||
// Get the data to assert/check against
|
||||
OCachedBean result = DB.find(OCachedBean.class, cachedBean.getId());
|
||||
cachedManyIds = (CachedManyIds) cachedBeanCountriesCache.get(result.getId());
|
||||
cachedManyIds = (CachedManyIds) cachedBeanCountriesCache.get(String.valueOf(result.getId()));
|
||||
|
||||
// assert that data and cache both show correct data
|
||||
assertEquals(1, result.getCountries().size());
|
||||
@@ -266,7 +263,7 @@ public class TestCacheCollectionIds extends BaseTestCase {
|
||||
* When updating a ManyToMany relations also the collection cache must be updated.
|
||||
*/
|
||||
@Test
|
||||
public void testUpdatingCollectionCacheForManyToManyRelationsWithinStatelessUpdate() {
|
||||
void testUpdatingCollectionCacheForManyToManyRelationsWithinStatelessUpdate() {
|
||||
// arrange
|
||||
ResetBasicData.reset();
|
||||
|
||||
@@ -289,7 +286,7 @@ public class TestCacheCollectionIds extends BaseTestCase {
|
||||
|
||||
// assert that the cache contains the expected entry
|
||||
assertEquals(1, cachedBeanCountriesCache.size());
|
||||
CachedManyIds dummyEntry = (CachedManyIds) cachedBeanCountriesCache.get(dummyLoad.getId());
|
||||
CachedManyIds dummyEntry = (CachedManyIds) cachedBeanCountriesCache.get(String.valueOf(dummyLoad.getId()));
|
||||
assertNotNull(dummyEntry);
|
||||
assertEquals(2, dummyEntry.getIdList().size());
|
||||
assertTrue(dummyEntry.getIdList().contains("NZ"));
|
||||
@@ -307,7 +304,7 @@ public class TestCacheCollectionIds extends BaseTestCase {
|
||||
|
||||
assertEquals(1, cachedBeanCountriesCache.size());
|
||||
|
||||
CachedManyIds cachedManyIds = (CachedManyIds) cachedBeanCountriesCache.get(update.getId());
|
||||
CachedManyIds cachedManyIds = (CachedManyIds) cachedBeanCountriesCache.get(String.valueOf(update.getId()));
|
||||
|
||||
// assert cache updated
|
||||
assertEquals(1, cachedManyIds.getIdList().size());
|
||||
@@ -321,8 +318,7 @@ public class TestCacheCollectionIds extends BaseTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdating_noChange() throws InterruptedException {
|
||||
|
||||
void testUpdating_noChange() throws InterruptedException {
|
||||
ResetBasicData.reset();
|
||||
|
||||
try (Transaction txn = DB.beginTransaction()) {
|
||||
@@ -355,7 +351,7 @@ public class TestCacheCollectionIds extends BaseTestCase {
|
||||
*/
|
||||
@Test
|
||||
@Disabled
|
||||
public void testClearingCollectionCacheOnORMUpdate() {
|
||||
void testClearingCollectionCacheOnORMUpdate() {
|
||||
// arrange
|
||||
ResetBasicData.reset();
|
||||
|
||||
@@ -390,7 +386,7 @@ public class TestCacheCollectionIds extends BaseTestCase {
|
||||
*/
|
||||
@Test
|
||||
@Disabled
|
||||
public void testClearingCollectionCacheOnExternalModification() {
|
||||
void testClearingCollectionCacheOnExternalModification() {
|
||||
// arrange
|
||||
ResetBasicData.reset();
|
||||
|
||||
|
||||
@@ -162,16 +162,18 @@ public class TestQueryCache extends BaseTestCase {
|
||||
sql = LoggedSql.stop();
|
||||
assertThat(sql).hasSize(1);
|
||||
|
||||
|
||||
LoggedSql.start();
|
||||
findCountNoTxn();
|
||||
sql = LoggedSql.stop();
|
||||
assertThat(sql).hasSize(0);
|
||||
|
||||
LoggedSql.start();
|
||||
findCountTxn();
|
||||
sql = LoggedSql.stop();
|
||||
assertThat(sql).hasSize(0);
|
||||
// Oracle does not support READ_UNCOMMITTED as expected
|
||||
if (!isOracle()) {
|
||||
LoggedSql.start();
|
||||
findCountTxn();
|
||||
sql = LoggedSql.stop();
|
||||
assertThat(sql).hasSize(0);
|
||||
}
|
||||
}
|
||||
|
||||
private void findCountNoTxn() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.tests.cascade;
|
||||
|
||||
import io.ebean.DB;
|
||||
import io.ebean.test.LoggedSql;
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -9,6 +10,7 @@ import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class TestOrphanCollectionReplacement extends BaseTestCase {
|
||||
@@ -41,7 +43,16 @@ class TestOrphanCollectionReplacement extends BaseTestCase {
|
||||
updatedRoles.addAll(List.of(role));
|
||||
fetchedParent.setChildren(updatedRoles);
|
||||
|
||||
LoggedSql.start();
|
||||
DB.save(fetchedParent);
|
||||
var sql = LoggedSql.stop();
|
||||
if (isH2() || isPostgresCompatible()) { // using deleted=true vs deleted=1
|
||||
assertThat(sql).hasSize(4);
|
||||
assertThat(sql.get(0)).contains("update coone_many set deleted=true where coone_id = ? and not ( id ");
|
||||
assertThat(sql.get(1)).contains(" -- bind(");
|
||||
assertThat(sql.get(2)).contains("insert into coone_many (coone_id, name, deleted) values (?,?,?)");
|
||||
assertThat(sql.get(3)).contains(" -- bind(");
|
||||
}
|
||||
}
|
||||
|
||||
COOne fetchedUser2 = DB.find(COOne.class, parentId);
|
||||
|
||||
@@ -189,7 +189,7 @@ public class TestChangeLog extends BaseTestCase {
|
||||
return DatabaseFactory.create(config);
|
||||
}
|
||||
|
||||
public static class TDChangeLogPrepare implements ChangeLogPrepare {
|
||||
static class TDChangeLogPrepare implements ChangeLogPrepare {
|
||||
@Override
|
||||
public boolean prepare(ChangeSet changes) {
|
||||
changes.setUserId("appUser1");
|
||||
@@ -198,7 +198,7 @@ public class TestChangeLog extends BaseTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public static class TDChangeLogListener implements ChangeLogListener {
|
||||
static class TDChangeLogListener implements ChangeLogListener {
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
@@ -226,7 +226,7 @@ public class TestChangeLog extends BaseTestCase {
|
||||
|
||||
}
|
||||
|
||||
public static class TDChangeLogRegister implements ChangeLogRegister {
|
||||
static class TDChangeLogRegister implements ChangeLogRegister {
|
||||
|
||||
@Override
|
||||
public ChangeLogFilter getChangeFilter(Class<?> beanType) {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.tests.idkeys;
|
||||
|
||||
import io.ebean.DB;
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.idkeys.db.EaObject;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class TestEaObject extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
void insert() {
|
||||
EaObject bean = new EaObject("fred");
|
||||
DB.save(bean);
|
||||
assertThat(bean.id()).isGreaterThan(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package org.tests.idkeys.db;
|
||||
|
||||
import io.ebean.Model;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
@Entity
|
||||
@Table(name = "ea_object")
|
||||
public class EaObject extends Model {
|
||||
|
||||
@Id
|
||||
@Column(name = "object_id", nullable = false)
|
||||
@GeneratedValue(
|
||||
strategy = GenerationType.AUTO,
|
||||
generator = "t_object_sequence_generator"
|
||||
)
|
||||
@SequenceGenerator(
|
||||
name = "t_object_sequence_generator",
|
||||
sequenceName = "object_id_seq"
|
||||
)
|
||||
long id;
|
||||
|
||||
final String name;
|
||||
|
||||
public EaObject(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public long id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.tests.model.basic;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OrderBy;
|
||||
import javax.persistence.Table;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name = "e_basic_tree")
|
||||
public class EBasicTree {
|
||||
|
||||
@Id
|
||||
private int id;
|
||||
|
||||
@ManyToOne
|
||||
private EBasicTree parent;
|
||||
|
||||
@OneToMany
|
||||
@OrderBy("ref.name")
|
||||
private List<EBasicTree> children;
|
||||
|
||||
@ManyToOne
|
||||
private EBasic ref;
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public EBasicTree getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public void setParent(EBasicTree parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public List<EBasicTree> getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
public void setChildren(List<EBasicTree> children) {
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
public EBasic getRef() {
|
||||
return ref;
|
||||
}
|
||||
|
||||
public void setRef(EBasic ref) {
|
||||
this.ref = ref;
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ public class MyEBasicConfigStartup implements ServerConfigStartup {
|
||||
serverConfig.add(new EbasicBulkListener());
|
||||
}
|
||||
|
||||
public static class EbasicBulkListener implements BulkTableEventListener {
|
||||
private static class EbasicBulkListener implements BulkTableEventListener {
|
||||
|
||||
final Set<String> s = new HashSet<>();
|
||||
|
||||
@@ -49,7 +49,7 @@ public class MyEBasicConfigStartup implements ServerConfigStartup {
|
||||
|
||||
}
|
||||
|
||||
public static class EbasicPersistList extends AbstractBeanPersistListener {
|
||||
private static class EbasicPersistList extends AbstractBeanPersistListener {
|
||||
|
||||
@Override
|
||||
public boolean isRegisterFor(Class<?> cls) {
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package org.tests.o2m;
|
||||
|
||||
import io.ebean.DB;
|
||||
import io.ebean.test.LoggedSql;
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.o2m.dm.GoodsEntity;
|
||||
import org.tests.o2m.dm.WorkflowEntity;
|
||||
import org.tests.o2m.dm.WorkflowOperationEntity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class StatefulO2MSoftDelete extends BaseTestCase {
|
||||
@Test
|
||||
void statefulUpdateShouldntDelete() {
|
||||
var bomGoods = new GoodsEntity();
|
||||
DB.save(bomGoods);
|
||||
|
||||
var goods = new GoodsEntity();
|
||||
var workflow = new WorkflowEntity();
|
||||
var operation1 = new WorkflowOperationEntity();
|
||||
operation1.setName("operation 1");
|
||||
goods.setWorkflowEntity(workflow);
|
||||
workflow.setOperations(List.of(operation1));
|
||||
|
||||
DB.save(goods);
|
||||
|
||||
LoggedSql.start();
|
||||
// replace workflow entity
|
||||
var goodsFromDB = DB.find(GoodsEntity.class, goods.getId());
|
||||
goodsFromDB.setWorkflowEntity(new WorkflowEntity());
|
||||
|
||||
DB.update(goodsFromDB);
|
||||
var updateSql = LoggedSql.stop();
|
||||
updateSql.forEach(sql -> assertThat(sql).doesNotContain("delete from workflow_entity"));
|
||||
if (isH2()) {
|
||||
assertThat(updateSql.get(4)).contains("update workflow_operation_entity set deleted=true where workflow_id = ?");
|
||||
assertThat(updateSql.get(6)).contains("update workflow_entity set when_modified=?, deleted=? where id=?");
|
||||
}
|
||||
}
|
||||
}
|
||||
+116
-11
@@ -5,10 +5,7 @@ import io.ebean.DB;
|
||||
import io.ebean.test.LoggedSql;
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.o2m.dm.GoodsEntity;
|
||||
import org.tests.o2m.dm.PersonEntity;
|
||||
import org.tests.o2m.dm.WorkflowEntity;
|
||||
import org.tests.o2m.dm.WorkflowOperationEntity;
|
||||
import org.tests.o2m.dm.*;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.util.List;
|
||||
@@ -140,7 +137,14 @@ class TestOneToManyStatelessUpdateResultsInSoftDelete extends BaseTestCase {
|
||||
assertThat(goodsAfterInsert.getWorkflowEntity().getOperations()).hasSize(1);
|
||||
goodsAfterInsert.getWorkflowEntity().setOperations(List.of());
|
||||
|
||||
LoggedSql.start();
|
||||
DB.save(goodsAfterInsert);
|
||||
var sql = LoggedSql.collect();
|
||||
if (isH2() || isPostgresCompatible()) { // using deleted=true vs deleted=1
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql.get(0)).contains("update workflow_operation_entity set deleted=true where workflow_id = ?");
|
||||
}
|
||||
|
||||
assertThat(goodsAfterInsert.getWorkflowEntity().getOperations()).isEmpty();
|
||||
assertThat(DB.find(GoodsEntity.class, goods.getId()).getWorkflowEntity().getOperations()).isEmpty();
|
||||
|
||||
@@ -157,12 +161,27 @@ class TestOneToManyStatelessUpdateResultsInSoftDelete extends BaseTestCase {
|
||||
|
||||
// Using save() throws io.ebean.DuplicateKeyException: Error when batch flush on sql: insert into workflow_entity ...
|
||||
// Must be an update() and not save() for this to be a "stateless update"
|
||||
LoggedSql.collect();
|
||||
DB.update(goodsStateless);
|
||||
sql = LoggedSql.collect();
|
||||
assertThat(sql).isNotEmpty();
|
||||
if (isH2() || isPostgresCompatible()) { // using deleted=true vs deleted=1
|
||||
assertThat(sql).hasSize(7);
|
||||
assertThat(sql.get(0)).contains("update workflow_entity set when_modified=? where id=?");
|
||||
assertThat(sql.get(1)).contains(" -- bind(");
|
||||
assertThat(sql.get(2)).contains("update workflow_operation_entity set deleted=true where workflow_id = ?");
|
||||
assertThat(sql.get(3)).contains(" -- bind(");
|
||||
assertThat(sql.get(4)).contains("insert into workflow_operation_entity (name, version, when_created, when_modified");
|
||||
assertThat(sql.get(5)).contains(" -- bind(");
|
||||
assertThat(sql.get(6)).contains("update goods_entity set when_modified=?, workflow_entity_id=? where id=?");
|
||||
}
|
||||
|
||||
var ops = workflow.getOperations();
|
||||
// shouldn't contain deleted operations
|
||||
assertThat(ops).hasSize(1);
|
||||
assertThat(goodsStateless.getWorkflowEntity().getOperations().get(0).getId()).isNotEqualTo(operation1.getId());
|
||||
|
||||
LoggedSql.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -197,17 +216,23 @@ class TestOneToManyStatelessUpdateResultsInSoftDelete extends BaseTestCase {
|
||||
// uncommenting this lines makes the test pass
|
||||
//assertThat(goodsStateless.getWorkflowEntity().getOperations().size()).isEqualTo(0);
|
||||
|
||||
var sql = LoggedSql.stop();
|
||||
sql.forEach(System.out::println);
|
||||
|
||||
System.out.println("BEFORE TRY");
|
||||
LoggedSql.start();
|
||||
var sql = LoggedSql.collect();
|
||||
if (isH2() || isPostgresCompatible()) { // using deleted=true vs deleted=1
|
||||
assertThat(sql).hasSize(5);
|
||||
assertThat(sql.get(0)).contains("update workflow_entity set when_modified=? where id=?");
|
||||
assertThat(sql.get(1)).contains(" -- bind(");
|
||||
assertThat(sql.get(2)).contains("update workflow_operation_entity set deleted=true where workflow_id = ?");
|
||||
assertThat(sql.get(3)).contains(" -- bind(");
|
||||
assertThat(sql.get(4)).contains("update goods_entity set when_modified=?, workflow_entity_id=? where id=?");
|
||||
}
|
||||
|
||||
try (var writer = new StringWriter()) {
|
||||
var mapper = new ObjectMapper();
|
||||
mapper.writeValue(writer, goodsStateless);
|
||||
sql = LoggedSql.stop();
|
||||
sql.forEach(System.out::println);
|
||||
// queries fired to load the object graph for writing as json
|
||||
assertThat(sql).hasSize(7);
|
||||
sql.forEach(s -> assertThat(s).startsWith("select "));
|
||||
/*
|
||||
select t0.id, t0.name, t0.workflow_entity_id, t0.version, t0.when_created, t0.when_modified from goods_entity t0 where t0.id = ?; --bind(4, ) --micros(161)
|
||||
select t0.id, t0.name, t0.version, t0.when_created, t0.when_modified, t0.created_by, t0.updated_by, t0.workflow_entity_id from goods_entity t0 where t0.id = ?; --bind(4, ) --micros(525)
|
||||
@@ -230,9 +255,89 @@ class TestOneToManyStatelessUpdateResultsInSoftDelete extends BaseTestCase {
|
||||
|
||||
writer.flush();
|
||||
var serialized = writer.toString();
|
||||
System.out.println(serialized);
|
||||
// System.out.println(serialized);
|
||||
assertThat(serialized).isNotEmpty();
|
||||
var readGoods = mapper.readValue(writer.toString(), GoodsEntity.class);
|
||||
assertThat(readGoods.getWorkflowEntity().getOperations()).hasSize(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void setArrayListDoInsertInsteadUpdate() {
|
||||
var attachment1 = new Attachment();
|
||||
attachment1.setName("File1");
|
||||
var attachment2 = new Attachment();
|
||||
attachment2.setName("File2");
|
||||
|
||||
var goods = new GoodsEntity();
|
||||
goods.setName("goods1");
|
||||
goods.setAttachments(List.of(attachment1, attachment2));
|
||||
|
||||
DB.save(goods);
|
||||
|
||||
String goodAsJson = DB.json().toJson(goods);
|
||||
var marshaledGoods = DB.json().toBean(GoodsEntity.class, goodAsJson);
|
||||
var attachment3a = new Attachment();
|
||||
attachment3a.setName("File3");
|
||||
marshaledGoods.getAttachments().add(attachment3a);
|
||||
|
||||
var persistedGoods = DB.find(GoodsEntity.class, goods.getId());
|
||||
|
||||
// this was not deleting orphans and so the inserts throw exception due primary key conflict
|
||||
persistedGoods.setAttachments(marshaledGoods.getAttachments());
|
||||
LoggedSql.start();
|
||||
try {
|
||||
logger.info("Saving goods with set new attachments list");
|
||||
DB.save(persistedGoods);
|
||||
} catch (Exception e) {
|
||||
logger.error("Insert instead update", e);
|
||||
}
|
||||
var sql = LoggedSql.collect();
|
||||
assertThat(sql).isNotEmpty();
|
||||
assertThat(sql.get(0)).contains("delete from attachment where goods_entity_id = ?");
|
||||
assertThat(sql.get(1)).contains(" -- bind(");
|
||||
assertThat(sql.get(2)).contains("insert into attachment (id, goods_entity_id, name, ");
|
||||
assertThat(sql.get(3)).contains(" -- bind(");
|
||||
assertThat(sql.get(4)).contains(" -- bind(");
|
||||
if (isH2() || isPostgresCompatible() || isMySql()) { // i.e. using identity, not using sequence
|
||||
assertThat(sql.get(5)).contains("insert into attachment (goods_entity_id, name,");
|
||||
assertThat(sql.get(6)).contains(" -- bind(");
|
||||
}
|
||||
|
||||
persistedGoods = DB.find(GoodsEntity.class, goods.getId());
|
||||
|
||||
// this works good using .clear() and .addAll()
|
||||
// because here we are mutating the collection, it detects the
|
||||
// orphan removals occurring via the .clear()
|
||||
marshaledGoods = DB.json().toBean(GoodsEntity.class, goodAsJson);
|
||||
var attachment3b = new Attachment();
|
||||
attachment3b.setName("File3");
|
||||
marshaledGoods.getAttachments().add(attachment3b);
|
||||
|
||||
persistedGoods.getAttachments().clear();
|
||||
persistedGoods.getAttachments().addAll(marshaledGoods.getAttachments());
|
||||
LoggedSql.collect();
|
||||
try {
|
||||
logger.info("Saving goods with clear/added attachments");
|
||||
DB.save(persistedGoods);
|
||||
} catch (Exception e) {
|
||||
logger.error("Insert instead update", e);
|
||||
}
|
||||
sql = LoggedSql.stop();
|
||||
assertThat(sql.get(0)).contains("delete from attachment where id=?");
|
||||
assertThat(sql.get(1)).contains(" -- bind(");
|
||||
assertThat(sql.get(2)).contains(" -- bind(");
|
||||
assertThat(sql.get(3)).contains(" -- bind(");
|
||||
assertThat(sql.get(4)).contains("insert into attachment (id, goods_entity_id, name,");
|
||||
assertThat(sql.get(5)).contains(" -- bind(");
|
||||
assertThat(sql.get(6)).contains(" -- bind(");
|
||||
if (isH2() || isPostgresCompatible()) { // using identity, not using sequence
|
||||
assertThat(sql).hasSize(9);
|
||||
assertThat(sql.get(7)).contains("insert into attachment (goods_entity_id, name, ");
|
||||
assertThat(sql.get(8)).contains(" -- bind(");
|
||||
}
|
||||
|
||||
var persistedGoods2 = DB.find(GoodsEntity.class, goods.getId());
|
||||
assertThat(persistedGoods2.getAttachments()).hasSize(3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.tests.o2m.dm;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
||||
@Entity
|
||||
public class Attachment extends HistoryColumns {
|
||||
private String name;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
package org.tests.o2m.dm;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.*;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
public class GoodsEntity extends HistoryColumns {
|
||||
@@ -11,6 +10,9 @@ public class GoodsEntity extends HistoryColumns {
|
||||
@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
|
||||
private WorkflowEntity workflowEntity;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
|
||||
private List<Attachment> attachments;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@@ -26,4 +28,12 @@ public class GoodsEntity extends HistoryColumns {
|
||||
public void setWorkflowEntity(WorkflowEntity workflowEntity) {
|
||||
this.workflowEntity = workflowEntity;
|
||||
}
|
||||
|
||||
public List<Attachment> getAttachments() {
|
||||
return attachments;
|
||||
}
|
||||
|
||||
public void setAttachments(List<Attachment> attachments) {
|
||||
this.attachments = attachments;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package org.tests.query;
|
||||
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.PagedList;
|
||||
import io.ebean.test.LoggedSql;
|
||||
import io.ebean.xtest.IgnorePlatform;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.model.basic.Order;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
@@ -17,6 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
public class TestAddOrderByWithFirstRowsMaxRows extends BaseTestCase {
|
||||
|
||||
@IgnorePlatform({Platform.MYSQL, Platform.MARIADB})
|
||||
@Test
|
||||
public void test_firstRows() {
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user