Compare commits

..
2621 changed files with 26183 additions and 40549 deletions
+5 -8
View File
@@ -1,10 +1,7 @@
name: Build
on:
pull_request:
push:
branches: master
on: [push, pull_request]
jobs:
build:
@@ -20,14 +17,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v2
with:
java-version: ${{ matrix.java_version }}
distribution: 'zulu'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v2
env:
cache-name: maven-cache
with:
@@ -39,5 +36,5 @@ jobs:
# - name: Maven single test
# run: mvn --batch-mode clean verify -Dtest="io.ebeaninternal.server.core.DefaultServer_getReferenceTest" -DfailIfNoTests=false
- name: Build with Maven
run: mvn -T 8 clean test
run: mvn clean package
+4 -4
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v2
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v2
env:
cache-name: maven-cache
with:
@@ -35,4 +35,4 @@ jobs:
~/.m2
key: build-${{ env.cache-name }}
- name: db2
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-db2.properties
run: mvn clean test -Dprops.file=testconfig/ebean-db2.properties
+4 -4
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v2
with:
java-version: ${{ matrix.java_version }}
distribution: 'zulu'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v2
env:
cache-name: maven-cache
with:
@@ -37,5 +37,5 @@ jobs:
- name: Maven version
run: mvn --version
- name: H2Database
run: mvn -T 8 clean package
run: mvn clean package
+39
View File
@@ -0,0 +1,39 @@
name: JDK 18-ea
on:
workflow_dispatch:
schedule:
- cron: '30 6 * * 1,3,5'
jobs:
build:
runs-on: ${{ matrix.os }}
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
java_version: [18-ea]
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v2
- name: Set up Java
uses: actions/setup-java@v2
with:
java-version: ${{ matrix.java_version }}
distribution: 'zulu'
- name: Maven cache
uses: actions/cache@v2
env:
cache-name: maven-cache
with:
path:
~/.m2
key: build-${{ env.cache-name }}
- name: Build with Maven
run: mvn package
+6 -4
View File
@@ -16,18 +16,20 @@ jobs:
strategy:
fail-fast: false
matrix:
java_version: [GA,EA]
## valhalla - failing on javadoc with:
## javadoc: error - The code being documented uses packages in the unnamed module, but the packages defined in https://ebean.io/platforms/ebean-platform-h2/apidocs/ are in named modules.
java_version: [GA,EA,loom,metropolis,panama]
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
- name: Set up Java
uses: oracle-actions/setup-java@v1
with:
website: jdk.java.net
release: ${{ matrix.java_version }}
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v2
env:
cache-name: maven-cache
with:
@@ -37,5 +39,5 @@ jobs:
- name: Maven version
run: mvn --version
- name: Build with Maven
run: mvn -T 8 test
run: mvn package
+4 -4
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v2
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v2
env:
cache-name: maven-cache
with:
@@ -35,4 +35,4 @@ jobs:
~/.m2
key: build-${{ env.cache-name }}
- name: mariadb 10.6
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-mariadb.properties
run: mvn clean test -Dprops.file=testconfig/ebean-mariadb.properties
+3 -3
View File
@@ -17,14 +17,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v2
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v2
env:
cache-name: maven-cache
with:
+4 -6
View File
@@ -16,26 +16,24 @@ jobs:
strategy:
fail-fast: false
matrix:
java_version: [11, 17, 21]
java_version: [11, 17]
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v2
with:
java-version: ${{ matrix.java_version }}
distribution: 'zulu'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v2
env:
cache-name: maven-cache
with:
path:
~/.m2
key: build-${{ env.cache-name }}
- name: Maven version
run: mvn --version
- name: Build with Maven
run: mvn package
+4 -4
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v2
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v2
env:
cache-name: maven-cache
with:
@@ -35,4 +35,4 @@ jobs:
~/.m2
key: build-${{ env.cache-name }}
- name: mysql
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-mysql.properties
run: mvn clean test -Dprops.file=testconfig/ebean-mysql.properties
@@ -1,5 +1,5 @@
name: Oracle
name: Oracle18
on:
workflow_dispatch:
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v2
with:
java-version: ${{ matrix.java_version }}
distribution: 'zulu'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v2
env:
cache-name: maven-cache
with:
@@ -35,4 +35,4 @@ jobs:
~/.m2
key: build-${{ env.cache-name }}
- name: oracle
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-oracle.properties
run: mvn clean test -Dprops.file=testconfig/ebean-oracle.properties
+4 -4
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v2
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v2
env:
cache-name: maven-cache
with:
@@ -35,4 +35,4 @@ jobs:
~/.m2
key: build-${{ env.cache-name }}
- name: postgres
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-postgres.properties
run: mvn clean test -Dprops.file=testconfig/ebean-postgres.properties
+3 -3
View File
@@ -17,14 +17,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v2
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v2
env:
cache-name: maven-cache
with:
+4 -4
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v2
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v2
env:
cache-name: maven-cache
with:
@@ -35,4 +35,4 @@ jobs:
~/.m2
key: build-${{ env.cache-name }}
- name: sqlserver 2017
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-sqlserver17.properties
run: mvn clean test -Dprops.file=testconfig/ebean-sqlserver17.properties
+3 -3
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v2
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v2
env:
cache-name: maven-cache
with:
-1
View File
@@ -11,7 +11,6 @@ ebean-profiling*.xml
/db
/mydb.db
profiling/
.DS_Store
# Intellij project files
*.iml
+12 -11
View File
@@ -4,13 +4,13 @@ Overview of ebean.properties file
### DbMigration options
You can set individual values for different platforms when generating migrations.
You can set individual values for different platforms when generating migrations
`dbmigration.platform.<PLATFORM>.databaseSequenceBatchSize`
For DB's using sequences this is the number of sequence values prefetched.
`dbmigration.platform.<PLATFORM>.dbuuid`
Control, how UUID generation should work - it affects which column type is generated in DDL. Possible values:
Control, how UUID generation should work - it affects DDL which column type is generated. Possible values:
- BINARY enforces binary UUID
- VARCHAR enforces varchar UUID
- BINARY_OPTIMIZED enforces binary-optimized UUID (makes sense only with Type1 ID)
@@ -19,7 +19,7 @@ Control, how UUID generation should work - it affects which column type is gener
- AUTO_VARCHAR (default) use varchar when platform does not support UUID
`dbmigration.platform.<PLATFORM>.uuidStoreAsBinary`
Same as setting dbuuid to BINARY.
Same as setting dbuuid to BINARY
`dbmigration.platform.<PLATFORM>.geometrySRID`
The Geometry SRID value (default 4326).
@@ -30,6 +30,7 @@ The ID type (IDENTITY, SEQUENCE, GENERATOR, EXTERNAL)
`dbmigration.platform.<PLATFORM>.mapping`
Adjust the mapping. For example `BOOLEAN=integer(32);BIT=tinyint(3)`
`ebean.migration.applyPrefix`
Set this to "V" to be compatible with FlywayDB.
@@ -49,7 +50,7 @@ Set to true if the DB migration should be generated on server start.
The version of a pending drop that should be generated as the next migration.
`ebean.migration.includeGeneratedFileComment`
Adds the header about the migration files being generated when true. Reading 'THIS IS A GENERATED FILE - DO NOT MODIFY'
TODO
`ebean.migration.metaTable`
For running migration the DB table that holds migration execution status. Default 'db_migration'
@@ -64,17 +65,17 @@ Subdirectory the model xml files go into. Default 'model'
Suffix. Default '.model.xml'
`ebean.migration.name`
Description text that can be appended to the version to become the ddl script file name.
Description text that can be appended to the version to become the ddl script file name
`ebean.migration.patchInsertOn`
Migration versions that should be added to history without running.
migration versions that should be added to history without running.
`ebean.migration.patchResetChecksumOn`
migration versions that should have their checksum reset and not run.
Use this if you get a 'Checksum mismatch' error.
`ebean.migration.placeholders`
A comma and equals delimited map of placeholders that are substituted in SQL scripts when running migration (used by DB Migration runner only).
A comma and equals delimited placeholders that are substituted in SQL scripts when running migration (used by DB Migration runner only).
`ebean.migration.platform`
The database platform to generate migration DDL for.
@@ -89,7 +90,7 @@ The migration version name (typically FlywayDb compatible). Example: 1.1.1_2
### Ebean UUID options
`ebean.uuidVersion`
Controls how the UUIDs are generated. Possible values:
Controls, how the UUIDs are generated. Possible values
- VERSION4 (default) generate random V4 UUIDs,
- VERSION1 generate rfc4122 compliant Type 1 UUIDs (requires a state file)
- VERSION1RND generate fake Type 1 UUIDs
@@ -97,7 +98,7 @@ Controls how the UUIDs are generated. Possible values:
Note, that V1 UUIDs in conjunction with AUTO_BINARY_OPTIMIZED will give you the best index performance, but you MUST understand how this works to avoid collisions.
`ebean.uuidStateFile`
The state file that is required to generate V1 UUIDs.
The state file that is Required to generate V1 UUIDs
### DocStoreConfig
@@ -106,7 +107,7 @@ The state file that is required to generate V1 UUIDs.
True when the Document store integration is active/on.
`ebean.docstore.allowAllCertificates`
Set to true such that the client allows connections to invalid/self-signed SSL certificates.
Set to true such that the client allows connections to invalid/self signed SSL certificates.
`ebean.docstore.bulkBatchSize`
The default batch size to use for the Bulk API calls.
@@ -191,7 +192,7 @@ Suffix appended to the base table to derive the view that contains the union of
Set to true if the DataSource uses autoCommit. Indicates that Ebean should use autoCommit friendly Transactions and TransactionManager.
`ebean.autoReadOnlyDataSource`
When true create a read only DataSource using readOnlyDataSourceConfig defaulting values from dataSourceConfig.
When true create a read only DataSource using readOnlyDataSourceConfig defaulting values from dataSourceConfig
`ebean.autostart`
Should the server start all
+6 -37
View File
@@ -1,55 +1,26 @@
[![Build](https://github.com/ebean-orm/ebean/actions/workflows/build.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/build.yml)
[![Maven Central : ebean](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/ebean-orm/ebean/blob/master/LICENSE)
[![Multi-JDK Build](https://github.com/ebean-orm/ebean/actions/workflows/multi-jdk-build.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/multi-jdk-build.yml)
[![JDK 18-ea](https://github.com/ebean-orm/ebean/actions/workflows/jdk-18-ea.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/jdk-18-ea.yml)
##### Build with database platforms
[![H2Database](https://github.com/ebean-orm/ebean/actions/workflows/h2database.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/h2database.yml)
[![Postgres](https://github.com/ebean-orm/ebean/actions/workflows/postgres.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/postgres.yml)
[![MySql](https://github.com/ebean-orm/ebean/actions/workflows/mysql.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/mysql.yml)
[![MariaDB](https://github.com/ebean-orm/ebean/actions/workflows/mariadb.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/mariadb.yml)
[![Oracle](https://github.com/ebean-orm/ebean/actions/workflows/oracle.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/oracle.yml)
[![SqlServer](https://github.com/ebean-orm/ebean/actions/workflows/sqlserver.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/sqlserver.yml)
[![DB2 LUW](https://github.com/ebean-orm/ebean/actions/workflows/db2luw.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/db2luw.yml)
[![Yugabyte](https://github.com/ebean-orm/ebean/actions/workflows/yugabyte.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/yugabyte.yml)
##### Build with Java Early Access versions
#### Builds against EA (Early Access) versions of Java (19, Loom, panama etc)
[![ebean EA](https://github.com/ebean-orm/ebean/actions/workflows/jdk-ea.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/jdk-ea.yml)
[![datasource EA](https://github.com/ebean-orm/ebean-datasource/actions/workflows/jdk-ea.yml/badge.svg)](https://github.com/ebean-orm/ebean-datasource/actions/workflows/jdk-ea.yml)
[![migration EA](https://github.com/ebean-orm/ebean-migration/actions/workflows/jdk-ea.yml/badge.svg)](https://github.com/ebean-orm/ebean-migration/actions/workflows/jdk-ea.yml)
[![test-docker EA](https://github.com/ebean-orm/ebean-test-docker/actions/workflows/jdk-ea.yml/badge.svg)](https://github.com/ebean-orm/ebean-test-docker/actions/workflows/jdk-ea.yml)
[![ebean-agent EA](https://github.com/ebean-orm/ebean-agent/actions/workflows/jdk-ea.yml/badge.svg)](https://github.com/ebean-orm/ebean-agent/actions/workflows/jdk-ea.yml)
----------------------
# Ebean ORM for Java & Kotlin
**Multiple abstraction levels**: Ebean provides multiple levels of query abstraction [ORM Queries, mixed with SQL](https://ebean.io/docs/intro/queries/orm-query), [DTO Queries](https://ebean.io/docs/intro/queries/dto-query), [SqlQuery and JDBC](https://ebean.io/docs/intro/queries/sql-query).
Work at the highest level of abstraction and drop down levels as needed.
**Database migrations**: Built in [DB migration](https://ebean.io/docs/db-migrations/) generation and running. Support for "rebase" migrations as well as repeatable, init and 'normal' migrations.
**Awesome SQL**: Ebean produces SQL that you would hand craft yourself. Use great SQL, never generate SQL cartesian product, always honor relational limit/offset.
**Automated query tuning**: For ORM queries Ebean can profile the object graph being used and either [automatically tune the query](https://ebean.io/docs/query/background/autotune).
**Docker test containers**: [Docker test containers](https://ebean.io/docs/testing/) for all the supported databases. Get 100% test coverage on all the features of the database we use.
**Type safe queries**: We can build queries using type safe [query beans](https://ebean.io/docs/query/query-beans). IDE auto-complete when writing queries, compile time checking and it's FUN.
**Performance isn't optional**: Optimise queries to only fetch what we need (partial objects). Automatically avoid N+1 via a smart load context.
#### Benefits of ORM
* Automatically avoid N+1
* L2 caching to reduce database load
* Queries mixing database and L2 cache
* Automatically tune ORM queries
* Elasticsearch for search or L3 cache
----------------------
# Sponsors
<table>
<tbody>
@@ -79,14 +50,13 @@ Work at the highest level of abstraction and drop down levels as needed.
</table>
## Need help?
Post questions or issues to the [Ebean google group](https://groups.google.com/forum/#!forum/ebean)
or [github discussions](https://github.com/ebean-orm/ebean/discussions)
Post questions or issues to the Ebean google group - https://groups.google.com/forum/#!forum/ebean
## Documentation
Goto [https://ebean.io/docs/](https://ebean.io/docs/)
## Maven central
[Maven central - g:io.ebean](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22io.ebean%22%20)
[Maven central - io.ebean](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22io.ebean%22%20)
## Building Ebean from source
@@ -120,4 +90,3 @@ To set this option as the global default for IntelliJ use:
`Run - Edit Configurations -> Edit configuration templates -> JUnit -> modify options - Do not use module-path option`
end
+6 -13
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>14.0.2</version>
<relativePath>../..</relativePath>
<version>13.6.2-SNAPSHOT</version>
</parent>
<name>ebean-clickhouse</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
@@ -32,23 +31,17 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-clickhouse</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -13
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>14.0.2</version>
<relativePath>../..</relativePath>
<version>13.6.2-SNAPSHOT</version>
</parent>
<name>ebean-cockroach</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
@@ -32,23 +31,17 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -13
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>14.0.2</version>
<relativePath>../..</relativePath>
<version>13.6.2-SNAPSHOT</version>
</parent>
<name>ebean-db2</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
@@ -32,23 +31,17 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-db2</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -13
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>14.0.2</version>
<relativePath>../..</relativePath>
<version>13.6.2-SNAPSHOT</version>
</parent>
<name>ebean-h2</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
@@ -32,23 +31,17 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -13
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>14.0.2</version>
<relativePath>../..</relativePath>
<version>13.6.2-SNAPSHOT</version>
</parent>
<name>ebean-hana</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
@@ -32,23 +31,17 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-hana</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -13
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>14.0.2</version>
<relativePath>../..</relativePath>
<version>13.6.2-SNAPSHOT</version>
</parent>
<name>ebean-mariadb</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
@@ -32,23 +31,17 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mariadb</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -13
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>14.0.2</version>
<relativePath>../..</relativePath>
<version>13.6.2-SNAPSHOT</version>
</parent>
<name>ebean-mysql</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
@@ -32,23 +31,17 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mysql</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -13
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>14.0.2</version>
<relativePath>../..</relativePath>
<version>13.6.2-SNAPSHOT</version>
</parent>
<name>ebean-nuodb</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
@@ -32,23 +31,17 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-nuodb</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -13
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>14.0.2</version>
<relativePath>../..</relativePath>
<version>13.6.2-SNAPSHOT</version>
</parent>
<name>ebean-oracle</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
@@ -32,23 +31,17 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-oracle</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
</dependencies>
-85
View File
@@ -1,85 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.0.2</version>
<relativePath>../..</relativePath>
</parent>
<name>ebean-postgis</name>
<description>ebean-postgis composite</description>
<artifactId>ebean-postgis</artifactId>
<properties>
<postgis.jdbc.version>2.5.1</postgis.jdbc.version>
<postgres.jdbc.version>42.7.2</postgres.jdbc.version>
</properties>
<dependencies>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-datasource</artifactId>
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.0.2</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgis-types</artifactId>
<version>14.0.2</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgres.jdbc.version}</version>
<exclusions>
<!-- exclude unnecessary checker framework -->
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.postgis</groupId>
<artifactId>postgis-jdbc</artifactId>
<version>${postgis.jdbc.version}</version>
</dependency>
</dependencies>
</project>
@@ -1,7 +0,0 @@
package io.ebean.postgis.assembly;
/**
* Nothing interesting here - required placeholder for javadoc.
*/
public class Assembly {
}
@@ -1,10 +0,0 @@
module io.ebean.postgis {
requires transitive io.ebean.api;
requires transitive io.ebean.core;
requires transitive io.ebean.datasource;
requires transitive io.ebean.querybean;
requires transitive io.ebean.platform.postgres;
// requires transitive io.ebean.postgis.types;
}
+6 -13
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>14.0.2</version>
<relativePath>../..</relativePath>
<version>13.6.2-SNAPSHOT</version>
</parent>
<name>ebean-postgres</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
@@ -32,23 +31,17 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -13
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>14.0.2</version>
<relativePath>../..</relativePath>
<version>13.6.2-SNAPSHOT</version>
</parent>
<name>ebean-sqlite</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
@@ -32,23 +31,17 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlite</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -13
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>14.0.2</version>
<relativePath>../..</relativePath>
<version>13.6.2-SNAPSHOT</version>
</parent>
<name>ebean-sqlserver</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
@@ -32,23 +31,17 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlserver</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -13
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>14.0.2</version>
<relativePath>../..</relativePath>
<version>13.6.2-SNAPSHOT</version>
</parent>
<name>ebean-yugabyte</name>
@@ -17,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
@@ -32,23 +31,17 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
</dependencies>
+6 -31
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>14.0.2</version>
<relativePath>../..</relativePath>
<version>13.6.2-SNAPSHOT</version>
</parent>
<name>ebean (all platforms)</name>
@@ -17,31 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-joda-time</artifactId>
<version>14.0.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jackson-jsonnode</artifactId>
<version>14.0.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jackson-mapper</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
@@ -50,23 +31,17 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-all</artifactId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</dependency>
</dependencies>
+1 -2
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</parent>
<artifactId>composites</artifactId>
@@ -23,7 +23,6 @@
<module>ebean-nuodb</module>
<module>ebean-oracle</module>
<module>ebean-postgres</module>
<module>ebean-postgis</module>
<!-- <module>sqlanywhere</module>-->
<module>ebean-sqlite</module>
<module>ebean-sqlserver</module>
+28 -53
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.0.2</version>
<version>13.6.2-SNAPSHOT</version>
</parent>
<name>ebean api</name>
@@ -13,17 +13,21 @@
<dependencies>
<!--
Projects are expected to explicit depend on version
of slf4j that they want to use
-->
<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-applog</artifactId>
<version>1.0</version>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
<scope>provided</scope>
</dependency>
<!-- exclude avaje-applog-slf4j to direct logging to something else -->
<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-applog-slf4j</artifactId>
<version>1.0</version>
<artifactId>avaje-config</artifactId>
<version>2.0</version>
</dependency>
<!--
@@ -33,31 +37,25 @@
<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-lang</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-config</artifactId>
<version>3.12</version>
<version>1.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>jakarta-persistence-api</artifactId>
<version>${ebean-persistence-api.version}</version>
<artifactId>persistence-api</artifactId>
<version>2.2.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-annotation</artifactId>
<version>${ebean-annotation.version}</version>
<version>8.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-types</artifactId>
<version>${ebean-types.version}</version>
<version>2.2</version>
</dependency>
<dependency>
@@ -66,14 +64,6 @@
<version>${ebean-datasource.version}</version>
</dependency>
<!-- Support MdcBackgroundExecutorWrapper -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
<optional>true</optional>
</dependency>
<!-- Jackson core used internally by Ebean -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
@@ -90,42 +80,27 @@
<optional>true</optional>
</dependency>
<!-- JAVAX-DEPENDENCY-START ___
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<optional>true</optional>
</dependency>
____ JAVAX-DEPENDENCY-END -->
<!-- JAKARTA-DEPENDENCY-START -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<optional>true</optional>
<groupId>io.avaje</groupId>
<artifactId>junit</artifactId>
<version>1.1</version>
<scope>test</scope>
</dependency>
<!-- JAKARTA-DEPENDENCY-END -->
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/ebean-maven-version.txt</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<excludes>
<exclude>**/ebean-maven-version.txt</exclude>
</excludes>
</resource>
</resources>
</build>
</project>
@@ -1,6 +1,6 @@
package io.ebean;
import jakarta.persistence.PessimisticLockException;
import javax.persistence.PessimisticLockException;
/**
* Thrown when failing to acquire a pessimistic lock.
@@ -12,7 +12,6 @@ import java.util.Optional;
* </p>
* <pre>{@code
*
* @Component
* public class CustomerFinder extends BeanFinder<Long,Customer> {
*
* @Inject
@@ -27,31 +26,29 @@ import java.util.Optional;
*
* @param <I> The ID type
* @param <T> The Bean type
*
* @see BeanRepository
*/
@NonNullApi
public abstract class BeanFinder<I,T> {
protected final Database database;
protected final Database server;
protected final Class<T> type;
/**
* Create with the given bean type and Database instance.
*
* @param type The bean type
* @param database The Database instance typically created via Spring factory or equivalent.
* @param server The Database instance typically created via Spring factory or equivalent.
*/
protected BeanFinder(Class<T> type, Database database) {
protected BeanFinder(Class<T> type, Database server) {
this.type = type;
this.database = database;
this.server = server;
}
/**
* Return the Database to use.
*/
public Database db() {
return database;
return server;
}
/**
@@ -73,10 +70,10 @@ public abstract class BeanFinder<I,T> {
* <p>
* This is equivalent to {@link DB#byName(String)}
*
* @param name The name of the Database. If this is null then the default Database is returned.
* @param server The name of the Database. If this is null then the default Database is returned.
*/
public Database db(String name) {
return DB.byName(name);
public Database db(String server) {
return DB.byName(server);
}
/**
@@ -6,15 +6,11 @@ import io.ebean.bean.EntityBean;
import java.util.Collection;
/**
* Provides find and persist functionality for use with "Dependency Injection style" use of Ebean.
* Provides finder functionality for use with "Dependency Injection style" use of Ebean.
* <p>
* Extend the BeanRepository with additional finder and persisting methods as needed by the
* application. The intention is to keep all the related logic together, for example, all the
* persisting and finding logic for Customer would be in CustomerRepository.
*
* <pre>{@code
*
* @Component
* @Repository
* public class CustomerRepository extends BeanRepository<Long,Customer> {
*
* @Inject
@@ -54,10 +50,10 @@ public abstract class BeanRepository<I, T> extends BeanFinder<I, T> {
* }</pre>
*
* @param type The bean type
* @param database The Database instance typically created via Spring factory or equivalent
* @param server The Database instance typically created via Spring factory or equivalent
*/
protected BeanRepository(Class<T> type, Database database) {
super(type, database);
protected BeanRepository(Class<T> type, Database server) {
super(type, server);
}
/**
@@ -126,8 +122,8 @@ public abstract class BeanRepository<I, T> extends BeanFinder<I, T> {
/**
* Save all the beans in the collection.
*/
public int saveAll(Collection<T> beans) {
return db().saveAll(beans);
public int saveAll(Collection<T> bean) {
return db().saveAll(bean);
}
/**
+57 -7
View File
@@ -5,10 +5,11 @@ import io.avaje.lang.Nullable;
import io.ebean.annotation.TxIsolation;
import io.ebean.cache.ServerCacheManager;
import io.ebean.plugin.Property;
import io.ebean.text.csv.CsvReader;
import io.ebean.text.json.JsonContext;
import jakarta.persistence.OptimisticLockException;
import jakarta.persistence.PersistenceException;
import javax.persistence.OptimisticLockException;
import javax.persistence.PersistenceException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -237,7 +238,7 @@ public final class DB {
}
/**
* The batch will be flushing automatically but, you can use this to explicitly
* The batch will be flushing automatically but you can use this to explicitly
* flush the batch if you like.
* <p>
* Flushing occurs automatically when:
@@ -266,6 +267,49 @@ public final class DB {
getDefault().register(transactionCallback);
}
/**
* Commit the current transaction.
*/
public static void commitTransaction() {
getDefault().commitTransaction();
}
/**
* Rollback the current transaction.
*/
public static void rollbackTransaction() {
getDefault().rollbackTransaction();
}
/**
* If the current transaction has already been committed do nothing otherwise
* rollback the transaction.
* <p>
* It is preferable to use <em>try with resources</em> rather than this.
* <p>
* Useful to put in a finally block to ensure the transaction is ended, rather
* than a rollbackTransaction() in each catch block.
* <p>
* Code example:
*
* <pre>{@code
* DB.beginTransaction();
* try {
* // do some fetching and or persisting
*
* // commit at the end
* DB.commitTransaction();
*
* } finally {
* // if commit didn't occur then rollback the transaction
* DB.endTransaction();
* }
* }</pre>
*/
public static void endTransaction() {
getDefault().endTransaction();
}
/**
* Mark the current transaction as rollback only.
*/
@@ -741,6 +785,12 @@ public final class DB {
return getDefault().createUpdate(beanType, ormUpdate);
}
/**
* Create a CsvReader for a given beanType.
*/
public static <T> CsvReader<T> createCsvReader(Class<T> beanType) {
return getDefault().createCsvReader(beanType);
}
/**
* Create a named query.
@@ -911,7 +961,7 @@ public final class DB {
*
* DB.execute(scope, new TxRunnable() {
* public void run() {
* User u1 = DB.find(User.class, 1);
* User u1 = DB.find(User.class, 1);
* ...
* }
* });
@@ -960,9 +1010,9 @@ public final class DB {
*
* DB.executeCall(scope, new Callable<String>() {
* public String call() {
* User u1 = DB.find(User.class, 1);
* ...
* return u1.getEmail();
* User u1 = DB.find(User.class, 1);
* ...
* return u1.getEmail();
* }
* });
* }</pre>
@@ -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);
}
}
@@ -1,104 +0,0 @@
package io.ebean;
final class DInsertOptionsBuilder implements InsertOptions.Builder {
private Boolean getGeneratedKeys;
private boolean onConflictUpdate;
private boolean onConflictNothing;
private String constraint;
private String uniqueColumns;
private String updateSet;
@Override
public InsertOptions.Builder onConflictNothing() {
this.onConflictNothing = true;
return this;
}
@Override
public InsertOptions.Builder onConflictUpdate() {
this.onConflictUpdate = true;
return this;
}
@Override
public InsertOptions.Builder constraint(String constraint) {
this.constraint = constraint;
return this;
}
@Override
public InsertOptions.Builder uniqueColumns(String uniqueColumns) {
this.uniqueColumns = uniqueColumns;
return this;
}
@Override
public InsertOptions.Builder updateSet(String updateSet) {
this.updateSet = updateSet;
return this;
}
@Override
public InsertOptions.Builder getGeneratedKeys(boolean getGeneratedKeys) {
this.getGeneratedKeys = getGeneratedKeys;
return this;
}
@Override
public InsertOptions build() {
return new Options(constraint, uniqueColumns, updateSet, onConflictUpdate, onConflictNothing, getGeneratedKeys);
}
static final class Options implements InsertOptions {
private static final String UPDATE = "U";
private static final String NOTHING = "N";
private static final String NORMAL = "_";
private final String key;
private final Boolean getGeneratedKeys;
private final String constraint;
private final String uniqueColumns;
private final String updateSet;
Options(String constraint, String uniqueColumns, String updateSet, boolean onConflictUpdate, boolean onConflictNothing, Boolean getGeneratedKeys) {
this.constraint = constraint;
this.uniqueColumns = uniqueColumns;
this.updateSet = updateSet;
this.getGeneratedKeys = getGeneratedKeys;
this.key = (onConflictUpdate ? UPDATE : onConflictNothing ? NOTHING : NORMAL)
+ '+' + plus(constraint)
+ '+' + plus(uniqueColumns)
+ '+' + plus(updateSet);
}
private String plus(String val) {
return val == null ? "" : val;
}
@Override
public String key() {
return key;
}
@Override
public String constraint() {
return constraint;
}
@Override
public String uniqueColumns() {
return uniqueColumns;
}
@Override
public String updateSet() {
return updateSet;
}
@Override
public Boolean getGetGeneratedKeys() {
return getGeneratedKeys;
}
}
}
@@ -1,9 +1,9 @@
package io.ebean;
import jakarta.persistence.PersistenceException;
import javax.persistence.PersistenceException;
/**
* Thrown when a foreign key constraint is enforced or a field is too large.
* Thrown when a foreign key constraint is enforced.
*/
public class DataIntegrityException extends PersistenceException {
private static final long serialVersionUID = -6740171949170180970L;
@@ -14,11 +14,4 @@ public class DataIntegrityException extends PersistenceException {
public DataIntegrityException(String message, Throwable cause) {
super(message, cause);
}
/**
* Create with message only.
*/
public DataIntegrityException(String message) {
super(message);
}
}
+259 -166
View File
@@ -9,10 +9,11 @@ import io.ebean.config.DatabaseConfig;
import io.ebean.meta.MetaInfoManager;
import io.ebean.plugin.Property;
import io.ebean.plugin.SpiServer;
import io.ebean.text.csv.CsvReader;
import io.ebean.text.json.JsonContext;
import jakarta.persistence.OptimisticLockException;
import jakarta.persistence.PersistenceException;
import javax.persistence.OptimisticLockException;
import javax.persistence.PersistenceException;
import javax.sql.DataSource;
import java.util.Collection;
import java.util.List;
@@ -29,24 +30,29 @@ import java.util.concurrent.Callable;
* singleton (see {@link DatabaseConfig#setRegister(boolean)}). The DB
* singleton is essentially a map of Database's that have been registered
* with it.
* </p>
* <p>
* The Database can then be retrieved later via {@link DB#byName(String)}.
* </p>
*
* <h5>The 'default' Database</h5>
* <p>
* One Database can be designated as the 'default' or 'primary' Database
* (see {@link DatabaseConfig#setDefaultServer(boolean)}). Many methods on DB
* (see {@link DatabaseConfig#setDefaultServer(boolean)}. Many methods on DB
* such as {@link DB#find(Class)} etc are actually just a convenient way to
* call methods on the 'default/primary' Database.
* </p>
*
* <h5>Constructing a Database</h5>
* <p>
* Databases are constructed by the DatabaseFactory. They can be created
* programmatically via {@link DatabaseFactory#create(DatabaseBuilder)} or they
* Database's are constructed by the DatabaseFactory. They can be created
* programmatically via {@link DatabaseFactory#create(DatabaseConfig)} or they
* can be automatically constructed on demand using configuration information in
* the application.properties file.
* </p>
*
* <h5>Example: Get a Database</h5>
* <p>
* <pre>{@code
*
* // Get access to the Human Resources Database
@@ -65,19 +71,22 @@ import java.util.concurrent.Callable;
*
* <h5>Database vs DB API</h5>
* <p>
* Database provides additional API compared with DB. For example, it
* Database provides additional API compared with DB. For example it
* provides more control over the use of Transactions that is not available in
* the DB API.
* </p>
*
* <p>
* <em>External Transactions:</em> If you wanted to use transactions created
* externally to Ebean then Database provides additional methods where you
* can explicitly pass a transaction (that can be created externally).
* </p>
*
* <p>
* <em>Bypass ThreadLocal Mechanism:</em> If you want to bypass the built-in
* <em>Bypass ThreadLocal Mechanism:</em> If you want to bypass the built in
* ThreadLocal transaction management you can use the createTransaction()
* method. Example: a single thread requires more than one transaction.
* </p>
*
* @see DB
* @see DatabaseFactory
@@ -86,23 +95,6 @@ import java.util.concurrent.Callable;
@NonNullApi
public interface Database {
/**
* Return a new database builder.
* <pre>{@code
*
* // build the 'default' database using configuration
* // from application.properties / application.yaml
*
* Database db = Database.builder()
* .loadFromProperties()
* .build();
*
* }</pre>
*/
static DatabaseBuilder builder() {
return new DatabaseConfig();
}
/**
* Shutdown the Database instance.
*/
@@ -112,10 +104,12 @@ public interface Database {
* Shutdown the Database instance programmatically.
* <p>
* This method is not normally required. Ebean registers a shutdown hook and shuts down cleanly.
* </p>
* <p>
* If the under underlying DataSource is the Ebean implementation then you
* also have the option of shutting down the DataSource and de-registering the
* also have the option of shutting down the DataSource and deregistering the
* JDBC driver.
* </p>
*
* @param shutdownDataSource if true then shutdown the underlying DataSource if it is the Ebean
* DataSource implementation.
@@ -161,10 +155,10 @@ public interface Database {
* <p>
* Note many platforms have multiple specific platform types so often we want to
* get the base platform via {@link Platform#base()}.
*
* </p>
* <pre>{@code
*
* Platform platform = database.platform().base();
* Platform platform = database.getPlatform().base();
* if (platform == Platform.MYSQL) {
* // do MySql specific function
* }
@@ -183,7 +177,8 @@ public interface Database {
/**
* Return the BeanState for a given entity bean.
* <p>
* This will throw an IllegalArgumentException if the bean is not an enhanced entity bean.
* This will return null if the bean is not an enhanced entity bean.
* </p>
*/
BeanState beanState(Object bean);
@@ -197,6 +192,7 @@ public interface Database {
* <p>
* For example, if the id value passed in is a String but ought to be a Long or UUID etc
* then it will automatically be converted.
* </p>
*
* @param bean The entity bean to set the id value on.
* @param id The id value to set.
@@ -208,6 +204,7 @@ public interface Database {
* <p>
* When null is passed in for b, then the 'OldValues' of a is used for the
* difference comparison.
* </p>
*/
Map<String, ValuePair> diff(Object newBean, Object oldBean);
@@ -217,9 +214,14 @@ public interface Database {
* Useful if you use BeanPostConstructListeners or &#64;PostConstruct Annotations.
* In this case you should not use "new Bean...()". Making all bean constructors protected
* could be a good idea here.
* </p>
*/
<T> T createEntityBean(Class<T> type);
/**
* Create a CsvReader for a given beanType.
*/
<T> CsvReader<T> createCsvReader(Class<T> beanType);
/**
* Create an Update query to perform a bulk update.
@@ -246,6 +248,7 @@ public interface Database {
* Create a named query.
* <p>
* For RawSql the named query is expected to be in ebean.xml.
* </p>
*
* @param beanType The type of entity bean
* @param namedQuery The name of the query
@@ -301,14 +304,17 @@ public interface Database {
* <p>
* You can use the methods on the Query object to specify fetch paths,
* predicates, order by, limits etc.
* </p>
* <p>
* You then use findList(), findSet(), findMap() and findOne() to execute
* the query and return the collection or bean.
* </p>
* <p>
* Note that a query executed by {@link Query#findList()}
* {@link Query#findSet()} etc will execute against the same Database from
* which is was created.
*
* </p>
* <p>
* <pre>{@code
*
* // Find order 2 specifying explicitly the parts of the object graph to
@@ -338,7 +344,7 @@ public interface Database {
* Create a query using native SQL.
* <p>
* The native SQL can contain named parameters or positioned parameters.
*
* </p>
* <pre>{@code
*
* String sql = "select c.id, c.name from customer c where c.name like ? order by c.name";
@@ -361,10 +367,12 @@ public interface Database {
* <p>
* This will only work when a IdGenerator is on the bean such as for beans
* that use a DB sequence or UUID.
* </p>
* <p>
* For DB's supporting getGeneratedKeys and sequences such as Oracle10 you do
* not need to use this method generally. It is made available for more
* complex cases where it is useful to get an ID prior to some processing.
* </p>
*/
Object nextId(Class<?> beanType);
@@ -373,8 +381,10 @@ public interface Database {
* going back to the database.
* <p>
* This produces and returns a new list with the sort and filters applied.
* </p>
* <p>
* Refer to {@link Filter} for an example of its use.
* </p>
*/
<T> Filter<T> filter(Class<T> beanType);
@@ -391,10 +401,12 @@ public interface Database {
* <p>
* If you leave off any keywords the defaults are ascending order and treating
* nulls as high values.
* </p>
* <p>
* Note that the sorting uses a Comparator and Collections.sort(); and does
* not invoke a DB query.
*
* </p>
* <p>
* <pre>{@code
*
* // find orders and their customers
@@ -419,15 +431,17 @@ public interface Database {
<T> void sort(List<T> list, String sortByClause);
/**
* Create an orm update where you will supply the insert/update or delete
* Create a orm update where you will supply the insert/update or delete
* statement (rather than using a named one that is already defined using the
* &#064;NamedUpdates annotation).
* <p>
* The orm update differs from the sql update in that it you can use the bean
* name and bean property names rather than table and column names.
* </p>
* <p>
* An example:
*
* </p>
* <p>
* <pre>{@code
*
* // The bean name and properties - "topic","postCount" and "id"
@@ -452,6 +466,7 @@ public interface Database {
* <p>
* DTO beans are just normal bean like classes with public constructor(s) and setters.
* They do not need to be registered with DB before use.
* </p>
*
* @param dtoType The type of the DTO bean the rows will be mapped into.
* @param sql The SQL query to execute.
@@ -464,6 +479,7 @@ public interface Database {
* <p>
* DTO beans are just normal bean like classes with public constructor(s) and setters.
* They do not need to be registered with DB before use.
* </p>
*
* @param dtoType The type of the DTO bean the rows will be mapped into.
* @param namedQuery The name of the query
@@ -477,8 +493,10 @@ public interface Database {
*
* <p>
* Refer to {@link DtoQuery} for native sql queries returning DTO beans.
* </p>
* <p>
* Refer to {@link #findNative(Class, String)} for native sql queries returning entity beans.
* </p>
*/
SqlQuery sqlQuery(String sql);
@@ -487,9 +505,11 @@ public interface Database {
* <p>
* Use this to execute a Insert Update or Delete statement. The statement will
* be native to the database and contain database table and column names.
* </p>
*
* <p>
* See {@link SqlUpdate} for example usage.
* </p>
*
* @return The SqlUpdate instance to set parameters and execute
*/
@@ -502,7 +522,7 @@ public interface Database {
/**
* Register a TransactionCallback on the currently active transaction.
* <p>
* <p/>
* If there is no currently active transaction then a PersistenceException is thrown.
*
* @param transactionCallback The transaction callback to be registered with the current transaction.
@@ -516,6 +536,7 @@ public interface Database {
* You will want to do this if you want multiple Transactions in a single
* thread or generally use transactions outside of the TransactionThreadLocal
* management.
* </p>
*/
Transaction createTransaction();
@@ -523,6 +544,7 @@ public interface Database {
* Create a new transaction additionally specifying the isolation level.
* <p>
* Note that this transaction is NOT stored in a thread local.
* </p>
*/
Transaction createTransaction(TxIsolation isolation);
@@ -530,77 +552,86 @@ public interface Database {
* Start a transaction with 'REQUIRED' semantics.
* <p>
* With REQUIRED semantics if an active transaction already exists that transaction will be used.
* </p>
* <p>
* The transaction is stored in a ThreadLocal variable and typically you only
* need to use the returned Transaction <em>IF</em> you wish to do things like
* use batch mode, change the transaction isolation level, use savepoints or
* log comments to the transaction log.
* </p>
* <p>
* Example of using a transaction to span multiple calls to find(), save()
* etc.
* </p>
* <p>
* Example of using a transaction to span multiple calls to find(), save() etc.
*
* <h3>Using try with resources</h3>
* <pre>{@code
*
* // start a transaction (stored in a ThreadLocal)
* try (Transaction txn = database.beginTransaction()) {
* // start a transaction (stored in a ThreadLocal)
*
* Order order = database.find(Order.class, 10);
* ...
* database.save(order);
* try (Transaction txn = database.beginTransaction()) {
*
* txn.commit();
* }
* Order order = database.find(Order.class, 10);
* ...
* database.save(order);
*
* txn.commit();
* }
*
* }</pre>
*
* <p>
* <h3>Using try finally block</h3>
* <pre>{@code
*
* // start a transaction (stored in a ThreadLocal)
* Transaction txn = database.beginTransaction();
* try {
* Order order = database.find(Order.class,10);
* // start a transaction (stored in a ThreadLocal)
* Transaction txn = database.beginTransaction();
* try {
* Order order = database.find(Order.class,10);
*
* database.save(order);
* txn.commit();
* database.save(order);
*
* txn.commit();
*
* } finally {
* txn.end();
* }
*
* } finally {
* txn.end();
* }
* }</pre>
*
* <p>
* <h3>Transaction options</h3>
* <pre>{@code
*
* try (Transaction txn = database.beginTransaction()) {
* try (Transaction txn = database.beginTransaction()) {
*
* // explicitly turn on/off JDBC batch use
* txn.setBatchMode(true);
* txn.setBatchSize(50);
* // explicitly turn on/off JDBC batch use
* txn.setBatchMode(true);
* txn.setBatchSize(50);
*
* // control flushing when mixing save and queries
* txn.setBatchFlushOnQuery(false);
* // control flushing when mixing save and queries
* txn.setBatchFlushOnQuery(false);
*
* // turn off persist cascade if needed
* txn.setPersistCascade(false);
* // turn off persist cascade if needed
* txn.setPersistCascade(false);
*
* // for large batch insert processing when we do not
* // ... need the generatedKeys, don't get them
* txn.setBatchGetGeneratedKeys(false);
* // for large batch insert processing when we do not
* // ... need the generatedKeys, don't get them
* txn.setBatchGetGeneratedKeys(false);
*
* // explicitly flush the JDBC batch buffer
* txn.flush();
* // explicitly flush the JDBC batch buffer
* txn.flush();
*
* ...
* ...
*
* txn.commit();
* }
* txn.commit();
* }
*
* }</pre>
* <p>
* <p>
* If you want to externalise the transaction management then you use
* createTransaction() and pass the transaction around to the various methods on
* Database yourself.
* </p>
*/
Transaction beginTransaction();
@@ -612,9 +643,11 @@ public interface Database {
/**
* Start a transaction typically specifying REQUIRES_NEW or REQUIRED semantics.
* <p>
* <p>
* Note that this provides an try finally alternative to using {@link #executeCall(TxScope, Callable)} or
* {@link #execute(TxScope, Runnable)}.
*
* </p>
* <p>
* <h3>REQUIRES_NEW example:</h3>
* <pre>{@code
* // Start a new transaction. If there is a current transaction
@@ -661,16 +694,57 @@ public interface Database {
* This only is useful when JDBC batch is used. Flush occurs automatically when the
* transaction commits or batch size is reached. This manually flushes the JDBC batch
* buffer.
* </p>
* <p>
* This is the same as <code>currentTransaction().flush()</code>.
* </p>
*/
void flush();
/**
* Commit the current transaction.
*/
void commitTransaction();
/**
* Rollback the current transaction.
*/
void rollbackTransaction();
/**
* If the current transaction has already been committed do nothing otherwise
* rollback the transaction.
* <p>
* Useful to put in a finally block to ensure the transaction is ended, rather
* than a rollbackTransaction() in each catch block.
* </p>
* <p>
* Code example:
* <p>
* <pre>{@code
*
* database.beginTransaction();
* try {
* // do some fetching and or persisting ...
*
* // commit at the end
* database.commitTransaction();
*
* } finally {
* // if commit didn't occur then rollback the transaction
* database.endTransaction();
* }
*
* }</pre>
*/
void endTransaction();
/**
* Refresh the values of a bean.
* <p>
* Note that this resets OneToMany and ManyToMany properties so that if they
* are accessed a lazy load will refresh the many property.
* </p>
*/
void refresh(Object bean);
@@ -689,11 +763,12 @@ public interface Database {
* // Fetch order 1
* Order order = database.find(Order.class, 1);
* }</pre>
*
* <p>
* <p>
* If you want more control over the query then you can use createQuery() and
* Query.findOne();
*
* </p>
* <p>
* <pre>{@code
* // ... additionally fetching customer, customer shipping address,
* // order details, and the product associated with each order detail.
@@ -735,9 +810,10 @@ public interface Database {
* <p>
* This will not perform a query against the database unless some property other
* that the id property is accessed.
* </p>
* <p>
* It is most commonly used to set a 'foreign key' on another bean like:
*
* </p>
* <pre>{@code
*
* Product product = database.getReference(Product.class, 1);
@@ -777,10 +853,12 @@ public interface Database {
* <p>
* The extended API has the options for executing queries that take an explicit
* transaction as an argument.
* </p>
* <p>
* Typically, we only need to use the extended API when we do NOT want to use the
* Typically we only need to use the extended API when we do NOT want to use the
* usual ThreadLocal based mechanism to obtain the current transaction but instead
* supply the transaction explicitly.
* </p>
*/
ExtendedServer extended();
@@ -789,27 +867,32 @@ public interface Database {
* <p>
* If there is no current transaction one will be created and committed for
* you automatically.
* </p>
* <p>
* Save can cascade along relationships. For this to happen you need to
* specify a cascade of CascadeType.ALL or CascadeType.PERSIST on the
* OneToMany, OneToOne or ManyToMany annotation.
* </p>
* <p>
* In this example below the details property has a CascadeType.ALL set so
* saving an order will also save all its details.
*
* </p>
* <p>
* <pre>{@code
* public class Order { ...
*
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
* List<OrderDetail> details;
* ...
* List<OrderDetail> details;
* ...
* }
* }</pre>
* <p>
* <p>
* When a save cascades via a OneToMany or ManyToMany Ebean will automatically
* set the 'parent' object to the 'detail' object. In the example below in
* saving the order and cascade saving the order details the 'parent' order
* will be set against each order detail when it is saved.
* </p>
*/
void save(Object bean) throws OptimisticLockException;
@@ -827,13 +910,16 @@ public interface Database {
* Delete the bean.
* <p>
* This will return true if the bean was deleted successfully or JDBC batch is being used.
* </p>
* <p>
* If there is no current transaction one will be created and committed for
* you automatically.
* </p>
* <p>
* If the Bean does not have a version property (or loaded version property) and
* the bean does not exist then this returns false indicating that nothing was
* deleted. Note that, if JDBC batch mode is used then this always returns true.
* </p>
*/
boolean delete(Object bean) throws OptimisticLockException;
@@ -841,10 +927,12 @@ public interface Database {
* Delete the bean with an explicit transaction.
* <p>
* This will return true if the bean was deleted successfully or JDBC batch is being used.
* </p>
* <p>
* If the Bean does not have a version property (or loaded version property) and
* the bean does not exist then this returns false indicating that nothing was
* deleted. However, if JDBC batch mode is used then this always returns true.
* </p>
*/
boolean delete(Object bean, Transaction transaction) throws OptimisticLockException;
@@ -926,13 +1014,16 @@ public interface Database {
* <p>
* If you wish to execute a Sql Select natively then you should use the
* SqlQuery object or DtoQuery.
* </p>
* <p>
* Note that the table modification information is automatically deduced and
* you do not need to call the DB.externalModification() method when you
* use this method.
* </p>
* <p>
* Example:
*
* </p>
* <p>
* <pre>{@code
*
* // example that uses 'named' parameters
@@ -960,6 +1051,7 @@ public interface Database {
* transaction.
* <p>
* This returns the number of rows that where inserted, updated or deleted.
* </p>
*/
int execute(Update<?> update);
@@ -973,7 +1065,8 @@ public interface Database {
* For making calls to stored procedures.
* <p>
* Example:
*
* </p>
* <p>
* <pre>{@code
*
* String sql = "{call sp_order_modify(?,?,?)}";
@@ -998,19 +1091,23 @@ public interface Database {
* <p>
* If you use database.execute(UpdateSql) then the table modification information
* is automatically deduced and you do not need to call this method yourself.
* </p>
* <p>
* This information is used to invalidate objects out of the cache and
* potentially text indexes. This information is also automatically broadcast
* across the cluster.
* </p>
* <p>
* If there is a transaction then this information is placed into the current
* transactions event information. When the transaction is committed this
* information is registered (with the transaction manager). If this
* transaction is rolled back then none of the transaction event information
* registers including the information you put in via this method.
* </p>
* <p>
* If there is NO current transaction when you call this method then this
* information is registered immediately (with the transaction manager).
* </p>
*
* @param tableName the name of the table that was modified
* @param inserted true if rows where inserted into the table
@@ -1050,6 +1147,7 @@ public interface Database {
* Note: This checks only the root bean!
* <p>
* <pre>{@code
*
* // there is a unique constraint on title
*
* Document doc = new Document();
@@ -1078,7 +1176,7 @@ public interface Database {
* // uniqueProperties > [title]
* // custom msg > property[title] value[One flew over the cuckoo's nest]
*
* }
* }
*
* }</pre>
*
@@ -1102,12 +1200,13 @@ public interface Database {
* dirty so that it is not skipped.
* <p>
* <pre>{@code
* Customer customer = database.find(Customer, id);
*
* // mark the bean as dirty so that a save() or update() will
* // increment the version property
* database.markAsDirty(customer);
* database.save(customer);
* Customer customer = database.find(Customer, id);
*
* // mark the bean as dirty so that a save() or update() will
* // increment the version property
* database.markAsDirty(customer);
* database.save(customer);
*
* }</pre>
*/
@@ -1120,17 +1219,18 @@ public interface Database {
* <b>Stateless updates:</b> Note that the bean does not have to be previously fetched to call
* update().You can create a new instance and set some of its properties programmatically for via
* JSON/XML marshalling etc. This is described as a 'stateless update'.
* </p>
* <p>
* <b>Optimistic Locking: </b> Note that if the version property is not set when update() is
* called then no optimistic locking is performed (internally ConcurrencyMode.NONE is used).
*
* </p>
* <pre>{@code
*
* // A 'stateless update' example
* Customer customer = new Customer();
* customer.setId(7);
* customer.setName("ModifiedNameNoOCC");
* database.update(customer);
* // A 'stateless update' example
* Customer customer = new Customer();
* customer.setId(7);
* customer.setName("ModifiedNameNoOCC");
* database.update(customer);
*
* }</pre>
*/
@@ -1181,56 +1281,26 @@ public interface Database {
* Compared to save() this forces bean to perform an insert rather than trying to decide
* based on the bean state. As such this is useful when you fetch beans from one database
* and want to insert them into another database (and you want to explicitly insert them).
* </p>
*/
void insert(Object bean);
/**
* Insert the bean with options (ON CONFLICT DO UPDATE | DO NOTHING).
* <p>
* Currently, this is limited to use with Postgres only,
* <p>
* When using this ebean will look to determine the unique columns by looking at
* the mapping like {@code @Column(unique=true} and {@code @Index(unique=true}.
*/
void insert(Object bean, InsertOptions insertOptions);
/**
* Insert the bean with a transaction.
*/
void insert(Object bean, Transaction transaction);
/**
* Insert the beans with options (ON CONFLICT DO UPDATE | DO NOTHING) and transaction.
* <p>
* Currently, this is limited to use with Postgres only,
*/
void insert(Object bean, InsertOptions insertOptions, Transaction transaction);
/**
* Insert a collection of beans. If there is no current transaction one is created and used to
* insert all the beans in the collection.
*/
void insertAll(Collection<?> beans);
/**
* Insert the beans with options - typically ON CONFLICT DO UPDATE | DO NOTHING.
* <p>
* Currently, this is limited to use with Postgres only,
*/
void insertAll(Collection<?> beans, InsertOptions options);
/**
* Insert a collection of beans with an explicit transaction.
*/
void insertAll(Collection<?> beans, Transaction transaction);
/**
* Insert the beans with options (ON CONFLICT DO UPDATE | DO NOTHING) and transaction.
* <p>
* Currently, this is limited to use with Postgres only,
*/
void insertAll(Collection<?> beans, InsertOptions options, Transaction transaction);
/**
* Execute explicitly passing a transaction.
*/
@@ -1244,18 +1314,21 @@ public interface Database {
/**
* Execute a Runnable in a Transaction with an explicit scope.
* <p>
* The scope can control the transaction type, isolation and rollback semantics.
*
* The scope can control the transaction type, isolation and rollback
* semantics.
* </p>
* <p>
* <pre>{@code
* // set specific transactional scope settings
* TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE);
*
* database.execute(scope, new Runnable() {
* public void run() {
* User u1 = database.find(User.class, 1);
* ...
* }
* });
* // set specific transactional scope settings
* TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE);
*
* database.execute(scope, new Runnable() {
* public void run() {
* User u1 = database.find(User.class, 1);
* ...
* }
* });
*
* }</pre>
*/
@@ -1266,19 +1339,21 @@ public interface Database {
* <p>
* The default scope runs with REQUIRED and by default will rollback on any
* exception (checked or runtime).
*
* </p>
* <p>
* <pre>{@code
* database.execute(() -> {
*
* User u1 = database.find(User.class, 1);
* User u2 = database.find(User.class, 2);
* database.execute(() -> {
*
* u1.setName("u1 mod");
* u2.setName("u2 mod");
* User u1 = database.find(User.class, 1);
* User u2 = database.find(User.class, 2);
*
* u1.save();
* u2.save();
* });
* u1.setName("u1 mod");
* u2.setName("u2 mod");
*
* u1.save();
* u2.save();
* });
*
* }</pre>
*/
@@ -1289,16 +1364,18 @@ public interface Database {
* <p>
* The scope can control the transaction type, isolation and rollback
* semantics.
*
* </p>
* <p>
* <pre>{@code
*
* // set specific transactional scope settings
* TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE);
*
* database.executeCall(scope, new Callable<String>() {
* public String call() {
* User u1 = database.find(User.class, 1);
* ...
* return u1.getEmail();
* public String call() {
* User u1 = database.find(User.class, 1);
* ...
* return u1.getEmail();
* }
* });
*
@@ -1311,8 +1388,10 @@ public interface Database {
* <p>
* The default scope runs with REQUIRED and by default will rollback on any
* exception (checked or runtime).
*
* </p>
* <p>
* <pre>{@code
*
* database.executeCall(new Callable<String>() {
* public String call() {
* User u1 = database.find(User.class, 1);
@@ -1327,6 +1406,7 @@ public interface Database {
* return u1.getEmail();
* }
* });
*
* }</pre>
*/
<T> T executeCall(Callable<T> callable);
@@ -1337,7 +1417,8 @@ public interface Database {
ServerCacheManager cacheManager();
/**
* Return the BackgroundExecutor service for asynchronous processing of queries.
* Return the BackgroundExecutor service for asynchronous processing of
* queries.
*/
BackgroundExecutor backgroundExecutor();
@@ -1346,30 +1427,33 @@ public interface Database {
* <p>
* This instance is safe to be used concurrently by multiple threads and this
* method is cheap to call.
*
* </p>
* <p>
* <h3>Simple example:</h3>
* <pre>{@code
* JsonContext json = database.json();
* String jsonOutput = json.toJson(list);
* System.out.println(jsonOutput);
* }</pre>
*
* JsonContext json = database.json();
* String jsonOutput = json.toJson(list);
* System.out.println(jsonOutput);
*
* }</pre>
* <p>
* <h3>Using PathProperties:</h3>
* <pre>{@code
* // specify just the properties we want
* PathProperties paths = PathProperties.parse("name, status, anniversary");
*
* List<Customer> customers =
* database.find(Customer.class)
* // apply those paths to the query (only fetch what we need)
* .apply(paths)
* .where().ilike("name", "rob%")
* .findList();
* // specify just the properties we want
* PathProperties paths = PathProperties.parse("name, status, anniversary");
*
* // ... get the json
* JsonContext jsonContext = database.json();
* String json = jsonContext.toJson(customers, paths);
* List<Customer> customers =
* database.find(Customer.class)
* // apply those paths to the query (only fetch what we need)
* .apply(paths)
* .where().ilike("name", "rob%")
* .findList();
*
* // ... get the json
* JsonContext jsonContext = database.json();
* String json = jsonContext.toJson(customers, paths);
*
* }</pre>
*
@@ -1394,6 +1478,7 @@ public interface Database {
* Publish a single bean given its type and id returning the resulting live bean.
* <p>
* The values are published from the draft to the live bean.
* </p>
*
* @param <T> the type of the entity bean
* @param beanType the type of the entity bean
@@ -1408,6 +1493,7 @@ public interface Database {
* This will use the current transaction or create one if required.
* <p>
* The values are published from the draft to the live bean.
* </p>
*
* @param <T> the type of the entity bean
* @param beanType the type of the entity bean
@@ -1420,6 +1506,7 @@ public interface Database {
* Publish the beans that match the query returning the resulting published beans.
* <p>
* The values are published from the draft beans to the live beans.
* </p>
*
* @param <T> the type of the entity bean
* @param query the query used to select the draft beans to publish
@@ -1432,6 +1519,7 @@ public interface Database {
* This will use the current transaction or create one if required.
* <p>
* The values are published from the draft beans to the live beans.
* </p>
*
* @param <T> the type of the entity bean
* @param query the query used to select the draft beans to publish
@@ -1443,6 +1531,7 @@ public interface Database {
* <p>
* The values from the live beans are set back to the draft bean and the
* <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset.
* </p>
*
* @param <T> the type of the entity bean
* @param beanType the type of the entity bean
@@ -1457,6 +1546,7 @@ public interface Database {
* <p>
* The values from the live beans are set back to the draft bean and the
* <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset.
* </p>
*
* @param <T> the type of the entity bean
* @param beanType the type of the entity bean
@@ -1470,6 +1560,7 @@ public interface Database {
* <p>
* The values from the live beans are set back to the draft bean and the
* <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset.
* </p>
*
* @param <T> the type of the entity bean
* @param query the query used to select the draft beans to restore
@@ -1482,6 +1573,7 @@ public interface Database {
* <p>
* The values from the live beans are set back to the draft bean and the
* <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset.
* </p>
*
* @param <T> the type of the entity bean
* @param query the query used to select the draft beans to restore
@@ -1493,6 +1585,7 @@ public interface Database {
* <p>
* Validate the query checking the where and orderBy expression paths to confirm if
* they represent valid properties/path for the given bean type.
* </p>
*/
<T> Set<String> validateQuery(Query<T> query);
@@ -1518,6 +1611,6 @@ public interface Database {
/**
* Truncate the base tables for the given bean types.
*/
void truncate(Class<?>... beanTypes);
void truncate(Class<?>... tables);
}
File diff suppressed because it is too large Load Diff
@@ -1,11 +1,13 @@
package io.ebean;
import io.ebean.config.ContainerConfig;
import io.ebean.config.DatabaseConfig;
import io.ebean.service.SpiContainer;
import io.ebean.service.SpiContainerFactory;
import jakarta.persistence.PersistenceException;
import javax.persistence.PersistenceException;
import java.util.Iterator;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.concurrent.locks.ReentrantLock;
@@ -74,10 +76,9 @@ public final class DatabaseFactory {
*
* }</pre>
*/
public static Database create(DatabaseBuilder builder) {
public static Database create(DatabaseConfig config) {
lock.lock();
try {
var config = builder.settings();
if (config.getName() == null) {
throw new PersistenceException("The name is null (it is required)");
}
@@ -101,7 +102,7 @@ public final class DatabaseFactory {
/**
* Create using the DatabaseConfig additionally specifying a classLoader to use as the context class loader.
*/
public static Database createWithContextClassLoader(DatabaseBuilder config, ClassLoader classLoader) {
public static Database createWithContextClassLoader(DatabaseConfig config, ClassLoader classLoader) {
lock.lock();
try {
ClassLoader currentContextLoader = Thread.currentThread().getContextClassLoader();
@@ -131,7 +132,7 @@ public final class DatabaseFactory {
}
}
private static Database createInternal(DatabaseBuilder.Settings config) {
private static Database createInternal(DatabaseConfig config) {
return container(config.getContainerConfig()).createServer(config);
}
@@ -145,9 +146,12 @@ public final class DatabaseFactory {
if (container != null) {
return container;
}
if (containerConfig == null) {
// effectively load configuration from ebean.properties
Properties properties = DbPrimary.getProperties();
containerConfig = new ContainerConfig();
containerConfig.loadFromProperties(properties);
}
container = createContainer(containerConfig);
return container;
@@ -156,7 +160,7 @@ public final class DatabaseFactory {
/**
* Create the container instance using the configuration.
*/
private static SpiContainer createContainer(ContainerConfig containerConfig) {
protected static SpiContainer createContainer(ContainerConfig containerConfig) {
Iterator<SpiContainerFactory> factories = ServiceLoader.load(SpiContainerFactory.class).iterator();
if (factories.hasNext()) {
return factories.next().create(containerConfig);
+13 -11
View File
@@ -2,20 +2,20 @@ package io.ebean;
import io.ebean.config.BeanNotEnhancedException;
import io.ebean.datasource.DataSourceConfigurationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.persistence.PersistenceException;
import javax.persistence.PersistenceException;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
import static java.lang.System.Logger.Level.ERROR;
/**
* Holds Database instances.
*/
final class DbContext {
private static final System.Logger log = EbeanVersion.log;
private static final Logger log = LoggerFactory.getLogger("io.ebean");
static {
EbeanVersion.getVersion();
}
@@ -23,9 +23,14 @@ final class DbContext {
private static final DbContext INSTANCE = new DbContext();
private final ConcurrentHashMap<String, Database> concMap = new ConcurrentHashMap<>();
private final HashMap<String, Database> syncMap = new HashMap<>();
private final ReentrantLock lock = new ReentrantLock();
/**
* The 'default' Database.
*/
private Database defaultDatabase;
private DbContext() {
@@ -38,19 +43,16 @@ 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) {
log.log(ERROR, "Error trying to create the default Database", e);
log.error("Error trying to create the default Database", e);
throw new RuntimeException(e);
}
}
@@ -67,9 +69,9 @@ final class DbContext {
*/
Database getDefault() {
if (defaultDatabase == null) {
String msg = "The default Database has not been defined?"
+ " This is normally set via the ebean.datasource.default property."
+ " Otherwise it should be registered programmatically via registerServer()";
String msg = "The default Database has not been defined?";
msg += " This is normally set via the ebean.datasource.default property.";
msg += " Otherwise it should be registered programmatically via registerServer()";
throw new PersistenceException(msg);
}
return defaultDatabase;
@@ -44,12 +44,25 @@ final class DbPrimary {
* Return the default database name.
*/
static String getDefaultServerName() {
lock.lock();
try {
getProperties();
return defaultServerName;
} finally {
lock.unlock();
}
}
/**
* Return the default configuration Properties.
*/
static Properties getProperties() {
lock.lock();
try {
if (defaultServerName == null) {
defaultServerName = determineDefaultServerName();
}
return defaultServerName;
return Config.asProperties();
} finally {
lock.unlock();
}
@@ -63,9 +76,9 @@ final class DbPrimary {
defaultServerName = System.getProperty("db", defaultServerName);
defaultServerName = System.getProperty("ebean_db", defaultServerName);
if (isEmpty(defaultServerName)) {
defaultServerName = Config.getOptional("datasource.default").orElse(null);
defaultServerName = Config.get("datasource.default", null);
if (isEmpty(defaultServerName)) {
defaultServerName = Config.getOptional("ebean.default.datasource").orElse(null);
defaultServerName = Config.get("ebean.default.datasource", null);
}
}
if (defaultServerName == null) {
@@ -3,8 +3,6 @@ package io.ebean;
import io.avaje.lang.NonNullApi;
import io.avaje.lang.Nullable;
import javax.sql.DataSource;
import java.sql.Connection;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
@@ -131,11 +129,6 @@ public interface DtoQuery<T> extends CancelableQuery {
*/
DtoQuery<T> setParameter(String name, Object value);
/**
* Bind the named parameter to SQL NULL.
*/
DtoQuery<T> setNullParameter(String name, int jdbcType);
/**
* Bind the named multi-value array parameter which we would use with Postgres ANY.
* <p>
@@ -148,11 +141,6 @@ public interface DtoQuery<T> extends CancelableQuery {
*/
DtoQuery<T> setParameter(int position, Object value);
/**
* Set a positioned parameter to SQL NULL.
*/
DtoQuery<T> setNullParameter(int position, int jdbcType);
/**
* Set the index of the first row of the results to return.
*/
@@ -207,21 +195,4 @@ public interface DtoQuery<T> extends CancelableQuery {
* Use the explicit transaction to execute the query.
*/
DtoQuery<T> usingTransaction(Transaction transaction);
/**
* Execute the query using the given connection.
*/
DtoQuery<T> usingConnection(Connection connection);
/**
* 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.DatabaseBuilder#readOnlyDataSource(DataSource)} then
* by default when a query is run without an active transaction, it uses the read-only data
* source. We use {@code usingMaster()} to instead ensure that the query is executed
* against the master data source.
*/
DtoQuery<T> usingMaster();
}
@@ -2,28 +2,6 @@ package io.ebean;
/**
* Thrown when a duplicate is attempted on a unique constraint.
* <p>
* In terms of catching this exception with the view of continuing processing
* using the same transaction look to use {@link Transaction#rollbackAndContinue()}.
*
* <pre>{@code
*
* try (Transaction txn = database.beginTransaction()) {
*
* try {
* ...
* database.save(bean);
* database.flush();
* } catch (DuplicateKeyException e) {
* // carry on processing using the transaction
* txn.rollbackAndContinue();
* ...
* }
*
* txn.commit();
* }
*
* }</pre>
*/
public class DuplicateKeyException extends DataIntegrityException {
private static final long serialVersionUID = -4771932723285724817L;
@@ -1,15 +1,12 @@
package io.ebean;
import io.avaje.applog.AppLog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.Properties;
import static java.lang.System.Logger.Level.*;
/**
* Class to determine the ebean version.
*
@@ -17,7 +14,7 @@ import static java.lang.System.Logger.Level.*;
*/
public final class EbeanVersion {
public static final System.Logger log = AppLog.getLogger("io.ebean");
private static final Logger log = LoggerFactory.getLogger("io.ebean");
/**
* Maintain the minimum ebean-agent version manually based on required ebean-agent bug fixes.
@@ -25,7 +22,6 @@ public final class EbeanVersion {
private static final int MIN_AGENT_MAJOR_VERSION = 12;
private static final int MIN_AGENT_MINOR_VERSION = 12;
private static String version = "unknown";
static {
readVersion();
checkAgentVersion();
@@ -33,16 +29,14 @@ public final class EbeanVersion {
private static void readVersion() {
try {
try (InputStream in = ClassLoader.getSystemResourceAsStream("META-INF/ebean-maven-version.txt")) {
try (InputStream in = ClassLoader.getSystemResourceAsStream("META-INF/maven/io.ebean/ebean-api/pom.properties")) {
if (in != null) {
try (LineNumberReader reader = new LineNumberReader(new InputStreamReader(in))) {
version = reader.readLine();
log.log(INFO, "ebean version: {0}", version);
}
version = readVersion(in);
}
}
log.info("ebean version: {}", version);
} catch (IOException e) {
log.log(WARNING, "Could not determine ebean version: {0}", e.getMessage());
log.warn("Could not determine ebean version: {}", e.getMessage());
}
}
@@ -54,13 +48,13 @@ public final class EbeanVersion {
String agentVersion = readVersion(in);
if (agentVersion != null) {
if (checkMinAgentVersion(agentVersion)) {
log.log(ERROR, "Expected minimum ebean-agent version {0}.{1}.0 but we have {2}, please update the ebean-agent", MIN_AGENT_MAJOR_VERSION, MIN_AGENT_MINOR_VERSION, agentVersion);
log.error("Expected minimum ebean-agent version {}.{}.0 but we have {}, please update the ebean-agent", MIN_AGENT_MAJOR_VERSION, MIN_AGENT_MINOR_VERSION, agentVersion);
}
}
}
}
} catch (IOException e) {
log.log(WARNING, "Could not check minimum ebean-agent version {0}.{1}.0 required due to - {2}", MIN_AGENT_MAJOR_VERSION, MIN_AGENT_MINOR_VERSION, e.getMessage());
log.warn("Could not check minimum ebean-agent version {}.{}.0 required due to - {}", MIN_AGENT_MAJOR_VERSION, MIN_AGENT_MINOR_VERSION, e.getMessage());
}
}
@@ -94,7 +88,7 @@ public final class EbeanVersion {
}
/**
* Returns the ebean version (read from META-INF/ebean-maven-version.txt)
* Returns the ebean version (read from /META-INF/maven/io.ebean/ebean/pom.properties)
*/
public static String getVersion() {
return version;
+39 -46
View File
@@ -30,25 +30,18 @@ public final class Expr {
private Expr() {
}
/**
* Return the underlying expression factory.
*/
public static ExpressionFactory factory() {
return DB.expressionFactory();
}
/**
* Equal To - property equal to the given value.
*/
public static Expression eq(String propertyName, Object value) {
return factory().eq(propertyName, value);
return DB.expressionFactory().eq(propertyName, value);
}
/**
* Not Equal To - property not equal to the given value.
*/
public static Expression ne(String propertyName, Object value) {
return factory().ne(propertyName, value);
return DB.expressionFactory().ne(propertyName, value);
}
/**
@@ -56,7 +49,7 @@ public final class Expr {
* using a lower() function to make it case insensitive).
*/
public static Expression ieq(String propertyName, String value) {
return factory().ieq(propertyName, value);
return DB.expressionFactory().ieq(propertyName, value);
}
/**
@@ -66,28 +59,28 @@ public final class Expr {
* </p>
*/
public static Expression inRange(String propertyName, Object value1, Object value2) {
return factory().inRange(propertyName, value1, value2);
return DB.expressionFactory().inRange(propertyName, value1, value2);
}
/**
* Between - property between the two given values.
*/
public static Expression between(String propertyName, Object value1, Object value2) {
return factory().between(propertyName, value1, value2);
return DB.expressionFactory().between(propertyName, value1, value2);
}
/**
* Between - value between two given properties.
*/
public static Expression between(String lowProperty, String highProperty, Object value) {
return factory().betweenProperties(lowProperty, highProperty, value);
return DB.expressionFactory().betweenProperties(lowProperty, highProperty, value);
}
/**
* Greater Than - property greater than the given value.
*/
public static Expression gt(String propertyName, Object value) {
return factory().gt(propertyName, value);
return DB.expressionFactory().gt(propertyName, value);
}
/**
@@ -95,42 +88,42 @@ public final class Expr {
* value.
*/
public static Expression ge(String propertyName, Object value) {
return factory().ge(propertyName, value);
return DB.expressionFactory().ge(propertyName, value);
}
/**
* Less Than - property less than the given value.
*/
public static Expression lt(String propertyName, Object value) {
return factory().lt(propertyName, value);
return DB.expressionFactory().lt(propertyName, value);
}
/**
* Less Than or Equal to - property less than or equal to the given value.
*/
public static Expression le(String propertyName, Object value) {
return factory().le(propertyName, value);
return DB.expressionFactory().le(propertyName, value);
}
/**
* Is Null - property is null.
*/
public static Expression isNull(String propertyName) {
return factory().isNull(propertyName);
return DB.expressionFactory().isNull(propertyName);
}
/**
* Is Not Null - property is not null.
*/
public static Expression isNotNull(String propertyName) {
return factory().isNotNull(propertyName);
return DB.expressionFactory().isNotNull(propertyName);
}
/**
* Case insensitive {@link #exampleLike(Object)}
*/
public static ExampleExpression iexampleLike(Object example) {
return factory().iexampleLike(example);
return DB.expressionFactory().iexampleLike(example);
}
/**
@@ -138,14 +131,14 @@ public final class Expr {
* LikeType.RAW (you need to add you own wildcards % and _).
*/
public static ExampleExpression exampleLike(Object example) {
return factory().exampleLike(example);
return DB.expressionFactory().exampleLike(example);
}
/**
* Create the query by Example expression specifying more options.
*/
public static ExampleExpression exampleLike(Object example, boolean caseInsensitive, LikeType likeType) {
return factory().exampleLike(example, caseInsensitive, likeType);
return DB.expressionFactory().exampleLike(example, caseInsensitive, likeType);
}
/**
@@ -153,7 +146,7 @@ public final class Expr {
* characters % (percentage) and _ (underscore).
*/
public static Expression like(String propertyName, String value) {
return factory().like(propertyName, value);
return DB.expressionFactory().like(propertyName, value);
}
/**
@@ -162,14 +155,14 @@ public final class Expr {
* a lower() function to make the expression case insensitive.
*/
public static Expression ilike(String propertyName, String value) {
return factory().ilike(propertyName, value);
return DB.expressionFactory().ilike(propertyName, value);
}
/**
* Starts With - property like value%.
*/
public static Expression startsWith(String propertyName, String value) {
return factory().startsWith(propertyName, value);
return DB.expressionFactory().startsWith(propertyName, value);
}
/**
@@ -177,14 +170,14 @@ public final class Expr {
* lower() function to make the expression case insensitive.
*/
public static Expression istartsWith(String propertyName, String value) {
return factory().istartsWith(propertyName, value);
return DB.expressionFactory().istartsWith(propertyName, value);
}
/**
* Ends With - property like %value.
*/
public static Expression endsWith(String propertyName, String value) {
return factory().endsWith(propertyName, value);
return DB.expressionFactory().endsWith(propertyName, value);
}
/**
@@ -192,14 +185,14 @@ public final class Expr {
* function to make the expression case insensitive.
*/
public static Expression iendsWith(String propertyName, String value) {
return factory().iendsWith(propertyName, value);
return DB.expressionFactory().iendsWith(propertyName, value);
}
/**
* Contains - property like %value%.
*/
public static Expression contains(String propertyName, String value) {
return factory().contains(propertyName, value);
return DB.expressionFactory().contains(propertyName, value);
}
/**
@@ -207,42 +200,42 @@ public final class Expr {
* function to make the expression case insensitive.
*/
public static Expression icontains(String propertyName, String value) {
return factory().icontains(propertyName, value);
return DB.expressionFactory().icontains(propertyName, value);
}
/**
* For collection properties that are empty (have not existing elements).
*/
public static Expression isEmpty(String propertyName) {
return factory().isEmpty(propertyName);
return DB.expressionFactory().isEmpty(propertyName);
}
/**
* For collection properties that are not empty (have existing elements).
*/
public static Expression isNotEmpty(String propertyName) {
return factory().isNotEmpty(propertyName);
return DB.expressionFactory().isNotEmpty(propertyName);
}
/**
* In - property has a value in the array of values.
*/
public static Expression in(String propertyName, Object[] values) {
return factory().in(propertyName, values);
return DB.expressionFactory().in(propertyName, values);
}
/**
* In - using a subQuery.
*/
public static Expression in(String propertyName, Query<?> subQuery) {
return factory().in(propertyName, subQuery);
return DB.expressionFactory().in(propertyName, subQuery);
}
/**
* In - property has a value in the collection of values.
*/
public static Expression in(String propertyName, Collection<?> values) {
return factory().in(propertyName, values);
return DB.expressionFactory().in(propertyName, values);
}
/**
@@ -279,14 +272,14 @@ public final class Expr {
* }</pre>
*/
public static Expression inOrEmpty(String propertyName, Collection<?> values) {
return factory().inOrEmpty(propertyName, values);
return DB.expressionFactory().inOrEmpty(propertyName, values);
}
/**
* Id Equal to - ID property is equal to the value.
*/
public static Expression idEq(Object value) {
return factory().idEq(value);
return DB.expressionFactory().idEq(value);
}
/**
@@ -299,7 +292,7 @@ public final class Expr {
* @param propertyMap a map keyed by property names.
*/
public static Expression allEq(Map<String, Object> propertyMap) {
return factory().allEq(propertyMap);
return DB.expressionFactory().allEq(propertyMap);
}
/**
@@ -310,7 +303,7 @@ public final class Expr {
* </p>
*/
public static Expression raw(String raw, Object value) {
return factory().raw(raw, value);
return DB.expressionFactory().raw(raw, value);
}
/**
@@ -321,48 +314,48 @@ public final class Expr {
* </p>
*/
public static Expression raw(String raw, Object[] values) {
return factory().raw(raw, values);
return DB.expressionFactory().raw(raw, values);
}
/**
* Add raw expression with no parameters.
*/
public static Expression raw(String raw) {
return factory().raw(raw);
return DB.expressionFactory().raw(raw);
}
/**
* And - join two expressions with a logical and.
*/
public static Expression and(Expression expOne, Expression expTwo) {
return factory().and(expOne, expTwo);
return DB.expressionFactory().and(expOne, expTwo);
}
/**
* Or - join two expressions with a logical or.
*/
public static Expression or(Expression expOne, Expression expTwo) {
return factory().or(expOne, expTwo);
return DB.expressionFactory().or(expOne, expTwo);
}
/**
* Negate the expression (prefix it with NOT).
*/
public static Expression not(Expression exp) {
return factory().not(exp);
return DB.expressionFactory().not(exp);
}
/**
* Return a list of expressions that will be joined by AND's.
*/
public static <T> Junction<T> conjunction(Query<T> query) {
return factory().conjunction(query);
return DB.expressionFactory().conjunction(query);
}
/**
* Return a list of expressions that will be joined by OR's.
*/
public static <T> Junction<T> disjunction(Query<T> query) {
return factory().disjunction(query);
return DB.expressionFactory().disjunction(query);
}
}
@@ -1,6 +1,10 @@
package io.ebean;
import io.ebean.search.*;
import io.ebean.search.Match;
import io.ebean.search.MultiMatch;
import io.ebean.search.TextCommonTerms;
import io.ebean.search.TextQueryString;
import io.ebean.search.TextSimple;
import java.util.Collection;
import java.util.Map;
@@ -36,11 +40,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.
*/
@@ -118,11 +117,6 @@ public interface ExpressionFactory {
*/
Expression arrayIsNotEmpty(String propertyName);
/**
* Equal To the result of a sub-query.
*/
Expression eq(String propertyName, Query<?> subQuery);
/**
* Equal To - property equal to the given value.
*/
@@ -133,11 +127,6 @@ public interface ExpressionFactory {
*/
Expression eqOrNull(String propertyName, Object value);
/**
* Not Equal To the result of a sub-query.
*/
Expression ne(String propertyName, Query<?> subQuery);
/**
* Not Equal To - property not equal to the given value.
*/
@@ -192,23 +181,6 @@ public interface ExpressionFactory {
*/
Expression inRangeWith(String lowProperty, String highProperty, Object value);
/**
* A Property is in Range between 2 properties.
*
* <pre>{@code
*
* .orderDate.inRangeWith(QOrder.Alias.product.startDate, QOrder.Alias.product.endDate)
*
* // which equates to
* product.startDate <= orderDate and (orderDate < product.endDate or product.endDate is null)
*
* }</pre>
*
* <p>
* This is a convenience expression combining a number of simple expressions.
*/
Expression inRangeWithProperties(String propertyName, String lowProperty, String highProperty);
/**
* Between - property between the two given values.
*/
@@ -235,21 +207,11 @@ public interface ExpressionFactory {
*/
Expression geOrNull(String propertyName, Object value);
/**
* Greater Than the result of a sub-query.
*/
Expression gt(String propertyName, Query<?> subQuery);
/**
* Greater Than - property greater than the given value.
*/
Expression gt(String propertyName, Object value);
/**
* Greater Than or Equal to the result of a sub-query.
*/
Expression ge(String propertyName, Query<?> subQuery);
/**
* Greater Than or Equal to - property greater than or equal to the given
* value.
@@ -272,21 +234,11 @@ public interface ExpressionFactory {
*/
Expression leOrNull(String propertyName, Object value);
/**
* Less Than the result of a sub-query.
*/
Expression lt(String propertyName, Query<?> subQuery);
/**
* Less Than - property less than the given value.
*/
Expression lt(String propertyName, Object value);
/**
* Less Than or Equal to the result of a sub-query.
*/
Expression le(String propertyName, Query<?> subQuery);
/**
* Less Than or Equal to - property less than or equal to the given value.
*/
@@ -374,11 +326,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.
*/
@@ -429,94 +376,6 @@ public interface ExpressionFactory {
*/
Expression inOrEmpty(String propertyName, Collection<?> values);
/**
* EXISTS a raw SQL SubQuery.
*
* @param sqlSubQuery The SQL SubQuery
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
Expression exists(String sqlSubQuery, Object... bindValues);
/**
* Not EXISTS a raw SQL SubQuery.
*
* @param sqlSubQuery The SQL SubQuery
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
Expression notExists(String sqlSubQuery, Object... bindValues);
/**
* IN a raw SQL SubQuery.
*
* @param propertyName The bean property
* @param sqlSubQuery The SQL SubQuery
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
Expression inSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
/**
* Not IN a raw SQL SubQuery.
*
* @param propertyName The bean property
* @param sqlSubQuery The SQL SubQuery
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
Expression notInSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
/**
* Equal To a raw SQL SubQuery.
*
* @param propertyName The bean property
* @param sqlSubQuery The SQL SubQuery
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
Expression eqSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
/**
* Not Equal To a raw SQL SubQuery.
*
* @param propertyName The bean property
* @param sqlSubQuery The SQL SubQuery
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
Expression neSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
/**
* Greater Than or Equal To a raw SQL SubQuery.
*
* @param propertyName The bean property
* @param sqlSubQuery The SQL SubQuery
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
Expression geSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
/**
* Greater Than a raw SQL SubQuery.
*
* @param propertyName The bean property
* @param sqlSubQuery The SQL SubQuery
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
Expression gtSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
/**
* Less Than or Equal To a raw SQL SubQuery.
*
* @param propertyName The bean property
* @param sqlSubQuery The SQL SubQuery
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
Expression leSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
/**
* Less Than a raw SQL SubQuery.
*
* @param propertyName The bean property
* @param sqlSubQuery The SQL SubQuery
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
Expression ltSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
/**
* Not In - property has a value in the array of values.
*/
@@ -4,7 +4,7 @@ import io.avaje.lang.NonNullApi;
import io.avaje.lang.Nullable;
import io.ebean.search.*;
import jakarta.persistence.NonUniqueResultException;
import javax.persistence.NonUniqueResultException;
import java.sql.Connection;
import java.sql.Timestamp;
import java.util.*;
@@ -54,12 +54,14 @@ public interface ExpressionList<T> {
Query<T> orderById(boolean orderById);
/**
* @deprecated migrate to {@link #orderBy(String)}
* Set the order by clause replacing the existing order by clause if there is
* one.
* <p>
* This follows SQL syntax using commas between each property with the
* optional asc and desc keywords representing ascending and descending order
* respectively.
*/
@Deprecated(since = "13.19", forRemoval = true)
default ExpressionList<T> order(String orderByClause) {
return orderBy(orderByClause);
}
ExpressionList<T> order(String orderByClause);
/**
* Set the order by clause replacing the existing order by clause if there is
@@ -72,12 +74,15 @@ public interface ExpressionList<T> {
ExpressionList<T> orderBy(String orderBy);
/**
* @deprecated migrate to {@link #orderBy()}.
* Return the OrderBy so that you can append an ascending or descending
* property to the order by clause.
* <p>
* This will never return a null. If no order by clause exists then an 'empty'
* OrderBy object is returned.
* <p>
* This is the same as <code>orderBy()</code>
*/
@Deprecated(forRemoval = true)
default OrderBy<T> order() {
return orderBy();
}
OrderBy<T> order();
/**
* Return the OrderBy so that you can append an ascending or descending
@@ -90,6 +95,12 @@ public interface ExpressionList<T> {
*/
OrderBy<T> orderBy();
/**
* Deprecated migrate to {@link #orderBy(String)}
*/
@Deprecated
Query<T> setOrderBy(String orderBy);
/**
* Apply the path properties to the query replacing the select and fetch clauses.
*/
@@ -372,15 +383,6 @@ public interface ExpressionList<T> {
*/
<A> List<A> findSingleAttributeList();
/**
* Executes the query returning a set of values for a single property.
* <p>
* This can be used to cache sets.
*
* @return a HashSet of values for the selegted property
*/
<A> Set<A> findSingleAttributeSet();
/**
* Execute a query returning a single value of a single property/column.
* <pre>{@code
@@ -393,7 +395,6 @@ public interface ExpressionList<T> {
*
* }</pre>
*/
@Nullable
default <A> A findSingleAttribute() {
List<A> list = findSingleAttributeList();
return !list.isEmpty() ? list.get(0) : null;
@@ -508,8 +509,6 @@ public interface ExpressionList<T> {
ExpressionList<T> filterMany(String manyProperty);
/**
* @deprecated for removal - migrate to {@link #filterManyRaw(String, String, Object...)}.
* <p>
* Add filter expressions to the many property.
*
* <pre>{@code
@@ -526,29 +525,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).
@@ -843,40 +821,16 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> addAll(ExpressionList<T> exprList);
/**
* Equal To the result of a sub-query.
*/
ExpressionList<T> eq(String propertyName, Query<?> subQuery);
/**
* Equal To - property is equal to a given value.
*/
ExpressionList<T> eq(String propertyName, Object value);
/**
* Is EQUAL TO if value is non-null and otherwise no expression is added to the query.
* <p>
* This is the EQUAL TO equivalent to {@link #inOrEmpty(String, Collection)} where the expression/predicate
* is only added when the value is non-null.
* <p>
* This is effectively a helper method that allows a query to be built in fluid style where some predicates are
* effectively optional. We can use <code>eqIfPresent()</code> rather than having a separate if block.
* <p>
* Another option is to instead globally use {@link io.ebean.config.DatabaseConfig#setExpressionEqualsWithNullAsNoop(boolean)}
* but that is not always desirable.
*/
ExpressionList<T> eqIfPresent(String propertyName, @Nullable Object value);
/**
* Equal To or Null - property is equal to a given value or null.
*/
ExpressionList<T> eqOrNull(String propertyName, Object value);
/**
* Not Equal To the result of a sub-query.
*/
ExpressionList<T> ne(String propertyName, Query<?> subQuery);
/**
* Not Equal To - property not equal to the given value.
*/
@@ -913,23 +867,6 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> inRangeWith(String lowProperty, String highProperty, Object value);
/**
* A Property is in Range between 2 properties.
*
* <pre>{@code
*
* .orderDate.inRangeWith(QOrder.Alias.product.startDate, QOrder.Alias.product.endDate)
*
* // which equates to
* product.startDate <= orderDate and (orderDate < product.endDate or product.endDate is null)
*
* }</pre>
*
* <p>
* This is a convenience expression combining a number of simple expressions.
*/
ExpressionList<T> inRangeWithProperties(String propertyName, String lowProperty, String highProperty);
/**
* In Range - {@code property >= value1 and property < value2}.
* <p>
@@ -948,11 +885,6 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> betweenProperties(String lowProperty, String highProperty, Object value);
/**
* Greater Than the result of a sub-query.
*/
ExpressionList<T> gt(String propertyName, Query<?> subQuery);
/**
* Greater Than - property greater than the given value.
*/
@@ -964,17 +896,9 @@ public interface ExpressionList<T> {
ExpressionList<T> gtOrNull(String propertyName, Object value);
/**
* Is GREATER THAN if value is non-null and otherwise no expression is added to the query.
* <p>
* This is effectively a helper method that allows a query to be built in fluid style where some predicates are
* effectively optional. We can use <code>gtIfPresent()</code> rather than having a separate if block.
* Greater Than or Equal to OR Null - ({@code >= or null }).
*/
ExpressionList<T> gtIfPresent(String propertyName, @Nullable Object value);
/**
* Greater Than or Equal to the result of a sub-query.
*/
ExpressionList<T> ge(String propertyName, Query<?> subQuery);
ExpressionList<T> geOrNull(String propertyName, Object value);
/**
* Greater Than or Equal to - property greater than or equal to the given
@@ -982,25 +906,6 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> ge(String propertyName, Object value);
/**
* Greater Than or Equal to OR Null - ({@code >= or null }).
*/
ExpressionList<T> geOrNull(String propertyName, Object value);
/**
* Is GREATER THAN OR EQUAL TO if value is non-null and otherwise no expression is added to the query.
* <p>
* This is effectively a helper method that allows a query to be built in fluid style where some predicates are
* effectively optional. We can use <code>geIfPresent()</code> rather than having a separate if block.
*/
ExpressionList<T> geIfPresent(String propertyName, @Nullable Object value);
/**
* Less Than the result of a sub-query.
*/
ExpressionList<T> lt(String propertyName, Query<?> subQuery);
/**
* Less Than - property less than the given value.
*/
@@ -1011,36 +916,15 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> ltOrNull(String propertyName, Object value);
/**
* Is LESS THAN if value is non-null and otherwise no expression is added to the query.
* <p>
* This is effectively a helper method that allows a query to be built in fluid style where some predicates are
* effectively optional. We can use <code>ltIfPresent()</code> rather than having a separate if block.
*/
ExpressionList<T> ltIfPresent(String propertyName, @Nullable Object value);
/**
* Less Than or Equal to the result of a sub-query.
*/
ExpressionList<T> le(String propertyName, Query<?> subQuery);
/**
* Less Than or Equal to - property less than or equal to the given value.
*/
ExpressionList<T> le(String propertyName, Object value);
/**
* Less Than or Equal to OR Null - ({@code <= or null }).
*/
ExpressionList<T> leOrNull(String propertyName, Object value);
/**
* Is LESS THAN OR EQUAL TO if value is non-null and otherwise no expression is added to the query.
* <p>
* This is effectively a helper method that allows a query to be built in fluid style where some predicates are
* effectively optional. We can use <code>leIfPresent()</code> rather than having a separate if block.
* Less Than or Equal to - property less than or equal to the given value.
*/
ExpressionList<T> leIfPresent(String propertyName, @Nullable Object value);
ExpressionList<T> le(String propertyName, Object value);
/**
* Is Null - property is null.
@@ -1154,99 +1038,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.
*
* @param sqlSubQuery The SQL SubQuery
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
ExpressionList<T> exists(String sqlSubQuery, Object... bindValues);
/**
* Not EXISTS a raw SQL SubQuery.
*
* @param sqlSubQuery The SQL SubQuery
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
ExpressionList<T> notExists(String sqlSubQuery, Object... bindValues);
/**
* IN a raw SQL SubQuery.
*
* @param propertyName The bean property
* @param sqlSubQuery The SQL SubQuery
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
ExpressionList<T> inSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
/**
* Not IN a raw SQL SubQuery.
*
* @param propertyName The bean property
* @param sqlSubQuery The SQL SubQuery
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
ExpressionList<T> notInSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
/**
* Equal To a raw SQL SubQuery.
*
* @param propertyName The bean property
* @param sqlSubQuery The SQL SubQuery
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
ExpressionList<T> eqSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
/**
* Not Equal To a raw SQL SubQuery.
*
* @param propertyName The bean property
* @param sqlSubQuery The SQL SubQuery
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
ExpressionList<T> neSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
/**
* Greater Than a raw SQL SubQuery.
*
* @param propertyName The bean property
* @param sqlSubQuery The SQL SubQuery
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
ExpressionList<T> gtSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
/**
* Greater Than or Equal To a raw SQL SubQuery.
*
* @param propertyName The bean property
* @param sqlSubQuery The SQL SubQuery
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
ExpressionList<T> geSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
/**
* Less Than a raw SQL SubQuery.
*
* @param propertyName The bean property
* @param sqlSubQuery The SQL SubQuery
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
ExpressionList<T> ltSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
/**
* Less Than or Equal To a raw SQL SubQuery.
*
* @param propertyName The bean property
* @param sqlSubQuery The SQL SubQuery
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
ExpressionList<T> leSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
/**
* In - using a subQuery.
*/
@@ -1869,8 +1660,4 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> endNot();
/**
* Clears the current expression list.
*/
ExpressionList<T> clear();
}
@@ -1,21 +1,480 @@
package io.ebean;
import io.avaje.lang.Nullable;
import javax.persistence.NonUniqueResultException;
import java.time.Clock;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
/**
* The extended API for Database.
* <p>
* This provides the finder methods that take an explicit transaction rather than obtaining
* the transaction from the usual mechanism (which is ThreadLocal based).
* </p>
* <p>
* In general we only want to use this ExtendedServer API when we want to avoid / bypass
* the use of the mechanism to get the current transaction and instead explicitly supply
* the transaction to use.
* </p>
* <p>
* Note that in all cases the transaction supplied can be null and in this case the Database
* will use the normal mechanism to obtain the transaction to use.
* </p>
*/
public interface ExtendedServer {
/**
* Deprecated but no yet determined suitable replacement (to support testing only change of clock).
* <p>
* Return the NOW time from the Clock.
*/
long clockNow();
/**
* Set the Clock to use for <code>@WhenCreated</code> and <code>@WhenModified</code>.
* <p>
* Note that we only expect to change the Clock for testing purposes.
* </p>
*/
@Deprecated
void setClock(Clock clock);
/**
* Execute the query returning true if a row is found.
* <p>
* The query is executed using max rows of 1 and will only select the id property.
* This method is really just a convenient way to optimise a query to perform a
* 'does a row exist in the db' check.
* </p>
*
* <h2>Example:</h2>
* <pre>{@code
*
* boolean userExists = query().where().eq("email", "rob@foo.com").exists();
*
* }</pre>
*
* <h2>Example using a query bean:</h2>
* <pre>{@code
*
* boolean userExists = new QContact().email.equalTo("rob@foo.com").exists();
*
* }</pre>
*
* @return True if the query finds a matching row in the database
*/
<T> boolean exists(Query<T> ormQuery, Transaction transaction);
/**
* Return the number of 'top level' or 'root' entities this query should return.
*
* @see Query#findCount()
* @see Query#findFutureCount()
*/
<T> int findCount(Query<T> query, Transaction transaction);
/**
* Return the Id values of the query as a List.
*
* @see Query#findIds()
*/
<A, T> List<A> findIds(Query<T> query, Transaction transaction);
/**
* Return a QueryIterator for the query.
* <p>
* Generally using {@link #findEach(Query, Consumer, Transaction)} or
* {@link #findEachWhile(Query, Predicate, Transaction)} is preferred
* to findIterate(). The reason is that those methods automatically take care of
* closing the queryIterator (and the underlying jdbc statement and resultSet).
* <p>
* This is similar to findEach in that not all the result beans need to be held
* in memory at the same time and as such is good for processing large queries.
*
* @see Query#findIterate()
* @see Query#findEach(Consumer)
* @see Query#findEachWhile(Predicate)
*/
<T> QueryIterator<T> findIterate(Query<T> query, Transaction transaction);
/**
* Execute the query returning the result as a Stream.
* <p>
* Note that this can support very large queries iterating any number of results.
* To do so internally it can use multiple persistence contexts.
* <p>
* Note that the stream needs to be closed so use with try with resources.
* </p>
*/
<T> Stream<T> findStream(Query<T> query, Transaction transaction);
/**
* Execute the query visiting the each bean one at a time.
* <p>
* Unlike findList() this is suitable for processing a query that will return
* a very large resultSet. The reason is that not all the result beans need to be
* held in memory at the same time and instead processed one at a time.
* </p>
* <p>
* Internally this query using a PersistenceContext scoped to each bean (and the
* beans associated object graph).
* </p>
* <p>
* <pre>{@code
*
* DB.find(Order.class)
* .where().eq("status", Order.Status.NEW)
* .order().asc("id")
* .findEach((Order order) -> {
*
* // do something with the order bean
* System.out.println(" -- processing order ... " + order);
* });
*
* }</pre>
*
* @see Query#findEach(Consumer)
* @see Query#findEachWhile(Predicate)
*/
<T> void findEach(Query<T> query, Consumer<T> consumer, Transaction transaction);
/**
* Execute findEach with batch consumer.
*
* @see Query#findEach(int, Consumer)
*/
<T> void findEach(Query<T> query, int batch, Consumer<List<T>> consumer, Transaction t);
/**
* Execute the query visiting the each bean one at a time.
* <p>
* Compared to findEach() this provides the ability to stop processing the query
* results early by returning false for the Predicate.
* </p>
* <p>
* Unlike findList() this is suitable for processing a query that will return
* a very large resultSet. The reason is that not all the result beans need to be
* held in memory at the same time and instead processed one at a time.
* </p>
* <p>
* Internally this query using a PersistenceContext scoped to each bean (and the
* beans associated object graph).
* </p>
* <p>
* <pre>{@code
*
* DB.find(Order.class)
* .where().eq("status", Order.Status.NEW)
* .order().asc("id")
* .findEachWhile((Order order) -> {
*
* // do something with the order bean
* System.out.println(" -- processing order ... " + order);
*
* boolean carryOnProcessing = ...
* return carryOnProcessing;
* });
*
* }</pre>
*
* @see Query#findEach(Consumer)
* @see Query#findEachWhile(Predicate)
*/
<T> void findEachWhile(Query<T> query, Predicate<T> consumer, Transaction transaction);
/**
* Return versions of a @History entity bean.
* <p>
* Generally this query is expected to be a find by id or unique predicates query.
* It will execute the query against the history returning the versions of the bean.
* </p>
*/
<T> List<Version<T>> findVersions(Query<T> query, Transaction transaction);
/**
* Execute a query returning a list of beans.
* <p>
* Generally you are able to use {@link Query#findList()} rather than
* explicitly calling this method. You could use this method if you wish to
* explicitly control the transaction used for the query.
* </p>
* <p>
* <pre>{@code
*
* List<Customer> customers = DB.find(Customer.class)
* .where().ilike("name", "rob%")
* .findList();
*
* }</pre>
*
* @param <T> the type of entity bean to fetch.
* @param query the query to execute.
* @param transaction the transaction to use (can be null).
* @return the list of fetched beans.
* @see Query#findList()
*/
<T> List<T> findList(Query<T> query, Transaction transaction);
/**
* Execute find row count query in a background thread.
* <p>
* This returns a Future object which can be used to cancel, check the
* execution status (isDone etc) and get the value (with or without a
* timeout).
* </p>
*
* @param query the query to execute the row count on
* @param transaction the transaction (can be null).
* @return a Future object for the row count query
* @see Query#findFutureCount()
*/
<T> FutureRowCount<T> findFutureCount(Query<T> query, Transaction transaction);
/**
* Execute find Id's query in a background thread.
* <p>
* This returns a Future object which can be used to cancel, check the
* execution status (isDone etc) and get the value (with or without a
* timeout).
* </p>
*
* @param query the query to execute the fetch Id's on
* @param transaction the transaction (can be null).
* @return a Future object for the list of Id's
* @see Query#findFutureIds()
*/
<T> FutureIds<T> findFutureIds(Query<T> query, Transaction transaction);
/**
* Execute find list query in a background thread returning a FutureList object.
* <p>
* This returns a Future object which can be used to cancel, check the
* execution status (isDone etc) and get the value (with or without a timeout).
* <p>
* This query will execute in it's own PersistenceContext and using its own transaction.
* What that means is that it will not share any bean instances with other queries.
*
* @param query the query to execute in the background
* @param transaction the transaction (can be null).
* @return a Future object for the list result of the query
* @see Query#findFutureList()
*/
<T> FutureList<T> findFutureList(Query<T> query, Transaction transaction);
/**
* Return a PagedList for this query using firstRow and maxRows.
* <p>
* The benefit of using this over findList() is that it provides functionality to get the
* total row count etc.
* </p>
* <p>
* If maxRows is not set on the query prior to calling findPagedList() then a
* PersistenceException is thrown.
* </p>
* <p>
* <pre>{@code
*
* PagedList<Order> pagedList = DB.find(Order.class)
* .setFirstRow(50)
* .setMaxRows(20)
* .findPagedList();
*
* // fetch the total row count in the background
* pagedList.loadRowCount();
*
* List<Order> orders = pagedList.getList();
* int totalRowCount = pagedList.getTotalRowCount();
*
* }</pre>
*
* @return The PagedList
* @see Query#findPagedList()
*/
<T> PagedList<T> findPagedList(Query<T> query, Transaction transaction);
/**
* Execute the query returning a set of entity beans.
* <p>
* Generally you are able to use {@link Query#findSet()} rather than
* explicitly calling this method. You could use this method if you wish to
* explicitly control the transaction used for the query.
* </p>
* <p>
* <pre>{@code
*
* Set<Customer> customers = DB.find(Customer.class)
* .where().ilike("name", "rob%")
* .findSet();
*
* }</pre>
*
* @param <T> the type of entity bean to fetch.
* @param query the query to execute
* @param transaction the transaction to use (can be null).
* @return the set of fetched beans.
* @see Query#findSet()
*/
<T> Set<T> findSet(Query<T> query, Transaction transaction);
/**
* Execute the query returning the entity beans in a Map.
* <p>
* Generally you are able to use {@link Query#findMap()} rather than
* explicitly calling this method. You could use this method if you wish to
* explicitly control the transaction used for the query.
* </p>
*
* @param <T> the type of entity bean to fetch.
* @param query the query to execute.
* @param transaction the transaction to use (can be null).
* @return the map of fetched beans.
* @see Query#findMap()
*/
<K, T> Map<K, T> findMap(Query<T> query, Transaction transaction);
/**
* Execute the query returning a list of values for a single property.
* <p>
* <h3>Example 1:</h3>
* <pre>{@code
*
* List<String> names =
* DB.find(Customer.class)
* .select("name")
* .order().asc("name")
* .findSingleAttributeList();
*
* }</pre>
* <h3>Example 2:</h3>
* <pre>{@code
*
* List<String> names =
* DB.find(Customer.class)
* .setDistinct(true)
* .select("name")
* .where().eq("status", Customer.Status.NEW)
* .order().asc("name")
* .setMaxRows(100)
* .findSingleAttributeList();
*
* }</pre>
*
* @return the list of values for the selected property
* @see Query#findSingleAttributeList()
*/
<A, T> List<A> findSingleAttributeList(Query<T> query, Transaction transaction);
/**
* Execute the query returning at most one entity bean or null (if no matching
* bean is found).
* <p>
* This will throw a NonUniqueResultException if the query finds more than one result.
* </p>
* <p>
* Generally you are able to use {@link Query#findOne()} rather than
* explicitly calling this method. You could use this method if you wish to
* explicitly control the transaction used for the query.
* </p>
*
* @param <T> the type of entity bean to fetch.
* @param query the query to execute.
* @param transaction the transaction to use (can be null).
* @return the list of fetched beans.
* @throws NonUniqueResultException if more than one result was found
* @see Query#findOne()
*/
@Nullable
<T> T findOne(Query<T> query, Transaction transaction);
/**
* Similar to findOne() but returns an Optional (rather than nullable).
*/
<T> Optional<T> findOneOrEmpty(Query<T> query, Transaction transaction);
/**
* Execute as a delete query deleting the 'root level' beans that match the predicates
* in the query.
* <p>
* Note that if the query includes joins then the generated delete statement may not be
* optimal depending on the database platform.
* </p>
*
* @param query the query used for the delete
* @param transaction the transaction to use (can be null)
* @param <T> the type of entity bean to fetch.
* @return the number of beans/rows that were deleted
*/
<T> int delete(Query<T> query, Transaction transaction);
/**
* Execute the update query returning the number of rows updated.
* <p>
* The update query must be created using {@link Database#update(Class)}.
* </p>
*
* @param query the update query to execute
* @param transaction the optional transaction to use for the update (can be null)
* @param <T> the type of entity bean
* @return The number of rows updated
*/
<T> int update(Query<T> query, Transaction transaction);
/**
* Execute the sql query returning a list of MapBean.
* <p>
* Generally you are able to use {@link SqlQuery#findList()} rather than
* explicitly calling this method. You could use this method if you wish to
* explicitly control the transaction used for the query.
* </p>
*
* @param query the query to execute.
* @param transaction the transaction to use (can be null).
* @return the list of fetched MapBean.
* @see SqlQuery#findList()
*/
List<SqlRow> findList(SqlQuery query, Transaction transaction);
/**
* Execute the SqlQuery iterating a row at a time.
* <p>
* This streaming type query is useful for large query execution as only 1 row needs to be held in memory.
* </p>
*/
void findEach(SqlQuery query, Consumer<SqlRow> consumer, Transaction transaction);
/**
* Execute the SqlQuery iterating a row at a time with the ability to stop consuming part way through.
* <p>
* Returning false after processing a row stops the iteration through the query results.
* </p>
* <p>
* This streaming type query is useful for large query execution as only 1 row needs to be held in memory.
* </p>
*/
void findEachWhile(SqlQuery query, Predicate<SqlRow> consumer, Transaction transaction);
/**
* Execute the sql query returning a single MapBean or null.
* <p>
* This will throw a PersistenceException if the query found more than one
* result.
* </p>
* <p>
* Generally you are able to use {@link SqlQuery#findOne()} rather than
* explicitly calling this method. You could use this method if you wish to
* explicitly control the transaction used for the query.
* </p>
*
* @param query the query to execute.
* @param transaction the transaction to use (can be null).
* @return the fetched MapBean or null if none was found.
* @see SqlQuery#findOne()
*/
@Nullable
SqlRow findOne(SqlQuery query, Transaction transaction);
}
@@ -8,9 +8,6 @@ import java.util.List;
* Intended to be used as a base class for 'Finder' implementations that can then
* be injected or used as public static fields on the associated entity bean.
* <p>
* When using dependency injection {@link BeanRepository} and {@link BeanFinder}
* are expected to be used rather than this Finder.
* <p>
* These 'finders' are a place to organise all the finder methods for that bean type
* and specific finder methods are expected to be added (find by unique properties etc).
* </p>
@@ -57,8 +54,6 @@ import java.util.List;
*
* }</pre>
*
* @see BeanRepository
* @see BeanFinder
*/
@NonNullApi
public class Finder<I, T> {
@@ -1,6 +1,6 @@
package io.ebean;
import jakarta.persistence.PersistenceException;
import javax.persistence.PersistenceException;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
@@ -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,119 +0,0 @@
package io.ebean;
import io.avaje.lang.Nullable;
/**
* Options to be used with insert such as ON CONFLICT DO UPDATE | NOTHING.
*/
public interface InsertOptions {
/**
* Use ON CONFLICT UPDATE with automatic determination of the unique columns to conflict on.
* <p>
* Uses mapping to determine the unique columns - {@code @Column(unique=true)} and {@code @Index(unique=true)} .
*/
InsertOptions ON_CONFLICT_UPDATE = InsertOptions.builder()
.onConflictUpdate()
.build();
/**
* Use ON CONFLICT DO NOTHING with automatic determination of the unique columns to conflict on.
* <p>
* Uses mapping to determine the unique columns - {@code @Column(unique=true)} and {@code @Index(unique=true)} .
*/
InsertOptions ON_CONFLICT_NOTHING = InsertOptions.builder()
.onConflictNothing()
.build();
/**
* Return a builder for InsertOptions.
*/
static Builder builder() {
return new DInsertOptionsBuilder();
}
/**
* Return the constraint name that is used for ON CONFLICT.
*/
@Nullable
String constraint();
/**
* Return the unique columns that is used for ON CONFLICT.
* <p>
* When not explicitly set will use mapping like {@code @Column(unique=true)} to determine the
* non-unique columns.
*/
@Nullable
String uniqueColumns();
/**
* Return the ON CONFLICT UPDATE SET clause.
* <p>
* When not set will use the non-unique columns.
*/
@Nullable
String updateSet();
/**
* Return if GetGeneratedKeys should be used to fetch the generated keys after insert.
*/
@Nullable
Boolean getGetGeneratedKeys();
/**
* Return the key for these build options.
*/
String key();
/**
* The builder for InsertOptions.
*/
interface Builder {
/**
* Use a ON CONFLICT UPDATE automatically determining the unique columns.
*/
Builder onConflictUpdate();
/**
* Use a ON CONFLICT DO NOTHING automatically determining the unique columns.
*/
Builder onConflictNothing();
/**
* Specify an explicit conflict constraint name.
* <p>
* When this is used then unique columns will not be used.
*/
Builder constraint(String constraint);
/**
* Specify the unique columns for the conflict target.
* <p>
* When not specified and constraint is also not specified then
* it will automatically determine the unique columns
* based on mapping like {@code @Column(unique=true)} and
* {@code @Index(unique=true)} .
*/
Builder uniqueColumns(String uniqueColumns);
/**
* Specify the ON CONFLICT DO UPDATE SET clause.
* <p>
* When not specified ebean will include all the non-unique columns.
*/
Builder updateSet(String updateSet);
/**
* Specify if GetGeneratedKeys should be used to return generated keys.
*/
Builder getGeneratedKeys(boolean getGeneratedKeys);
/**
* Build and return the insert options.
*/
InsertOptions build();
}
}
@@ -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;
}
}
+20 -2
View File
@@ -231,6 +231,18 @@ public class OrderBy<T> implements Serializable {
return this;
}
/**
* Return true if this order by can be used in select clause.
*/
public boolean supportsSelect() {
for (Property property : list) {
if (!property.supportsSelect()) {
return false;
}
}
return true;
}
/**
* A property and its ascending descending order.
*/
@@ -333,10 +345,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();
}
@@ -391,6 +403,12 @@ public class OrderBy<T> implements Serializable {
this.ascending = ascending;
}
/**
* Support use in select clause if no collation or nulls ordering.
*/
boolean supportsSelect() {
return nulls == null;
}
}
private void parse(String orderByClause) {
@@ -1,6 +1,6 @@
package io.ebean;
import jakarta.persistence.PersistenceException;
import javax.persistence.PersistenceException;
/**
* Captures and wraps IOException's occurring during ElasticSearch processing etc.
@@ -17,17 +17,17 @@ public interface ProfileLocation {
}
/**
* Create and return a new ProfileLocation with line number.
* Create and return a new ProfileLocation with a given lineNumber and label.
*/
static ProfileLocation createWithLine() {
return XServiceProvider.profileLocationFactory().createWithLine();
static ProfileLocation create(int lineNumber, String label) {
return XServiceProvider.profileLocationFactory().create(lineNumber, label);
}
/**
* Create and return a new ProfileLocation with a given lineNumber and label.
* Create and return a new ProfileLocation with a given location.
*/
static ProfileLocation create(String label) {
return XServiceProvider.profileLocationFactory().create(label);
static ProfileLocation createAt(String location) {
return XServiceProvider.profileLocationFactory().createAt(location);
}
/**
+23 -92
View File
@@ -3,15 +3,13 @@ package io.ebean;
import io.avaje.lang.NonNullApi;
import io.avaje.lang.Nullable;
import jakarta.persistence.NonUniqueResultException;
import javax.sql.DataSource;
import javax.persistence.NonUniqueResultException;
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.DatabaseBuilder#readOnlyDataSource(DataSource)} then
* by default when a query is run without an active transaction, it uses the read-only data
* source. 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>
@@ -950,12 +926,7 @@ public interface Query<T> extends CancelableQuery {
<A> List<A> findSingleAttributeList();
/**
* Execute the query returning a hashset of values for a single property.
*/
<A> Set<A> findSingleAttributeSet();
/**
* Execute a query returning a single value or null for a single property/column.
* Execute a query returning a single value of a single property/column.
* <p>
* <pre>{@code
*
@@ -967,28 +938,8 @@ public interface Query<T> extends CancelableQuery {
*
* }</pre>
*/
@Nullable
<A> A findSingleAttribute();
/**
* Execute the query returning a single optional attribute value.
* <p>
* <h3>Example</h3>
* <pre>{@code
*
* Optional<String> maybeName =
* new QCustomer()
* .select(name)
* .id.eq(42)
* .status.eq(NEW)
* .findSingleAttributeOrEmpty();
*
* }</pre>
*
* @return an optional value for the selected property
*/
<A> Optional<A> findSingleAttributeOrEmpty();
/**
* Return true if this is countDistinct query.
*/
@@ -1415,9 +1366,13 @@ public interface Query<T> extends CancelableQuery {
Query<T> orderBy(String orderByClause);
/**
* @deprecated migrate to {@link #orderBy()}.
* Set the order by clause replacing the existing order by clause if there is
* one.
* <p>
* This follows SQL syntax using commas between each property with the
* optional asc and desc keywords representing ascending and descending order
* respectively.
*/
@Deprecated(since = "13.19", forRemoval = true)
default Query<T> order(String orderByClause) {
return orderBy(orderByClause);
}
@@ -1434,9 +1389,14 @@ public interface Query<T> extends CancelableQuery {
OrderBy<T> orderBy();
/**
* @deprecated migrate to {@link #orderBy()}.
* Return the OrderBy so that you can append an ascending or descending
* property to the order by clause.
* <p>
* This will never return a null. If no order by clause exists then an 'empty'
* OrderBy object is returned.
* <p>
* This is the same as <code>orderBy()</code>
*/
@Deprecated(since = "13.19", forRemoval = true)
default OrderBy<T> order() {
return orderBy();
}
@@ -1447,9 +1407,8 @@ public interface Query<T> extends CancelableQuery {
Query<T> setOrderBy(OrderBy<T> orderBy);
/**
* @deprecated migrate to {@link #setOrderBy(OrderBy)}.
* Set an OrderBy object to replace any existing OrderBy clause.
*/
@Deprecated(since = "13.19", forRemoval = true)
default Query<T> setOrder(OrderBy<T> orderBy) {
return setOrderBy(orderBy);
}
@@ -1601,14 +1560,6 @@ public interface Query<T> extends CancelableQuery {
*/
Query<T> setLabel(String label);
/**
* Set a SQL query hint.
* <p>
* This results in an inline comment that immediately follows
* after the select keyword in the form: {@code /*+ hint *\/ }
*/
Query<T> setHint(String hint);
/**
* Set to true if this query should execute against the doc store.
* <p>
@@ -1622,6 +1573,13 @@ public interface Query<T> extends CancelableQuery {
*/
Query<T> setReadOnly(boolean readOnly);
/**
* Will be deprecated - migrate to use setBeanCacheMode(CacheMode.RECACHE).
* <p>
* When set to true all the beans from this query are loaded into the bean cache.
*/
Query<T> setLoadBeanCache(boolean loadBeanCache);
/**
* Set a timeout on this query.
* <p>
@@ -1803,31 +1761,4 @@ public interface Query<T> extends CancelableQuery {
*/
Query<T> orderById(boolean orderById);
/**
* Type safe query bean properties and expressions (marker interface).
* <p>
* Implemented by query bean properties and expressions based on those properties.
* <p>
* The base type determines which {@link StdOperators} can be used on the property.
*
* @param <T> The property type.
*/
interface Property<T> {
/**
* Return a property given the expression.
*/
static <T> Property<T> of(String expression) {
return new SimpleProperty<>(expression);
}
/**
* Return the property in string expression form.
* <p>
* This is a path to a database column (like "name" or "billingAddress.city") or a function
* wrapping a path (like <em>lower(name)</em>, <em>concat(name, '-', billingAddress.city)</em>
*/
@Override
String toString();
}
}
@@ -1,6 +1,6 @@
package io.ebean;
import jakarta.persistence.OptimisticLockException;
import javax.persistence.OptimisticLockException;
/**
* Thrown at SERIALIZABLE isolation level for non-recoverable concurrent conflict.
@@ -1,15 +0,0 @@
package io.ebean;
final class SimpleProperty<T> implements Query.Property<T> {
private final String expression;
SimpleProperty(String expression) {
this.expression = expression;
}
@Override
public String toString() {
return expression;
}
}
+1 -30
View File
@@ -2,10 +2,8 @@ package io.ebean;
import io.avaje.lang.NonNullApi;
import io.avaje.lang.Nullable;
import javax.sql.DataSource;
import java.io.Serializable;
import java.sql.Connection;
import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
@@ -42,28 +40,6 @@ import java.util.function.Predicate;
@NonNullApi
public interface SqlQuery extends Serializable, CancelableQuery {
/**
* Execute the query using the given transaction.
*/
SqlQuery usingTransaction(Transaction transaction);
/**
* Execute the query using the given connection.
*/
SqlQuery usingConnection(Connection connection);
/**
* 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.DatabaseBuilder#readOnlyDataSource(DataSource)}then
* by default when a query is run without an active transaction, it uses the read-only data
* source. 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.
*/
@@ -322,11 +298,6 @@ public interface SqlQuery extends Serializable, CancelableQuery {
*/
interface TypeQuery<T> {
/**
* Execute the query using the given transaction.
*/
TypeQuery<T> usingTransaction(Transaction transaction);
/**
* Return the single value.
*/
@@ -1,331 +0,0 @@
package io.ebean;
import io.ebean.Query.Property;
import java.util.Collection;
/**
* Standard Operators for use with strongly typed query construction.
* <p>
* This is currently deemed to be experimental and subject to change.
*/
public final class StdOperators {
// ---- Functions ---- //
/**
* Sum of the given property.
*/
public static Property<Number> sum(Property<? extends Number> property) {
return Property.of("sum(" + property + ")");
}
/**
* Count of the given property.
*/
public static Property<Number> count(Property<?> property) {
return Property.of("count(" + property + ")");
}
/**
* Average of the given property.
*/
public static <T> Property<T> avg(Property<T> property) {
return Property.of("avg(" + property + ")");
}
/**
* Max of the given property.
*/
public static <T> Property<T> max(Property<T> property) {
return Property.of("max(" + property + ")");
}
/**
* Min of the given property.
*/
public static <T> Property<T> min(Property<T> property) {
return Property.of("min(" + property + ")");
}
/**
* Coalesce of the property and value.
*/
public static <T> Property<T> coalesce(Property<T> property, Object value) {
return Property.of("coalesce(" + property.toString() + "," + sqlValue(value) + ")");
}
/**
* Lower of the given property.
*/
public static Property<String> lower(Property<String> property) {
return Property.of("lower(" + property + ")");
}
/**
* Upper of the given property.
*/
public static Property<String> upper(Property<String> property) {
return Property.of("upper(" + property + ")");
}
/**
* Concat of the given property and values or other properties.
*/
public static Property<String> concat(Property<?> property, Object... values) {
StringBuilder expression = new StringBuilder(50);
expression.append("concat(").append(property.toString());
for (Object value : values) {
expression.append(',').append(sqlConcatString(value));
}
expression.append(')');
return Property.of(expression.toString());
}
private static String sqlConcatString(Object value) {
if (value instanceof Property) {
return value.toString();
} else {
return sqlQuote(value);
}
}
/**
* Allows numbers to be unquoted.
*/
private static String sqlValue(Object value) {
if (value instanceof Property || value instanceof Number) {
return value.toString();
} else {
return sqlQuote(value);
}
}
/**
* SQL quoted escaping single quotes.
*/
private static String sqlQuote(Object value) {
return "'" + String.valueOf(value).replace("'", "''") + "'";
}
// ---- Operators ---- //
/**
* Equal to - for a property and value.
*/
public static <T> Expression eq(Property<T> property, T value) {
return Expr.eq(property.toString(), value);
}
/**
* Equal to - for a property and sub-query.
*/
public static <T> Expression eq(Property<T> property, Query<?> subQuery) {
return Expr.in(property.toString(), subQuery);
}
/**
* Equal to or null - for a property and value.
*/
public static <T> Expression eqOrNull(Property<T> property, T value) {
return Expr.factory().eqOrNull(property.toString(), value);
}
/**
* Not equal to - for a property and value.
*/
public static <T> Expression ne(Property<T> property, T value) {
return Expr.ne(property.toString(), value);
}
/**
* Not equal to - for a property and sub-query.
*/
public static <T> Expression ne(Property<T> property, Query<?> subQuery) {
return Expr.ne(property.toString(), subQuery);
}
/**
* Greater than - for a property and value.
*/
public static <T> Expression gt(Property<T> property, T value) {
return Expr.gt(property.toString(), value);
}
/**
* Greater than - for a property and sub-query.
*/
public static <T> Expression gt(Property<T> property, Query<?> subQuery) {
return Expr.gt(property.toString(), subQuery);
}
/**
* Greater than or null - for a property and value.
*/
public static <T> Expression gtOrNull(Property<T> property, T value) {
return Expr.factory().gtOrNull(property.toString(), value);
}
/**
* Greater than or equal to - for a property and value.
*/
public static <T> Expression ge(Property<T> property, T value) {
return Expr.ge(property.toString(), value);
}
/**
* Greater than or equal to - for a property and sub-query.
*/
public static <T> Expression ge(Property<T> property, Query<?> subQuery) {
return Expr.ge(property.toString(), subQuery);
}
/**
* Greater than or null - for a property and value.
*/
public static <T> Expression geOrNull(Property<T> property, T value) {
return Expr.factory().geOrNull(property.toString(), value);
}
/**
* Less than - for a property and value.
*/
public static <T> Expression lt(Property<T> property, T value) {
return Expr.lt(property.toString(), value);
}
/**
* Less than - for a property and sub-query.
*/
public static <T> Expression lt(Property<T> property, Query<?> subQuery) {
return Expr.lt(property.toString(), subQuery);
}
/**
* Less than or null - for a property and value.
*/
public static <T> Expression ltOrNull(Property<T> property, T value) {
return Expr.factory().ltOrNull(property.toString(), value);
}
/**
* Greater than or equal to - for a property and value.
*/
public static <T> Expression le(Property<T> property, T value) {
return Expr.le(property.toString(), value);
}
/**
* Greater than or equal to - for a property and sub-query.
*/
public static <T> Expression le(Property<T> property, Query<?> subQuery) {
return Expr.le(property.toString(), subQuery);
}
/**
* Greater than or equal to or null - for a property and value.
*/
public static <T> Expression leOrNull(Property<T> property, T value) {
return Expr.factory().leOrNull(property.toString(), value);
}
/**
* In range - for a property and values.
*/
public static <T> Expression inRange(Property<T> property, T lowValue, T highValue) {
return Expr.factory().inRange(property.toString(), lowValue, highValue);
}
/**
* In range - for properties and a value.
*/
public static <T> Expression inRange(Property<T> lowProperty, Property<T> highProperty, T value) {
return Expr.factory().inRangeWith(lowProperty.toString(), highProperty.toString(), value);
}
/**
* In range - for properties.
*/
public static <T> Expression inRange(Property<T> lowProperty, Property<T> property, Property<T> highProperty) {
return Expr.factory().inRangeWithProperties(lowProperty.toString(), property.toString(), highProperty.toString());
}
/**
* In - for a given property and collection of values.
*/
public static <T> Expression in(Property<T> property, Collection<T> value) {
return Expr.in(property.toString(), value);
}
/**
* In - for a given property and sub-query.
*/
public static <T> Expression in(Property<T> property, Query<?> subQuery) {
return Expr.in(property.toString(), subQuery);
}
/**
* In or empty - for a given property and collection of values.
*/
public static <T> Expression inOrEmpty(Property<T> property, Collection<T> value) {
return Expr.inOrEmpty(property.toString(), value);
}
/**
* Not In - for a given property and collection of values.
*/
public static <T> Expression notIn(Property<T> property, Collection<T> value) {
return Expr.factory().notIn(property.toString(), value);
}
/**
* Not In - for a given property and sub-query.
*/
public static <T> Expression notIn(Property<T> property, Query<?> subQuery) {
return Expr.factory().notIn(property.toString(), subQuery);
}
// ---- String operators ---- //
/**
* Like - for a given property and value.
*/
public static Expression like(Property<String> property, String value) {
return Expr.like(property.toString(), value);
}
/**
* Case-insensitive Like - for a given property and value.
*/
public static Expression ilike(Property<String> property, String value) {
return Expr.ilike(property.toString(), value);
}
/**
* Starts with - for a given property and value.
*/
public static Expression startsWith(Property<String> property, String value) {
return Expr.startsWith(property.toString(), value);
}
/**
* Case-insensitive starts with - for a given property and value.
*/
public static Expression istartsWith(Property<String> property, String value) {
return Expr.istartsWith(property.toString(), value);
}
/**
* Contains - for a given property and value.
*/
public static Expression contains(Property<String> property, String value) {
return Expr.contains(property.toString(), value);
}
/**
* Case-insensitive contains - for a given property and value.
*/
public static Expression icontains(Property<String> property, String value) {
return Expr.icontains(property.toString(), value);
}
}
@@ -5,7 +5,7 @@ import io.ebean.annotation.PersistBatch;
import io.ebean.config.DatabaseConfig;
import io.ebean.config.DocStoreConfig;
import jakarta.persistence.PersistenceException;
import javax.persistence.PersistenceException;
import java.sql.Connection;
/**
@@ -144,35 +144,6 @@ public interface Transaction extends AutoCloseable {
*/
void rollback(Throwable e) throws PersistenceException;
/**
* Performs a rollback on the underlying JDBC connection with the intention of
* continuing to use this same transaction and performing a commit or rollback
* later to complete the transaction.
* <p>
* Typically used when catching {@link DuplicateKeyException} where we wish to
* rollback work done at that point but carry on processing using the transaction.
*
* <pre>{@code
*
* try (Transaction txn = database.beginTransaction()) {
*
* try {
* ...
* database.save(bean);
* database.flush();
* } catch (DuplicateKeyException e) {
* // carry on processing using the transaction
* txn.rollbackAndContinue();
* ...
* }
*
* txn.commit();
* }
*
* }</pre>
*/
void rollbackAndContinue();
/**
* Set when we want nested transactions to use Savepoint's.
* <p>
@@ -14,7 +14,7 @@ package io.ebean;
*
* int rows = DB.update(Customer.class)
* .set("status", Customer.Status.ACTIVE)
* .set("whenUpdated", Instant.now())
* .set("updtime", new Timestamp(System.currentTimeMillis()))
* .where()
* .gt("id", 1000)
* .update();
@@ -25,20 +25,6 @@ package io.ebean;
* update o_customer set status=?, updtime=? where id > ?
*
* }</pre>
*
* <h4>Example: Using query bean</h4>
* <pre>{@code
*
* var cust = QCustomer.alias();
*
* int rows = new QCustomer()
* .id.gt(1000)
* .asUpdate()
* .set(cust.status, Customer.Status.COMPLETE)
* .set(cust.whenUpdated, Instant.now())
* .update();
*
* }</pre>
* <p>
* Note that if the where() clause contains a join then the SQL update changes to use a
* <code> WHERE ID IN () </code> form.
@@ -54,7 +40,7 @@ package io.ebean;
*
* int rows = DB.update(Customer.class)
* .set("status", Customer.Status.ACTIVE)
* .set("whenUpdated", Instant.now())
* .set("updtime", new Timestamp(System.currentTimeMillis()))
* .where()
* .eq("status", Customer.Status.NEW)
* .eq("billingAddress.country", nz)
@@ -87,7 +73,7 @@ public interface UpdateQuery<T> {
*
* int rows = DB.update(Customer.class)
* .set("status", Customer.Status.ACTIVE)
* .set("whenUpdated", Instant.now())
* .set("updtime", new Timestamp(System.currentTimeMillis()))
* .where()
* .gt("id", 1000)
* .update();
@@ -99,27 +85,6 @@ public interface UpdateQuery<T> {
*/
UpdateQuery<T> set(String property, Object value);
/**
* Set the value of a property.
* <p>
* <pre>{@code
*
* var cust = QCustomer.alias();
*
* int rows = new QCustomer()
* .id.gt(1000)
* .asUpdate()
* .set(cust.status, Customer.Status.COMPLETE)
* .set(cust.whenUpdated, Instant.now())
* .update();
*
* }</pre>
*
* @param property The bean property to be set
* @param value The value to set the property to
*/
<P> UpdateQuery<T> set(Query.Property<P> property, P value);
/**
* Set the property to be null.
* <p>
@@ -137,13 +102,6 @@ public interface UpdateQuery<T> {
*/
UpdateQuery<T> setNull(String property);
/**
* Set the property to be null.
*
* @param property The bean property to be set
*/
UpdateQuery<T> setNull(Query.Property<?> property);
/**
* Set using a property expression that does not need any bind values.
* <p>
@@ -77,12 +77,12 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
/**
* Return the bean that owns this collection.
*/
EntityBean owner();
EntityBean getOwnerBean();
/**
* Return the bean property name this collection represents.
*/
String propertyName();
String getPropertyName();
/**
* Check after the lazy load that the underlying collection is not null
@@ -99,7 +99,7 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
* This is so that the filter can be applied on refresh.
* </p>
*/
ExpressionList<?> filterMany();
ExpressionList<?> getFilterMany();
/**
* Set the filter that was used in building this collection.
@@ -154,7 +154,7 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
/**
* Returns the underlying collection of beans from the Set, Map or List.
*/
Collection<E> actualDetails();
Collection<E> getActualDetails();
/**
* Returns the underlying entries so for Maps this is a collection of
@@ -162,7 +162,7 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
* <p>
* For maps this returns the entrySet as we need the keys of the map.
*/
Collection<?> actualEntries();
Collection<?> getActualEntries();
/**
* return true if there are real rows held. Return false is this is using
@@ -195,7 +195,7 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
/**
* Return the current modify listening mode. Can be null for on newly created beans.
*/
ModifyListenMode modifyListening();
ModifyListenMode getModifyListening();
/**
* Add an object to the additions list.
@@ -217,13 +217,13 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
* Return the list of objects added to the list set or map. These will used to
* insert rows into the intersection table of a ManyToMany.
*/
Set<E> modifyAdditions();
Set<E> getModifyAdditions();
/**
* Return the list of objects removed from the list set or map. These will
* used to delete rows from the intersection table of a ManyToMany.
*/
Set<E> modifyRemovals();
Set<E> getModifyRemovals();
/**
* Reset the set of additions and deletions. This is called after the
@@ -239,5 +239,5 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
/**
* Return a shallow copy of this collection that is modifiable.
*/
BeanCollection<E> shallowCopy();
BeanCollection<E> getShallowCopy();
}
@@ -13,7 +13,7 @@ public interface BeanLoader {
/**
* Return the name of the associated Database.
*/
String name();
String getName();
/**
* Invoke the lazy loading for this bean.
@@ -8,15 +8,15 @@ public interface CallOrigin {
/**
* Return the top element. Typically the top stack element with class and line.
*/
String top();
String getTopElement();
/**
* Return the full description of the call origin.
*/
String description();
String getFullDescription();
/**
* Compute and return an origin key based on the query hash.
*/
String key(int queryHash);
String getOriginKey(int queryHash);
}
@@ -2,7 +2,6 @@ package io.ebean.bean;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import static io.ebean.util.EncodeB64.enc;
@@ -28,27 +27,20 @@ public final class CallStack implements Serializable, CallOrigin {
private final String zeroHash;
private final String pathHash;
private final Object[] callStack;
private final StackTraceElement[] callStack;
private final int hc;
public CallStack(Object[] callStack, int zeroHash, int pathHash) {
public CallStack(StackTraceElement[] callStack, int zeroHash, int pathHash) {
this.callStack = callStack;
this.hc = computeHashCode();
this.zeroHash = enc(zeroHash);
this.pathHash = enc(pathHash);
}
public CallStack(List<StackWalker.StackFrame> frames) {
this.callStack = frames.toArray(new Object[0]);
this.hc = computeHashCode();
this.zeroHash = enc(callStack[0].toString().hashCode());
this.pathHash = enc(hc);
}
private int computeHashCode() {
int hc = 0;
for (Object element : callStack) {
hc = 92821 * hc + element.toString().hashCode();
for (StackTraceElement element : callStack) {
hc = 92821 * hc + element.hashCode();
}
return hc;
}
@@ -79,7 +71,7 @@ public final class CallStack implements Serializable, CallOrigin {
* Return the first element of the call stack.
*/
@Override
public String top() {
public String getTopElement() {
return callStack[0].toString();
}
@@ -87,7 +79,7 @@ public final class CallStack implements Serializable, CallOrigin {
* Return the call stack lines appended with the given newLine string.
*/
@Override
public String description() {
public String getFullDescription() {
StringBuilder sb = new StringBuilder(400);
for (int i = 0; i < callStack.length; i++) {
if (i > 0) {
@@ -99,7 +91,7 @@ public final class CallStack implements Serializable, CallOrigin {
}
@Override
public String key(int queryHash) {
public String getOriginKey(int queryHash) {
return enc(queryHash) + "." + zeroHash + "." + pathHash;
}
@@ -6,23 +6,17 @@ import java.io.Serializable;
import java.util.Map;
import java.util.Set;
/**
* This is the object associated to every entity bean using byte code enhancement.
* <p>
* This provides per property state such as loaded state, changed state, original values
* as well as bean level dirty state etc.
*/
public interface EntityBeanIntercept extends Serializable {
/**
* Return the 'owning' entity bean.
*/
EntityBean owner();
EntityBean getOwner();
/**
* Return the persistenceContext.
*/
PersistenceContext persistenceContext();
PersistenceContext getPersistenceContext();
/**
* Set the persistenceContext.
@@ -37,7 +31,7 @@ public interface EntityBeanIntercept extends Serializable {
/**
* Return the ownerId (IdClass).
*/
Object ownerId();
Object getOwnerId();
/**
* Set the ownerId (IdClass).
@@ -47,12 +41,12 @@ public interface EntityBeanIntercept extends Serializable {
/**
* Return the owning bean for an embedded bean.
*/
Object embeddedOwner();
Object getEmbeddedOwner();
/**
* Return the property index (for the parent) of this embedded bean.
*/
int embeddedOwnerIndex();
int getEmbeddedOwnerIndex();
/**
* Clear the getter callback.
@@ -229,7 +223,7 @@ public interface EntityBeanIntercept extends Serializable {
/**
* Return the original value that was changed via an update.
*/
Object origValue(int propertyIndex);
Object getOrigValue(int propertyIndex);
/**
* Finds the index position of a given property. Returns -1 if the
@@ -240,12 +234,12 @@ public interface EntityBeanIntercept extends Serializable {
/**
* Return the property name for the given property.
*/
String property(int propertyIndex);
String getProperty(int propertyIndex);
/**
* Return the number of properties.
*/
int propertyLength();
int getPropertyLength();
/**
* Set the loaded state of the property given it's name.
@@ -288,14 +282,8 @@ public interface EntityBeanIntercept extends Serializable {
*/
void markPropertyAsChanged(int propertyIndex);
/**
* Set the changed state for the given property.
*/
void setChangedProperty(int propertyIndex);
/**
* Set the changed and loaded state for the given property.
*/
void setChangeLoaded(int propertyIndex);
/**
@@ -303,9 +291,6 @@ public interface EntityBeanIntercept extends Serializable {
*/
void setEmbeddedPropertyDirty(int propertyIndex);
/**
* Set the original value for the property.
*/
void setOriginalValue(int propertyIndex, Object value);
/**
@@ -321,17 +306,17 @@ public interface EntityBeanIntercept extends Serializable {
/**
* Return the set of property names for a partially loaded bean.
*/
Set<String> loadedPropertyNames();
Set<String> getLoadedPropertyNames();
/**
* Return the array of flags indicating the dirty properties.
*/
boolean[] dirtyProperties();
boolean[] getDirtyProperties();
/**
* Return the set of dirty properties.
*/
Set<String> dirtyPropertyNames();
Set<String> getDirtyPropertyNames();
/**
* Recursively add dirty properties.
@@ -346,7 +331,7 @@ public interface EntityBeanIntercept extends Serializable {
/**
* Return a map of dirty properties with their new and old values.
*/
Map<String, ValuePair> dirtyValues();
Map<String, ValuePair> getDirtyValues();
/**
* Recursively add dirty properties.
@@ -361,7 +346,7 @@ public interface EntityBeanIntercept extends Serializable {
/**
* Return a dirty property hash taking into account embedded beans.
*/
StringBuilder dirtyPropertyKey();
StringBuilder getDirtyPropertyKey();
/**
* Add and return a dirty property hash.
@@ -371,22 +356,19 @@ public interface EntityBeanIntercept extends Serializable {
/**
* Return a loaded property hash.
*/
StringBuilder loadedPropertyKey();
StringBuilder getLoadedPropertyKey();
/**
* Return the loaded state for all the properties.
*/
boolean[] loaded();
boolean[] getLoaded();
/**
* Return the index of the property that triggered the lazy load.
*/
int lazyLoadPropertyIndex();
int getLazyLoadPropertyIndex();
/**
* Return the property that triggered the lazy load.
*/
String lazyLoadProperty();
String getLazyLoadProperty();
/**
* Load the bean when it is a reference.
@@ -403,9 +385,6 @@ public interface EntityBeanIntercept extends Serializable {
*/
void initialisedMany(int propertyIndex);
/**
* Invoke the PreGetterCallback if it has been set due to getter for the given property.
*/
void preGetterCallback(int propertyIndex);
/**
@@ -423,14 +402,8 @@ public interface EntityBeanIntercept extends Serializable {
*/
void preSetterMany(boolean interceptField, int propertyIndex, Object oldValue, Object newValue);
/**
* Set the property changed state, bean dirtyState and property original value.
*/
void setChangedPropertyValue(int propertyIndex, boolean setDirtyState, Object origValue);
/**
* Set the dirty state on the bean.
*/
void setDirtyStatus();
/**
@@ -497,7 +470,7 @@ public interface EntityBeanIntercept extends Serializable {
/**
* Return the sort order value for an order column.
*/
int sortOrder();
int getSortOrder();
/**
* Set the sort order value for an order column.
@@ -509,9 +482,6 @@ public interface EntityBeanIntercept extends Serializable {
*/
void setDeletedFromCollection(boolean deletedFromCollection);
/**
* Return true if the bean was orphan deleted from a collection.
*/
boolean isOrphanDelete();
/**
@@ -522,12 +492,9 @@ public interface EntityBeanIntercept extends Serializable {
/**
* Returns the loadErrors.
*/
Map<String, Exception> loadErrors();
Map<String, Exception> getLoadErrors();
/**
* Return true if the property has its changed state set.
*/
boolean isChangedProp(int propertyIndex);
boolean isChangedProp(int i);
/**
* Return the MutableValueInfo for the given property or null.
@@ -6,36 +6,21 @@ import java.util.Collections;
import java.util.Map;
import java.util.Set;
/**
* EntityBeanIntercept optimised for read only use.
* <p>
* For the read only use this intercept doesn't need to hold any state that is normally
* required for updates such as per property changed, loaded, dirty state, original values
* bean state etc.
*/
public class InterceptReadOnly implements EntityBeanIntercept {
private final EntityBean owner;
/**
* Create with a given entity.
*/
public InterceptReadOnly(Object ownerBean) {
this.owner = (EntityBean) ownerBean;
}
@Override
public String toString() {
return "InterceptReadOnly{" + owner + '}';
}
@Override
public EntityBean owner() {
public EntityBean getOwner() {
return owner;
}
@Override
public PersistenceContext persistenceContext() {
public PersistenceContext getPersistenceContext() {
return null;
}
@@ -50,7 +35,7 @@ public class InterceptReadOnly implements EntityBeanIntercept {
}
@Override
public Object ownerId() {
public Object getOwnerId() {
return null;
}
@@ -60,12 +45,12 @@ public class InterceptReadOnly implements EntityBeanIntercept {
}
@Override
public Object embeddedOwner() {
public Object getEmbeddedOwner() {
return null;
}
@Override
public int embeddedOwnerIndex() {
public int getEmbeddedOwnerIndex() {
return 0;
}
@@ -230,7 +215,7 @@ public class InterceptReadOnly implements EntityBeanIntercept {
}
@Override
public Object origValue(int propertyIndex) {
public Object getOrigValue(int propertyIndex) {
return null;
}
@@ -240,12 +225,12 @@ public class InterceptReadOnly implements EntityBeanIntercept {
}
@Override
public String property(int propertyIndex) {
public String getProperty(int propertyIndex) {
return null;
}
@Override
public int propertyLength() {
public int getPropertyLength() {
return 0;
}
@@ -320,17 +305,17 @@ public class InterceptReadOnly implements EntityBeanIntercept {
}
@Override
public Set<String> loadedPropertyNames() {
public Set<String> getLoadedPropertyNames() {
return Collections.emptySet();
}
@Override
public boolean[] dirtyProperties() {
public boolean[] getDirtyProperties() {
return new boolean[0];
}
@Override
public Set<String> dirtyPropertyNames() {
public Set<String> getDirtyPropertyNames() {
return Collections.emptySet();
}
@@ -345,7 +330,7 @@ public class InterceptReadOnly implements EntityBeanIntercept {
}
@Override
public Map<String, ValuePair> dirtyValues() {
public Map<String, ValuePair> getDirtyValues() {
return Collections.emptyMap();
}
@@ -360,7 +345,7 @@ public class InterceptReadOnly implements EntityBeanIntercept {
}
@Override
public StringBuilder dirtyPropertyKey() {
public StringBuilder getDirtyPropertyKey() {
return null;
}
@@ -370,22 +355,22 @@ public class InterceptReadOnly implements EntityBeanIntercept {
}
@Override
public StringBuilder loadedPropertyKey() {
public StringBuilder getLoadedPropertyKey() {
return null;
}
@Override
public boolean[] loaded() {
public boolean[] getLoaded() {
return new boolean[0];
}
@Override
public int lazyLoadPropertyIndex() {
public int getLazyLoadPropertyIndex() {
return 0;
}
@Override
public String lazyLoadProperty() {
public String getLazyLoadProperty() {
return null;
}
@@ -495,7 +480,7 @@ public class InterceptReadOnly implements EntityBeanIntercept {
}
@Override
public int sortOrder() {
public int getSortOrder() {
return 0;
}
@@ -520,7 +505,7 @@ public class InterceptReadOnly implements EntityBeanIntercept {
}
@Override
public Map<String, Exception> loadErrors() {
public Map<String, Exception> getLoadErrors() {
return null;
}
@@ -4,8 +4,8 @@ import io.ebean.DB;
import io.ebean.Database;
import io.ebean.ValuePair;
import jakarta.persistence.EntityNotFoundException;
import jakarta.persistence.PersistenceException;
import javax.persistence.EntityNotFoundException;
import javax.persistence.PersistenceException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@@ -21,6 +21,7 @@ import java.util.concurrent.locks.ReentrantLock;
* <p>
* This provides the mechanisms to support deferred fetching of reference beans
* and oldValues generation for concurrency checking.
* </p>
*/
public final class InterceptReadWrite implements EntityBeanIntercept {
@@ -31,23 +32,30 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
private static final int STATE_LOADED = 2;
/**
* Used when a bean is partially loaded.
* Used when a bean is partially filled.
*/
private static final byte FLAG_LOADED_PROP = 1;
private static final byte FLAG_CHANGED_PROP = 2;
private static final byte FLAG_CHANGEDLOADED_PROP = 3;
/**
* Flags indicating if a property is a dirty embedded bean. Used to distinguish between an
* embedded bean being completely overwritten vs one with embedded properties that are dirty.
* Flags indicating if a property is a dirty embedded bean. Used to distinguish
* between an embedded bean being completely overwritten and one of its
* embedded properties being made dirty.
*/
private static final byte FLAG_EMBEDDED_DIRTY = 4;
/**
* Flags indicating if a property is a dirty embedded bean. Used to distinguish
* between an embedded bean being completely overwritten and one of its
* embedded properties being made dirty.
*/
private static final byte FLAG_ORIG_VALUE_SET = 8;
/**
* Flags indicating if the mutable hash is set.
*/
private static final byte FLAG_MUTABLE_HASH_SET = 16;
private final ReentrantLock lock = new ReentrantLock();
private transient final ReentrantLock lock = new ReentrantLock();
private transient NodeUsageCollector nodeUsageCollector;
private transient PersistenceContext persistenceContext;
private transient BeanLoader beanLoader;
@@ -70,9 +78,10 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
private boolean readOnly;
private boolean dirty;
/**
* Flag set to disable lazy loading.
* Flag set to disable lazy loading - typically for SQL "report" type entity beans.
*/
private boolean disableLazyLoad;
/**
* Flag set when lazy loading failed due to the underlying bean being deleted in the DB.
*/
@@ -98,7 +107,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
private MutableValueNext[] mutableNext;
/**
* Create with a given entity.
* Create a intercept with a given entity.
*/
public InterceptReadWrite(Object ownerBean) {
this.owner = (EntityBean) ownerBean;
@@ -114,30 +123,12 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
}
@Override
public String toString() {
return "InterceptReadWrite@" + hashCode() + "{state=" + state +
(dirty ? " dirty;" : "") +
(forceUpdate ? " forceUpdate;" : "") +
(readOnly ? " readOnly;" : "") +
(disableLazyLoad ? " disableLazyLoad;" : "") +
(lazyLoadFailure ? " lazyLoadFailure;" : "") +
(fullyLoadedBean ? " fullyLoadedBean;" : "") +
(loadedFromCache ? " loadedFromCache;" : "") +
", pc=" + System.identityHashCode(persistenceContext) +
", flags=" + Arrays.toString(flags) +
(lazyLoadProperty > -1 ? (", lazyLoadProperty=" + lazyLoadProperty) : "") +
", loader=" + beanLoader +
(ownerId != null ? (", ownerId=" + ownerId) : "") +
'}';
}
@Override
public EntityBean owner() {
public EntityBean getOwner() {
return owner;
}
@Override
public PersistenceContext persistenceContext() {
public PersistenceContext getPersistenceContext() {
return persistenceContext;
}
@@ -152,7 +143,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
}
@Override
public Object ownerId() {
public Object getOwnerId() {
return ownerId;
}
@@ -162,12 +153,12 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
}
@Override
public Object embeddedOwner() {
public Object getEmbeddedOwner() {
return embeddedOwner;
}
@Override
public int embeddedOwnerIndex() {
public int getEmbeddedOwnerIndex() {
return embeddedOwnerIndex;
}
@@ -191,13 +182,13 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
public void setBeanLoader(BeanLoader beanLoader, PersistenceContext ctx) {
this.beanLoader = beanLoader;
this.persistenceContext = ctx;
this.ebeanServerName = beanLoader.name();
this.ebeanServerName = beanLoader.getName();
}
@Override
public void setBeanLoader(BeanLoader beanLoader) {
this.beanLoader = beanLoader;
this.ebeanServerName = beanLoader.name();
this.ebeanServerName = beanLoader.getName();
}
@Override
@@ -380,7 +371,8 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
@Override
public void setEmbeddedLoaded(Object embeddedBean) {
if (embeddedBean instanceof EntityBean) {
((EntityBean) embeddedBean)._ebean_getIntercept().setLoaded();
EntityBean eb = (EntityBean) embeddedBean;
eb._ebean_getIntercept().setLoaded();
}
}
@@ -400,7 +392,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
}
@Override
public Object origValue(int propertyIndex) {
public Object getOrigValue(int propertyIndex) {
if ((flags[propertyIndex] & (FLAG_ORIG_VALUE_SET | FLAG_MUTABLE_HASH_SET)) == FLAG_MUTABLE_HASH_SET) {
// mutable hash set, but not ORIG_VALUE
setOriginalValue(propertyIndex, mutableInfo[propertyIndex].get());
@@ -413,7 +405,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
@Override
public int findProperty(String propertyName) {
final String[] names = owner._ebean_getPropertyNames();
String[] names = owner._ebean_getPropertyNames();
for (int i = 0; i < names.length; i++) {
if (names[i].equals(propertyName)) {
return i;
@@ -423,7 +415,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
}
@Override
public String property(int propertyIndex) {
public String getProperty(int propertyIndex) {
if (propertyIndex == -1) {
return null;
}
@@ -431,13 +423,13 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
}
@Override
public int propertyLength() {
public int getPropertyLength() {
return flags.length;
}
@Override
public void setPropertyLoaded(String propertyName, boolean loaded) {
final int position = findProperty(propertyName);
int position = findProperty(propertyName);
if (position == -1) {
throw new IllegalArgumentException("Property " + propertyName + " not found");
}
@@ -531,23 +523,23 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
}
@Override
public Set<String> loadedPropertyNames() {
public Set<String> getLoadedPropertyNames() {
if (fullyLoadedBean) {
return null;
}
final Set<String> props = new LinkedHashSet<>();
Set<String> props = new LinkedHashSet<>();
for (int i = 0; i < flags.length; i++) {
if ((flags[i] & FLAG_LOADED_PROP) != 0) {
props.add(property(i));
props.add(getProperty(i));
}
}
return props;
}
@Override
public boolean[] dirtyProperties() {
final int len = propertyLength();
final boolean[] dirties = new boolean[len];
public boolean[] getDirtyProperties() {
int len = getPropertyLength();
boolean[] dirties = new boolean[len];
for (int i = 0; i < len; i++) {
// this, or an embedded property has been changed - recurse
dirties[i] = (flags[i] & (FLAG_CHANGED_PROP + FLAG_EMBEDDED_DIRTY)) != 0;
@@ -556,31 +548,31 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
}
@Override
public Set<String> dirtyPropertyNames() {
final Set<String> props = new LinkedHashSet<>();
public Set<String> getDirtyPropertyNames() {
Set<String> props = new LinkedHashSet<>();
addDirtyPropertyNames(props, null);
return props;
}
@Override
public void addDirtyPropertyNames(Set<String> props, String prefix) {
final int len = propertyLength();
int len = getPropertyLength();
for (int i = 0; i < len; i++) {
if (isChangedProp(i)) {
// the property has been changed on this bean
props.add((prefix == null ? property(i) : prefix + property(i)));
props.add((prefix == null ? getProperty(i) : prefix + getProperty(i)));
} else if ((flags[i] & FLAG_EMBEDDED_DIRTY) != 0) {
// an embedded property has been changed - recurse
final EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
embeddedBean._ebean_getIntercept().addDirtyPropertyNames(props, property(i) + ".");
EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
embeddedBean._ebean_getIntercept().addDirtyPropertyNames(props, getProperty(i) + ".");
}
}
}
@Override
public boolean hasDirtyProperty(Set<String> propertyNames) {
final String[] names = owner._ebean_getPropertyNames();
final int len = propertyLength();
String[] names = owner._ebean_getPropertyNames();
int len = getPropertyLength();
for (int i = 0; i < len; i++) {
if (isChangedProp(i)) {
if (propertyNames.contains(names[i])) {
@@ -596,46 +588,46 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
}
@Override
public Map<String, ValuePair> dirtyValues() {
final Map<String, ValuePair> dirtyValues = new LinkedHashMap<>();
public Map<String, ValuePair> getDirtyValues() {
Map<String, ValuePair> dirtyValues = new LinkedHashMap<>();
addDirtyPropertyValues(dirtyValues, null);
return dirtyValues;
}
@Override
public void addDirtyPropertyValues(Map<String, ValuePair> dirtyValues, String prefix) {
final int len = propertyLength();
int len = getPropertyLength();
for (int i = 0; i < len; i++) {
if (isChangedProp(i)) {
// the property has been changed on this bean
final String propName = (prefix == null ? property(i) : prefix + property(i));
final Object newVal = owner._ebean_getField(i);
final Object oldVal = origValue(i);
String propName = (prefix == null ? getProperty(i) : prefix + getProperty(i));
Object newVal = owner._ebean_getField(i);
Object oldVal = getOrigValue(i);
if (notEqual(oldVal, newVal)) {
dirtyValues.put(propName, new ValuePair(newVal, oldVal));
}
} else if ((flags[i] & FLAG_EMBEDDED_DIRTY) != 0) {
// an embedded property has been changed - recurse
final EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
embeddedBean._ebean_getIntercept().addDirtyPropertyValues(dirtyValues, property(i) + ".");
EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
embeddedBean._ebean_getIntercept().addDirtyPropertyValues(dirtyValues, getProperty(i) + ".");
}
}
}
@Override
public void addDirtyPropertyValues(BeanDiffVisitor visitor) {
final int len = propertyLength();
int len = getPropertyLength();
for (int i = 0; i < len; i++) {
if (isChangedProp(i)) {
// the property has been changed on this bean
final Object newVal = owner._ebean_getField(i);
final Object oldVal = origValue(i);
Object newVal = owner._ebean_getField(i);
Object oldVal = getOrigValue(i);
if (notEqual(oldVal, newVal)) {
visitor.visit(i, newVal, oldVal);
}
} else if ((flags[i] & FLAG_EMBEDDED_DIRTY) != 0) {
// an embedded property has been changed - recurse
final EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
visitor.visitPush(i);
embeddedBean._ebean_getIntercept().addDirtyPropertyValues(visitor);
visitor.visitPop();
@@ -644,8 +636,8 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
}
@Override
public StringBuilder dirtyPropertyKey() {
final StringBuilder sb = new StringBuilder();
public StringBuilder getDirtyPropertyKey() {
StringBuilder sb = new StringBuilder();
addDirtyPropertyKey(sb);
return sb;
}
@@ -655,23 +647,24 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
if (sortOrder > 0) {
sb.append("s,");
}
final int len = propertyLength();
int len = getPropertyLength();
for (int i = 0; i < len; i++) {
if ((flags[i] & FLAG_CHANGED_PROP) != 0) { // we do not check against mutablecontent here.
sb.append(i).append(',');
} else if ((flags[i] & FLAG_EMBEDDED_DIRTY) != 0) {
// an embedded property has been changed - recurse
EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
sb.append(i).append('[');
((EntityBean) owner._ebean_getField(i))._ebean_getIntercept().addDirtyPropertyKey(sb);
embeddedBean._ebean_getIntercept().addDirtyPropertyKey(sb);
sb.append(']');
}
}
}
@Override
public StringBuilder loadedPropertyKey() {
final StringBuilder sb = new StringBuilder();
final int len = propertyLength();
public StringBuilder getLoadedPropertyKey() {
StringBuilder sb = new StringBuilder();
int len = getPropertyLength();
for (int i = 0; i < len; i++) {
if (isLoadedProperty(i)) {
sb.append(i).append(',');
@@ -681,8 +674,8 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
}
@Override
public boolean[] loaded() {
final boolean[] ret = new boolean[flags.length];
public boolean[] getLoaded() {
boolean[] ret = new boolean[flags.length];
for (int i = 0; i < ret.length; i++) {
ret[i] = (flags[i] & FLAG_LOADED_PROP) != 0;
}
@@ -690,13 +683,13 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
}
@Override
public int lazyLoadPropertyIndex() {
public int getLazyLoadPropertyIndex() {
return lazyLoadProperty;
}
@Override
public String lazyLoadProperty() {
return property(lazyLoadProperty);
public String getLazyLoadProperty() {
return getProperty(lazyLoadProperty);
}
@Override
@@ -706,7 +699,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
if (beanLoader == null) {
final Database database = DB.byName(ebeanServerName);
if (database == null) {
throw new PersistenceException(ebeanServerName == null ? "No registered default server" : "Database [" + ebeanServerName + "] is not registered");
throw new PersistenceException("Database [" + ebeanServerName + "] was not found?");
}
// For stand alone reference bean or after deserialisation lazy load
// using the ebeanServer. Synchronise only on the bean.
@@ -734,14 +727,14 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
}
if (lazyLoadFailure) {
// failed when batch lazy loaded by another bean in the batch
throw new EntityNotFoundException("(Lazy) loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted. BeanLoader: " + beanLoader);
throw new EntityNotFoundException("(Lazy) loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted");
}
if (lazyLoadProperty == -1) {
lazyLoadProperty = loadProperty;
loader.loadBean(this);
if (lazyLoadFailure) {
// failed when lazy loading this bean
throw new EntityNotFoundException("Lazy loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted. BeanLoader: " + beanLoader);
throw new EntityNotFoundException("Lazy loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted.");
}
// bean should be loaded and intercepting now. setLoaded() has
// been called by the lazy loading mechanism
@@ -836,7 +829,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
loadBean(propertyIndex);
}
if (nodeUsageCollector != null) {
nodeUsageCollector.addUsed(property(propertyIndex));
nodeUsageCollector.addUsed(getProperty(propertyIndex));
}
}
@@ -985,7 +978,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
}
@Override
public int sortOrder() {
public int getSortOrder() {
return sortOrder;
}
@@ -1014,19 +1007,19 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
}
@Override
public Map<String, Exception> loadErrors() {
public Map<String, Exception> getLoadErrors() {
if (loadErrors == null) {
return Collections.emptyMap();
}
Map<String, Exception> ret = null;
int len = propertyLength();
int len = getPropertyLength();
for (int i = 0; i < len; i++) {
final Exception loadError = loadErrors[i];
Exception loadError = loadErrors[i];
if (loadError != null) {
if (ret == null) {
ret = new LinkedHashMap<>();
}
ret.put(property(i), loadError);
ret.put(getProperty(i), loadError);
}
}
return ret;
@@ -8,6 +8,7 @@ import java.util.Objects;
* <p>
* It represents a location relative to the root of an object graph and specific
* to a query and call stack hash.
* </p>
*/
public final class ObjectGraphNode implements Serializable {
@@ -16,7 +17,7 @@ public final class ObjectGraphNode implements Serializable {
/**
* Identifies the origin.
*/
private final ObjectGraphOrigin origin;
private final ObjectGraphOrigin originQueryPoint;
/**
* The path relative to the root.
@@ -27,26 +28,26 @@ public final class ObjectGraphNode implements Serializable {
* Create at a sub level.
*/
public ObjectGraphNode(ObjectGraphNode parent, String path) {
this.origin = parent.origin();
this.path = parent.childPath(path);
this.originQueryPoint = parent.getOriginQueryPoint();
this.path = parent.getChildPath(path);
}
/**
* Create an the root level.
*/
public ObjectGraphNode(ObjectGraphOrigin origin, String path) {
this.origin = origin;
public ObjectGraphNode(ObjectGraphOrigin originQueryPoint, String path) {
this.originQueryPoint = originQueryPoint;
this.path = path;
}
/**
* Return the origin query point.
*/
public ObjectGraphOrigin origin() {
return origin;
public ObjectGraphOrigin getOriginQueryPoint() {
return originQueryPoint;
}
private String childPath(String childPath) {
private String getChildPath(String childPath) {
if (path == null) {
return childPath;
} else if (childPath == null) {
@@ -59,18 +60,18 @@ public final class ObjectGraphNode implements Serializable {
/**
* Return the path relative to the root.
*/
public String path() {
public String getPath() {
return path;
}
@Override
public String toString() {
return "origin:" + origin + " path[" + path + "]";
return "origin:" + originQueryPoint + " path[" + path + "]";
}
@Override
public int hashCode() {
int hc = 92821 * origin.hashCode();
int hc = 92821 * originQueryPoint.hashCode();
hc = 92821 * hc + (path == null ? 0 : path.hashCode());
return hc;
}
@@ -86,6 +87,6 @@ public final class ObjectGraphNode implements Serializable {
ObjectGraphNode e = (ObjectGraphNode) obj;
return (Objects.equals(e.path, path))
&& e.origin.equals(origin);
&& e.originQueryPoint.equals(originQueryPoint);
}
}
@@ -28,38 +28,38 @@ public final class ObjectGraphOrigin implements Serializable {
this.callOrigin = callOrigin;
this.beanType = beanType;
this.queryHash = queryHash;
this.key = callOrigin.key(queryHash);
this.key = callOrigin.getOriginKey(queryHash);
}
/**
* The key includes the queryPlan hash and the callStack hash. This becomes
* the unique identifier for a query point.
*/
public String key() {
public String getKey() {
return key;
}
/**
* The type of bean the query is fetching.
*/
public String beanType() {
public String getBeanType() {
return beanType;
}
/**
* The call stack involved.
*/
public CallOrigin callOrigin() {
public CallOrigin getCallOrigin() {
return callOrigin;
}
public String top() {
return callOrigin.top();
public String getTopElement() {
return callOrigin.getTopElement();
}
@Override
public String toString() {
return "key[" + key + "] type[" + beanType + "] " + callOrigin.top();
return "key[" + key + "] type[" + beanType + "] " + callOrigin.getTopElement();
}
@Override
@@ -19,7 +19,7 @@ public abstract class SingleBeanLoader implements BeanLoader {
}
@Override
public String name() {
public String getName() {
return database.name();
}
@@ -1,5 +1,7 @@
package io.ebean.bean;
import io.ebean.common.BeanMap;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.Map;
@@ -45,7 +47,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 +79,7 @@ public final class ToStringBuilder {
*/
public void end() {
if (counter <= MAX) {
sb.append(')');
sb.append(")");
}
}
@@ -90,7 +92,7 @@ public final class ToStringBuilder {
} else {
sb.append(", ");
}
sb.append(name).append(':');
sb.append(name).append(":");
}
private void value(Object value) {
@@ -110,7 +112,7 @@ public final class ToStringBuilder {
} else {
String content = String.valueOf(value);
if (content.length() > TRIM_LENGTH) {
content = content.substring(0, TRIM_LENGTH) + " (trimmed)";
content = content.substring(0, TRIM_LENGTH) + " <trimmed>";
}
sb.append(content);
if (sb.length() >= MAX_TOTAL_CONTENT) {
@@ -125,20 +127,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 +153,7 @@ public final class ToStringBuilder {
return;
}
boolean firstElement = true;
sb.append('[');
sb.append("[");
for (Object o : c) {
if (firstElement) {
firstElement = false;
@@ -163,7 +165,7 @@ public final class ToStringBuilder {
return;
}
}
sb.append(']');
sb.append("]");
}
private boolean push(Object bean) {
@@ -178,7 +180,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;
@@ -6,6 +6,7 @@ import java.util.Set;
* Notification event that dependent tables have been modified.
* <p>
* This is sent to other interested servers (in the cluster).
* </p>
*/
public class ServerCacheNotification {
@@ -1,16 +1,17 @@
package io.ebean.cache;
import io.ebean.DatabaseBuilder;
import io.ebean.config.DatabaseConfig;
/**
* Plugin that provides a ServerCacheNotify implementation.
* <p>
* Is supplied this will be used to send the ServerCacheNotification event to other cluster members.
* </p>
*/
public interface ServerCacheNotifyPlugin {
/**
* Create a ServerCacheNotify implementation given the server configuration.
*/
ServerCacheNotify create(DatabaseBuilder config);
ServerCacheNotify create(DatabaseConfig config);
}
@@ -1,7 +1,7 @@
package io.ebean.cache;
import io.ebean.BackgroundExecutor;
import io.ebean.DatabaseBuilder;
import io.ebean.config.DatabaseConfig;
/**
* The plugin interface that creates a ServerCacheFactory.
@@ -11,5 +11,5 @@ public interface ServerCachePlugin {
/**
* Create the ServerCacheFactory given the server config and background executor service.
*/
ServerCacheFactory create(DatabaseBuilder config, BackgroundExecutor executor);
ServerCacheFactory create(DatabaseConfig config, BackgroundExecutor executor);
}
@@ -29,11 +29,6 @@ public class ServerCacheStatistics {
protected long evictCount;
protected long gcCount;
protected long idleCount;
protected long ttlCount;
protected long lruCount;
@Override
public String toString() {
//noinspection StringBufferReplaceableByString
@@ -48,10 +43,6 @@ public class ServerCacheStatistics {
sb.append(" remove:").append(removeCount);
sb.append(" clear:").append(clearCount);
sb.append(" evict:").append(evictCount);
sb.append(" gc:").append(gcCount);
sb.append(" idle:").append(idleCount);
sb.append(" ttl:").append(ttlCount);
sb.append(" lru:").append(lruCount);
return sb.toString();
}
@@ -200,37 +191,4 @@ public class ServerCacheStatistics {
return evictCount;
}
/**
* Set the count of entries removed by the garbage collection.
*/
public void setGcCount(long gcCount) {
this.gcCount = gcCount;
}
/**
* Return the count of entries removed by the garbage collection.
*/
public long getGcCount() {
return gcCount;
}
public void setIdleCount(long idleCount) {
this.idleCount = idleCount;
}
public long getIdleCount() {
return idleCount;
}
public void setTtlCount(long ttlCount) {
this.ttlCount = ttlCount;
}
public long getTtlCount() {
return ttlCount;
}
public void setLruCount(long lruCount) {
this.lruCount = lruCount;
}
}
+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();
}
@@ -17,28 +17,39 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
private static final long serialVersionUID = 3365725236140187588L;
protected final ReentrantLock lock = new ReentrantLock();
protected boolean readOnly;
protected boolean disableLazyLoad;
/**
* The Database this is associated with. (used for lazy fetch).
*/
protected transient BeanCollectionLoader loader;
protected transient ExpressionList<?> filterMany;
/**
* Flag set when registered with the batch loading context.
*/
protected boolean registeredWithLoadContext;
protected String ebeanServerName;
/**
* The owning bean (used for lazy fetch).
*/
protected EntityBean ownerBean;
/**
* The name of this property in the owning bean (used for lazy fetch).
*/
protected String propertyName;
protected ModifyHolder<E> modifyHolder;
protected ModifyListenMode modifyListenMode;
protected boolean modifyListening;
/**
@@ -59,17 +70,17 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
}
@Override
public EntityBean owner() {
public EntityBean getOwnerBean() {
return ownerBean;
}
@Override
public String propertyName() {
public String getPropertyName() {
return propertyName;
}
@Override
public ExpressionList<?> filterMany() {
public ExpressionList<?> getFilterMany() {
return filterMany;
}
@@ -115,7 +126,8 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
void checkReadOnly() {
if (readOnly) {
throw new IllegalStateException("This collection is in ReadOnly mode");
String msg = "This collection is in ReadOnly mode";
throw new IllegalStateException(msg);
}
}
@@ -129,7 +141,7 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
}
@Override
public ModifyListenMode modifyListening() {
public ModifyListenMode getModifyListening() {
return modifyListenMode;
}
@@ -182,7 +194,7 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
}
@Override
public Set<E> modifyAdditions() {
public Set<E> getModifyAdditions() {
if (modifyHolder == null) {
return null;
} else {
@@ -191,7 +203,7 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
}
@Override
public Set<E> modifyRemovals() {
public Set<E> getModifyRemovals() {
if (modifyHolder == null) {
return null;
} else {
@@ -213,7 +225,7 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
}
/**
* Copies all relevant properties for a clone. See {@link #shallowCopy()}
* Copies all relevant properties for a clone. See {@link #getShallowCopy()}
*/
protected void setFromOriginal(AbstractBeanCollection<E> other) {
this.disableLazyLoad = other.disableLazyLoad;
@@ -3,10 +3,15 @@ package io.ebean.common;
import io.ebean.bean.*;
import java.io.Serializable;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
/**
* List capable of lazy loading and modification awareness.
* List capable of lazy loading.
*/
public final class BeanList<E> extends AbstractBeanCollection<E> implements List<E>, BeanCollectionAdd {
@@ -68,7 +73,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
if (list == null) {
list = new ArrayList<>();
}
list.addAll((Collection<? extends E>) other.actualDetails());
list.addAll((Collection<? extends E>) other.getActualDetails());
}
@Override
@@ -145,6 +150,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
* Set the actual underlying list.
* <p>
* This is primarily for the deferred fetching function.
* </p>
*/
@SuppressWarnings("unchecked")
public void setActualList(List<?> list) {
@@ -154,17 +160,17 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
/**
* Return the actual underlying list.
*/
public List<E> actualList() {
public List<E> getActualList() {
return list;
}
@Override
public Collection<E> actualDetails() {
public Collection<E> getActualDetails() {
return list;
}
@Override
public Collection<?> actualEntries() {
public Collection<?> getActualEntries() {
return list;
}
@@ -200,11 +206,12 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
* Specifically obj does not need to be a BeanList but any list. This does not
* use the FindMany, fetchedMaxRows or finishedFetch properties in the equals
* test.
* </p>
*/
@Override
public boolean equals(Object other) {
public boolean equals(Object obj) {
init();
return list.equals(other);
return list.equals(obj);
}
@Override
@@ -237,40 +244,40 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
}
@Override
public boolean add(E bean) {
public boolean add(E o) {
checkReadOnly();
init();
if (modifyListening) {
if (list.add(bean)) {
modifyAddition(bean);
if (list.add(o)) {
modifyAddition(o);
return true;
} else {
return false;
}
}
return list.add(bean);
return list.add(o);
}
@Override
public boolean addAll(Collection<? extends E> beans) {
public boolean addAll(Collection<? extends E> c) {
checkReadOnly();
init();
if (modifyListening) {
// all elements in c are added (no contains checking)
getModifyHolder().modifyAdditionAll(beans);
getModifyHolder().modifyAdditionAll(c);
}
return list.addAll(beans);
return list.addAll(c);
}
@Override
public boolean addAll(int index, Collection<? extends E> beans) {
public boolean addAll(int index, Collection<? extends E> c) {
checkReadOnly();
init();
if (modifyListening) {
// all elements in c are added (no contains checking)
getModifyHolder().modifyAdditionAll(beans);
getModifyHolder().modifyAdditionAll(c);
}
return list.addAll(index, beans);
return list.addAll(index, c);
}
@Override
@@ -280,23 +287,23 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
// and fetch just the Id's
initClear();
if (modifyListening) {
for (E element : list) {
getModifyHolder().modifyRemoval(element);
for (E aList : list) {
getModifyHolder().modifyRemoval(aList);
}
}
list.clear();
}
@Override
public boolean contains(Object bean) {
public boolean contains(Object o) {
init();
return list.contains(bean);
return list.contains(o);
}
@Override
public boolean containsAll(Collection<?> beans) {
public boolean containsAll(Collection<?> c) {
init();
return list.containsAll(beans);
return list.containsAll(c);
}
@Override
@@ -306,9 +313,9 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
}
@Override
public int indexOf(Object bean) {
public int indexOf(Object o) {
init();
return list.indexOf(bean);
return list.indexOf(o);
}
@Override
@@ -320,29 +327,31 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
@Override
public Iterator<E> iterator() {
init();
if (readOnly) {
if (isReadOnly()) {
return new ReadOnlyListIterator<>(list.listIterator());
}
if (modifyListening) {
return new ModifyIterator<>(this, list.iterator());
Iterator<E> it = list.iterator();
return new ModifyIterator<>(this, it);
}
return list.iterator();
}
@Override
public int lastIndexOf(Object bean) {
public int lastIndexOf(Object o) {
init();
return list.lastIndexOf(bean);
return list.lastIndexOf(o);
}
@Override
public ListIterator<E> listIterator() {
init();
if (readOnly) {
if (isReadOnly()) {
return new ReadOnlyListIterator<>(list.listIterator());
}
if (modifyListening) {
return new ModifyListIterator<>(this, list.listIterator());
ListIterator<E> it = list.listIterator();
return new ModifyListIterator<>(this, it);
}
return list.listIterator();
}
@@ -350,11 +359,12 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
@Override
public ListIterator<E> listIterator(int index) {
init();
if (readOnly) {
if (isReadOnly()) {
return new ReadOnlyListIterator<>(list.listIterator(index));
}
if (modifyListening) {
return new ModifyListIterator<>(this, list.listIterator(index));
ListIterator<E> it = list.listIterator(index);
return new ModifyListIterator<>(this, it);
}
return list.listIterator(index);
}
@@ -379,17 +389,17 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
}
@Override
public boolean remove(Object bean) {
public boolean remove(Object o) {
checkReadOnly();
init();
if (modifyListening) {
boolean isRemove = list.remove(bean);
boolean isRemove = list.remove(o);
if (isRemove) {
modifyRemoval(bean);
modifyRemoval(o);
}
return isRemove;
}
return list.remove(bean);
return list.remove(o);
}
@Override
@@ -453,7 +463,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
@Override
public List<E> subList(int fromIndex, int toIndex) {
init();
if (readOnly) {
if (isReadOnly()) {
return Collections.unmodifiableList(list.subList(fromIndex, toIndex));
}
if (modifyListening) {
@@ -469,13 +479,13 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
}
@Override
public <T> T[] toArray(T[] array) {
public <T> T[] toArray(T[] a) {
init();
//noinspection SuspiciousToArrayCall
return list.toArray(array);
return list.toArray(a);
}
private static final class ReadOnlyListIterator<E> implements ListIterator<E>, Serializable {
private static class ReadOnlyListIterator<E> implements ListIterator<E>, Serializable {
private static final long serialVersionUID = 3097271091406323699L;
@@ -533,7 +543,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
}
@Override
public BeanCollection<E> shallowCopy() {
public BeanCollection<E> getShallowCopy() {
BeanList<E> copy = new BeanList<>(new CopyOnFirstWriteList<>(list));
copy.setFromOriginal(this);
return copy;
@@ -5,10 +5,14 @@ import io.ebean.bean.BeanCollectionLoader;
import io.ebean.bean.EntityBean;
import io.ebean.bean.ToStringBuilder;
import java.util.*;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
/**
* Map capable of lazy loading and modification aware.
* Map capable of lazy loading.
*/
public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Map<K, E> {
@@ -67,7 +71,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
public void loadFrom(BeanCollection<?> other) {
BeanMap<K, E> otherMap = (BeanMap<K, E>) other;
internalPutNull();
map.putAll(otherMap.actualMap());
map.putAll(otherMap.getActualMap());
}
public void internalPutNull() {
@@ -171,7 +175,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
/**
* Return the actual underlying map.
*/
public Map<K, E> actualMap() {
public Map<K, E> getActualMap() {
return map;
}
@@ -179,7 +183,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
* Returns the collection of beans (map values).
*/
@Override
public Collection<E> actualDetails() {
public Collection<E> getActualDetails() {
return map.values();
}
@@ -187,7 +191,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
* Returns the map entrySet.
*/
@Override
public Collection<?> actualEntries() {
public Collection<?> getActualEntries() {
return map.entrySet();
}
@@ -243,7 +247,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
@Override
public Set<Entry<K, E>> entrySet() {
init();
if (readOnly) {
if (isReadOnly()) {
return Collections.unmodifiableSet(map.entrySet());
}
return modifyListening ? new ModifyEntrySet<>(this, map.entrySet()) : map.entrySet();
@@ -264,7 +268,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
@Override
public Set<K> keySet() {
init();
if (readOnly) {
if (isReadOnly()) {
return Collections.unmodifiableSet(map.keySet());
}
return modifyListening ? new ModifyKeySet<>(this, map.keySet()) : map.keySet();
@@ -335,14 +339,14 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
@Override
public Collection<E> values() {
init();
if (readOnly) {
if (isReadOnly()) {
return Collections.unmodifiableCollection(map.values());
}
return modifyListening ? new ModifyCollection<>(this, map.values()) : map.values();
}
@Override
public BeanCollection<E> shallowCopy() {
public BeanCollection<E> getShallowCopy() {
BeanMap<K, E> copy = new BeanMap<>(new LinkedHashMap<>(map));
copy.setFromOriginal(this);
return copy;
@@ -9,7 +9,7 @@ import java.util.LinkedHashSet;
import java.util.Set;
/**
* Set capable of lazy loading and modification aware.
* Set capable of lazy loading.
*/
public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E>, BeanCollectionAdd {
@@ -67,7 +67,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
if (set == null) {
set = new LinkedHashSet<>();
}
set.addAll((Collection<? extends E>) other.actualDetails());
set.addAll((Collection<? extends E>) other.getActualDetails());
}
@Override
@@ -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 {
@@ -155,17 +155,17 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
/**
* Return the actual underlying set.
*/
public Set<E> actualSet() {
public Set<E> getActualSet() {
return set;
}
@Override
public Collection<E> actualDetails() {
public Collection<E> getActualDetails() {
return set;
}
@Override
public Collection<?> actualEntries() {
public Collection<?> getActualEntries() {
return set;
}
@@ -210,27 +210,27 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
// -----------------------------------------------------//
@Override
public boolean add(E bean) {
public boolean add(E o) {
checkReadOnly();
init();
if (modifyListening) {
if (set.add(bean)) {
modifyAddition(bean);
if (set.add(o)) {
modifyAddition(o);
return true;
} else {
return false;
}
}
return set.add(bean);
return set.add(o);
}
@Override
public boolean addAll(Collection<? extends E> beans) {
public boolean addAll(Collection<? extends E> addCollection) {
checkReadOnly();
init();
if (modifyListening) {
boolean changed = false;
for (E bean : beans) {
for (E bean : addCollection) {
if (set.add(bean)) {
// register the addition of the bean
modifyAddition(bean);
@@ -239,7 +239,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
}
return changed;
}
return set.addAll(beans);
return set.addAll(addCollection);
}
@Override
@@ -255,15 +255,15 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
}
@Override
public boolean contains(Object bean) {
public boolean contains(Object o) {
init();
return set.contains(bean);
return set.contains(o);
}
@Override
public boolean containsAll(Collection<?> beans) {
public boolean containsAll(Collection<?> c) {
init();
return set.containsAll(beans);
return set.containsAll(c);
}
@Override
@@ -275,7 +275,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
@Override
public Iterator<E> iterator() {
init();
if (readOnly) {
if (isReadOnly()) {
return new ReadOnlyIterator<>(set.iterator());
}
if (modifyListening) {
@@ -285,17 +285,17 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
}
@Override
public boolean remove(Object bean) {
public boolean remove(Object o) {
checkReadOnly();
init();
if (modifyListening) {
if (set.remove(bean)) {
modifyRemoval(bean);
if (set.remove(o)) {
modifyRemoval(o);
return true;
}
return false;
}
return set.remove(bean);
return set.remove(o);
}
@Override
@@ -349,13 +349,13 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
}
@Override
public <T> T[] toArray(T[] array) {
public <T> T[] toArray(T[] a) {
init();
//noinspection SuspiciousToArrayCall
return set.toArray(array);
return set.toArray(a);
}
private static final class ReadOnlyIterator<E> implements Iterator<E>, Serializable {
private static class ReadOnlyIterator<E> implements Iterator<E>, Serializable {
private static final long serialVersionUID = 2577697326745352605L;
@@ -382,7 +382,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
}
@Override
public BeanCollection<E> shallowCopy() {
public BeanCollection<E> getShallowCopy() {
BeanSet<E> copy = new BeanSet<>(new LinkedHashSet<>(set));
copy.setFromOriginal(this);
return copy;
@@ -3,9 +3,9 @@ package io.ebean.config;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.util.AnnotationUtil;
import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Inheritance;
import jakarta.persistence.Table;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Inheritance;
import javax.persistence.Table;
import static io.ebean.util.StringHelper.isNull;
@@ -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) {
@@ -237,7 +237,7 @@ public abstract class AbstractNamingConvention implements NamingConvention {
}
buffer.append(rhsTableName);
int maxTableNameLength = databasePlatform.maxTableNameLength();
int maxTableNameLength = databasePlatform.getMaxTableNameLength();
// maxConstraintNameLength is used as the max table name length.
if (buffer.length() > maxTableNameLength) {
@@ -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();
}
@@ -1,7 +1,5 @@
package io.ebean.config;
import io.ebean.DatabaseBuilder;
/**
* Used to provide some automatic configuration early in the creation of a Database.
*/
@@ -10,11 +8,11 @@ public interface AutoConfigure {
/**
* Perform configuration for the DatabaseConfig prior to properties load.
*/
void preConfigure(DatabaseBuilder config);
void preConfigure(DatabaseConfig config);
/**
* Provide some configuration the DatabaseConfig prior to server creation but after properties have been applied.
*/
void postConfigure(DatabaseBuilder config);
void postConfigure(DatabaseConfig config);
}
@@ -6,10 +6,6 @@ import java.util.concurrent.Callable;
* BackgroundExecutorWrapper that can be used to wrap tasks that are sent to background (i.e. another thread).
* It should copy all necessary thread-local variables. See {@link MdcBackgroundExecutorWrapper} for implementation details.
*
* Note: only tasks that are executed immediately (submit, execute) are wrapped. Periodic or scheduled tasks are not wrapped,
* as these may keep copied variables in memory either forever or until the scheduled task is finished.
* The caller is responsible to handle these cases.
*
* @author Roland Praml, FOCONIS AG
*/
public interface BackgroundExecutorWrapper {
@@ -15,6 +15,7 @@ public class ContainerConfig {
private String namespace;
private String podName;
private int port;
private Properties properties;
/**
@@ -122,4 +123,5 @@ public class ContainerConfig {
protected boolean getProperty(Properties properties, String key, boolean defaultValue) {
return "true".equalsIgnoreCase(properties.getProperty(key, Boolean.toString(defaultValue)));
}
}
File diff suppressed because it is too large Load Diff
@@ -1,7 +1,5 @@
package io.ebean.config;
import io.ebean.DatabaseBuilder;
/**
* Provides a ServiceLoader based mechanism to configure a DatabaseConfig.
* <p>
@@ -37,5 +35,5 @@ public interface DatabaseConfigProvider {
* Typically we explicitly register entity bean classes and thus avoid classpath scanning.
* </p>
*/
void apply(DatabaseBuilder config);
void apply(DatabaseConfig config);
}
@@ -135,16 +135,16 @@ 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]));
}
return sb.toString().replace(" ", "_");
return sb.toString();
}
/**
@@ -27,6 +27,7 @@ public class DbConstraintNormalise {
* quoted identifier characters (",',[,] etc).
*/
public String normaliseTable(String tableName) {
tableName = trimQuotes(tableName);
int lastPeriod = tableName.lastIndexOf('.');
if (lastPeriod > -1) {
@@ -58,6 +59,7 @@ public class DbConstraintNormalise {
* Trim off the platform quoted identifier quotes like [ ' and ".
*/
public String trimQuotes(String identifier) {
if (identifier == null) {
return "";
}
@@ -1,22 +0,0 @@
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
}
@@ -5,7 +5,7 @@ import java.util.List;
/**
* Loads and returns entity classes to register with Ebean databases.
*/
public interface EntityClassRegister {
public interface ModuleInfoLoader {
/**
* Return entity classes to register for a named DB (not default DB).

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