Compare commits

..
Author SHA1 Message Date
Rob Bygrave df7b04877d #3121 BindMaxLength validation
At deploy time derive a BindMaxLength property to use
per BeanProperty
2023-06-26 21:16:32 +12:00
Rob Bygrave 4683877e0b Merge branch 'string-length-validation' of github.com:FOCONIS/ebean into FOCONIS-string-length-validation 2023-06-23 16:51:34 +12:00
Roland Praml d0020ab8ce Length validation less invasive 2023-06-20 14:47:20 +02:00
Roland Praml 9b3b8ad46a extended DataBind, so that it could return the last bound object 2023-06-20 13:03:04 +02:00
Roland Praml ca3c02bc1c Failing test for SqlServer 2023-06-19 13:48:00 +02:00
451 changed files with 2379 additions and 5102 deletions
+6 -7
View File
@@ -2,10 +2,9 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.22.0</version>
<relativePath>../..</relativePath>
<version>13.20.1-SNAPSHOT</version>
</parent>
<name>ebean-clickhouse</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
@@ -42,13 +41,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-clickhouse</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -7
View File
@@ -2,10 +2,9 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.22.0</version>
<relativePath>../..</relativePath>
<version>13.20.1-SNAPSHOT</version>
</parent>
<name>ebean-cockroach</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
@@ -42,13 +41,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -7
View File
@@ -2,10 +2,9 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.22.0</version>
<relativePath>../..</relativePath>
<version>13.20.1-SNAPSHOT</version>
</parent>
<name>ebean-db2</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
@@ -42,13 +41,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-db2</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -7
View File
@@ -2,10 +2,9 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.22.0</version>
<relativePath>../..</relativePath>
<version>13.20.1-SNAPSHOT</version>
</parent>
<name>ebean-h2</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
@@ -42,13 +41,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -7
View File
@@ -2,10 +2,9 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.22.0</version>
<relativePath>../..</relativePath>
<version>13.20.1-SNAPSHOT</version>
</parent>
<name>ebean-hana</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
@@ -42,13 +41,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-hana</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -7
View File
@@ -2,10 +2,9 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.22.0</version>
<relativePath>../..</relativePath>
<version>13.20.1-SNAPSHOT</version>
</parent>
<name>ebean-mariadb</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
@@ -42,13 +41,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mariadb</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -7
View File
@@ -2,10 +2,9 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.22.0</version>
<relativePath>../..</relativePath>
<version>13.20.1-SNAPSHOT</version>
</parent>
<name>ebean-mysql</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
@@ -42,13 +41,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mysql</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -7
View File
@@ -2,10 +2,9 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.22.0</version>
<relativePath>../..</relativePath>
<version>13.20.1-SNAPSHOT</version>
</parent>
<name>ebean-nuodb</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
@@ -42,13 +41,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-nuodb</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -7
View File
@@ -2,10 +2,9 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.22.0</version>
<relativePath>../..</relativePath>
<version>13.20.1-SNAPSHOT</version>
</parent>
<name>ebean-oracle</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
@@ -42,13 +41,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-oracle</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -7
View File
@@ -2,10 +2,9 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.22.0</version>
<relativePath>../..</relativePath>
<version>13.20.1-SNAPSHOT</version>
</parent>
<name>ebean-postgres</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
@@ -42,13 +41,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -7
View File
@@ -2,10 +2,9 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.22.0</version>
<relativePath>../..</relativePath>
<version>13.20.1-SNAPSHOT</version>
</parent>
<name>ebean-sqlite</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
@@ -42,13 +41,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlite</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -7
View File
@@ -2,10 +2,9 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.22.0</version>
<relativePath>../..</relativePath>
<version>13.20.1-SNAPSHOT</version>
</parent>
<name>ebean-sqlserver</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
@@ -42,13 +41,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlserver</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -7
View File
@@ -2,10 +2,9 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.22.0</version>
<relativePath>../..</relativePath>
<version>13.20.1-SNAPSHOT</version>
</parent>
<name>ebean-yugabyte</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
@@ -42,13 +41,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
</dependencies>
+7 -8
View File
@@ -2,10 +2,9 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.22.0</version>
<relativePath>../..</relativePath>
<version>13.20.1-SNAPSHOT</version>
</parent>
<name>ebean (all platforms)</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
@@ -41,7 +40,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jackson-mapper</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
@@ -60,13 +59,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-all</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
</dependencies>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</parent>
<artifactId>composites</artifactId>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</parent>
<name>ebean api</name>
-6
View File
@@ -267,21 +267,15 @@ public final class DB {
}
/**
* Deprecated for removal migrate using try-with-resources and commit on the transaction itself.
* <p>
* Commit the current transaction.
*/
@Deprecated(forRemoval = true)
public static void commitTransaction() {
getDefault().commitTransaction();
}
/**
* Deprecated for removal migrate to using try-with-resources and rollback on the transaction itself.
* <p>
* Rollback the current transaction.
*/
@Deprecated(forRemoval = true)
public static void rollbackTransaction() {
getDefault().rollbackTransaction();
}
@@ -1,49 +0,0 @@
package io.ebean;
import io.ebean.service.SpiInTuples;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Default implementation of SpiInTuples.
*/
final class DInTuples implements SpiInTuples {
private final String[] properties;
private final int propertyCount;
private final List<Object[]> entries = new ArrayList<>();
DInTuples(String[] properties) {
this.properties = properties;
this.propertyCount = properties.length;
}
@Override
public InTuples add(Object... values) {
if (values.length != propertyCount) {
throw new IllegalArgumentException("Require " + propertyCount + " values but got " + values.length);
}
entries.add(values);
return this;
}
/**
* Return the first property name.
*/
@Override
public String[] properties() {
return properties;
}
/**
* Return all the value pairs.
*/
@Override
public List<Object[]> entries() {
return Collections.unmodifiableList(entries);
}
}
@@ -3,7 +3,7 @@ package io.ebean;
import javax.persistence.PersistenceException;
/**
* Thrown when a foreign key constraint is enforced.
* Thrown when a foreign key constraint is enforced or a field is too large.
*/
public class DataIntegrityException extends PersistenceException {
private static final long serialVersionUID = -6740171949170180970L;
@@ -14,4 +14,11 @@ public class DataIntegrityException extends PersistenceException {
public DataIntegrityException(String message, Throwable cause) {
super(message, cause);
}
/**
* Create with message only.
*/
public DataIntegrityException(String message) {
super(message);
}
}
@@ -650,19 +650,13 @@ public interface Database {
void flush();
/**
* Deprecated for removal migrate using try-with-resources and commit on the transaction itself.
* <p>
* Commit the current transaction.
*/
@Deprecated(forRemoval = true)
void commitTransaction();
/**
* Deprecated for removal migrate to using try-with-resources and rollback on the transaction itself.
* <p>
* Rollback the current transaction.
*/
@Deprecated(forRemoval = true)
void rollbackTransaction();
/**
@@ -38,15 +38,12 @@ final class DbContext {
}
}
} catch (BeanNotEnhancedException e) {
String msg = "Bean is not enhanced? See https://ebean.io/docs/trouble-shooting#not-enhanced";
log.log(ERROR, msg, e);
throw e;
} catch (DataSourceConfigurationException e) {
String msg = "Configuration error creating DataSource for the default Database." +
" This typically means a missing application-test.yaml or missing ebean-test dependency." +
" See https://ebean.io/docs/trouble-shooting#datasource";
log.log(ERROR, msg, e);
throw new DataSourceConfigurationException(msg, e);
} catch (Throwable e) {
@@ -205,16 +205,4 @@ public interface DtoQuery<T> extends CancelableQuery {
* Use the explicit transaction to execute the query.
*/
DtoQuery<T> usingTransaction(Transaction transaction);
/**
* Ensure that the master DataSource is used if there is a read only data source
* being used (that is using a read replica database potentially with replication lag).
* <p>
* When the database is configured with a read-only DataSource via
* say {@link io.ebean.config.DatabaseConfig#setReadOnlyDataSource(DataSource)} then
* by default when a query is run without an active transaction, it uses the read-only data
* source. We we use {@code usingMaster()} to instead ensure that the query is executed
* against the master data source.
*/
DtoQuery<T> usingMaster();
}
@@ -36,11 +36,6 @@ import java.util.Map;
*/
public interface ExpressionFactory {
/**
* Return a new ExpressionList.
*/
<T> ExpressionList<T> expressionList();
/**
* Path exists - for the given path in a JSON document.
*/
@@ -374,11 +369,6 @@ public interface ExpressionFactory {
*/
Expression inPairs(Pairs pairs);
/**
* In expression using multiple columns.
*/
Expression inTuples(InTuples pairs);
/**
* In - property has a value in the array of values.
*/
@@ -56,7 +56,7 @@ public interface ExpressionList<T> {
/**
* Deprecated migrate to {@link #orderBy(String)}
*/
@Deprecated(since = "13.19", forRemoval = true)
@Deprecated(since = "13.19")
default ExpressionList<T> order(String orderByClause) {
return orderBy(orderByClause);
}
@@ -74,7 +74,7 @@ public interface ExpressionList<T> {
/**
* Deprecated migrate to orderBy().
*/
@Deprecated(forRemoval = true)
@Deprecated
default OrderBy<T> order() {
return orderBy();
}
@@ -508,8 +508,6 @@ public interface ExpressionList<T> {
ExpressionList<T> filterMany(String manyProperty);
/**
* Deprecated for removal - migrate to filterManyRaw()
* <p>
* Add filter expressions to the many property.
*
* <pre>{@code
@@ -526,29 +524,8 @@ public interface ExpressionList<T> {
* @param expressions Filter expressions with and, or and ? or ?1 type bind parameters
* @param params Bind parameters used in the expressions
*/
@Deprecated(forRemoval = true)
ExpressionList<T> filterMany(String manyProperty, String expressions, Object... params);
/**
* Add filter expressions for the many path. The expressions can include SQL functions if
* desired and the property names are translated to column names.
* <p>
* The expressions can contain placeholders for bind values using <code>?</code> or <code>?1</code> style.
*
* <pre>{@code
*
* new QCustomer()
* .name.startsWith("Postgres")
* .contacts.filterManyRaw("status = ? and firstName like ?", Contact.Status.NEW, "Rob%")
* .findList();
*
* }</pre>
*
* @param rawExpressions The raw expressions which can include ? and ?1 style bind parameter placeholders
* @param params The parameter values to bind
*/
ExpressionList<T> filterManyRaw(String manyProperty, String rawExpressions, Object... params);
/**
* Specify specific properties to fetch on the main/root bean (aka partial
* object).
@@ -1154,11 +1131,6 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> inPairs(Pairs pairs);
/**
* In expression using multiple columns.
*/
ExpressionList<T> inTuples(InTuples pairs);
/**
* EXISTS a raw SQL SubQuery.
*
@@ -1,36 +0,0 @@
package io.ebean;
/**
* IN expression using multiple columns.
* <p>
* Currently this is not supported with SQLServer or DB2.
* <p>
* Produces SQL expression in the form of (A,B,C) IN ((a0,b0,c0), (a1,b1,c1), ... )
* where A,B,C are the properties in the tuples.
*/
public interface InTuples {
/**
* Create given the properties in the tuples.
*/
static InTuples of(String... properties) {
return new DInTuples(properties);
}
/**
* Create given the properties in the tuples.
*/
static InTuples of(Query.Property<?>... properties) {
String[] props = new String[properties.length];
for (int i = 0; i < properties.length; i++) {
props[i] = properties[i].toString();
}
return new DInTuples(props);
}
/**
* Add a tuple entry. All values must be non-null.
*/
InTuples add(Object... values);
}
@@ -1,42 +0,0 @@
package io.ebean;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Helper methods for Lists.
*/
public final class Lists {
private Lists() {
}
/**
* Partition the source List into sub-lists with a maximum size.
* <p>
* The sub-lists will all be the max size except for the last sub-list
* which can potentially be smaller.
*
* @param source The source list
* @param max The max size of each partition
* @param <T> The list element type
* @return List of sub-list partitions
*/
public static <T> List<List<T>> partition(List<T> source, int max) {
final int totalCount = source.size();
if (totalCount == 0) {
return Collections.emptyList();
} else if (totalCount <= max) {
return List.of(source);
}
final int numOfPartitions = (totalCount + max - 1) / max; // round up
final var dest = new ArrayList<List<T>>(numOfPartitions);
for (int i = 0; i < numOfPartitions; i++) {
final int from = i * max;
final int to = Math.min(from + max, totalCount);
dest.add(source.subList(from, to));
}
return dest;
}
}
@@ -333,10 +333,10 @@ public class OrderBy<T> implements Serializable {
sb.append(property);
}
if (!ascending) {
sb.append(' ').append("desc");
sb.append(" ").append("desc");
}
if (nulls != null) {
sb.append(' ').append(nulls).append(' ').append(highLow);
sb.append(" ").append(nulls).append(" ").append(highLow);
}
return sb.toString();
}
+3 -27
View File
@@ -4,14 +4,12 @@ import io.avaje.lang.NonNullApi;
import io.avaje.lang.Nullable;
import javax.persistence.NonUniqueResultException;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.Timestamp;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
@@ -672,16 +670,6 @@ public interface Query<T> extends CancelableQuery {
*/
Query<T> apply(FetchPath fetchPath);
/**
* Apply changes to the query conditional on the supplied predicate.
* <p>
* Typically, the changes are extra predicates etc.
*
* @param predicate The predicate which when true the changes are applied
* @param apply The changes to apply to the query
*/
Query<T> alsoIf(BooleanSupplier predicate, Consumer<Query<T>> apply);
/**
* Execute the query using the given transaction.
*/
@@ -697,18 +685,6 @@ public interface Query<T> extends CancelableQuery {
*/
Query<T> usingDatabase(Database database);
/**
* Ensure that the master DataSource is used if there is a read only data source
* being used (that is using a read replica database potentially with replication lag).
* <p>
* When the database is configured with a read-only DataSource via
* say {@link io.ebean.config.DatabaseConfig#setReadOnlyDataSource(DataSource)} then
* by default when a query is run without an active transaction, it uses the read-only data
* source. We we use {@code usingMaster()} to instead ensure that the query is executed
* against the master data source.
*/
Query<T> usingMaster();
/**
* Execute the query returning the list of Id's.
* <p>
@@ -1398,7 +1374,7 @@ public interface Query<T> extends CancelableQuery {
/**
* Deprecated migrate to orderBy().
*/
@Deprecated(since = "13.19", forRemoval = true)
@Deprecated(since = "13.19")
default Query<T> order(String orderByClause) {
return orderBy(orderByClause);
}
@@ -1417,7 +1393,7 @@ public interface Query<T> extends CancelableQuery {
/**
* Deprecated migrate to orderBy().
*/
@Deprecated(since = "13.19", forRemoval = true)
@Deprecated(since = "13.19")
default OrderBy<T> order() {
return orderBy();
}
@@ -1430,7 +1406,7 @@ public interface Query<T> extends CancelableQuery {
/**
* Deprecated migrate to setOrderBy().
*/
@Deprecated(since = "13.19", forRemoval = true)
@Deprecated(since = "13.19")
default Query<T> setOrder(OrderBy<T> orderBy) {
return setOrderBy(orderBy);
}
@@ -45,18 +45,6 @@ public interface SqlQuery extends Serializable, CancelableQuery {
*/
SqlQuery usingTransaction(Transaction transaction);
/**
* Ensure that the master DataSource is used if there is a read only data source
* being used (that is using a read replica database potentially with replication lag).
* <p>
* When the database is configured with a read-only DataSource via
* say {@link io.ebean.config.DatabaseConfig#setReadOnlyDataSource(DataSource)} then
* by default when a query is run without an active transaction, it uses the read-only data
* source. We we use {@code usingMaster()} to instead ensure that the query is executed
* against the master data source.
*/
SqlQuery usingMaster();
/**
* Execute the query returning a list.
*/
@@ -77,9 +77,9 @@ public final class StdOperators {
StringBuilder expression = new StringBuilder(50);
expression.append("concat(").append(property.toString());
for (Object value : values) {
expression.append(',').append(sqlConcatString(value));
expression.append(",").append(sqlConcatString(value));
}
expression.append(')');
expression.append(")");
return Property.of(expression.toString());
}
@@ -45,7 +45,7 @@ public final class ToStringBuilder {
id.putIfAbsent(bean, 0);
}
if (counter <= MAX) {
sb.append(bean.getClass().getSimpleName()).append('@').append(counter).append('(');
sb.append(bean.getClass().getSimpleName()).append("@").append(counter).append("(");
}
}
@@ -77,7 +77,7 @@ public final class ToStringBuilder {
*/
public void end() {
if (counter <= MAX) {
sb.append(')');
sb.append(")");
}
}
@@ -90,7 +90,7 @@ public final class ToStringBuilder {
} else {
sb.append(", ");
}
sb.append(name).append(':');
sb.append(name).append(":");
}
private void value(Object value) {
@@ -125,20 +125,20 @@ public final class ToStringBuilder {
sb.append("{}");
} else {
boolean firstElement = true;
sb.append('{');
sb.append("{");
for (Map.Entry<?, ?> entry : map.entrySet()) {
if (firstElement) {
firstElement = false;
} else {
sb.append(", ");
}
sb.append(entry.getKey()).append(':');
sb.append(entry.getKey()).append(":");
value(entry.getValue());
if (counter > MAX) {
return;
}
}
sb.append('}');
sb.append("}");
}
}
@@ -151,7 +151,7 @@ public final class ToStringBuilder {
return;
}
boolean firstElement = true;
sb.append('[');
sb.append("[");
for (Object o : c) {
if (firstElement) {
firstElement = false;
@@ -163,7 +163,7 @@ public final class ToStringBuilder {
return;
}
}
sb.append(']');
sb.append("]");
}
private boolean push(Object bean) {
@@ -178,7 +178,7 @@ public final class ToStringBuilder {
Integer idx = id.putIfAbsent(bean, counter++);
if (idx != null) {
--counter;
sb.append(bean.getClass().getSimpleName()).append('@').append(idx);
sb.append(bean.getClass().getSimpleName()).append("@").append(idx);
return false;
}
first = true;
+1 -1
View File
@@ -69,7 +69,7 @@ public class TenantAwareKey {
public String toString() {
StringBuilder sb = new StringBuilder(key.toString());
if (tenantId != null) {
sb.append(':').append(tenantId);
sb.append(":").append(tenantId);
}
return sb.toString();
}
@@ -119,7 +119,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
try {
if (set == null) {
if (!disableLazyLoad && modifyListening) {
lazyLoadCollection(false);
lazyLoadCollection(true);
} else {
set = new LinkedHashSet<>();
}
@@ -136,7 +136,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
if (disableLazyLoad) {
set = new LinkedHashSet<>();
} else {
lazyLoadCollection(false);
lazyLoadCollection(true);
}
}
} finally {
@@ -228,7 +228,7 @@ public abstract class AbstractNamingConvention implements NamingConvention {
public TableName getM2MJoinTableName(TableName lhsTable, TableName rhsTable) {
StringBuilder buffer = new StringBuilder();
buffer.append(unQuote(lhsTable.getName()));
buffer.append('_');
buffer.append("_");
String rhsTableName = unQuote(rhsTable.getName());
if (rhsTableName.indexOf('_') < rhsPrefixLength) {
@@ -271,10 +271,10 @@ public abstract class AbstractNamingConvention implements NamingConvention {
public String getTableName(String catalog, String schema, String name) {
StringBuilder sb = new StringBuilder();
if (!isNull(catalog)) {
sb.append(quoteIdentifiers(catalog)).append('.');
sb.append(quoteIdentifiers(catalog)).append(".");
}
if (!isNull(schema)) {
sb.append(quoteIdentifiers(schema)).append('.');
sb.append(quoteIdentifiers(schema)).append(".");
}
return sb.append(quoteIdentifiers(name)).toString();
}
@@ -540,6 +540,7 @@ public class DatabaseConfig {
private String dumpMetricsOptions;
private LengthCheck lengthCheck = LengthCheck.OFF;
private Function<String, String> metricNaming = MetricNamingMatch.INSTANCE;
/**
@@ -2376,7 +2377,7 @@ public class DatabaseConfig {
* Sorry if returning Set rather than List breaks code but it feels safer to
* do that than a subtle change to return a shallow copy which you will not detect.
*/
@Deprecated(forRemoval = true)
@Deprecated
public Set<Class<?>> getClasses() {
return classes;
}
@@ -2919,6 +2920,7 @@ public class DatabaseConfig {
jdbcFetchSizeFindEach = p.getInt("jdbcFetchSizeFindEach", jdbcFetchSizeFindEach);
jdbcFetchSizeFindList = p.getInt("jdbcFetchSizeFindList", jdbcFetchSizeFindList);
databasePlatformName = p.get("databasePlatformName", databasePlatformName);
lengthCheck = p.getEnum(LengthCheck.class, "lengthCheck", lengthCheck);
uuidVersion = p.getEnum(UuidVersion.class, "uuidVersion", uuidVersion);
uuidStateFile = p.get("uuidStateFile", uuidStateFile);
@@ -3389,7 +3391,7 @@ public class DatabaseConfig {
/**
* Deprecated - migrate to isLoadModuleInfo().
*/
@Deprecated(forRemoval = true)
@Deprecated
public boolean isAutoLoadModuleInfo() {
return loadModuleInfo;
}
@@ -3419,6 +3421,20 @@ public class DatabaseConfig {
this.metricNaming = metricNaming;
}
/**
* Returns the length check mode.
*/
public LengthCheck getLengthCheck() {
return lengthCheck;
}
/**
* Sets the length check mode.
*/
public void setLengthCheck(LengthCheck lengthCheck) {
this.lengthCheck = lengthCheck;
}
public enum UuidVersion {
VERSION4,
VERSION1,
@@ -135,12 +135,12 @@ public class DbConstraintNaming {
*/
protected String joinColumnNames(String[] columns) {
if (columns.length == 1) {
return normaliseColumn(columns[0]).replace(" ", "_");
return normaliseColumn(columns[0]);
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < columns.length; i++) {
if (i > 0) {
sb.append('_');
sb.append("_");
}
sb.append(normaliseColumn(columns[i]));
}
@@ -0,0 +1,22 @@
package io.ebean.config;
/**
* Defines the length-check mode.
*
* @author Roland Praml, FOCONIS AG
*/
public enum LengthCheck {
/**
* By default, length checking is off. This means, strings/jsons and files are passed to the DB and the DB might or might not check the length.
* The DB has to check the data length. Note this is not possible for certain datatypes (e.g. clob without size)
*/
OFF,
/**
* When enabling length check, ebean validates strings/json strings and files before saving them to DB.
*/
ON,
/**
* Same as "ON", but take the UTF8-bytelength for validation. This may be useful, if you have an UTF8 based charset (default for DB2)
*/
UTF8
}
@@ -117,12 +117,12 @@ public final class TableName {
// Add schema
if (schema != null) {
if (buffer.length() > 0) {
buffer.append('.');
buffer.append(".");
}
buffer.append(schema);
}
if (buffer.length() > 0) {
buffer.append('.');
buffer.append(".");
}
return buffer.append(name).toString();
}
@@ -23,11 +23,11 @@ public class BasicSqlLimitOffset implements BasicSqlLimiter {
sb.append(dbSql);
if (maxRows > 0) {
sb.append(' ').append(LIMIT);
sb.append(' ').append(maxRows);
sb.append(" ").append(LIMIT);
sb.append(" ").append(maxRows);
}
if (firstRow > 0) {
sb.append(' ').append(OFFSET).append(' ');
sb.append(" ").append(OFFSET).append(" ");
sb.append(firstRow);
}
return sb.toString();
@@ -118,28 +118,28 @@ final class MetricsAsJson implements ServerMetricsAsJson {
private void objStart() throws IOException {
objKeyCounter = 0;
writer.append('{');
writer.append("{");
}
private void objEnd() throws IOException {
writer.append('}');
writer.append("}");
}
private void listStart() throws IOException {
listCounter = 0;
writer.append('[');
writer.append("[");
writer.append(newLine);
}
private void listEnd() throws IOException {
writer.append(']');
writer.append("]");
}
private void key(String key) throws IOException {
if (objKeyCounter++ > 0) {
writer.append(", ");
}
writer.append('"').append(key).append("\":");
writer.append("\"").append(key).append("\":");
}
private void val(long count) throws IOException {
@@ -147,12 +147,12 @@ final class MetricsAsJson implements ServerMetricsAsJson {
}
private void val(String val) throws IOException {
writer.append('"').append(val).append('"');
writer.append("\"").append(val).append("\"");
}
private void metricStart(MetaMetric metric) throws IOException {
if (listCounter++ > 0) {
writer.append(',').append(newLine);
writer.append(",").append(newLine);
}
objStart();
key("name");
@@ -1,22 +0,0 @@
package io.ebean.service;
import io.ebean.InTuples;
import java.util.List;
/**
* Internal extension to InTuples.
*/
public interface SpiInTuples extends InTuples {
/**
* Return the properties of the tuples.
*/
String[] properties();
/**
* Return all the tuple entries.
*/
List<Object[]> entries();
}
@@ -205,7 +205,7 @@ public class PathProperties implements FetchPath {
sb.append(it.next());
hasNext = it.hasNext();
if (hasNext) {
sb.append(',');
sb.append(",");
}
}
return sb.toString();
@@ -25,14 +25,14 @@ public final class CamelCaseHelper {
lastUpper = i;
} else if (Character.isDigit(c)) {
if (i > lastUpper + 1 && !digitsCompressed) {
sb.append('_');
sb.append("_");
lastUpper = i;
}
sb.append(c);
} else if (Character.isUpperCase(c)) {
if (i > lastUpper + 1) {
sb.append('_');
sb.append("_");
}
sb.append(Character.toLowerCase(c));
lastUpper = i;
@@ -1,82 +0,0 @@
package io.ebean;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
class ListsTest {
@Test
void partition_empty() {
List<List<Integer>> partitions = Lists.partition(List.of(), 5);
assertThat(partitions).isEmpty();
}
@Test
void partition_lt() {
List<List<Integer>> partitions = Lists.partition(List.of(1, 2, 3, 4), 5);
assertThat(partitions).hasSize(1);
assertThat(partitions.get(0)).hasSize(4);
}
@Test
void partition_eq() {
List<List<Integer>> partitions = Lists.partition(List.of(1, 2, 3, 4, 5), 5);
assertThat(partitions).hasSize(1);
assertThat(partitions.get(0)).hasSize(5);
}
@Test
void partition_gt() {
List<List<Integer>> partitions = Lists.partition(List.of(1, 2, 3, 4, 5, 6), 5);
assertThat(partitions).hasSize(2);
assertThat(partitions.get(0)).hasSize(5);
assertThat(partitions.get(1)).hasSize(1);
assertThat(partitions.get(0)).containsExactly(1, 2, 3, 4, 5);
assertThat(partitions.get(1)).containsExactly(6);
}
@Test
void partition_gt1_letters() {
var partitions = Lists.partition(List.of("a", "b", "c", "d"), 3);
assertThat(partitions).hasSize(2);
assertThat(partitions.get(0)).hasSize(3);
assertThat(partitions.get(1)).hasSize(1);
assertThat(partitions.get(0)).containsExactly("a", "b", "c");
assertThat(partitions.get(1)).containsExactly("d");
}
@Test
void partition_gt1a_letters() {
var partitions = Lists.partition(List.of("a", "b", "c", "d", "e"), 3);
assertThat(partitions).hasSize(2);
assertThat(partitions.get(0)).hasSize(3);
assertThat(partitions.get(1)).hasSize(2);
assertThat(partitions.get(0)).containsExactly("a", "b", "c");
assertThat(partitions.get(1)).containsExactly("d", "e");
}
@Test
void partition_eq2_letters() {
var partitions = Lists.partition(List.of("a", "b", "c", "d", "e", "f"), 3);
assertThat(partitions).hasSize(2);
assertThat(partitions.get(0)).hasSize(3);
assertThat(partitions.get(1)).hasSize(3);
assertThat(partitions.get(0)).containsExactly("a", "b", "c");
assertThat(partitions.get(1)).containsExactly("d", "e", "f");
}
@Test
void partition_gt2_letters() {
var partitions = Lists.partition(List.of("a", "b", "c", "d", "e", "f", "g"), 3);
assertThat(partitions).hasSize(3);
assertThat(partitions.get(0)).hasSize(3);
assertThat(partitions.get(1)).hasSize(3);
assertThat(partitions.get(2)).hasSize(1);
assertThat(partitions.get(0)).containsExactly("a", "b", "c");
assertThat(partitions.get(1)).containsExactly("d", "e", "f");
assertThat(partitions.get(2)).containsExactly("g");
}
}
+25 -25
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</parent>
<name>ebean bom</name>
@@ -89,25 +89,25 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
@@ -125,13 +125,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jackson-mapper</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-ddl-generator</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
@@ -155,46 +155,46 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>querybean-generator</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>kotlin-querybean-generator</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgis</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-redis</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-spring-txn</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<!-- platforms -->
@@ -202,67 +202,67 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-clickhouse</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-db2</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-h2</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-hana</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-mariadb</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-mysql</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-nuodb</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-oracle</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgres</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-sqlite</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-sqlserver</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
</dependencies>
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</parent>
<artifactId>ebean-core-type</artifactId>
@@ -16,7 +16,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
@@ -174,4 +174,9 @@ public interface DataBinder {
*/
String popJson();
/**
* Returns the last bound object (e.g. for BindValidation). Note for InputStreams you'll get an InputStreamInfo.
*/
Object popLastObject();
}
@@ -0,0 +1,27 @@
package io.ebean.core.type;
import java.io.InputStream;
/**
* Helper to transports length info of DataBind.setBinaryStream(stream, length) to BindValidation
*
* @author Roland Praml, FOCONIS AG
*/
public final class InputStreamInfo {
private final InputStream stream;
private final long length;
public InputStreamInfo(InputStream stream, long length) {
this.stream = stream;
this.length = length;
}
public InputStream stream() {
return stream;
}
public long length() {
return length;
}
}
+6 -6
View File
@@ -3,7 +3,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</parent>
<artifactId>ebean-core</artifactId>
@@ -22,7 +22,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
@@ -46,7 +46,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
</dependency>
<dependency>
@@ -159,21 +159,21 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlserver</artifactId>
<version>13.22.0</version>
<version>13.20.1-SNAPSHOT</version>
<scope>test</scope>
</dependency>
@@ -73,13 +73,13 @@ public final class BindParams implements Serializable {
for (Param param : positionedParameters) {
tempBindCount = param.queryBindCount();
bc += tempBindCount;
builder.append('p').append(bc).append(" ?:").append(tempBindCount).append(',');
builder.append("p").append(bc).append(" ?:").append(tempBindCount).append(",");
}
for (Map.Entry<String, Param> entry : namedParameters.entrySet()) {
tempBindCount = entry.getValue().queryBindCount();
bc += tempBindCount;
builder.append('n').append(bc).append(" k:").append(entry.getKey()).append(" ?:").append(tempBindCount).append(',');
builder.append("n").append(bc).append(" k:").append(entry.getKey()).append(" ?:").append(tempBindCount).append(",");
}
}
@@ -111,12 +111,7 @@ public final class LoadManyRequest extends LoadRequest {
loadContext.configureQuery(query);
if (onlyIds) {
// lazy loading invoked via clear() and removeAll()
String mapKey = many.mapKey();
if (mapKey != null) {
query.select(mapKey);
} else {
query.select(many.targetIdProperty());
}
query.select(many.targetIdProperty());
}
return query;
}
@@ -61,4 +61,9 @@ public interface SpiDtoQuery<T> extends DtoQuery<T>, SpiSqlBinding {
*/
SpiQuery<?> ormQuery();
/**
* Return the explicit transaction used to execute the query.
*/
Transaction transaction();
}
@@ -66,11 +66,6 @@ public interface SpiEbeanServer extends SpiServer, ExtendedServer, BeanCollectio
*/
CallOrigin createCallOrigin();
/**
* Override in order to return SpiQuery
*/
<T> SpiQuery<T> createQuery(Class<T> beanType);
/**
* Return the PersistenceContextScope to use defined at query or server level.
*/
@@ -140,9 +135,8 @@ public interface SpiEbeanServer extends SpiServer, ExtendedServer, BeanCollectio
* Create a ServerTransaction for query purposes.
*
* @param tenantId For multi-tenant lazy loading provide the tenantId to use.
* @param useMaster Set to true when the query should use the master data source.
*/
SpiTransaction createReadOnlyTransaction(Object tenantId, boolean useMaster);
SpiTransaction createReadOnlyTransaction(Object tenantId);
/**
* An event from another server in the cluster used to notify local
@@ -153,7 +147,7 @@ public interface SpiEbeanServer extends SpiServer, ExtendedServer, BeanCollectio
/**
* Compile a query.
*/
<T> CQuery<T> compileQuery(Type type, SpiQuery<T> query, Transaction transaction);
<T> CQuery<T> compileQuery(Type type, Query<T> query, Transaction transaction);
/**
* Execute the findId's query but without copying the query.
@@ -162,12 +156,12 @@ public interface SpiEbeanServer extends SpiServer, ExtendedServer, BeanCollectio
* the query has finished (if executing in a background thread).
* </p>
*/
<A, T> List<A> findIdsWithCopy(SpiQuery<T> query);
<A, T> List<A> findIdsWithCopy(Query<T> query, Transaction transaction);
/**
* Execute the findCount query but without copying the query.
*/
<T> int findCountWithCopy(SpiQuery<T> query);
<T> int findCountWithCopy(Query<T> query, Transaction transaction);
/**
* Load a batch of Associated One Beans.
@@ -295,7 +289,7 @@ public interface SpiEbeanServer extends SpiServer, ExtendedServer, BeanCollectio
/**
* Execute the underlying ORM query returning as a JDBC ResultSet to map to DTO beans.
*/
SpiResultSet findResultSet(SpiQuery<?> ormQuery);
SpiResultSet findResultSet(SpiQuery<?> ormQuery, SpiTransaction transaction);
/**
* Visit all the metrics (typically reporting them).
@@ -327,57 +321,136 @@ public interface SpiEbeanServer extends SpiServer, ExtendedServer, BeanCollectio
*/
SpiQueryBindCapture createQueryBindCapture(SpiQueryPlan queryPlan);
<T> boolean exists(SpiQuery<T> ormQuery);
<T> int findCount(SpiQuery<T> query);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
<T> boolean exists(Query<T> ormQuery, Transaction transaction);
<A, T> List<A> findIds(SpiQuery<T> query);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
<T> int findCount(Query<T> query, Transaction transaction);
<T> QueryIterator<T> findIterate(SpiQuery<T> query);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
<A, T> List<A> findIds(Query<T> query, Transaction transaction);
<T> Stream<T> findStream(SpiQuery<T> query);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
<T> QueryIterator<T> findIterate(Query<T> query, Transaction transaction);
<T> void findEach(SpiQuery<T> query, Consumer<T> consumer);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
<T> Stream<T> findStream(Query<T> query, Transaction transaction);
<T> void findEach(SpiQuery<T> query, int batch, Consumer<List<T>> consumer);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
<T> void findEach(Query<T> query, Consumer<T> consumer, Transaction transaction);
<T> void findEachWhile(SpiQuery<T> query, Predicate<T> consumer);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
<T> void findEach(Query<T> query, int batch, Consumer<List<T>> consumer, Transaction t);
<T> List<Version<T>> findVersions(SpiQuery<T> query);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
<T> void findEachWhile(Query<T> query, Predicate<T> consumer, Transaction transaction);
<T> List<T> findList(SpiQuery<T> query);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
<T> List<Version<T>> findVersions(Query<T> query, Transaction transaction);
<T> FutureRowCount<T> findFutureCount(SpiQuery<T> query);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
<T> List<T> findList(Query<T> query, Transaction transaction);
<T> FutureIds<T> findFutureIds(SpiQuery<T> query);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
<T> FutureRowCount<T> findFutureCount(Query<T> query, Transaction transaction);
<T> FutureList<T> findFutureList(SpiQuery<T> query);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
<T> FutureIds<T> findFutureIds(Query<T> query, Transaction transaction);
<T> PagedList<T> findPagedList(SpiQuery<T> query);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
<T> FutureList<T> findFutureList(Query<T> query, Transaction transaction);
<T> Set<T> findSet(SpiQuery<T> query);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
<T> PagedList<T> findPagedList(Query<T> query, Transaction transaction);
<K, T> Map<K, T> findMap(SpiQuery<T> query);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
<T> Set<T> findSet(Query<T> query, Transaction transaction);
<A, T> List<A> findSingleAttributeList(SpiQuery<T> query);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
<K, T> Map<K, T> findMap(Query<T> query, Transaction transaction);
<A, T> Set<A> findSingleAttributeSet(SpiQuery<T> query);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
<A, T> List<A> findSingleAttributeList(Query<T> query, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
<A, T> Set<A> findSingleAttributeSet(Query<T> query, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Nullable
<T> T findOne(SpiQuery<T> query);
<T> T findOne(Query<T> query, Transaction transaction);
<T> Optional<T> findOneOrEmpty(SpiQuery<T> query);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
<T> Optional<T> findOneOrEmpty(Query<T> query, Transaction transaction);
<T> int delete(SpiQuery<T> query);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
<T> int delete(Query<T> query, Transaction transaction);
<T> int update(SpiQuery<T> query);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
<T> int update(Query<T> query, Transaction transaction);
List<SqlRow> findList(SpiSqlQuery query);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
List<SqlRow> findList(SqlQuery query, Transaction transaction);
void findEach(SpiSqlQuery query, Consumer<SqlRow> consumer);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
void findEach(SqlQuery query, Consumer<SqlRow> consumer, Transaction transaction);
void findEachWhile(SpiSqlQuery query, Predicate<SqlRow> consumer);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
void findEachWhile(SqlQuery query, Predicate<SqlRow> consumer, Transaction transaction);
/**
* Deprecated migrate to using {@link SqlQuery#usingTransaction(Transaction)}.
*/
@Nullable
SqlRow findOne(SpiSqlQuery query);
SqlRow findOne(SqlQuery query, Transaction transaction);
}
@@ -36,11 +36,6 @@ public interface SpiExpressionRequest {
*/
SpiExpressionRequest append(String expression);
/**
* Append to the expression sql without any parsing.
*/
SpiExpressionRequest append(char c);
/**
* Append to the expression sql with logical property parsing to db columns with logical path prefix.
* <p>
@@ -235,16 +235,6 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
*/
String planLabel();
/**
* Return the transaction explicitly assigned or null.
*/
SpiTransaction transaction();
/**
* Return true if this query should not use the read only data source.
*/
boolean isUseMaster();
/**
* Return true if this is a "find by id" query. This includes a check for a single "equal to" expression for the Id.
*/
@@ -877,6 +867,17 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
*/
boolean isDisableReadAudit();
/**
* Return true if this is a query executing in the background.
*/
boolean isFutureFetch();
/**
* Set to true to indicate the query is executing in a background thread
* asynchronously.
*/
void setFutureFetch(boolean futureFetch);
/**
* Set the readEvent for future queries (as prepared in foreground thread).
*/
@@ -1,23 +1,10 @@
package io.ebeaninternal.api;
import io.avaje.lang.Nullable;
/**
* SQL query binding (for SqlQuery and DtoQuery).
*/
public interface SpiSqlBinding extends SpiCancelableQuery {
/**
* Return the transaction explicitly associated to the query.
*/
@Nullable
SpiTransaction transaction();
/**
* Return true if this query should not use the read only data source.
*/
boolean isUseMaster();
/**
* Return the named or positioned parameters.
*/
@@ -1,10 +1,17 @@
package io.ebeaninternal.api;
import io.avaje.lang.Nullable;
import io.ebean.SqlQuery;
import io.ebean.Transaction;
/**
* SQL query - Internal extension to SqlQuery.
*/
public interface SpiSqlQuery extends SqlQuery, SpiSqlBinding {
/**
* Return the transaction explicitly associated to the query.
*/
@Nullable
Transaction transaction();
}
@@ -1,10 +1,14 @@
package io.ebeaninternal.server.bind;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.InputStreamInfo;
import io.ebeaninternal.api.CoreLog;
import io.ebeaninternal.server.core.timezone.DataTimeZone;
import java.io.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.math.BigDecimal;
import java.sql.*;
import java.util.ArrayList;
@@ -23,6 +27,8 @@ public class DataBind implements DataBinder {
protected int pos;
private String json;
private Object lastObject = null;
public DataBind(DataTimeZone dataTimeZone, PreparedStatement pstmt, Connection connection) {
this.dataTimeZone = dataTimeZone;
this.pstmt = pstmt;
@@ -65,16 +71,19 @@ public class DataBind implements DataBinder {
@Override
public void setObject(Object value) throws SQLException {
pstmt.setObject(++pos, value);
lastObject = value;
}
@Override
public final void setObject(Object value, int sqlType) throws SQLException {
pstmt.setObject(++pos, value, sqlType);
lastObject = value;
}
@Override
public void setNull(int jdbcType) throws SQLException {
pstmt.setNull(++pos, jdbcType);
lastObject = null;
}
@Override
@@ -96,7 +105,7 @@ public class DataBind implements DataBinder {
}
}
private void closeInputStreams() {
public void closeInputStreams() {
if (inputStreams != null) {
for (InputStream inputStream : inputStreams) {
try {
@@ -117,36 +126,43 @@ public class DataBind implements DataBinder {
@Override
public void setString(String value) throws SQLException {
pstmt.setString(++pos, value);
lastObject = value;
}
@Override
public final void setInt(int value) throws SQLException {
pstmt.setInt(++pos, value);
lastObject = null;
}
@Override
public final void setLong(long value) throws SQLException {
pstmt.setLong(++pos, value);
lastObject = null;
}
@Override
public final void setShort(short value) throws SQLException {
pstmt.setShort(++pos, value);
lastObject = null;
}
@Override
public final void setFloat(float value) throws SQLException {
pstmt.setFloat(++pos, value);
lastObject = null;
}
@Override
public final void setDouble(double value) throws SQLException {
pstmt.setDouble(++pos, value);
lastObject = null;
}
@Override
public final void setBigDecimal(BigDecimal value) throws SQLException {
pstmt.setBigDecimal(++pos, value);
lastObject = null;
}
@Override
@@ -157,6 +173,7 @@ public class DataBind implements DataBinder {
} else {
pstmt.setDate(++pos, value);
}
lastObject = null;
}
@Override
@@ -167,6 +184,7 @@ public class DataBind implements DataBinder {
} else {
pstmt.setTimestamp(++pos, value);
}
lastObject = null;
}
@Override
@@ -177,26 +195,31 @@ public class DataBind implements DataBinder {
} else {
pstmt.setTime(++pos, value);
}
lastObject = null;
}
@Override
public void setBoolean(boolean value) throws SQLException {
pstmt.setBoolean(++pos, value);
lastObject = null;
}
@Override
public void setBytes(byte[] value) throws SQLException {
pstmt.setBytes(++pos, value);
lastObject = value;
}
@Override
public void setByte(byte value) throws SQLException {
pstmt.setByte(++pos, value);
lastObject = null;
}
@Override
public void setChar(char value) throws SQLException {
pstmt.setString(++pos, String.valueOf(value));
lastObject = null;
}
@Override
@@ -211,21 +234,31 @@ public class DataBind implements DataBinder {
}
inputStreams.add(inputStream);
pstmt.setBinaryStream(++pos, inputStream, length);
lastObject = new InputStreamInfo(inputStream, length);
}
@Override
public void setBlob(byte[] bytes) throws SQLException {
pstmt.setBinaryStream(++pos, new ByteArrayInputStream(bytes), bytes.length);
lastObject = bytes;
}
@Override
public void setClob(String content) throws SQLException {
pstmt.setCharacterStream(++pos, new StringReader(content), content.length());
lastObject = content;
}
@Override
public void setArray(String arrayType, Object[] elements) throws SQLException {
pstmt.setArray(++pos, connection.createArrayOf(arrayType, elements));
lastObject = null;
}
@Override
public Object popLastObject() {
Object ret = lastObject;
lastObject = null;
return ret;
}
}
@@ -33,10 +33,10 @@ public abstract class AbstractSqlQueryRequest implements CancelableQuery {
/**
* Create the BeanFindRequest.
*/
AbstractSqlQueryRequest(SpiEbeanServer server, SpiSqlBinding query) {
AbstractSqlQueryRequest(SpiEbeanServer server, SpiSqlBinding query, Transaction t) {
this.server = server;
this.query = query;
this.transaction = query.transaction();
this.transaction = (SpiTransaction) t;
this.query.setCancelableQuery(this);
}
@@ -48,7 +48,7 @@ public abstract class AbstractSqlQueryRequest implements CancelableQuery {
transaction = server.currentServerTransaction();
if (transaction == null || !transaction.isActive()) {
// create a local readOnly transaction
transaction = server.createReadOnlyTransaction(null, query.isUseMaster());
transaction = server.createReadOnlyTransaction(null);
createdTransaction = true;
}
}
@@ -48,7 +48,7 @@ public abstract class BeanRequest {
*/
public void commitTransIfRequired() {
if (createdTransaction) {
transaction.commit();
server.commitTransaction();
}
}
@@ -87,7 +87,7 @@ final class DefaultBeanLoader {
query.setLoadDescription("+lazy", null);
}
query.select(parentDesc.idBinder().idSelect());
query.select(parentDesc.idBinder().getIdProperty());
if (onlyIds) {
query.fetch(many.name(), many.targetIdProperty());
} else {
@@ -106,7 +106,7 @@ final class DefaultBeanLoader {
query.setReadOnly(true);
}
server.findOne(query);
server.findOne(query, null);
if (beanCollection != null) {
if (beanCollection.checkEmptyLazyLoad()) {
if (log.isLoggable(DEBUG)) {
@@ -127,7 +127,6 @@ final class DefaultBeanLoader {
throw new RuntimeException("Nothing in batch?");
}
final SpiQuery<?> query = server.createQuery(loadRequest.beanType());
query.usingTransaction(loadRequest.transaction());
loadRequest.configureQuery(query);
loadRequest.postLoad(executeQuery(loadRequest, query));
}
@@ -138,15 +137,14 @@ final class DefaultBeanLoader {
private List<?> executeQuery(LoadRequest loadRequest, SpiQuery<?> query) {
if (onIterateUseExtraTxn && loadRequest.isParentFindIterate()) {
// MySql - we need a different transaction to execute the secondary query
SpiTransaction extraTxn = server.createReadOnlyTransaction(query.tenantId(), query.isUseMaster());
SpiTransaction extraTxn = server.createReadOnlyTransaction(query.tenantId());
try {
query.usingTransaction(extraTxn);
return server.findList(query);
return server.findList(query, extraTxn);
} finally {
extraTxn.end();
}
} else {
return server.findList(query);
return server.findList(query, loadRequest.transaction());
}
}
@@ -440,9 +440,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
* Compile a query. Only valid for ORM queries.
*/
@Override
public <T> CQuery<T> compileQuery(Type type, SpiQuery<T> query, Transaction transaction) {
query.usingTransaction(transaction);
SpiOrmQueryRequest<T> qr = createQueryRequest(type, query);
public <T> CQuery<T> compileQuery(Type type, Query<T> query, Transaction transaction) {
SpiOrmQueryRequest<T> qr = createQueryRequest(type, query, transaction);
OrmQueryRequest<T> orm = (OrmQueryRequest<T>) qr;
return cqueryEngine.buildQuery(orm);
}
@@ -904,8 +903,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
@Override
public SpiResultSet findResultSet(SpiQuery<?> ormQuery) {
SpiOrmQueryRequest<?> request = createQueryRequest(ormQuery.type(), ormQuery);
public SpiResultSet findResultSet(SpiQuery<?> ormQuery, SpiTransaction transaction) {
SpiOrmQueryRequest<?> request = createQueryRequest(ormQuery.type(), ormQuery, transaction);
request.initTransIfRequired();
return request.findResultSet();
}
@@ -936,26 +935,24 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
@Override
public <T> T find(Class<T> beanType, Object id, @Nullable Transaction transaction) {
Objects.requireNonNull(id);
SpiQuery<T> query = createQuery(beanType);
query.usingTransaction(transaction);
query.setId(id);
return findId(query);
Query<T> query = createQuery(beanType).setId(id);
return findId(query, transaction);
}
<T> SpiOrmQueryRequest<T> createQueryRequest(Type type, SpiQuery<T> query) {
SpiOrmQueryRequest<T> request = buildQueryRequest(type, query);
<T> SpiOrmQueryRequest<T> createQueryRequest(Type type, Query<T> query, @Nullable Transaction transaction) {
SpiOrmQueryRequest<T> request = buildQueryRequest(type, query, transaction);
request.prepareQuery();
return request;
}
<T> SpiOrmQueryRequest<T> buildQueryRequest(Type type, SpiQuery<T> query) {
query.setType(type);
query.checkNamedParameters();
return buildQueryRequest(query);
<T> SpiOrmQueryRequest<T> buildQueryRequest(Type type, Query<T> query, @Nullable Transaction transaction) {
SpiQuery<T> spiQuery = (SpiQuery<T>) query;
spiQuery.setType(type);
spiQuery.checkNamedParameters();
return buildQueryRequest(spiQuery, transaction);
}
private <T> SpiOrmQueryRequest<T> buildQueryRequest(SpiQuery<T> query) {
SpiTransaction transaction = query.transaction();
private <T> SpiOrmQueryRequest<T> buildQueryRequest(SpiQuery<T> query, @Nullable Transaction transaction) {
if (transaction == null) {
transaction = currentServerTransaction();
}
@@ -976,7 +973,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
if (query.parentNode() == null) {
query.setOrigin(createCallOrigin());
}
return new OrmQueryRequest<>(this, queryEngine, query, transaction);
return new OrmQueryRequest<>(this, queryEngine, query, (SpiTransaction) transaction);
}
/**
@@ -984,8 +981,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
*/
@Nullable
@SuppressWarnings("unchecked")
private <T> T findIdCheckPersistenceContextAndCache(SpiQuery<T> query, Object id) {
SpiTransaction t = query.transaction();
private <T> T findIdCheckPersistenceContextAndCache(@Nullable Transaction transaction, SpiQuery<T> query, Object id) {
SpiTransaction t = (SpiTransaction) transaction;
if (t == null) {
t = currentServerTransaction();
}
@@ -1031,17 +1028,18 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
@Nullable
@SuppressWarnings("unchecked")
private <T> T findId(SpiQuery<T> query) {
query.setType(Type.BEAN);
if (SpiQuery.Mode.NORMAL == query.mode() && !query.isForceHitDatabase()) {
private <T> T findId(Query<T> query, @Nullable Transaction transaction) {
SpiQuery<T> spiQuery = (SpiQuery<T>) query;
spiQuery.setType(Type.BEAN);
if (SpiQuery.Mode.NORMAL == spiQuery.mode() && !spiQuery.isForceHitDatabase()) {
// See if we can skip doing the fetch completely by getting the bean from the
// persistence context or the bean cache
T bean = findIdCheckPersistenceContextAndCache(query, query.getId());
T bean = findIdCheckPersistenceContextAndCache(transaction, spiQuery, spiQuery.getId());
if (bean != null) {
return bean;
}
}
SpiOrmQueryRequest<T> request = buildQueryRequest(query);
SpiOrmQueryRequest<T> request = buildQueryRequest(spiQuery, transaction);
request.prepareQuery();
if (request.isUseDocStore()) {
return docStore().find(request);
@@ -1055,19 +1053,23 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
@Override
public <T> Optional<T> findOneOrEmpty(SpiQuery<T> query) {
return Optional.ofNullable(findOne(query));
public <T> Optional<T> findOneOrEmpty(Query<T> query, Transaction transaction) {
return Optional.ofNullable(findOne(query, transaction));
}
@Nullable
@Override
public <T> T findOne(SpiQuery<T> query) {
if (query.isFindById()) {
public <T> T findOne(Query<T> query, @Nullable Transaction transaction) {
SpiQuery<T> spiQuery = (SpiQuery<T>) query;
if (spiQuery.isFindById()) {
// actually a find by Id query
return findId(query);
return findId(query, transaction);
}
if (transaction == null) {
transaction = currentServerTransaction();
}
// a query that is expected to return either 0 or 1 beans
List<T> list = findList(query, true);
List<T> list = findList(query, transaction, true);
return extractUnique(list);
}
@@ -1084,10 +1086,10 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public <T> Set<T> findSet(SpiQuery<T> query) {
SpiOrmQueryRequest request = buildQueryRequest(Type.SET, query);
public <T> Set<T> findSet(Query<T> query, Transaction transaction) {
SpiOrmQueryRequest request = buildQueryRequest(Type.SET, query, transaction);
request.resetBeanCacheAutoMode(false);
if (request.isGetAllFromBeanCache()) {
if ((transaction == null || !transaction.isSkipCache()) && request.getFromBeanCache()) {
// hit bean cache and got all results from cache
return request.beanCacheHitsAsSet();
}
@@ -1106,10 +1108,10 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public <K, T> Map<K, T> findMap(SpiQuery<T> query) {
SpiOrmQueryRequest request = buildQueryRequest(Type.MAP, query);
public <K, T> Map<K, T> findMap(Query<T> query, @Nullable Transaction transaction) {
SpiOrmQueryRequest request = buildQueryRequest(Type.MAP, query, transaction);
request.resetBeanCacheAutoMode(false);
if (request.isGetAllFromBeanCache()) {
if ((transaction == null || !transaction.isSkipCache()) && request.getFromBeanCache()) {
// hit bean cache and got all results from cache
return request.beanCacheHitsAsMap();
}
@@ -1128,8 +1130,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
@Override
@SuppressWarnings("unchecked")
public <A, T> List<A> findSingleAttributeList(SpiQuery<T> query) {
SpiOrmQueryRequest<T> request = buildQueryRequest(Type.ATTRIBUTE, query);
public <A, T> List<A> findSingleAttributeList(Query<T> query, Transaction transaction) {
SpiOrmQueryRequest<T> request = buildQueryRequest(Type.ATTRIBUTE, query, transaction);
request.query().setSingleAttribute();
request.prepareQuery();
Object result = request.getFromQueryCache();
@@ -1146,8 +1148,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
@Override
@SuppressWarnings("unchecked")
public <A, T> Set<A> findSingleAttributeSet(SpiQuery<T> query) {
SpiOrmQueryRequest<T> request = buildQueryRequest(Type.ATTRIBUTE_SET, query);
public <A, T> Set<A> findSingleAttributeSet(Query<T> query, Transaction transaction) {
SpiOrmQueryRequest<T> request = buildQueryRequest(Type.ATTRIBUTE_SET, query, transaction);
request.query().setSingleAttribute();
request.prepareQuery();
Object result = request.getFromQueryCache();
@@ -1163,16 +1165,17 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
@Override
public <T> int findCount(SpiQuery<T> query) {
if (!query.isDistinct()) {
query = query.copy();
public <T> int findCount(Query<T> query, @Nullable Transaction transaction) {
SpiQuery<T> spiQuery = ((SpiQuery<T>) query);
if (!spiQuery.isDistinct()) {
spiQuery = spiQuery.copy();
}
return findCountWithCopy(query);
return findCountWithCopy(spiQuery, transaction);
}
@Override
public <T> int findCountWithCopy(SpiQuery<T> query) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.COUNT, query);
public <T> int findCountWithCopy(Query<T> query, @Nullable Transaction transaction) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.COUNT, query, transaction);
Integer result = request.getFromQueryCache();
if (result != null) {
return result;
@@ -1187,17 +1190,13 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
@Override
public boolean exists(Class<?> beanType, Object beanId, Transaction transaction) {
final DefaultOrmQuery<?> query = createQuery(beanType);
query.usingTransaction(transaction);
query.setId(beanId);
return !findIdsWithCopy(query).isEmpty();
return !findIdsWithCopy(find(beanType).setId(beanId), transaction).isEmpty();
}
@Override
public <T> boolean exists(SpiQuery<T> ormQuery) {
SpiQuery<T> ormQueryCopy = ormQuery.copy();
ormQueryCopy.setMaxRows(1);
SpiOrmQueryRequest<?> request = createQueryRequest(Type.EXISTS, ormQueryCopy);
public <T> boolean exists(Query<T> ormQuery, Transaction transaction) {
Query<T> ormQueryCopy = ormQuery.copy().setMaxRows(1);
SpiOrmQueryRequest<?> request = createQueryRequest(Type.EXISTS, ormQueryCopy, transaction);
List<Object> ids = request.getFromQueryCache();
if (ids != null) {
return !ids.isEmpty();
@@ -1211,14 +1210,14 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
@Override
public <A, T> List<A> findIds(SpiQuery<T> query) {
return findIdsWithCopy(query.copy());
public <A, T> List<A> findIds(Query<T> query, Transaction transaction) {
return findIdsWithCopy(((SpiQuery<T>) query).copy(), transaction);
}
@SuppressWarnings("unchecked")
@Override
public <A, T> List<A> findIdsWithCopy(SpiQuery<T> query) {
SpiOrmQueryRequest<?> request = createQueryRequest(Type.ID_LIST, query);
public <A, T> List<A> findIdsWithCopy(Query<T> query, Transaction transaction) {
SpiOrmQueryRequest<?> request = createQueryRequest(Type.ID_LIST, query, transaction);
Object result = request.getFromQueryCache();
if (result != null) {
if (Boolean.FALSE.equals(request.query().isReadOnly())) {
@@ -1236,8 +1235,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
@Override
public <T> int delete(SpiQuery<T> query) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.DELETE, query);
public <T> int delete(Query<T> query, Transaction transaction) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.DELETE, query, transaction);
try {
request.initTransIfRequired();
request.markNotQueryOnly();
@@ -1259,8 +1258,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
@Override
public <T> int update(SpiQuery<T> query) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.UPDATE, query);
public <T> int update(Query<T> query, Transaction transaction) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.UPDATE, query, transaction);
try {
request.initTransIfRequired();
request.markNotQueryOnly();
@@ -1271,44 +1270,29 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
@Override
public <T> FutureRowCount<T> findFutureCount(SpiQuery<T> query) {
SpiQuery<T> copy = query.copy();
boolean createdTransaction = false;
SpiTransaction transaction = query.transaction();
if (transaction == null) {
transaction = currentServerTransaction();
if (transaction == null) {
transaction = (SpiTransaction) createTransaction();
createdTransaction = true;
}
copy.usingTransaction(transaction);
}
var queryFuture = new QueryFutureRowCount<>(new CallableQueryCount<>(this, copy, createdTransaction));
public <T> FutureRowCount<T> findFutureCount(Query<T> query, Transaction transaction) {
SpiQuery<T> copy = ((SpiQuery<T>) query).copy();
copy.setFutureFetch(true);
Transaction newTxn = createTransaction();
QueryFutureRowCount<T> queryFuture = new QueryFutureRowCount<>(new CallableQueryCount<>(this, copy, newTxn));
backgroundExecutor.execute(queryFuture.futureTask());
return queryFuture;
}
@Override
public <T> FutureIds<T> findFutureIds(SpiQuery<T> query) {
SpiQuery<T> copy = query.copy();
boolean createdTransaction = false;
SpiTransaction transaction = query.transaction();
if (transaction == null) {
transaction = currentServerTransaction();
if (transaction == null) {
transaction = (SpiTransaction) createTransaction();
createdTransaction = true;
}
copy.usingTransaction(transaction);
}
QueryFutureIds<T> queryFuture = new QueryFutureIds<>(new CallableQueryIds<>(this, copy, createdTransaction));
public <T> FutureIds<T> findFutureIds(Query<T> query, Transaction transaction) {
SpiQuery<T> copy = ((SpiQuery<T>) query).copy();
copy.setFutureFetch(true);
Transaction newTxn = createTransaction();
QueryFutureIds<T> queryFuture = new QueryFutureIds<>(new CallableQueryIds<>(this, copy, newTxn));
backgroundExecutor.execute(queryFuture.futureTask());
return queryFuture;
}
@Override
public <T> FutureList<T> findFutureList(SpiQuery<T> query) {
SpiQuery<T> spiQuery = query.copy();
public <T> FutureList<T> findFutureList(Query<T> query, Transaction transaction) {
SpiQuery<T> spiQuery = (SpiQuery<T>) query.copy();
spiQuery.setFutureFetch(true);
// FutureList query always run in it's own persistence content
spiQuery.setPersistenceContext(new DefaultPersistenceContext());
if (!spiQuery.isDisableReadAudit()) {
@@ -1316,36 +1300,28 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
desc.readAuditFutureList(spiQuery);
}
// Create a new transaction solely to execute the findList() at some future time
boolean createdTransaction = false;
SpiTransaction transaction = query.transaction();
if (transaction == null) {
transaction = currentServerTransaction();
if (transaction == null) {
transaction = (SpiTransaction) createTransaction();
createdTransaction = true;
}
spiQuery.usingTransaction(transaction);
}
QueryFutureList<T> queryFuture = new QueryFutureList<>(new CallableQueryList<>(this, spiQuery, createdTransaction));
Transaction newTxn = createTransaction();
QueryFutureList<T> queryFuture = new QueryFutureList<>(new CallableQueryList<>(this, spiQuery, newTxn));
backgroundExecutor.execute(queryFuture.futureTask());
return queryFuture;
}
@Override
public <T> PagedList<T> findPagedList(SpiQuery<T> query) {
int maxRows = query.getMaxRows();
public <T> PagedList<T> findPagedList(Query<T> query, Transaction transaction) {
SpiQuery<T> spiQuery = (SpiQuery<T>) query;
int maxRows = spiQuery.getMaxRows();
if (maxRows == 0) {
throw new PersistenceException("maxRows must be specified for findPagedList() query");
}
if (query.isUseDocStore()) {
return docStore().findPagedList(createQueryRequest(Type.LIST, query));
if (spiQuery.isUseDocStore()) {
return docStore().findPagedList(createQueryRequest(Type.LIST, query, transaction));
}
return new LimitOffsetPagedList<>(this, query);
return new LimitOffsetPagedList<>(this, spiQuery);
}
@Override
public <T> QueryIterator<T> findIterate(SpiQuery<T> query) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query);
public <T> QueryIterator<T> findIterate(Query<T> query, Transaction transaction) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, transaction);
try {
request.initTransIfRequired();
return request.findIterate();
@@ -1356,8 +1332,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
@Override
public <T> Stream<T> findStream(SpiQuery<T> query) {
return toStream(findIterate(query));
public <T> Stream<T> findStream(Query<T> query, Transaction transaction) {
return toStream(findIterate(query, transaction));
}
private <T> Stream<T> toStream(QueryIterator<T> queryIterator) {
@@ -1365,8 +1341,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
@Override
public <T> void findEach(SpiQuery<T> query, Consumer<T> consumer) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query);
public <T> void findEach(Query<T> query, Consumer<T> consumer, Transaction transaction) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, transaction);
if (request.isUseDocStore()) {
docStore().findEach(request, consumer);
return;
@@ -1377,8 +1353,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
@Override
public <T> void findEach(SpiQuery<T> query, int batch, Consumer<List<T>> consumer) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query);
public <T> void findEach(Query<T> query, int batch, Consumer<List<T>> consumer, Transaction transaction) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, transaction);
// if (request.isUseDocStore()) {
// docStore().findEach(request, consumer);
// return;
@@ -1389,8 +1365,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
@Override
public <T> void findEachWhile(SpiQuery<T> query, Predicate<T> consumer) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query);
public <T> void findEachWhile(Query<T> query, Predicate<T> consumer, Transaction transaction) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, transaction);
if (request.isUseDocStore()) {
docStore().findEachWhile(request, consumer);
return;
@@ -1401,8 +1377,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
@Override
public <T> List<Version<T>> findVersions(SpiQuery<T> query) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.LIST, query);
public <T> List<Version<T>> findVersions(Query<T> query, @Nullable Transaction transaction) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.LIST, query, transaction);
try {
request.initTransIfRequired();
return request.findVersions();
@@ -1412,15 +1388,15 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
@Override
public <T> List<T> findList(SpiQuery<T> query) {
return findList(query, false);
public <T> List<T> findList(Query<T> query, Transaction transaction) {
return findList(query, transaction, false);
}
@SuppressWarnings("unchecked")
private <T> List<T> findList(SpiQuery<T> query, boolean findOne) {
SpiOrmQueryRequest<T> request = buildQueryRequest(Type.LIST, query);
private <T> List<T> findList(Query<T> query, @Nullable Transaction transaction, boolean findOne) {
SpiOrmQueryRequest<T> request = buildQueryRequest(Type.LIST, query, transaction);
request.resetBeanCacheAutoMode(findOne);
if (request.isGetAllFromBeanCache()) {
if ((transaction == null || !transaction.isSkipCache()) && request.getFromBeanCache()) {
// hit bean cache and got all results from cache
return request.beanCacheHits();
}
@@ -1442,16 +1418,16 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
@Nullable
@Override
public SqlRow findOne(SpiSqlQuery query) {
public SqlRow findOne(SqlQuery query, Transaction transaction) {
// no findId() method for SqlQuery...
// a query that is expected to return either 0 or 1 rows
List<SqlRow> list = findList(query);
List<SqlRow> list = findList(query, transaction);
return extractUnique(list);
}
@Override
public void findEach(SpiSqlQuery query, Consumer<SqlRow> consumer) {
RelationalQueryRequest request = new RelationalQueryRequest(this, relationalQueryEngine, query);
public void findEach(SqlQuery query, Consumer<SqlRow> consumer, Transaction transaction) {
RelationalQueryRequest request = new RelationalQueryRequest(this, relationalQueryEngine, query, transaction);
try {
request.initTransIfRequired();
request.findEach(consumer);
@@ -1461,8 +1437,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
@Override
public void findEachWhile(SpiSqlQuery query, Predicate<SqlRow> consumer) {
RelationalQueryRequest request = new RelationalQueryRequest(this, relationalQueryEngine, query);
public void findEachWhile(SqlQuery query, Predicate<SqlRow> consumer, Transaction transaction) {
RelationalQueryRequest request = new RelationalQueryRequest(this, relationalQueryEngine, query, transaction);
try {
request.initTransIfRequired();
request.findEachWhile(consumer);
@@ -1472,8 +1448,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
@Override
public List<SqlRow> findList(SpiSqlQuery query) {
RelationalQueryRequest request = new RelationalQueryRequest(this, relationalQueryEngine, query);
public List<SqlRow> findList(SqlQuery query, Transaction transaction) {
RelationalQueryRequest request = new RelationalQueryRequest(this, relationalQueryEngine, query, transaction);
try {
request.initTransIfRequired();
return request.findList();
@@ -1483,7 +1459,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
private <P> P executeSqlQuery(Function<RelationalQueryRequest, P> fun, SpiSqlQuery query) {
RelationalQueryRequest request = new RelationalQueryRequest(this, relationalQueryEngine, query);
RelationalQueryRequest request = new RelationalQueryRequest(this, relationalQueryEngine, query, query.transaction());
try {
request.initTransIfRequired();
return fun.apply(request);
@@ -2147,8 +2123,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
@Override
public SpiTransaction createReadOnlyTransaction(Object tenantId, boolean useMaster) {
return transactionManager.createReadOnlyTransaction(tenantId, useMaster);
public SpiTransaction createReadOnlyTransaction(Object tenantId) {
return transactionManager.createReadOnlyTransaction(tenantId);
}
/**
@@ -2203,10 +2179,9 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
Object id = idProperty.getValue(entityBean);
if (entityBean._ebean_getIntercept().isNew() && id != null) {
// Primary Key is changeable only on new models - so skip check if we are not new
SpiQuery<?> query = new DefaultOrmQuery<>(beanDesc, this, expressionFactory);
query.usingTransaction(transaction);
Query<?> query = new DefaultOrmQuery<>(beanDesc, this, expressionFactory);
query.setId(id);
if (findCount(query) > 0) {
if (findCount(query, transaction) > 0) {
return Collections.singleton(idProperty);
}
}
@@ -2225,8 +2200,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
@Nullable
private Set<Property> checkUniqueness(EntityBean entityBean, BeanDescriptor<?> beanDesc, BeanProperty[] props, @Nullable Transaction transaction) {
BeanProperty idProperty = beanDesc.idProperty();
SpiQuery<?> query = new DefaultOrmQuery<>(beanDesc, this, expressionFactory);
query.usingTransaction(transaction);
Query<?> query = new DefaultOrmQuery<>(beanDesc, this, expressionFactory);
ExpressionList<?> exprList = query.where();
if (!entityBean._ebean_getIntercept().isNew()) {
// if model is not new, exclude ourself.
@@ -2239,7 +2213,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
exprList.eq(prop.name(), value);
}
if (findCount(query) > 0) {
if (findCount(query, transaction) > 0) {
Set<Property> ret = new LinkedHashSet<>();
Collections.addAll(ret, props);
return ret;
@@ -281,9 +281,9 @@ public final class DefaultSqlUpdate implements Serializable, SpiSqlUpdate {
int offset = 0;
for (Object val : values) {
if (offset > 0) {
sqlExpand.append(',');
sqlExpand.append(",");
}
sqlExpand.append('?');
sqlExpand.append("?");
bindParams.setParameter(position + offset++, val);
}
bindExpansion += (offset - 1);
@@ -33,7 +33,7 @@ public final class DtoQueryRequest<T> extends AbstractSqlQueryRequest {
private DataReader dataReader;
DtoQueryRequest(SpiEbeanServer server, DtoQueryEngine engine, SpiDtoQuery<T> query) {
super(server, query);
super(server, query, query.transaction());
this.queryEngine = engine;
this.query = query;
query.obtainLocation();
@@ -52,8 +52,7 @@ public final class DtoQueryRequest<T> extends AbstractSqlQueryRequest {
query.setCancelableQuery(ormQuery);
// execute the underlying ORM query returning the ResultSet
ormQuery.usingTransaction(transaction);
SpiResultSet result = server.findResultSet(ormQuery);
SpiResultSet result = server.findResultSet(ormQuery, transaction);
this.pstmt = result.statement();
this.sql = ormQuery.getGeneratedSql();
setResultSet(result.resultSet(), ormQuery.queryPlanKey());
@@ -121,7 +121,7 @@ final class DumpMetrics {
}
private void appendQueryName(MetaQueryMetric metric, StringBuilder sb) {
sb.append("query:").append(padName(metric.name())).append(' ');
sb.append("query:").append(padName(metric.name())).append(" ");
}
private void appendProfileAndSql(MetaQueryMetric metric, StringBuilder sb) {
@@ -136,7 +136,7 @@ final class DumpMetrics {
private void log(MetaTimedMetric metric) {
StringBuilder sb = new StringBuilder();
sb.append(padNameTimed(metric.name())).append(' ');
sb.append(padNameTimed(metric.name())).append(" ");
appendCounters(metric, sb);
out(sb.toString());
}
@@ -56,10 +56,7 @@ final class MultiTenantDbCatalogSupplier implements DataSourceSupplier {
}
@Override
public Connection readOnlyConnection(Object tenantId, boolean useMaster) throws SQLException {
if (readOnly == null || useMaster) {
return catalogDataSource.getConnectionForTenant(tenantId);
}
public Connection readOnlyConnection(Object tenantId) throws SQLException {
return readOnly.getConnectionForTenant(tenantId);
}
@@ -106,6 +103,7 @@ final class MultiTenantDbCatalogSupplier implements DataSourceSupplier {
*/
@Override
public Connection getConnection() throws SQLException {
Connection connection = dataSource.getConnection();
connection.setCatalog(tenantCatalog());
return connection;
@@ -56,12 +56,8 @@ final class MultiTenantDbSchemaSupplier implements DataSourceSupplier {
}
@Override
public Connection readOnlyConnection(Object tenantId, boolean useMaster) throws SQLException {
if (readOnly == null || useMaster) {
return schemaDataSource.getConnectionForTenant(tenantId);
} else {
return readOnly.getConnectionForTenant(tenantId);
}
public Connection readOnlyConnection(Object tenantId) throws SQLException {
return readOnly.getConnectionForTenant(tenantId);
}
@Override
@@ -110,6 +106,7 @@ final class MultiTenantDbSchemaSupplier implements DataSourceSupplier {
*/
@Override
public Connection getConnection() throws SQLException {
Connection connection = dataSource.getConnection();
connection.setSchema(tenantSchema());
return connection;
@@ -43,8 +43,8 @@ final class MultiTenantDbSupplier implements DataSourceSupplier {
}
@Override
public Connection readOnlyConnection(Object tenantId, boolean useMaster) throws SQLException {
return dataSourceProvider.dataSource(tenantId).getConnection();
public Connection readOnlyConnection(Object tenantId) throws SQLException {
throw new SQLException("Not currently supported");
}
@Override
@@ -23,7 +23,7 @@ final class ObtainedTransactionImplicit extends ObtainedTransaction {
@Override
public void commitIfCreated() {
transaction.commit();
server.commitTransaction();
}
@Override
@@ -60,11 +60,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
return queryEngine.translate(this, bindLog, sql, e);
}
@Override
public boolean isGetAllFromBeanCache() {
return (transaction == null || !transaction.isSkipCache()) && getFromBeanCache();
}
@Override
public boolean isDeleteByStatement() {
if (!transaction.isPersistCascade() || beanDescriptor.isDeleteByStatement()) {
@@ -225,7 +220,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
} else {
// create an implicit transaction to execute this query
// potentially using read-only DataSource with autoCommit
transaction = server.createReadOnlyTransaction(query.tenantId(), query.isUseMaster());
transaction = server.createReadOnlyTransaction(query.tenantId());
}
createdTransaction = true;
}
@@ -44,7 +44,7 @@ public final class PersistDeferredRelationship {
return; // could not bind: TODO: should we log/throw an error?
}
// bind the where clause for the bean
Object[] idValues = beanDescriptor.idBinder().values(bean);
Object[] idValues = beanDescriptor.idBinder().getIdValues(bean);
for (int j = 0; j < idValues.length; j++) {
sqlUpdate.setParameter(pos + j, idValues[j]);
}
@@ -2,7 +2,7 @@ package io.ebeaninternal.server.core;
import io.ebean.*;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.SpiSqlQuery;
import io.ebeaninternal.api.SpiSqlBinding;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
@@ -22,8 +22,8 @@ public final class RelationalQueryRequest extends AbstractSqlQueryRequest {
private int estimateCapacity;
private int rows;
RelationalQueryRequest(SpiEbeanServer server, RelationalQueryEngine engine, SpiSqlQuery q) {
super(server, q);
RelationalQueryRequest(SpiEbeanServer server, RelationalQueryEngine engine, SqlQuery q, Transaction t) {
super(server, (SpiSqlBinding) q, t);
this.queryEngine = engine;
}
@@ -41,12 +41,8 @@ final class SimpleDataSourceProvider implements DataSourceSupplier {
}
@Override
public Connection readOnlyConnection(Object tenantId, boolean useMaster) throws SQLException {
if (readOnlyDataSource == null || useMaster) {
return dataSource.getConnection();
} else {
return readOnlyDataSource.getConnection();
}
public Connection readOnlyConnection(Object tenantId) throws SQLException {
return readOnlyDataSource.getConnection();
}
@Override
@@ -188,8 +188,4 @@ public interface SpiOrmQueryRequest<T> extends BeanQueryRequest<T>, DocQueryRequ
*/
boolean isDeleteByStatement();
/**
* Return true if hitting bean cache and returning all beans from cache.
*/
boolean isGetAllFromBeanCache();
}
@@ -1,12 +1,12 @@
package io.ebeaninternal.server.deploy;
import io.ebean.Query;
import io.ebean.Transaction;
import io.ebean.bean.BeanCollection;
import io.ebean.bean.BeanCollectionAdd;
import io.ebean.bean.BeanCollectionLoader;
import io.ebean.bean.EntityBean;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.api.json.SpiJsonWriter;
import io.ebeaninternal.server.query.CQueryCollectionAdd;
@@ -63,6 +63,11 @@ public interface BeanCollectionHelp<T> extends CQueryCollectionAdd<T> {
*/
BeanCollection<T> createReference(EntityBean parentBean);
/**
* Refresh the List Set or Map.
*/
void refresh(SpiEbeanServer server, Query<?> query, Transaction t, EntityBean parentBean);
/**
* Apply the new refreshed BeanCollection to the appropriate property of the parent bean.
*/
@@ -212,6 +212,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
private final EntityBean prototypeEntityBean;
private final IdBinder idBinder;
private final String idSelect;
private String idBinderInLHSSql;
private String idBinderIdSql;
private String deleteByIdSql;
@@ -354,11 +355,23 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
propertiesIndex[i] = propMap.get(ebi.property(i));
}
}
idSelect = initIdSelect();
}
public String idSelect() {
if (idBinder == null) throw new UnsupportedOperationException();
return idBinder.idSelect();
String initIdSelect() {
if (idProperty != null && !idProperty.name().equals("_idClass")) {
return idProperty.name();
} else if (entityType == EntityType.EMBEDDED) {
return null;
} else {
StringJoiner sj = new StringJoiner(",");
for (BeanProperty prop : propertiesNonMany) {
if (prop.isImportedPrimaryKey()) {
sj.add(prop.name());
}
}
return sj.toString().intern();
}
}
public boolean isJacksonCorePresent() {
@@ -530,10 +543,10 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
unidirectional.initialise(initContext);
}
idBinder.initialise();
idBinderInLHSSql = idBinder.bindInSql(baseTableAlias);
idBinderIdSql = idBinder.bindEqSql(baseTableAlias);
String idBinderInLHSSqlNoAlias = idBinder.bindInSql(null);
String idEqualsSql = idBinder.bindEqSql(null);
idBinderInLHSSql = idBinder.getBindIdInSql(baseTableAlias);
idBinderIdSql = idBinder.getBindIdSql(baseTableAlias);
String idBinderInLHSSqlNoAlias = idBinder.getBindIdInSql(null);
String idEqualsSql = idBinder.getBindIdSql(null);
deleteByIdSql = "delete from " + baseTable + " where " + idEqualsSql;
whereIdInSql = " where " + idBinderInLHSSqlNoAlias + " ";
deleteByIdInSql = "delete from " + baseTable + whereIdInSql;
@@ -855,10 +868,10 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
private SqlUpdate deleteByIdList(List<Object> idList, DeleteMode mode) {
String baseSql = mode.isHard() ? deleteByIdInSql : softDeleteByIdInSql;
StringBuilder sb = new StringBuilder(baseSql);
String inClause = idBinder.idInValueExprDelete(idList.size());
String inClause = idBinder.getIdInValueExprDelete(idList.size());
sb.append(inClause);
DefaultSqlUpdate delete = new DefaultSqlUpdate(sb.toString());
idBinder.addBindValues(delete, idList);
idBinder.addIdInBindValues(delete, idList);
return delete;
}
@@ -869,7 +882,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
private SqlUpdate deleteById(Object id, DeleteMode mode) {
String baseSql = mode.isHard() ? deleteByIdSql : softDeleteByIdSql;
DefaultSqlUpdate sqlDelete = new DefaultSqlUpdate(baseSql);
Object[] bindValues = idBinder.bindValues(id);
Object[] bindValues = idBinder.getBindValues(id);
for (Object bindValue : bindValues) {
sqlDelete.setParameter(bindValue);
}
@@ -1524,7 +1537,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
* Return a Sql update statement to set the importedId value (deferred execution).
*/
public String updateImportedIdSql(ImportedId prop) {
return "update " + baseTable + " set " + prop.importedIdClause() + " where " + idBinder.bindEqSql(null);
return "update " + baseTable + " set " + prop.importedIdClause() + " where " + idBinder.getBindIdSql(null);
}
/**
@@ -1618,7 +1631,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
* Return a raw expression for 'where parent id in ...' clause.
*/
String parentIdInExpr(int parentIdSize, String rawWhere) {
String inClause = idBinder.idInValueExpr(false, parentIdSize);
String inClause = idBinder.getIdInValueExpr(false, parentIdSize);
return idBinder.isIdInExpandedForm() ? inClause : rawWhere + inClause;
}
@@ -1671,7 +1684,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
if (alias == null) {
return idBinderIdSql;
} else {
return idBinder.bindEqSql(alias);
return idBinder.getBindIdSql(alias);
}
}
@@ -1697,7 +1710,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
* This 'flattens' any EmbeddedId or multiple Id property cases.
*/
public Object[] bindIdValues(Object idValue) {
return idBinder.bindValues(idValue);
return idBinder.getBindValues(idValue);
}
@Override
@@ -2105,7 +2118,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
* The usage is to provide simple id types for JSON processing (for embeddedId's).
*/
public Object idForJson(Object bean) {
return idBinder.convertForJson((EntityBean) bean);
return idBinder.getIdForJson((EntityBean) bean);
}
/**
@@ -2114,7 +2127,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
* The usage is to provide simple id types for JSON processing (for embeddedId's).
*/
Object convertIdFromJson(Object idValue) {
return idBinder.convertFromJson(idValue);
return idBinder.convertIdFromJson(idValue);
}
/**
@@ -2122,7 +2135,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
* included in the query.
*/
public String defaultOrderBy() {
return idBinder.orderBy();
return idBinder.getDefaultOrderBy();
}
/**
@@ -2437,13 +2450,9 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
BeanProperty _findBeanProperty(String propName) {
BeanProperty prop = propMap.get(propName);
if (prop == null) {
if ("_$IdClass$".equals(propName)) {
return idProperty;
} else if (inheritInfo != null) {
// search in sub types...
return inheritInfo.findSubTypeProperty(propName);
}
if (prop == null && inheritInfo != null) {
// search in sub types...
return inheritInfo.findSubTypeProperty(propName);
}
return prop;
}
@@ -3048,6 +3057,10 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
return idProperty;
}
public String idSelect() {
return idSelect;
}
/**
* Return true if this bean should be inserted rather than updated.
*
@@ -552,7 +552,7 @@ final class BeanDescriptorCacheHelp<T> {
if (val == null) {
return null;
}
sb.append(val).append(';');
sb.append(val).append(";");
}
return sb.toString();
}
@@ -23,6 +23,11 @@ abstract class BeanDescriptorElement<T> extends BeanDescriptor<T> {
this.elementHelp = elementHelp;
}
@Override
String initIdSelect() {
return null;
}
private String shortName(String name) {
int pos = name.lastIndexOf('.');
if (pos > 1) {
@@ -105,6 +105,7 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
private final String asOfViewSuffix;
private final boolean jacksonCorePresent;
private final int queryPlanTTLSeconds;
private final BindMaxLength bindMaxLength;
private int entityBeanCount;
private List<BeanDescriptor<?>> immutableDescriptorList;
/**
@@ -159,6 +160,19 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
this.changeLogListener = config.changeLogListener(bootupClasses.getChangeLogListener());
this.changeLogRegister = config.changeLogRegister(bootupClasses.getChangeLogRegister());
this.jacksonCorePresent = config.isJacksonCorePresent();
this.bindMaxLength = initMaxLength();
}
BindMaxLength initMaxLength() {
LengthCheck lengthCheck = this.config.getLengthCheck();
switch (lengthCheck) {
case OFF:
return null;
case UTF8:
return BindMaxLength.ofUtf8();
default:
return BindMaxLength.ofStandard();
}
}
@Override
@@ -518,7 +532,7 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
IdBinder idBinder = d.idBinder();
if (idBinder instanceof IdBinderEmbedded) {
IdBinderEmbedded embId = (IdBinderEmbedded) idBinder;
BeanDescriptor<?> idBeanDescriptor = embId.descriptor();
BeanDescriptor<?> idBeanDescriptor = embId.getIdBeanDescriptor();
Class<?> idType = idBeanDescriptor.type();
try {
idType.getDeclaredMethod("hashCode");
@@ -1502,6 +1516,10 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
return list;
}
public BindMaxLength bindMaxLength() {
return bindMaxLength;
}
/**
* Comparator to sort the BeanDescriptors by name.
*/
@@ -1,12 +1,12 @@
package io.ebeaninternal.server.deploy;
import io.ebean.Query;
import io.ebean.Transaction;
import io.ebean.bean.BeanCollection;
import io.ebean.bean.BeanCollectionAdd;
import io.ebean.bean.EntityBean;
import io.ebean.common.BeanList;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.api.json.SpiJsonWriter;
import java.io.IOException;
@@ -67,6 +67,12 @@ public class BeanListHelp<T> extends BaseCollectionHelp<T> {
return beanList;
}
@Override
public final void refresh(SpiEbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
BeanList<?> newBeanList = (BeanList<?>) server.findList(query, t);
refresh(newBeanList, parentBean);
}
@Override
public final void refresh(BeanCollection<?> bc, EntityBean parentBean) {
BeanList<?> newBeanList = (BeanList<?>) bc;
@@ -1,12 +1,12 @@
package io.ebeaninternal.server.deploy;
import io.ebean.Query;
import io.ebean.Transaction;
import io.ebean.bean.BeanCollection;
import io.ebean.bean.BeanCollectionAdd;
import io.ebean.bean.EntityBean;
import io.ebean.common.BeanMap;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.api.json.SpiJsonWriter;
import java.io.IOException;
@@ -113,6 +113,12 @@ public class BeanMapHelp<T> extends BaseCollectionHelp<T> {
return beanMap;
}
@Override
public final void refresh(SpiEbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
BeanMap<?, ?> newBeanMap = (BeanMap<?, ?>) server.findMap(query, t);
refresh(newBeanMap, parentBean);
}
@Override
public final void refresh(BeanCollection<?> bc, EntityBean parentBean) {
BeanMap<?, ?> newBeanMap = (BeanMap<?, ?>) bc;
@@ -69,7 +69,7 @@ public final class BeanNaturalKey {
public String calculateKey(Map<String, Object> map) {
StringBuilder sb = new StringBuilder();
for (BeanProperty prop : props) {
sb.append(prop.naturalKeyVal(map)).append(';');
sb.append(prop.naturalKeyVal(map)).append(";");
}
return sb.toString();
}
@@ -1,16 +1,20 @@
package io.ebeaninternal.server.deploy;
import com.fasterxml.jackson.core.JsonToken;
import io.ebean.DataIntegrityException;
import io.ebean.ValuePair;
import io.ebean.bean.EntityBean;
import io.ebean.bean.EntityBeanIntercept;
import io.ebean.bean.MutableValueInfo;
import io.ebean.bean.PersistenceContext;
import io.ebean.config.EncryptKey;
import io.ebean.config.LengthCheck;
import io.ebean.config.dbplatform.DbEncryptFunction;
import io.ebean.config.dbplatform.DbPlatformType;
import io.ebean.config.dbplatform.ExtraDbTypes;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
import io.ebean.core.type.InputStreamInfo;
import io.ebean.core.type.ScalarType;
import io.ebean.plugin.Property;
import io.ebean.text.StringParser;
@@ -46,6 +50,7 @@ import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.sql.Types;
import java.util.List;
@@ -166,6 +171,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
*/
private final String dbComment;
private final DbEncryptFunction dbEncryptFunction;
private final BindMaxLength bindMaxLength;
private int deployOrder;
final boolean jsonSerialize;
final boolean jsonDeserialize;
@@ -258,6 +264,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
}
this.jsonSerialize = deploy.isJsonSerialize();
this.jsonDeserialize = deploy.isJsonDeserialize();
this.bindMaxLength = deploy.bindMaxLength();
}
private String tableAliasIntern(BeanDescriptor<?> descriptor, String s, boolean dbEncrypted, String dbColumn) {
@@ -345,6 +352,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
this.elPlaceHolderEncrypted = override.replace(source.elPlaceHolderEncrypted, source.dbColumn);
this.jsonSerialize = source.jsonSerialize;
this.jsonDeserialize = source.jsonDeserialize;
this.bindMaxLength = source.bindMaxLength;
}
/**
@@ -456,8 +464,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
@Override
public void appendFrom(DbSqlContext ctx, SqlJoinType joinType, String manyWhere) {
if (formula && sqlFormulaJoin != null) {
String alias = ctx.tableAliasManyWhere(manyWhere);
ctx.appendFormulaJoin(sqlFormulaJoin, joinType, alias);
ctx.appendFormulaJoin(sqlFormulaJoin, joinType, manyWhere);
} else if (secondaryTableJoin != null) {
String relativePrefix = ctx.relativePrefix(secondaryTableJoinPrefix);
secondaryTableJoin.addJoin(joinType, relativePrefix, ctx);
@@ -555,6 +562,18 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
@SuppressWarnings("unchecked")
public void bind(DataBind b, Object value) throws SQLException {
scalarType.bind(b, value);
if (bindMaxLength != null) {
Object obj = b.popLastObject();
long length = bindMaxLength.length(dbLength, obj);
if (length > dbLength) {
b.closeInputStreams();
String s = String.valueOf(value); // take original bind value here.
if (s.length() > 50) {
s = s.substring(0, 47) + "...";
}
throw new DataIntegrityException("Cannot bind value '" + s + "' (effective length=" + length + ") to column '" + dbColumn + "' (length=" + dbLength + ")");
}
}
}
@SuppressWarnings(value = "unchecked")
@@ -1,8 +1,6 @@
package io.ebeaninternal.server.deploy;
import io.ebean.Query;
import io.ebean.SqlUpdate;
import io.ebean.Transaction;
import io.ebean.bean.EntityBean;
import io.ebean.core.type.DocPropertyType;
import io.ebean.text.PathProperties;
@@ -124,7 +122,7 @@ public abstract class BeanPropertyAssoc<T> extends BeanProperty implements STree
targetInheritInfo = targetDescriptor.inheritInfo();
saveRecurseSkippable = targetDescriptor.isSaveRecurseSkippable();
if (!targetIdBinder.isComplexId()) {
targetIdProperty = targetIdBinder.idSelect();
targetIdProperty = targetIdBinder.getIdProperty();
}
}
}
@@ -572,26 +570,4 @@ public abstract class BeanPropertyAssoc<T> extends BeanProperty implements STree
+ " or a @JoinColumn needs an explicit referencedColumnName specified?";
throw new PersistenceException(msg);
}
/**
* Create SqlUpdate statement to delete all child beans of the parent <code>id</code>.
*/
public abstract SqlUpdate deleteByParentId(Object id);
/**
* Create SqlUpdate statement to delete all child beans of the parent ids in <code>idList</code>.
*/
public abstract SqlUpdate deleteByParentIdList(List<Object> idList);
/**
* Find child beans of the parent <code>id</code>.
*/
public abstract List<Object> findIdsByParentId(Object id, Transaction transaction, boolean includeSoftDeletes);
/**
* Find child beans of the parent ids in <code>idList</code>.
*/
public abstract List<Object> findIdsByParentIdList(List<Object> idList, Transaction transaction, boolean includeSoftDeletes);
}
@@ -296,38 +296,23 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
// do not add to the selectChain at the top level of the Many bean
}
@Override
public SpiSqlUpdate deleteByParentId(Object parentId) {
return sqlHelp.deleteByParentId(parentId);
}
@Override
public SpiSqlUpdate deleteByParentIdList(List<Object> parentIdist) {
return sqlHelp.deleteByParentIdList(parentIdist);
}
/**
* Find the Id's of detail beans given a parent Id
*/
@Override
public List<Object> findIdsByParentId(Object parentId, Transaction t, boolean includeSoftDeletes) {
return sqlHelp.findIdsByParentId(parentId, t, includeSoftDeletes, null);
public SpiSqlUpdate deleteByParentId(Object parentId, List<Object> parentIdist) {
if (parentId != null) {
return sqlHelp.deleteByParentId(parentId);
} else {
return sqlHelp.deleteByParentIdList(parentIdist);
}
}
/**
* Find the Id's of detail beans given a parent Id and optionally exclude detail IDs
* Find the Id's of detail beans given a parent Id or list of parent Id's.
*/
public List<Object> findIdsByParentId(Object parentId, Transaction t, boolean includeSoftDeletes, Set<Object> excludeDetailIds) {
return sqlHelp.findIdsByParentId(parentId, t, includeSoftDeletes, excludeDetailIds);
}
/**
* Find the Id's of detail beans given a list of parent Id's.
*/
@Override
public List<Object> findIdsByParentIdList(List<Object> parentIdList, Transaction t, boolean includeSoftDeletes) {
return sqlHelp.findIdsByParentIdList(parentIdList, t, includeSoftDeletes);
public List<Object> findIdsByParentId(Object parentId, List<Object> parentIdList, Transaction t, List<Object> excludeDetailIds, boolean hard) {
if (parentId != null) {
return sqlHelp.findIdsByParentId(parentId, t, excludeDetailIds, hard);
} else {
return sqlHelp.findIdsByParentIdList(parentIdList, t, excludeDetailIds, hard);
}
}
/**
@@ -473,7 +458,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
*/
@Override
public Object[] assocIdValues(EntityBean bean) {
return targetDescriptor.idBinder().values(bean);
return targetDescriptor.idBinder().getIdValues(bean);
}
/**
@@ -481,7 +466,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
*/
@Override
public String assocIdExpression(String prefix, String operator) {
return targetDescriptor.idBinder().assocExpr(prefix, operator);
return targetDescriptor.idBinder().getAssocOneIdExpr(prefix, operator);
}
/**
@@ -489,7 +474,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
*/
@Override
public String assocIdInValueExpr(boolean not, int size) {
return targetDescriptor.idBinder().idInValueExpr(not, size);
return targetDescriptor.idBinder().getIdInValueExpr(not, size);
}
/**
@@ -497,7 +482,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
*/
@Override
public String assocIdInExpr(String prefix) {
return targetDescriptor.idBinder().assocInExpr(prefix);
return targetDescriptor.idBinder().getAssocIdInExpr(prefix);
}
@Override
@@ -755,7 +740,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
throw new PersistenceException(from + ": Could not find mapKey property " + mapKey + " on " + to);
}
public IntersectionRow buildManyDeleteChildren(EntityBean parentBean, Set<Object> excludeDetailIds) {
public IntersectionRow buildManyDeleteChildren(EntityBean parentBean, List<Object> excludeDetailIds) {
IntersectionRow row = new IntersectionRow(tableJoin.getTable(), targetDescriptor);
if (excludeDetailIds != null && !excludeDetailIds.isEmpty()) {
row.setExcludeIds(excludeDetailIds, targetDescriptor());
@@ -4,13 +4,12 @@ import io.ebean.Transaction;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.api.SpiSqlUpdate;
import io.ebeaninternal.server.core.DefaultSqlUpdate;
import io.ebeaninternal.server.deploy.visitor.BaseTablePropertyVisitor;
import io.ebeaninternal.server.deploy.visitor.VisitProperties;
import io.ebeaninternal.server.core.DefaultSqlUpdate;
import io.ebeaninternal.server.util.Str;
import java.util.List;
import java.util.Set;
class BeanPropertyAssocManySqlHelp<T> {
@@ -22,15 +21,13 @@ class BeanPropertyAssocManySqlHelp<T> {
private final String deleteByParentIdSql;
private final String deleteByParentIdInSql;
private final String elementCollectionInsertSql;
private final boolean idInExpandedForm;
BeanPropertyAssocManySqlHelp(BeanPropertyAssocMany<T> many, ExportedProperty[] exportedProperties) {
this.many = many;
this.exportedProperties = exportedProperties;
this.hasJoinTable = many.hasJoinTable();
this.descriptor = many.descriptor();
this.exportedPropertyBindProto = initExportedBindProto();
this.idInExpandedForm = descriptor.idBinder().isIdInExpandedForm();
this.exportedPropertyBindProto = deriveExportedPropertyBindProto();
String delStmt;
if (hasJoinTable) {
@@ -38,8 +35,8 @@ class BeanPropertyAssocManySqlHelp<T> {
} else {
delStmt = "delete from " + many.targetTable() + " where ";
}
deleteByParentIdSql = delStmt + rawParentIdEQ("");
deleteByParentIdInSql = delStmt;
deleteByParentIdSql = delStmt + deriveWhereParentIdSql(false, "");
deleteByParentIdInSql = delStmt + deriveWhereParentIdSql(true, "");
if (many.isElementCollection()) {
elementCollectionInsertSql = elementCollectionInsert();
} else {
@@ -48,7 +45,7 @@ class BeanPropertyAssocManySqlHelp<T> {
}
private String elementCollectionInsert() {
final StringBuilder sb = new StringBuilder(200);
StringBuilder sb = new StringBuilder(200);
sb.append("insert into ").append(many.targetTable()).append(" (");
append(sb);
@@ -57,7 +54,7 @@ class BeanPropertyAssocManySqlHelp<T> {
sb.append(") values (");
appendBind(sb, exportedProperties.length, true);
appendBind(sb, cols.colCount, false);
sb.append(')');
sb.append(")");
return sb.toString();
}
@@ -76,7 +73,7 @@ class BeanPropertyAssocManySqlHelp<T> {
@Override
public void visitEmbeddedScalar(BeanProperty p, BeanPropertyAssocOne<?> embedded) {
sb.append(',').append(p.dbColumn());
sb.append(",").append(p.dbColumn());
colCount++;
}
@@ -87,7 +84,7 @@ class BeanPropertyAssocManySqlHelp<T> {
@Override
public void visitScalar(BeanProperty p, boolean allowNonNull) {
sb.append(',').append(p.dbColumn());
sb.append(",").append(p.dbColumn());
colCount++;
}
@@ -99,14 +96,14 @@ class BeanPropertyAssocManySqlHelp<T> {
String lazyFetchOrderBy(String fetchOrderBy) {
// derive lazyFetchOrderBy
final String fkTableAlias = hasJoinTable ? "int_" : "t0";
final var sb = new StringBuilder(50);
StringBuilder sb = new StringBuilder(50);
for (int i = 0; i < exportedProperties.length; i++) {
if (i > 0) {
sb.append(", ");
}
// these fk columns are either on the intersection (int_) or base table (t0)
sb.append(fkTableAlias).append('.').append(exportedProperties[i].getForeignDbColumn());
String fkTableAlias = hasJoinTable ? "int_" : "t0";
sb.append(fkTableAlias).append(".").append(exportedProperties[i].getForeignDbColumn());
}
sb.append(", ").append(fetchOrderBy);
return sb.toString().trim();
@@ -116,50 +113,56 @@ class BeanPropertyAssocManySqlHelp<T> {
* Add a where clause to the query for a given list of parent Id's.
*/
void addWhereParentIdIn(SpiQuery<?> query, List<Object> parentIds) {
final String tableAlias = hasJoinTable ? "int_." : "t0.";
String tableAlias = hasJoinTable ? "int_." : "t0.";
if (hasJoinTable) {
query.setM2MIncludeJoin(many.inverseJoin);
}
final String rawWhere = rawParentIdIN(tableAlias, parentIds.size());
many.bindParentIdsIn(rawWhere, parentIds, query);
String rawWhere = deriveWhereParentIdSql(true, tableAlias);
String expr = descriptor.parentIdInExpr(parentIds.size(), rawWhere);
many.bindParentIdsIn(expr, parentIds, query);
}
List<Object> findIdsByParentId(Object parentId, Transaction t, boolean includeSoftDeletes, Set<Object> excludeDetailIds) {
final SpiEbeanServer server = descriptor.ebeanServer();
final SpiQuery<?> query = many.newQuery(server);
query.usingTransaction(t);
many.bindParentIdEq(rawParentIdEQ(""), parentId, query);
if (includeSoftDeletes) {
query.setIncludeSoftDeletes();
List<Object> findIdsByParentId(Object parentId, Transaction t, List<Object> excludeDetailIds, boolean hard) {
String rawWhere = deriveWhereParentIdSql(false, "");
SpiEbeanServer server = descriptor.ebeanServer();
SpiQuery<?> q = many.newQuery(server);
many.bindParentIdEq(rawWhere, parentId, q);
if (hard) {
q.setIncludeSoftDeletes();
}
if (excludeDetailIds != null && !excludeDetailIds.isEmpty()) {
query.where().not(query.getExpressionFactory().idIn(excludeDetailIds));
q.where().not(q.getExpressionFactory().idIn(excludeDetailIds));
}
return server.findIds(query);
return server.findIds(q, t);
}
List<Object> findIdsByParentIdList(List<Object> parentIds, Transaction t, boolean includeSoftDeletes) {
final SpiEbeanServer server = descriptor.ebeanServer();
final SpiQuery<?> query = many.newQuery(server);
query.usingTransaction(t);
many.bindParentIdsIn(rawParentIdIN("", parentIds.size()), parentIds, query);
if (includeSoftDeletes) {
query.setIncludeSoftDeletes();
List<Object> findIdsByParentIdList(List<Object> parentIds, Transaction t, List<Object> excludeDetailIds, boolean hard) {
String rawWhere = deriveWhereParentIdSql(true, "");
String inClause = buildInClauseBinding(parentIds.size(), exportedPropertyBindProto);
String expr = rawWhere + inClause;
SpiEbeanServer server = descriptor.ebeanServer();
SpiQuery<?> q = many.newQuery(server);
//Query<?> q = server.find(propertyType);
many.bindParentIdsIn(expr, parentIds, q);
if (hard) {
q.setIncludeSoftDeletes();
}
return server.findIds(query);
if (excludeDetailIds != null && !excludeDetailIds.isEmpty()) {
q.where().not(q.getExpressionFactory().idIn(excludeDetailIds));
}
return server.findIds(q, t);
}
SpiSqlUpdate deleteByParentId(Object parentId) {
final var sqlDelete = new DefaultSqlUpdate(deleteByParentIdSql);
DefaultSqlUpdate sqlDelete = new DefaultSqlUpdate(deleteByParentIdSql);
many.bindParentId(sqlDelete, parentId);
return sqlDelete;
}
SpiSqlUpdate deleteByParentIdList(List<Object> parentIds) {
final String rawWhere = rawParentIdIN("", parentIds.size());
final String sql = Str.add(deleteByParentIdInSql, rawWhere);
final var delete = new DefaultSqlUpdate(sql);
String sql = Str.add(deleteByParentIdInSql, buildInClauseBinding(parentIds.size(), exportedPropertyBindProto));
DefaultSqlUpdate delete = new DefaultSqlUpdate(sql);
many.bindParentIds(delete, parentIds);
return delete;
}
@@ -167,109 +170,73 @@ class BeanPropertyAssocManySqlHelp<T> {
private void appendBind(StringBuilder sb, int count, boolean skipComma) {
for (int i = 0; i < count; i++) {
if (!skipComma || i > 0) {
sb.append(',');
sb.append(",");
}
sb.append('?');
sb.append("?");
}
}
private void append(StringBuilder sb) {
for (int i = 0; i < exportedProperties.length; i++) {
String fkColumn = exportedProperties[i].getForeignDbColumn();
if (i > 0) {
sb.append(',');
sb.append(",");
}
sb.append(exportedProperties[i].getForeignDbColumn());
sb.append(fkColumn);
}
}
private String rawParentIdIN(String tableAlias, int size) {
if (idInExpandedForm) {
return rawParentIdExpanded(tableAlias, size);
} else {
return rawParentIdStandard(tableAlias, size);
private String deriveWhereParentIdSql(boolean inClause, String tableAlias) {
StringBuilder sb = new StringBuilder();
if (inClause) {
sb.append("(");
}
}
private String rawParentIdStandard(String tableAlias, int size) {
if (descriptor.isSimpleId()) {
return rawParentIdMultiBinder(tableAlias, size);
}
final var sb = new StringBuilder(100 + size * exportedPropertyBindProto.length());
sb.append('(');
for (int i = 0; i < exportedProperties.length; i++) {
String fkColumn = exportedProperties[i].getForeignDbColumn();
if (i > 0) {
sb.append(',');
sb.append(inClause ? "," : " and ");
}
sb.append(tableAlias).append(fkColumn);
}
sb.append(") in (");
for (int i = 0; i < size; i++) {
if (i > 0) {
sb.append(',');
if (!inClause) {
sb.append("=? ");
}
sb.append(exportedPropertyBindProto);
}
sb.append(')');
return sb.toString();
}
/**
* Potentially a MultiValue binder like Postgres ANY Array binding.
*/
private String rawParentIdMultiBinder(String tableAlias, int size) {
final String property = '(' + tableAlias + exportedProperties[0].getForeignDbColumn() + ')';
final String inValueExpr = descriptor.idBinder().idInValueExpr(false, size);
return property + inValueExpr;
}
private String rawParentIdExpanded(String tableAlias, int size) {
final String proto = parentIdExpandedProto(tableAlias);
final var result = new StringBuilder(size * (proto.length() + 2) + 10).append('(');
for (int i = 0; i < size; i++) {
if (i > 0) {
result.append(" or ");
}
result.append(proto);
}
return result.append(')').toString();
}
private String parentIdExpandedProto(String tableAlias) {
final var sb = new StringBuilder(60).append('(');
for (int i = 0; i < exportedProperties.length; i++) {
if (i > 0) {
sb.append(" and ");
}
sb.append(tableAlias).append(exportedProperties[i].getForeignDbColumn()).append("=?");
}
return sb.append(')').toString();
}
private String rawParentIdEQ(String tableAlias) {
final var sb = new StringBuilder(80);
for (int i = 0; i < exportedProperties.length; i++) {
if (i > 0) {
sb.append(" and ");
}
sb.append(tableAlias).append(exportedProperties[i].getForeignDbColumn()).append("=?");
if (inClause) {
sb.append(")");
}
return sb.toString();
}
private String initExportedBindProto() {
private String buildInClauseBinding(int size, String bindProto) {
if (descriptor.isSimpleId()) {
return descriptor.idBinder().getIdInValueExpr(false, size);
}
StringBuilder sb = new StringBuilder(10 + (size * (bindProto.length() + 1)));
sb.append(" in");
sb.append(" (");
for (int i = 0; i < size; i++) {
if (i > 0) {
sb.append(",");
}
sb.append(bindProto);
}
sb.append(") ");
return sb.toString();
}
private String deriveExportedPropertyBindProto() {
if (exportedProperties.length == 1) {
return "?";
}
final var sb = new StringBuilder(exportedProperties.length * 2 + 2);
sb.append('(');
StringBuilder sb = new StringBuilder();
sb.append("(");
for (int i = 0; i < exportedProperties.length; i++) {
if (i > 0) {
sb.append(',');
sb.append(",");
}
sb.append('?');
sb.append("?");
}
sb.append(')');
sb.append(")");
return sb.toString();
}
@@ -237,49 +237,51 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
return encrypted ? elPlaceHolderEncrypted : elPlaceHolder;
}
public SqlUpdate deleteByParentId(Object parentId, List<Object> parentIdist) {
if (parentId != null) {
return deleteByParentId(parentId);
} else {
return deleteByParentIdList(parentIdist);
}
}
@Override
public SqlUpdate deleteByParentIdList(List<Object> parentIds) {
String sql = deleteByParentIdInSql + targetIdBinder.idInValueExpr(false, parentIds.size());
private SqlUpdate deleteByParentIdList(List<Object> parentIds) {
String sql = deleteByParentIdInSql + targetIdBinder.getIdInValueExpr(false, parentIds.size());
DefaultSqlUpdate delete = new DefaultSqlUpdate(sql);
bindParentIds(delete, parentIds);
return delete;
}
@Override
public SqlUpdate deleteByParentId(Object parentId) {
private SqlUpdate deleteByParentId(Object parentId) {
DefaultSqlUpdate delete = new DefaultSqlUpdate(deleteByParentIdSql);
bindParentId(delete, parentId);
return delete;
}
@Override
public List<Object> findIdsByParentId(Object parentId, Transaction t, boolean includeSoftDeletes) {
String rawWhere = deriveWhereParentIdSql(false);
SpiEbeanServer server = server();
SpiQuery<?> q = server.createQuery(type());
q.usingTransaction(t);
bindParentIdEq(rawWhere, parentId, q);
if (includeSoftDeletes) {
q.setIncludeSoftDeletes();
public List<Object> findIdsByParentId(Object parentId, List<Object> parentIds, Transaction t) {
if (parentId != null) {
return findIdsByParentId(parentId, t);
} else {
return findIdsByParentIdList(parentIds, t);
}
return server.findIds(q);
}
@Override
public List<Object> findIdsByParentIdList(List<Object> parentIds, Transaction t, boolean includeSoftDeletes) {
private List<Object> findIdsByParentId(Object parentId, Transaction t) {
String rawWhere = deriveWhereParentIdSql(false);
SpiEbeanServer server = server();
Query<?> q = server.find(type());
bindParentIdEq(rawWhere, parentId, q);
return server.findIds(q, t);
}
private List<Object> findIdsByParentIdList(List<Object> parentIds, Transaction t) {
String rawWhere = deriveWhereParentIdSql(true);
String inClause = idBinder().idInValueExpr(false, parentIds.size());
String inClause = idBinder().getIdInValueExpr(false, parentIds.size());
String expr = rawWhere + inClause;
SpiEbeanServer server = server();
SpiQuery<?> q = server.createQuery(type());
q.usingTransaction(t);
Query<?> q = server.find(type());
bindParentIdsIn(expr, parentIds, q);
if (includeSoftDeletes) {
q.setIncludeSoftDeletes();
}
return server.findIds(q);
return server.findIds(q, t);
}
void addFkey() {
@@ -485,7 +487,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
*/
@Override
public Object[] assocIdValues(EntityBean bean) {
return targetDescriptor.idBinder().values(bean);
return targetDescriptor.idBinder().getIdValues(bean);
}
/**
@@ -493,7 +495,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
*/
@Override
public String assocIdExpression(String prefix, String operator) {
return targetDescriptor.idBinder().assocExpr(prefix, operator);
return targetDescriptor.idBinder().getAssocOneIdExpr(prefix, operator);
}
/**
@@ -501,7 +503,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
*/
@Override
public String assocIdInValueExpr(boolean not, int size) {
return targetDescriptor.idBinder().idInValueExpr(not, size);
return targetDescriptor.idBinder().getIdInValueExpr(not, size);
}
/**
@@ -509,7 +511,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
*/
@Override
public String assocIdInExpr(String prefix) {
return targetDescriptor.idBinder().assocInExpr(prefix);
return targetDescriptor.idBinder().getAssocIdInExpr(prefix);
}
@Override
@@ -611,24 +613,12 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
}
}
/**
* Add table join with explicit table alias.
*/
@Override
public SqlJoinType addJoin(SqlJoinType joinType, String a1, String a2, DbSqlContext ctx) {
if (sqlFormulaJoin != null) {
ctx.appendFormulaJoin(sqlFormulaJoin, joinType, a1);
}
return super.addJoin(joinType, a1, a2, ctx);
}
@Override
public void appendFrom(DbSqlContext ctx, SqlJoinType joinType, String manyWhere) {
if (!isTransient && !primaryKeyExport) {
localHelp.appendFrom(ctx, joinType);
if (sqlFormulaJoin != null) {
String alias = ctx.tableAliasManyWhere(manyWhere);
ctx.appendFormulaJoin(sqlFormulaJoin, joinType, alias);
ctx.appendFormulaJoin(sqlFormulaJoin, joinType, manyWhere);
}
}
}
@@ -1,12 +1,12 @@
package io.ebeaninternal.server.deploy;
import io.ebean.Query;
import io.ebean.Transaction;
import io.ebean.bean.BeanCollection;
import io.ebean.bean.BeanCollectionAdd;
import io.ebean.bean.EntityBean;
import io.ebean.common.BeanSet;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.api.json.SpiJsonWriter;
import java.io.IOException;
@@ -72,6 +72,12 @@ public class BeanSetHelp<T> extends BaseCollectionHelp<T> {
return beanSet;
}
@Override
public final void refresh(SpiEbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
BeanSet<?> newBeanSet = (BeanSet<?>) server.findSet(query, t);
refresh(newBeanSet, parentBean);
}
@Override
public final void refresh(BeanCollection<?> bc, EntityBean parentBean) {
BeanSet<?> newBeanSet = (BeanSet<?>) bc;
@@ -0,0 +1,68 @@
package io.ebeaninternal.server.deploy;
import io.ebean.core.type.InputStreamInfo;
import java.nio.charset.StandardCharsets;
public interface BindMaxLength {
/**
* Return a UTF8 based implementation.
*/
static BindMaxLength ofUtf8() {
return new UTF8();
}
/**
* Return a standard implementation.
*/
static BindMaxLength ofStandard() {
return new Standard();
}
/**
* Return the length of the object.
*/
long length(int dbLength, Object obj);
final class UTF8 implements BindMaxLength {
@Override
public long length(int dbLength, Object obj) {
if (obj instanceof String) {
String s = (String) obj;
int stringLength = s.length();
if (stringLength > dbLength) {
return stringLength;
} else if (stringLength * 4 <= dbLength) {
return -1;
} else {
return s.getBytes(StandardCharsets.UTF_8).length;
}
} else if (obj instanceof byte[]) {
return ((byte[]) obj).length;
} else if (obj instanceof InputStreamInfo) {
return ((InputStreamInfo) obj).length();
} else {
return -1;
}
}
}
final class Standard implements BindMaxLength {
@Override
public long length(int dbLength, Object obj) {
if (obj instanceof String) {
return ((String) obj).length();
} else if (obj instanceof byte[]) {
return ((byte[]) obj).length;
} else if (obj instanceof InputStreamInfo) {
return ((InputStreamInfo) obj).length();
} else {
return -1;
}
}
}
}
@@ -73,7 +73,7 @@ public interface DbSqlContext {
* Append a Sql Formula join. This converts the "${ta}" keyword to the current
* table alias.
*/
void appendFormulaJoin(String sqlFormulaJoin, SqlJoinType joinType, String tableAlias);
void appendFormulaJoin(String sqlFormulaJoin, SqlJoinType joinType, String manyWhere);
/**
* Return the current content length.
@@ -72,7 +72,7 @@ final class DetermineAggPath {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < pos; i++) {
if (i > 0) {
sb.append('.');
sb.append(".");
}
sb.append(paths[i]);
}
@@ -52,7 +52,7 @@ final class ExportedProperty {
public void appendWhere(StringBuilder sb, String alias, String path) {
sb.append(alias).append(foreignDbColumn).append(" = ");
if (path != null) {
sb.append(path).append('.');
sb.append(path).append(".");
}
sb.append(property.name());
}
@@ -51,9 +51,9 @@ public final class IntersectionBuilder {
if (i > 0) {
sb.append(", ");
}
sb.append('?');
sb.append("?");
}
sb.append(')');
sb.append(")");
return sb.toString();
}
@@ -11,14 +11,13 @@ import io.ebeaninternal.server.persist.DeleteMode;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public final class IntersectionRow {
private final String tableName;
private final BeanDescriptor<?> targetDescriptor;
private final LinkedHashMap<String, Object> values = new LinkedHashMap<>();
private Set<Object> excludeIds;
private List<Object> excludeIds;
private BeanDescriptor<?> excludeDescriptor;
IntersectionRow(String tableName, BeanDescriptor<?> targetDescriptor) {
@@ -34,7 +33,7 @@ public final class IntersectionRow {
/**
* Set Id's to exclude. This is for deleting non-attached detail Id's.
*/
void setExcludeIds(Set<Object> excludeIds, BeanDescriptor<?> excludeDescriptor) {
void setExcludeIds(List<Object> excludeIds, BeanDescriptor<?> excludeDescriptor) {
this.excludeIds = excludeIds;
this.excludeDescriptor = excludeDescriptor;
}
@@ -60,9 +59,9 @@ public final class IntersectionRow {
if (i > 0) {
sb.append(", ");
}
sb.append('?');
sb.append("?");
}
sb.append(')');
sb.append(")");
return new DefaultSqlUpdate(server, sb.toString(), bindParams);
}
@@ -105,9 +105,9 @@ public final class TableJoin {
@Override
public String toString() {
StringBuilder sb = new StringBuilder(30);
sb.append(type).append(' ').append(table).append(' ');
sb.append(type).append(" ").append(table).append(" ");
for (TableJoinColumn column : columns) {
sb.append(column).append(' ');
sb.append(column).append(" ");
}
return sb.toString();
}
@@ -160,9 +160,9 @@ public final class TableJoin {
if (i > 0) {
sb.append(" and ");
}
sb.append(a1).append('.').append(pair.getLocalDbColumn());
sb.append(a1).append(".").append(pair.getLocalDbColumn());
sb.append(" = ");
sb.append(a2).append('.').append(pair.getForeignDbColumn());
sb.append(a2).append(".").append(pair.getForeignDbColumn());
}
}
@@ -26,8 +26,6 @@ public interface IdBinder {
*/
void initialise();
String idSelect();
/**
* Return true if this is a compound key and must use expanded and or form.
*/
@@ -43,10 +41,19 @@ public interface IdBinder {
*/
Object readData(DataInput dataInput) throws IOException;
/**
* Return the name(s) of the Id property(s). Comma delimited if there is more
* than one.
* <p>
* This can be used to include in a query.
* </p>
*/
String getIdProperty();
/**
* Return the Id BeanProperty.
*/
STreeProperty beanProperty();
STreeProperty getBeanProperty();
/**
* Find a BeanProperty that is mapped to the database column.
@@ -59,25 +66,13 @@ public interface IdBinder {
*/
boolean isComplexId();
/**
* Return the number of properties that make up the id.
*/
default int size() {
return 1;
}
/**
* Return the default order by that may need to be used if the query includes
* a many property.
*/
String orderBy();
String getDefaultOrderBy();
String orderBy(String pathPrefix, boolean ascending);
/**
* Return the id values for a given bean.
*/
Object[] values(EntityBean bean);
String getOrderBy(String pathPrefix, boolean ascending);
/**
* Return the values as an array of scalar bindable values.
@@ -89,7 +84,8 @@ public interface IdBinder {
* Added primarily for Query.addWhere().add(Expr.idEq()) support.
* </p>
*/
Object[] bindValues(Object idValue);
Object[] getBindValues(Object idValue);
/**
* For EmbeddedId convert the idValue into a simple map.
@@ -98,7 +94,7 @@ public interface IdBinder {
* This is used to provide a simple JSON serializable version of the id value.
* </p>
*/
Object convertForJson(EntityBean idValue);
Object getIdForJson(EntityBean idValue);
/**
* For EmbeddedId the value is assumed to be a Map and this is
@@ -110,7 +106,12 @@ public interface IdBinder {
* This is used to provide a simple JSON serializable version of the id value.
* </p>
*/
Object convertFromJson(Object value);
Object convertIdFromJson(Object value);
/**
* Return the id values for a given bean.
*/
Object[] getIdValues(EntityBean bean);
/**
* Build a string of the logical expressions.
@@ -118,12 +119,12 @@ public interface IdBinder {
* Typically used to build a id = ? string.
* </p>
*/
String assocExpr(String prefix, String operator);
String getAssocOneIdExpr(String prefix, String operator);
/**
* Return the logical id in expression taking into account embedded id's.
*/
String assocInExpr(String prefix);
String getAssocIdInExpr(String prefix);
/**
* Binds an id value to a prepared statement.
@@ -138,27 +139,27 @@ public interface IdBinder {
/**
* Binds multiple id value to an update.
*/
void addBindValues(DefaultSqlUpdate sqlUpdate, Collection<?> ids);
void addIdInBindValues(DefaultSqlUpdate sqlUpdate, Collection<?> ids);
/**
* Binds multiple id value to a request.
*/
void addBindValues(SpiExpressionRequest request, Collection<?> ids);
void addIdInBindValues(SpiExpressionRequest request, Collection<?> ids);
/**
* Return the sql for binding the id using an IN clause.
*/
String bindInSql(String baseTableAlias);
String getBindIdInSql(String baseTableAlias);
/**
* Return the binding expression (like "?" or "(?,?)")for the Id.
*/
String idInValueExpr(boolean not, int size);
String getIdInValueExpr(boolean not, int size);
/**
* Same as getIdInValueExpr but for delete by id.
*/
String idInValueExprDelete(int size);
String getIdInValueExprDelete(int size);
void buildRawSqlSelectChain(String prefix, List<String> selectChain);
@@ -187,7 +188,7 @@ public interface IdBinder {
* Return the sql for binding the id to. This includes table alias and columns
* that make up the id.
*/
String bindEqSql(String baseTableAlias);
String getBindIdSql(String baseTableAlias);
/**
* Cast or convert the Id value if necessary and optionally set it.
@@ -35,7 +35,7 @@ public final class IdBinderEmbedded implements IdBinder {
public IdBinderEmbedded(boolean idInExpandedForm, BeanPropertyAssocOne<?> embIdProperty) {
this.idInExpandedForm = idInExpandedForm;
this.embIdProperty = embIdProperty;
this.idClass = "_$IdClass$".equals(embIdProperty.name());
this.idClass = "_idClass".equals(embIdProperty.name());
}
@Override
@@ -45,50 +45,71 @@ public final class IdBinderEmbedded implements IdBinder {
this.idInValueSql = idInExpandedForm ? idInExpanded() : idInCompressed();
}
@Override
public String idSelect() {
return embIdProperty.name();
}
@Override
public boolean isIdInExpandedForm() {
return idInExpandedForm;
}
private String idInExpanded() {
final StringBuilder sb = new StringBuilder(30);
sb.append('(');
StringBuilder sb = new StringBuilder(30);
sb.append("(");
for (int i = 0; i < props.length; i++) {
if (i > 0) {
sb.append(" and ");
}
sb.append(idDesc.baseTableAlias()).append('.').append(props[i].dbColumn()).append("=?");
sb.append(idDesc.baseTableAlias()).append(".").append(props[i].dbColumn()).append("=?");
}
sb.append(')');
sb.append(")");
return sb.toString();
}
private String idInCompressed() {
final StringBuilder sb = new StringBuilder(props.length * 2 + 2).append('(');
StringBuilder sb = new StringBuilder(20).append("(");
for (int i = 0; i < props.length; i++) {
if (i > 0) {
sb.append(',');
sb.append(",");
}
sb.append('?');
sb.append("?");
}
sb.append(')');
sb.append(")");
return sb.toString();
}
@Override
public BeanProperty beanProperty() {
public BeanProperty getBeanProperty() {
return embIdProperty;
}
public BeanDescriptor<?> descriptor() {
@Override
public String getOrderBy(String pathPrefix, boolean ascending) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < props.length; i++) {
if (i > 0) {
sb.append(", ");
}
if (pathPrefix != null) {
sb.append(pathPrefix).append(".");
}
if (!idClass) {
sb.append(embIdProperty.name()).append(".");
}
sb.append(props[i].name());
if (!ascending) {
sb.append(" desc");
}
}
return sb.toString();
}
public BeanDescriptor<?> getIdBeanDescriptor() {
return idDesc;
}
@Override
public String getIdProperty() {
return embIdProperty.name();
}
@Override
public void buildRawSqlSelectChain(String prefix, List<String> selectChain) {
if (!idClass) {
@@ -115,73 +136,57 @@ public final class IdBinderEmbedded implements IdBinder {
}
@Override
public int size() {
return props.length;
}
@Override
public String orderBy() {
return orderBy(null, true);
}
@Override
public String orderBy(String pathPrefix, boolean ascending) {
final StringBuilder sb = new StringBuilder(100);
public String getDefaultOrderBy() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < props.length; i++) {
if (i > 0) {
sb.append(", ");
}
if (pathPrefix != null) {
sb.append(pathPrefix).append('.');
}
if (!idClass) {
sb.append(embIdProperty.name()).append('.');
sb.append(embIdProperty.name()).append(".");
}
sb.append(props[i].name());
if (!ascending) {
sb.append(" desc");
}
}
return sb.toString();
}
public BeanProperty[] properties() {
public BeanProperty[] getProperties() {
return props;
}
@Override
public String idInValueExprDelete(int size) {
public String getIdInValueExprDelete(int size) {
if (size <= 0) {
throw new IndexOutOfBoundsException("The size must be at least 1");
}
if (!idInExpandedForm) {
return idInValueExpr(false, size);
return getIdInValueExpr(false, size);
}
final StringBuilder sb = new StringBuilder(80);
sb.append('(');
StringBuilder sb = new StringBuilder();
sb.append("(");
for (int j = 0; j < size; j++) {
if (j > 0) {
sb.append(" or ");
}
sb.append('(');
sb.append("(");
for (int i = 0; i < props.length; i++) {
if (i > 0) {
sb.append(" and ");
}
sb.append(props[i].dbColumn()).append("=?");
}
sb.append(')');
sb.append(")");
}
sb.append(") ");
return sb.toString();
}
@Override
public String idInValueExpr(boolean not, int size) {
public String getIdInValueExpr(boolean not, int size) {
if (size <= 0) {
throw new IndexOutOfBoundsException("The size must be at least 1");
}
final StringBuilder sb = new StringBuilder(80);
StringBuilder sb = new StringBuilder();
if (not) {
sb.append(" not");
}
@@ -204,16 +209,20 @@ public final class IdBinderEmbedded implements IdBinder {
}
@Override
public Object[] values(EntityBean bean) {
return bindValues(embIdProperty.getValue(bean));
public Object[] getIdValues(EntityBean bean) {
Object val = embIdProperty.getValue(bean);
Object[] bindValues = new Object[props.length];
for (int i = 0; i < props.length; i++) {
bindValues[i] = props[i].getValue((EntityBean) val);
}
return bindValues;
}
@Override
public Object[] bindValues(Object value) {
final EntityBean bean = (EntityBean) value;
final Object[] bindValues = new Object[props.length];
public Object[] getBindValues(Object value) {
Object[] bindValues = new Object[props.length];
for (int i = 0; i < props.length; i++) {
bindValues[i] = props[i].getValue(bean);
bindValues[i] = props[i].getValue((EntityBean) value);
}
return bindValues;
}
@@ -222,9 +231,9 @@ public final class IdBinderEmbedded implements IdBinder {
* Convert from embedded bean to Map.
*/
@Override
public Object convertForJson(EntityBean bean) {
final EntityBean ebValue = (EntityBean) embIdProperty.getValue(bean);
final Map<String, Object> map = new LinkedHashMap<>();
public Object getIdForJson(EntityBean bean) {
EntityBean ebValue = (EntityBean) embIdProperty.getValue(bean);
Map<String, Object> map = new LinkedHashMap<>();
for (BeanProperty prop : props) {
map.put(prop.name(), prop.getValue(ebValue));
}
@@ -236,9 +245,9 @@ public final class IdBinderEmbedded implements IdBinder {
*/
@Override
@SuppressWarnings("unchecked")
public Object convertFromJson(Object value) {
final Map<String, Object> map = (Map<String, Object>) value;
final EntityBean idValue = idDesc.createEntityBean();
public Object convertIdFromJson(Object value) {
Map<String, Object> map = (Map<String, Object>) value;
EntityBean idValue = idDesc.createEntityBean();
for (BeanProperty prop : props) {
prop.setValue(idValue, map.get(prop.name()));
}
@@ -247,43 +256,42 @@ public final class IdBinderEmbedded implements IdBinder {
@Override
public void bindId(DefaultSqlUpdate sqlUpdate, Object value) {
final EntityBean bean = (EntityBean) value;
for (BeanProperty prop : props) {
sqlUpdate.setParameter(prop.getValue(bean));
Object embFieldValue = prop.getValue((EntityBean) value);
sqlUpdate.setParameter(embFieldValue);
}
}
@Override
public void bindId(DataBind dataBind, Object value) throws SQLException {
final EntityBean bean = (EntityBean) value;
for (BeanProperty prop : props) {
prop.bind(dataBind, prop.getValue(bean));
Object embFieldValue = prop.getValue((EntityBean) value);
prop.bind(dataBind, embFieldValue);
}
}
@Override
public void addBindValues(DefaultSqlUpdate sqlUpdate, Collection<?> values) {
public void addIdInBindValues(DefaultSqlUpdate sqlUpdate, Collection<?> values) {
for (Object value : values) {
bindId(sqlUpdate, value);
}
}
@Override
public void addBindValues(SpiExpressionRequest request, Collection<?> values) {
public void addIdInBindValues(SpiExpressionRequest request, Collection<?> values) {
for (Object value : values) {
final EntityBean bean = (EntityBean) value;
for (BeanProperty prop : props) {
request.addBindValue(prop.getValue(bean));
request.addBindValue(prop.getValue((EntityBean) value));
}
}
}
@Override
public Object readData(DataInput dataInput) throws IOException {
final EntityBean embId = idDesc.createEntityBean();
EntityBean embId = idDesc.createEntityBean();
boolean notNull = true;
for (BeanProperty prop : props) {
final Object value = prop.readData(dataInput);
Object value = prop.readData(dataInput);
prop.setValue(embId, value);
if (value == null) {
notNull = false;
@@ -294,9 +302,9 @@ public final class IdBinderEmbedded implements IdBinder {
@Override
public void writeData(DataOutput dataOutput, Object idValue) throws IOException {
final EntityBean bean = (EntityBean) idValue;
for (BeanProperty prop : props) {
prop.writeData(dataOutput, prop.getValue(bean));
Object embFieldValue = prop.getValue((EntityBean) idValue);
prop.writeData(dataOutput, embFieldValue);
}
}
@@ -309,10 +317,10 @@ public final class IdBinderEmbedded implements IdBinder {
@Override
public Object read(DbReadContext ctx) throws SQLException {
final EntityBean embId = idDesc.createEntityBean();
EntityBean embId = idDesc.createEntityBean();
boolean nullValue = true;
for (BeanProperty prop : props) {
final Object value = prop.read(ctx);
Object value = prop.read(ctx);
if (value != null) {
prop.setValue(embId, value);
nullValue = false;
@@ -340,34 +348,34 @@ public final class IdBinderEmbedded implements IdBinder {
}
@Override
public String assocInExpr(String prefix) {
final StringBuilder sb = new StringBuilder(80);
sb.append('(');
public String getAssocIdInExpr(String prefix) {
StringBuilder sb = new StringBuilder();
sb.append("(");
for (int i = 0; i < props.length; i++) {
if (i > 0) {
sb.append(", ");
}
if (prefix != null) {
sb.append(prefix).append('.');
sb.append(prefix).append(".");
}
sb.append(props[i].name());
}
sb.append(')');
sb.append(")");
return sb.toString();
}
@Override
public String assocExpr(String prefix, String operator) {
final StringBuilder sb = new StringBuilder(100);
public String getAssocOneIdExpr(String prefix, String operator) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < props.length; i++) {
if (i > 0) {
sb.append(" and ");
}
if (prefix != null) {
sb.append(prefix).append('.');
sb.append(prefix).append(".");
}
if (!idClass) {
sb.append(embIdProperty.name()).append('.');
sb.append(embIdProperty.name()).append(".");
}
sb.append(props[i].name()).append(operator);
}
@@ -375,14 +383,14 @@ public final class IdBinderEmbedded implements IdBinder {
}
@Override
public String bindEqSql(String baseTableAlias) {
final StringBuilder sb = new StringBuilder(80);
public String getBindIdSql(String baseTableAlias) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < props.length; i++) {
if (i > 0) {
sb.append(" and ");
}
if (baseTableAlias != null) {
sb.append(baseTableAlias).append('.');
sb.append(baseTableAlias).append(".");
}
sb.append(props[i].dbColumn()).append("=?");
}
@@ -390,22 +398,22 @@ public final class IdBinderEmbedded implements IdBinder {
}
@Override
public String bindInSql(String baseTableAlias) {
public String getBindIdInSql(String baseTableAlias) {
if (idInExpandedForm) {
return "";
}
final StringBuilder sb = new StringBuilder(80);
sb.append('(');
StringBuilder sb = new StringBuilder();
sb.append("(");
for (int i = 0; i < props.length; i++) {
if (i > 0) {
sb.append(',');
sb.append(",");
}
if (baseTableAlias != null) {
sb.append(baseTableAlias).append('.');
sb.append(baseTableAlias).append(".");
}
sb.append(props[i].dbColumn());
}
sb.append(')');
sb.append(")");
return sb.toString();
}
@@ -434,14 +442,14 @@ public final class IdBinderEmbedded implements IdBinder {
@Override
public String cacheKey(Object value) {
final EntityBean bean = (EntityBean)value;
final StringBuilder sb = new StringBuilder(80);
EntityBean bean = (EntityBean)value;
StringBuilder sb = new StringBuilder();
for (BeanProperty prop : props) {
Object val = prop.getValue(bean);
if (val != null) {
sb.append(prop.format(val));
}
sb.append('|');
sb.append("|");
}
return sb.toString();
}
@@ -2,11 +2,11 @@ package io.ebeaninternal.server.deploy.id;
import io.ebean.bean.EntityBean;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.server.bind.DataBind;
import io.ebeaninternal.server.core.DefaultSqlUpdate;
import io.ebeaninternal.server.deploy.BeanProperty;
import io.ebeaninternal.server.deploy.DbReadContext;
import io.ebeaninternal.server.deploy.DbSqlContext;
import io.ebeaninternal.server.bind.DataBind;
import java.io.DataInput;
import java.io.DataOutput;
@@ -27,18 +27,13 @@ final class IdBinderEmpty implements IdBinder {
public void initialise() {
}
@Override
public String idSelect() {
return "";
}
@Override
public boolean isIdInExpandedForm() {
return false;
}
@Override
public String orderBy(String pathPrefix, boolean ascending) {
public String getOrderBy(String pathPrefix, boolean ascending) {
return pathPrefix;
}
@@ -47,7 +42,12 @@ final class IdBinderEmpty implements IdBinder {
}
@Override
public BeanProperty beanProperty() {
public BeanProperty getBeanProperty() {
return null;
}
@Override
public String getIdProperty() {
return null;
}
@@ -62,58 +62,58 @@ final class IdBinderEmpty implements IdBinder {
}
@Override
public String orderBy() {
public String getDefaultOrderBy() {
// this should never happen?
return "";
}
@Override
public String bindEqSql(String baseTableAlias) {
public String getBindIdSql(String baseTableAlias) {
return bindIdSql;
}
@Override
public String assocExpr(String prefix, String operator) {
public String getAssocOneIdExpr(String prefix, String operator) {
return null;
}
@Override
public String assocInExpr(String prefix) {
public String getAssocIdInExpr(String prefix) {
return null;
}
@Override
public String idInValueExprDelete(int size) {
return idInValueExpr(false, size);
public String getIdInValueExprDelete(int size) {
return getIdInValueExpr(false, size);
}
@Override
public String idInValueExpr(boolean not, int size) {
public String getIdInValueExpr(boolean not, int size) {
return "";
}
@Override
public String bindInSql(String baseTableAlias) {
public String getBindIdInSql(String baseTableAlias) {
return null;
}
@Override
public Object[] values(EntityBean bean) {
public Object[] getIdValues(EntityBean bean) {
return null;
}
@Override
public Object[] bindValues(Object idValue) {
public Object[] getBindValues(Object idValue) {
return new Object[]{idValue};
}
@Override
public Object convertForJson(EntityBean bean) {
public Object getIdForJson(EntityBean bean) {
return null;
}
@Override
public Object convertFromJson(Object value) {
public Object convertIdFromJson(Object value) {
return value;
}
@@ -126,11 +126,11 @@ final class IdBinderEmpty implements IdBinder {
}
@Override
public void addBindValues(DefaultSqlUpdate sqlUpdate, Collection<?> ids) {
public void addIdInBindValues(DefaultSqlUpdate sqlUpdate, Collection<?> ids) {
}
@Override
public void addBindValues(SpiExpressionRequest request, Collection<?> ids) {
public void addIdInBindValues(SpiExpressionRequest request, Collection<?> ids) {
}
@Override
@@ -45,21 +45,16 @@ public final class IdBinderSimple implements IdBinder {
// do nothing
}
@Override
public String idSelect() {
return idProperty.name();
}
@Override
public boolean isIdInExpandedForm() {
return false;
}
@Override
public String orderBy(String pathPrefix, boolean ascending) {
public String getOrderBy(String pathPrefix, boolean ascending) {
StringBuilder sb = new StringBuilder();
if (pathPrefix != null) {
sb.append(pathPrefix).append('.');
sb.append(pathPrefix).append(".");
}
sb.append(idProperty.name());
if (!ascending) {
@@ -74,10 +69,15 @@ public final class IdBinderSimple implements IdBinder {
}
@Override
public BeanProperty beanProperty() {
public BeanProperty getBeanProperty() {
return idProperty;
}
@Override
public String getIdProperty() {
return idProperty.name();
}
@Override
public BeanProperty findBeanProperty(String dbColumnName) {
if (dbColumnName.equalsIgnoreCase(idProperty.dbColumn())) {
@@ -92,12 +92,12 @@ public final class IdBinderSimple implements IdBinder {
}
@Override
public String orderBy() {
public String getDefaultOrderBy() {
return idProperty.name();
}
@Override
public String bindInSql(String baseTableAlias) {
public String getBindIdInSql(String baseTableAlias) {
if (baseTableAlias == null) {
return idProperty.dbColumn();
} else {
@@ -106,7 +106,7 @@ public final class IdBinderSimple implements IdBinder {
}
@Override
public String bindEqSql(String baseTableAlias) {
public String getBindIdSql(String baseTableAlias) {
if (baseTableAlias == null) {
return bindIdSql;
} else {
@@ -115,22 +115,22 @@ public final class IdBinderSimple implements IdBinder {
}
@Override
public Object[] values(EntityBean bean) {
public Object[] getIdValues(EntityBean bean) {
return new Object[]{idProperty.getValue(bean)};
}
@Override
public Object[] bindValues(Object idValue) {
public Object[] getBindValues(Object idValue) {
return new Object[]{idValue};
}
@Override
public String idInValueExprDelete(int size) {
return idInValueExpr(false, size);
public String getIdInValueExprDelete(int size) {
return getIdInValueExpr(false, size);
}
@Override
public String idInValueExpr(boolean not, int size) {
public String getIdInValueExpr(boolean not, int size) {
if (size <= 0) {
throw new IndexOutOfBoundsException("The size must be at least 1");
}
@@ -138,24 +138,24 @@ public final class IdBinderSimple implements IdBinder {
}
@Override
public void addBindValues(DefaultSqlUpdate sqlUpdate, Collection<?> ids) {
public void addIdInBindValues(DefaultSqlUpdate sqlUpdate, Collection<?> ids) {
sqlUpdate.setParameter(new MultiValueWrapper(ids));
}
@Override
public void addBindValues(SpiExpressionRequest request, Collection<?> values) {
public void addIdInBindValues(SpiExpressionRequest request, Collection<?> values) {
List<Object> copy = new ArrayList<>(values);
copy.replaceAll(idValue -> convertSetId(idValue, null));
request.addBindValue(new MultiValueWrapper(copy));
}
@Override
public Object convertForJson(EntityBean bean) {
public Object getIdForJson(EntityBean bean) {
return idProperty.getValue(bean);
}
@Override
public Object convertFromJson(Object value) {
public Object convertIdFromJson(Object value) {
// handle simple type conversion if required
return convertId(value);
}
@@ -208,11 +208,11 @@ public final class IdBinderSimple implements IdBinder {
}
@Override
public String assocExpr(String prefix, String operator) {
StringBuilder sb = new StringBuilder(25);
public String getAssocOneIdExpr(String prefix, String operator) {
StringBuilder sb = new StringBuilder();
if (prefix != null) {
sb.append(prefix);
sb.append('.');
sb.append(".");
}
sb.append(idProperty.name());
sb.append(operator);
@@ -220,11 +220,11 @@ public final class IdBinderSimple implements IdBinder {
}
@Override
public String assocInExpr(String prefix) {
public String getAssocIdInExpr(String prefix) {
StringBuilder sb = new StringBuilder();
if (prefix != null) {
sb.append(prefix);
sb.append('.');
sb.append(".");
}
sb.append(idProperty.name());
return sb.toString();
@@ -139,6 +139,10 @@ public class DeployBeanDescriptor<T> {
this.beanType = beanType;
}
public BindMaxLength bindMaxLength() {
return manager.bindMaxLength();
}
/**
* Set the IdClass to use.
*/
@@ -654,7 +658,7 @@ public class DeployBeanDescriptor<T> {
public void postAnnotations() {
if (idClass != null) {
idClassProperty = new DeployBeanPropertyAssocOne<>(this, idClass);
idClassProperty.setName("_$IdClass$");
idClassProperty.setName("_idClass");
idClassProperty.setEmbedded();
idClassProperty.setNullable(false);
}
@@ -809,7 +813,7 @@ public class DeployBeanDescriptor<T> {
for (DeployBeanProperty prop : propMap.values()) {
if (!prop.isTransient() && !(prop instanceof DeployBeanPropertyAssocMany<?>)) {
if (prop.isFetchEager()) {
sb.append(prop.getName()).append(',');
sb.append(prop.getName()).append(",");
} else {
hasLazyFetch = true;
}

Some files were not shown because too many files have changed in this diff Show More