mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-09-20 11:17:36 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15b3eb2bf3 | ||
|
|
f53c56490c | ||
|
|
559b39eedc | ||
|
|
0ebcba17f1 | ||
|
|
71edd33fa3 | ||
|
|
24b99d065a | ||
|
|
db7fbd5246 | ||
|
|
ca97338839 | ||
|
|
355144f16d | ||
|
|
7316fb8f1d | ||
|
|
475c30c2a2 | ||
|
|
5a11dcb2e3 | ||
|
|
66d29a7f0c | ||
|
|
e3af5cdeb4 | ||
|
|
c4bfa48b59 | ||
|
|
8473f9fd39 |
@@ -2,7 +2,6 @@
|
||||
name: Build
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
push:
|
||||
branches: master
|
||||
@@ -21,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'zulu'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'zulu'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: oracle-actions/setup-java@v1
|
||||
with:
|
||||
website: jdk.java.net
|
||||
release: ${{ matrix.java_version }}
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -20,19 +20,19 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
path:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: mariadb 10.11
|
||||
- name: mariadb 10.6
|
||||
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-mariadb.properties
|
||||
|
||||
@@ -17,14 +17,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'zulu'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'zulu'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -17,14 +17,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -20,19 +20,19 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
path:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: sqlserver 2022
|
||||
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-sqlserver.properties
|
||||
- name: sqlserver 2017
|
||||
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-sqlserver17.properties
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
name: Valhalla EA
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '39 2 * * 3'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
java_version: [valhalla]
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- 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@v4
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
path:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: Maven version
|
||||
run: mvn --version
|
||||
# - name: Prepare
|
||||
# run: ./jakarta-to-valhalla.sh
|
||||
- name: Build with Maven
|
||||
run: mvn package
|
||||
@@ -4,7 +4,7 @@ name: Yugabyte
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '10 3 * * 3'
|
||||
- cron: '10 3 * * *'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -20,14 +20,14 @@ jobs:
|
||||
os: [ubuntu-latest]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: ${{ matrix.java_version }}
|
||||
distribution: 'adopt'
|
||||
- name: Maven cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: maven-cache
|
||||
with:
|
||||
|
||||
@@ -56,7 +56,12 @@ Work at the highest level of abstraction and drop down levels as needed.
|
||||
<tr>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://www.foconis.de/" target="_blank">
|
||||
<img width="222px" src="https://group.foconis.com/download/ci/logo/png-72dpi/logo-quer/foconis-analytics-quer.png">
|
||||
<img width="222px" src="https://www.foconis.de/templates/yootheme/cache/foconis_logo_322-709da1de.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
<a href="https://www.payintech.com/" target="_blank">
|
||||
<img width="222px" src="https://ebean.io/images/sponsor_PayinTech-logo-noir.png">
|
||||
</a>
|
||||
</td>
|
||||
<td align="center" valign="middle">
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-clickhouse</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-db2</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-h2</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-hana</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-mariadb</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-mysql</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -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>16.0.0</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
<name>ebean-net-postgis</name>
|
||||
<description>ebean-net-postgis composite</description>
|
||||
<artifactId>ebean-net-postgis</artifactId>
|
||||
|
||||
<properties>
|
||||
<postgis.jdbc.version>2023.1.0</postgis.jdbc.version>
|
||||
<postgres.jdbc.version>42.7.2</postgres.jdbc.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>16.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>16.0.0</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>16.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>16.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-net-postgis-types</artifactId>
|
||||
<version>16.0.0</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;
|
||||
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-nuodb</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-oracle</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -22,13 +22,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -47,19 +47,19 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-postgis-types</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlite</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-sqlserver</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -42,13 +42,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-postgres</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
<relativePath>../..</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -17,13 +17,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-api</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-core</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -41,7 +41,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-jackson-mapper</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -60,13 +60,13 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-querybean</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-platform-all</artifactId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
+1
-2
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>composites</artifactId>
|
||||
@@ -24,7 +24,6 @@
|
||||
<module>ebean-oracle</module>
|
||||
<module>ebean-postgres</module>
|
||||
<module>ebean-postgis</module>
|
||||
<module>ebean-net-postgis</module>
|
||||
<!-- <module>sqlanywhere</module>-->
|
||||
<module>ebean-sqlite</module>
|
||||
<module>ebean-sqlserver</module>
|
||||
|
||||
+26
-5
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>ebean-parent</artifactId>
|
||||
<groupId>io.ebean</groupId>
|
||||
<version>16.0.0</version>
|
||||
<version>14.0.2</version>
|
||||
</parent>
|
||||
|
||||
<name>ebean api</name>
|
||||
@@ -26,16 +26,20 @@
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
Class retention Nonnull and Nullable annotations
|
||||
to assist with IDE auto-completion with Ebean API
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>org.jspecify</groupId>
|
||||
<artifactId>jspecify</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>avaje-lang</artifactId>
|
||||
<version>1.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.avaje</groupId>
|
||||
<artifactId>avaje-config</artifactId>
|
||||
<version>4.1</version>
|
||||
<version>3.12</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -86,6 +90,23 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- JAVAX-DEPENDENCY-START ___
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
____ JAVAX-DEPENDENCY-END -->
|
||||
<!-- JAKARTA-DEPENDENCY-START -->
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
<version>6.0.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!-- JAKARTA-DEPENDENCY-END -->
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package io.ebean;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import io.avaje.lang.NonNullApi;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -19,7 +20,7 @@ import java.util.concurrent.TimeUnit;
|
||||
* This also propagates MDC context from the current thread to the
|
||||
* background task if defined.
|
||||
*/
|
||||
@NullMarked
|
||||
@NonNullApi
|
||||
public interface BackgroundExecutor {
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
package io.ebean;
|
||||
|
||||
/**
|
||||
* Unsupported access of a property on an entity bean.
|
||||
* <p>
|
||||
* Attempted a lazy load operation on a bean that has disabled lazy loading
|
||||
* or attempt to mutate an unmodifiable bean.
|
||||
*/
|
||||
public class BeanAccessException extends UnsupportedOperationException {
|
||||
private static final long serialVersionUID = 1;
|
||||
|
||||
/**
|
||||
* Create with no message.
|
||||
*/
|
||||
public BeanAccessException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create with message.
|
||||
*/
|
||||
public BeanAccessException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package io.ebean;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import io.avaje.lang.NonNullApi;
|
||||
import io.avaje.lang.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -30,7 +30,7 @@ import java.util.Optional;
|
||||
*
|
||||
* @see BeanRepository
|
||||
*/
|
||||
@NullMarked
|
||||
@NonNullApi
|
||||
public abstract class BeanFinder<I,T> {
|
||||
|
||||
protected final Database database;
|
||||
@@ -155,10 +155,4 @@ public abstract class BeanFinder<I,T> {
|
||||
return db().findNative(type, nativeSql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a query using the ORM query language.
|
||||
*/
|
||||
protected Query<T> query(String ormQuery) {
|
||||
return db().createQuery(type, ormQuery);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.ebean;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import io.avaje.lang.NonNullApi;
|
||||
import io.ebean.bean.EntityBean;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -36,7 +36,7 @@ import java.util.Collection;
|
||||
* @param <I> The ID type
|
||||
* @param <T> The Bean type
|
||||
*/
|
||||
@NullMarked
|
||||
@NonNullApi
|
||||
public abstract class BeanRepository<I, T> extends BeanFinder<I, T> {
|
||||
|
||||
/**
|
||||
|
||||
@@ -89,7 +89,12 @@ public interface BeanState {
|
||||
* <p>
|
||||
* If a setter is called on a readOnly bean it will throw an exception.
|
||||
*/
|
||||
boolean isUnmodifiable();
|
||||
boolean isReadOnly();
|
||||
|
||||
/**
|
||||
* Set the readOnly status for the bean.
|
||||
*/
|
||||
void setReadOnly(boolean readOnly);
|
||||
|
||||
/**
|
||||
* Advanced - Used to programmatically build a partially or fully loaded
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package io.ebean;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import io.avaje.lang.NonNullApi;
|
||||
import io.avaje.lang.Nullable;
|
||||
import io.ebean.annotation.TxIsolation;
|
||||
import io.ebean.cache.ServerCacheManager;
|
||||
import io.ebean.plugin.Property;
|
||||
@@ -57,7 +57,7 @@ import java.util.concurrent.Callable;
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@NullMarked
|
||||
@NonNullApi
|
||||
public final class DB {
|
||||
|
||||
private static final DbContext context = DbContext.getInstance();
|
||||
@@ -605,7 +605,7 @@ public final class DB {
|
||||
* // find orders and their customers
|
||||
* List<Order> list = DB.find(Order.class)
|
||||
* .fetch("customer")
|
||||
* .orderBy("id")
|
||||
* .order("id")
|
||||
* .findList();
|
||||
*
|
||||
* // sort by customer name ascending, then by order shipDate
|
||||
@@ -741,21 +741,6 @@ public final class DB {
|
||||
return getDefault().createUpdate(beanType, ormUpdate);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a named query.
|
||||
* <p>
|
||||
* For RawSql the named query is expected to be in ebean.xml.
|
||||
*
|
||||
* @param beanType The type of entity bean
|
||||
* @param namedQuery The name of the query
|
||||
* @param <T> The type of entity bean
|
||||
* @return The query
|
||||
*/
|
||||
public static <T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery) {
|
||||
return getDefault().createNamedQuery(beanType, namedQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a query for a type of entity bean.
|
||||
* <p>
|
||||
@@ -775,43 +760,6 @@ public final class DB {
|
||||
return getDefault().createQuery(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the Ebean query language statement returning the query which can then
|
||||
* be modified (add expressions, change order by clause, change maxRows, change
|
||||
* fetch and select paths etc).
|
||||
* <p>
|
||||
* <h3>Example</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // Find order additionally fetching the customer, details and details.product name.
|
||||
*
|
||||
* String eql = "fetch customer fetch details fetch details.product (name) where id = :orderId ";
|
||||
*
|
||||
* Query<Order> query = DB.createQuery(Order.class, eql);
|
||||
* query.setParameter("orderId", 2);
|
||||
*
|
||||
* Order order = query.findOne();
|
||||
*
|
||||
* // This is the same as:
|
||||
*
|
||||
* Order order = DB.find(Order.class)
|
||||
* .fetch("customer")
|
||||
* .fetch("details")
|
||||
* .fetch("detail.product", "name")
|
||||
* .setId(2)
|
||||
* .findOne();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param beanType The type of bean to fetch
|
||||
* @param eql The Ebean query
|
||||
* @param <T> The type of the entity bean
|
||||
* @return The query with expressions defined as per the parsed query statement
|
||||
*/
|
||||
public static <T> Query<T> createQuery(Class<T> beanType, String eql) {
|
||||
return getDefault().createQuery(beanType, eql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a query for a type of entity bean.
|
||||
* <p>
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
package io.ebean;
|
||||
|
||||
final class DPaging implements Paging {
|
||||
|
||||
static final Paging NONE = new DPaging(0, 0, null);
|
||||
|
||||
static Paging build(int pgIndex, int pgSize, OrderBy<?> orderBy) {
|
||||
return new DPaging(pgIndex, pgSize, orderBy);
|
||||
}
|
||||
|
||||
static Paging build(int pgIndex, int pgSize) {
|
||||
return new DPaging(pgIndex, pgSize, null);
|
||||
}
|
||||
|
||||
private final int pageNumber;
|
||||
private final int pageSize;
|
||||
private final OrderBy<?> orderBy;
|
||||
|
||||
DPaging(int pageNumber, int pageSize, OrderBy<?> orderBy) {
|
||||
this.pageNumber = pageNumber;
|
||||
this.pageSize = pageSize;
|
||||
this.orderBy = orderBy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int pageIndex() {
|
||||
return pageNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int pageSize() {
|
||||
return pageSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrderBy<?> orderBy() {
|
||||
return orderBy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Paging withPage(int pageNumber) {
|
||||
return new DPaging(pageNumber, pageSize, orderBy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Paging withOrderBy(String orderByClause) {
|
||||
return new DPaging(pageNumber, pageSize, OrderBy.of(orderByClause));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package io.ebean;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import io.avaje.lang.NonNullApi;
|
||||
import io.avaje.lang.Nullable;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.annotation.TxIsolation;
|
||||
import io.ebean.cache.ServerCacheManager;
|
||||
@@ -83,7 +83,7 @@ import java.util.concurrent.Callable;
|
||||
* @see DatabaseFactory
|
||||
* @see DatabaseConfig
|
||||
*/
|
||||
@NullMarked
|
||||
@NonNullApi
|
||||
public interface Database {
|
||||
|
||||
/**
|
||||
@@ -137,7 +137,6 @@ public interface Database {
|
||||
/**
|
||||
* Return the associated read only DataSource for this Database instance (can be null).
|
||||
*/
|
||||
@Nullable
|
||||
DataSource readOnlyDataSource();
|
||||
|
||||
/**
|
||||
@@ -243,18 +242,6 @@ public interface Database {
|
||||
*/
|
||||
<T> UpdateQuery<T> update(Class<T> beanType);
|
||||
|
||||
/**
|
||||
* Create a named query.
|
||||
* <p>
|
||||
* For RawSql the named query is expected to be in ebean.xml.
|
||||
*
|
||||
* @param beanType The type of entity bean
|
||||
* @param namedQuery The name of the query
|
||||
* @param <T> The type of entity bean
|
||||
* @return The query
|
||||
*/
|
||||
<T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery);
|
||||
|
||||
/**
|
||||
* Create a query for an entity bean and synonym for {@link #find(Class)}.
|
||||
*
|
||||
@@ -262,41 +249,6 @@ public interface Database {
|
||||
*/
|
||||
<T> Query<T> createQuery(Class<T> beanType);
|
||||
|
||||
/**
|
||||
* Parse the Ebean query language statement returning the query which can then
|
||||
* be modified (add expressions, change order by clause, change maxRows, change
|
||||
* fetch and select paths etc).
|
||||
* <p>
|
||||
* <h3>Example</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // Find order additionally fetching the customer, details and details.product name.
|
||||
*
|
||||
* String ormQuery = "fetch customer fetch details fetch details.product (name) where id = :orderId ";
|
||||
*
|
||||
* Query<Order> query = DB.createQuery(Order.class, ormQuery);
|
||||
* query.setParameter("orderId", 2);
|
||||
*
|
||||
* Order order = query.findOne();
|
||||
*
|
||||
* // This is the same as:
|
||||
*
|
||||
* Order order = DB.find(Order.class)
|
||||
* .fetch("customer")
|
||||
* .fetch("details")
|
||||
* .fetch("detail.product", "name")
|
||||
* .setId(2)
|
||||
* .findOne();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param beanType The type of bean to fetch
|
||||
* @param ormQuery The Ebean ORM query
|
||||
* @param <T> The type of the entity bean
|
||||
* @return The query with expressions defined as per the parsed query statement
|
||||
*/
|
||||
<T> Query<T> createQuery(Class<T> beanType, String ormQuery);
|
||||
|
||||
/**
|
||||
* Create a query for a type of entity bean.
|
||||
* <p>
|
||||
@@ -401,7 +353,7 @@ public interface Database {
|
||||
* // find orders and their customers
|
||||
* List<Order> list = database.find(Order.class)
|
||||
* .fetch("customer")
|
||||
* .orderBy("id")
|
||||
* .order("id")
|
||||
* .findList();
|
||||
*
|
||||
* // sort by customer name ascending, then by order shipDate
|
||||
@@ -460,18 +412,6 @@ public interface Database {
|
||||
*/
|
||||
<T> DtoQuery<T> findDto(Class<T> dtoType, String sql);
|
||||
|
||||
/**
|
||||
* Create a named Query for DTO beans.
|
||||
* <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.
|
||||
*
|
||||
* @param dtoType The type of the DTO bean the rows will be mapped into.
|
||||
* @param namedQuery The name of the query
|
||||
* @param <T> The type of the DTO bean.
|
||||
*/
|
||||
<T> DtoQuery<T> createNamedDtoQuery(Class<T> dtoType, String namedQuery);
|
||||
|
||||
/**
|
||||
* Look to execute a native sql query that does not return beans but instead
|
||||
* returns SqlRow or direct access to ResultSet.
|
||||
@@ -773,6 +713,18 @@ public interface Database {
|
||||
*/
|
||||
<T> T reference(Class<T> beanType, Object id);
|
||||
|
||||
/**
|
||||
* Return the extended API for Database.
|
||||
* <p>
|
||||
* The extended API has the options for executing queries that take an explicit
|
||||
* transaction as an argument.
|
||||
* <p>
|
||||
* 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.
|
||||
*/
|
||||
ExtendedServer extended();
|
||||
|
||||
/**
|
||||
* Either Insert or Update the bean depending on its state.
|
||||
* <p>
|
||||
@@ -1374,109 +1326,6 @@ public interface Database {
|
||||
*/
|
||||
ScriptRunner script();
|
||||
|
||||
/**
|
||||
* Return the Document store.
|
||||
*/
|
||||
DocumentStore docStore();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param <T> the type of the entity bean
|
||||
* @param beanType the type of the entity bean
|
||||
* @param id the id of the entity bean
|
||||
* @param transaction the transaction the publish process should use (can be null)
|
||||
*/
|
||||
@Nullable
|
||||
<T> T publish(Class<T> beanType, Object id, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Publish a single bean given its type and id returning the resulting live bean.
|
||||
* This will use the current transaction or create one if required.
|
||||
* <p>
|
||||
* The values are published from the draft to the live bean.
|
||||
*
|
||||
* @param <T> the type of the entity bean
|
||||
* @param beanType the type of the entity bean
|
||||
* @param id the id of the entity bean
|
||||
*/
|
||||
@Nullable
|
||||
<T> T publish(Class<T> beanType, Object id);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param <T> the type of the entity bean
|
||||
* @param query the query used to select the draft beans to publish
|
||||
* @param transaction the transaction the publish process should use (can be null)
|
||||
*/
|
||||
<T> List<T> publish(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Publish the beans that match the query returning the resulting published beans.
|
||||
* This will use the current transaction or create one if required.
|
||||
* <p>
|
||||
* The values are published from the draft beans to the live beans.
|
||||
*
|
||||
* @param <T> the type of the entity bean
|
||||
* @param query the query used to select the draft beans to publish
|
||||
*/
|
||||
<T> List<T> publish(Query<T> query);
|
||||
|
||||
/**
|
||||
* Restore the draft bean back to the live state.
|
||||
* <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.
|
||||
*
|
||||
* @param <T> the type of the entity bean
|
||||
* @param beanType the type of the entity bean
|
||||
* @param id the id of the entity bean to restore
|
||||
* @param transaction the transaction the restore process should use (can be null)
|
||||
*/
|
||||
@Nullable
|
||||
<T> T draftRestore(Class<T> beanType, Object id, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Restore the draft bean back to the live state.
|
||||
* <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.
|
||||
*
|
||||
* @param <T> the type of the entity bean
|
||||
* @param beanType the type of the entity bean
|
||||
* @param id the id of the entity bean to restore
|
||||
*/
|
||||
@Nullable
|
||||
<T> T draftRestore(Class<T> beanType, Object id);
|
||||
|
||||
/**
|
||||
* Restore the draft beans matching the query back to the live state.
|
||||
* <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.
|
||||
*
|
||||
* @param <T> the type of the entity bean
|
||||
* @param query the query used to select the draft beans to restore
|
||||
* @param transaction the transaction the restore process should use (can be null)
|
||||
*/
|
||||
<T> List<T> draftRestore(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Restore the draft beans matching the query back to the live state.
|
||||
* <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.
|
||||
*
|
||||
* @param <T> the type of the entity bean
|
||||
* @param query the query used to select the draft beans to restore
|
||||
*/
|
||||
<T> List<T> draftRestore(Query<T> query);
|
||||
|
||||
/**
|
||||
* Returns the set of properties/paths that are unknown (do not map to known properties or paths).
|
||||
* <p>
|
||||
|
||||
@@ -13,8 +13,6 @@ import io.ebean.event.*;
|
||||
import io.ebean.event.changelog.ChangeLogListener;
|
||||
import io.ebean.event.changelog.ChangeLogPrepare;
|
||||
import io.ebean.event.changelog.ChangeLogRegister;
|
||||
import io.ebean.event.readaudit.ReadAuditLogger;
|
||||
import io.ebean.event.readaudit.ReadAuditPrepare;
|
||||
import jakarta.persistence.EnumType;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
@@ -691,38 +689,6 @@ public interface DatabaseBuilder {
|
||||
@Deprecated
|
||||
DatabaseBuilder setChangeLogAsync(boolean changeLogAsync);
|
||||
|
||||
/**
|
||||
* Set the ReadAuditLogger to use. If not set the default implementation is used
|
||||
* which logs the read events in JSON format to a standard named SLF4J logger
|
||||
* (which can be configured in say logback to log to a separate log file).
|
||||
*/
|
||||
default DatabaseBuilder readAuditLogger(ReadAuditLogger readAuditLogger) {
|
||||
return setReadAuditLogger(readAuditLogger);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated migrate to {@link #readAuditLogger(ReadAuditLogger)}.
|
||||
*/
|
||||
@Deprecated
|
||||
DatabaseBuilder setReadAuditLogger(ReadAuditLogger readAuditLogger);
|
||||
|
||||
/**
|
||||
* Set the ReadAuditPrepare to use.
|
||||
* <p>
|
||||
* It is expected that an implementation is used that read user context information
|
||||
* (user id, user ip address etc) and sets it on the ReadEvent bean before it is sent
|
||||
* to the ReadAuditLogger.
|
||||
*/
|
||||
default DatabaseBuilder readAuditPrepare(ReadAuditPrepare readAuditPrepare) {
|
||||
return setReadAuditPrepare(readAuditPrepare);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated migrate to {@link #readAuditPrepare(ReadAuditPrepare)}.
|
||||
*/
|
||||
@Deprecated
|
||||
DatabaseBuilder setReadAuditPrepare(ReadAuditPrepare readAuditPrepare);
|
||||
|
||||
/**
|
||||
* Set the configuration for profiling.
|
||||
*/
|
||||
@@ -1005,16 +971,6 @@ public interface DatabaseBuilder {
|
||||
@Deprecated
|
||||
DatabaseBuilder setAllQuotedIdentifiers(boolean allQuotedIdentifiers);
|
||||
|
||||
/**
|
||||
* Set to true if this Database is Document store only instance (has no JDBC DB).
|
||||
*/
|
||||
DatabaseBuilder setDocStoreOnly(boolean docStoreOnly);
|
||||
|
||||
/**
|
||||
* Set the configuration for the ElasticSearch integration.
|
||||
*/
|
||||
DatabaseBuilder setDocStoreConfig(DocStoreConfig docStoreConfig);
|
||||
|
||||
/**
|
||||
* Set the constraint naming convention used in DDL generation.
|
||||
*/
|
||||
@@ -1062,11 +1018,6 @@ public interface DatabaseBuilder {
|
||||
*/
|
||||
DatabaseBuilder readOnlyDatabase(boolean readOnlyDatabase);
|
||||
|
||||
/**
|
||||
* Set to false such that the instance does not register a JVM shutdown hook.
|
||||
*/
|
||||
DatabaseBuilder shutdownHook(boolean shutdownHook);
|
||||
|
||||
/**
|
||||
* Set a DataSource.
|
||||
*/
|
||||
@@ -1973,8 +1924,8 @@ public interface DatabaseBuilder {
|
||||
DatabaseBuilder setLocalOnlyL2Cache(boolean localOnlyL2Cache);
|
||||
|
||||
/**
|
||||
* Controls if Ebean should ignore <code>@javax.validation.contstraints.NotNull</code> or
|
||||
* <code>@jakarta.validation.contstraints.NotNull</code>
|
||||
* Controls if Ebean should ignore <code>&x64;javax.validation.contstraints.NotNull</code> or
|
||||
* <code>&x64;jakarta.validation.contstraints.NotNull</code>
|
||||
* with respect to generating a <code>NOT NULL</code> column.
|
||||
* <p>
|
||||
* Normally when Ebean sees javax NotNull annotation it means that column is defined as NOT NULL.
|
||||
@@ -2024,11 +1975,6 @@ public interface DatabaseBuilder {
|
||||
@Deprecated
|
||||
DatabaseBuilder setQueryPlanTTLSeconds(int queryPlanTTLSeconds);
|
||||
|
||||
/**
|
||||
* Set the EXPLAIN (with options) to use for query plan capture.
|
||||
*/
|
||||
DatabaseBuilder queryPlanExplain(String queryPlanExplain);
|
||||
|
||||
/**
|
||||
* Create a new PlatformConfig based of the one held but with overridden properties by reading
|
||||
* properties with the given path and prefix.
|
||||
@@ -2467,16 +2413,6 @@ public interface DatabaseBuilder {
|
||||
*/
|
||||
boolean isChangeLogAsync();
|
||||
|
||||
/**
|
||||
* Return the ReadAuditLogger to use.
|
||||
*/
|
||||
ReadAuditLogger getReadAuditLogger();
|
||||
|
||||
/**
|
||||
* Return the ReadAuditPrepare to use.
|
||||
*/
|
||||
ReadAuditPrepare getReadAuditPrepare();
|
||||
|
||||
/**
|
||||
* Return the tenancy catalog provider.
|
||||
*/
|
||||
@@ -2615,16 +2551,6 @@ public interface DatabaseBuilder {
|
||||
*/
|
||||
boolean isAllQuotedIdentifiers();
|
||||
|
||||
/**
|
||||
* Return true if this Database is a Document store only instance (has no JDBC DB).
|
||||
*/
|
||||
boolean isDocStoreOnly();
|
||||
|
||||
/**
|
||||
* Return the configuration for the ElasticSearch integration.
|
||||
*/
|
||||
DocStoreConfig getDocStoreConfig();
|
||||
|
||||
/**
|
||||
* Return the constraint naming convention used in DDL generation.
|
||||
*/
|
||||
@@ -2648,11 +2574,6 @@ public interface DatabaseBuilder {
|
||||
*/
|
||||
boolean readOnlyDatabase();
|
||||
|
||||
/**
|
||||
* Return if a JVM shutdown hook should be registered.
|
||||
*/
|
||||
boolean shutdownHook();
|
||||
|
||||
/**
|
||||
* Return the DataSource.
|
||||
*/
|
||||
@@ -3059,11 +2980,6 @@ public interface DatabaseBuilder {
|
||||
*/
|
||||
int getQueryPlanTTLSeconds();
|
||||
|
||||
/**
|
||||
* Return the EXPLAIN (with options) to use for capturing query plans.
|
||||
*/
|
||||
String getQueryPlanExplain();
|
||||
|
||||
/**
|
||||
* Return mapping locations to search for xml mapping via class path search.
|
||||
*/
|
||||
|
||||
@@ -5,6 +5,8 @@ import io.ebean.service.SpiContainer;
|
||||
import io.ebean.service.SpiContainerFactory;
|
||||
import jakarta.persistence.PersistenceException;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
@@ -155,10 +157,10 @@ public final class DatabaseFactory {
|
||||
* Create the container instance using the configuration.
|
||||
*/
|
||||
private static SpiContainer createContainer(ContainerConfig containerConfig) {
|
||||
SpiContainerFactory factory = XBootstrapService.containerFactory();
|
||||
if (factory == null) {
|
||||
throw new IllegalStateException("Service loader didn't find a SpiContainerFactory?");
|
||||
Iterator<SpiContainerFactory> factories = ServiceLoader.load(SpiContainerFactory.class).iterator();
|
||||
if (factories.hasNext()) {
|
||||
return factories.next().create(containerConfig);
|
||||
}
|
||||
return factory.create(containerConfig);
|
||||
throw new IllegalStateException("Service loader didn't find a SpiContainerFactory?");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
package io.ebean;
|
||||
|
||||
/**
|
||||
* Bean holding the details to update the document store.
|
||||
*/
|
||||
public final class DocStoreQueueEntry {
|
||||
|
||||
/**
|
||||
* Action to either update or delete a document from the index.
|
||||
*/
|
||||
public enum Action {
|
||||
|
||||
/**
|
||||
* Action is to update a document in the doc store.
|
||||
*/
|
||||
INDEX(1),
|
||||
|
||||
/**
|
||||
* Action is to delete a document from the doc store..
|
||||
*/
|
||||
DELETE(2),
|
||||
|
||||
/**
|
||||
* An update is required based on a change to a nested/embedded object at a given path.
|
||||
*/
|
||||
NESTED(3);
|
||||
|
||||
int value;
|
||||
|
||||
Action(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value associated with this action type.
|
||||
*/
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
private final Action type;
|
||||
|
||||
private final String queueId;
|
||||
|
||||
private final String path;
|
||||
|
||||
private final Object beanId;
|
||||
|
||||
/**
|
||||
* Construct for an INDEX or DELETE action.
|
||||
*/
|
||||
public DocStoreQueueEntry(Action type, String queueId, Object beanId) {
|
||||
this(type, queueId, null, beanId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct for an NESTED/embedded path invalidation action.
|
||||
*/
|
||||
public DocStoreQueueEntry(Action type, String queueId, String path, Object beanId) {
|
||||
this.type = type;
|
||||
this.queueId = queueId;
|
||||
this.path = path;
|
||||
this.beanId = beanId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the event type.
|
||||
*/
|
||||
public Action getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the associate queueId.
|
||||
*/
|
||||
public String getQueueId() {
|
||||
return queueId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the path if this is a nested update.
|
||||
*/
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bean id (which matches the document id).
|
||||
*/
|
||||
public Object getBeanId() {
|
||||
return beanId;
|
||||
}
|
||||
}
|
||||
@@ -1,312 +0,0 @@
|
||||
package io.ebean;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import io.ebean.docstore.DocQueryContext;
|
||||
import io.ebean.docstore.RawDoc;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Document storage operations.
|
||||
*/
|
||||
@NullMarked
|
||||
public interface DocumentStore {
|
||||
|
||||
/**
|
||||
* Update the associated document store using the result of the query.
|
||||
* <p>
|
||||
* This will execute the query against the database creating a document for each
|
||||
* bean graph and sending this to the document store.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that the select and fetch paths of the query is set for you to match the
|
||||
* document structure needed based on <code>@DocStore</code> and <code>@DocStoreEmbedded</code>
|
||||
* so what this query requires is the predicates only.
|
||||
* </p>
|
||||
* <p>
|
||||
* This query will be executed using findEach so it is safe to use a query
|
||||
* that will fetch a lot of beans. The default bulkBatchSize is used.
|
||||
* </p>
|
||||
*
|
||||
* @param query The query that selects object to send to the document store.
|
||||
*/
|
||||
<T> void indexByQuery(Query<T> query);
|
||||
|
||||
/**
|
||||
* Update the associated document store index using the result of the query additionally specifying a
|
||||
* bulkBatchSize to use for sending the messages to ElasticSearch.
|
||||
*
|
||||
* @param query The query that selects object to send to the document store.
|
||||
* @param bulkBatchSize The batch size to use when bulk sending to the document store.
|
||||
*/
|
||||
<T> void indexByQuery(Query<T> query, int bulkBatchSize);
|
||||
|
||||
/**
|
||||
* Update the document store for all beans of this type.
|
||||
* <p>
|
||||
* This is the same as indexByQuery where the query has no predicates and so fetches all rows.
|
||||
* </p>
|
||||
*/
|
||||
void indexAll(Class<?> beanType);
|
||||
|
||||
/**
|
||||
* Return the bean by fetching it's content from the document store.
|
||||
* If the document is not found null is returned.
|
||||
* <p>
|
||||
* Typically this is called indirectly by findOne() on the query.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* Customer customer =
|
||||
* database.find(Customer.class)
|
||||
* .setUseDocStore(true)
|
||||
* .setId(42)
|
||||
* .findOne();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@Nullable
|
||||
<T> T find(DocQueryContext<T> request);
|
||||
|
||||
/**
|
||||
* Execute the find list query. This request is prepared to execute secondary queries.
|
||||
* <p>
|
||||
* Typically this is called indirectly by findList() on the query that has setUseDocStore(true).
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<Customer> newCustomers =
|
||||
* database.find(Customer.class)
|
||||
* .setUseDocStore(true)
|
||||
* .where().eq("status, Customer.Status.NEW)
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
<T> List<T> findList(DocQueryContext<T> request);
|
||||
|
||||
/**
|
||||
* Execute the query against the document store returning the paged list.
|
||||
* <p>
|
||||
* The query should have <code>firstRow</code> or <code>maxRows</code> set prior to calling this method.
|
||||
* </p>
|
||||
* <p>
|
||||
* Typically this is called indirectly by findPagedList() on the query that has setUseDocStore(true).
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* PagedList<Customer> newCustomers =
|
||||
* database.find(Customer.class)
|
||||
* .setUseDocStore(true)
|
||||
* .where().eq("status, Customer.Status.NEW)
|
||||
* .setMaxRows(50)
|
||||
* .findPagedList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
<T> PagedList<T> findPagedList(DocQueryContext<T> request);
|
||||
|
||||
/**
|
||||
* Execute the query against the document store with the expectation of a large set of results
|
||||
* that are processed in a scrolling resultSet fashion.
|
||||
* <p>
|
||||
* For example, with the ElasticSearch doc store this uses SCROLL.
|
||||
* </p>
|
||||
* <p>
|
||||
* Typically this is called indirectly by findEach() on the query that has setUseDocStore(true).
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* database.find(Order.class)
|
||||
* .setUseDocStore(true)
|
||||
* .where()... // perhaps add predicates
|
||||
* .findEach((Order order) -> {
|
||||
* // process the bean ...
|
||||
* });
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
<T> void findEach(DocQueryContext<T> query, Consumer<T> consumer);
|
||||
|
||||
/**
|
||||
* Execute the query against the document store with the expectation of a large set of results
|
||||
* that are processed in a scrolling resultSet fashion.
|
||||
* <p>
|
||||
* Unlike findEach() this provides the opportunity to stop iterating through the large query.
|
||||
* </p>
|
||||
* <p>
|
||||
* For example, with the ElasticSearch doc store this uses SCROLL.
|
||||
* </p>
|
||||
* <p>
|
||||
* Typically this is called indirectly by findEachWhile() on the query that has setUseDocStore(true).
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* database.find(Order.class)
|
||||
* .setUseDocStore(true)
|
||||
* .where()... // perhaps add predicates
|
||||
* .findEachWhile(new Predicate<Order>() {
|
||||
* @Override
|
||||
* public void accept(Order bean) {
|
||||
* // process the bean
|
||||
*
|
||||
* // return true to continue, false to stop
|
||||
* // boolean shouldContinue = ...
|
||||
* return shouldContinue;
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
<T> void findEachWhile(DocQueryContext<T> query, Predicate<T> consumer);
|
||||
|
||||
/**
|
||||
* Find each processing raw documents.
|
||||
*
|
||||
* @param indexNameType The full index name and type
|
||||
* @param rawQuery The query to execute
|
||||
* @param consumer Consumer to process each document
|
||||
*/
|
||||
void findEach(String indexNameType, String rawQuery, Consumer<RawDoc> consumer);
|
||||
|
||||
/**
|
||||
* Find each processing raw documents stopping when the predicate returns false.
|
||||
*
|
||||
* @param indexNameType The full index name and type
|
||||
* @param rawQuery The query to execute
|
||||
* @param consumer Consumer to process each document until false is returned
|
||||
*/
|
||||
void findEachWhile(String indexNameType, String rawQuery, Predicate<RawDoc> consumer);
|
||||
|
||||
/**
|
||||
* Process the queue entries sending updates to the document store or queuing them for later processing.
|
||||
*/
|
||||
long process(List<DocStoreQueueEntry> queueEntries) throws IOException;
|
||||
|
||||
/**
|
||||
* Drop the index from the document store (similar to DDL drop table).
|
||||
* <pre>{@code
|
||||
*
|
||||
* DocumentStore documentStore = database.docStore();
|
||||
*
|
||||
* documentStore.dropIndex("product_copy");
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
void dropIndex(String indexName);
|
||||
|
||||
/**
|
||||
* Create an index given a mapping file as a resource in the classPath (similar to DDL create table).
|
||||
* <pre>{@code
|
||||
*
|
||||
* DocumentStore documentStore = database.docStore();
|
||||
*
|
||||
* // uses product_copy.mapping.json resource
|
||||
* // ... to define mappings for the index
|
||||
*
|
||||
* documentStore.createIndex("product_copy", null);
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param indexName the name of the new index
|
||||
* @param alias the alias of the index
|
||||
*/
|
||||
void createIndex(String indexName, String alias);
|
||||
|
||||
/**
|
||||
* Modify the settings on an index.
|
||||
* <p>
|
||||
* For example, this can be used be used to set elasticSearch refresh_interval
|
||||
* on an index before a bulk update.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // refresh_interval -1 ... disable refresh while bulk loading
|
||||
*
|
||||
* Map<String,Object> settings = new LinkedHashMap<>();
|
||||
* settings.put("refresh_interval", "-1");
|
||||
*
|
||||
* documentStore.indexSettings("product", settings);
|
||||
*
|
||||
* }</pre>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // refresh_interval 1s ... restore after bulk loading
|
||||
*
|
||||
* Map<String,Object> settings = new LinkedHashMap<>();
|
||||
* settings.put("refresh_interval", "1s");
|
||||
*
|
||||
* documentStore.indexSettings("product", settings);
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param indexName the name of the index to update settings on
|
||||
* @param settings the settings to set on the index
|
||||
*/
|
||||
void indexSettings(String indexName, Map<String, Object> settings);
|
||||
|
||||
/**
|
||||
* Copy the index to a new index.
|
||||
* <p>
|
||||
* This copy process does not use the database but instead will copy from the source index to a destination index.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* long copyCount = documentStore.copyIndex(Product.class, "product_copy");
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param beanType The bean type of the source index
|
||||
* @param newIndex The name of the index to copy to
|
||||
* @return the number of documents copied to the new index
|
||||
*/
|
||||
long copyIndex(Class<?> beanType, String newIndex);
|
||||
|
||||
/**
|
||||
* Copy entries from an index to a new index but limiting to documents that have been
|
||||
* modified since the sinceEpochMillis time.
|
||||
* <p>
|
||||
* To support this the document needs to have a <code>@WhenModified</code> property.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* long copyCount = documentStore.copyIndex(Product.class, "product_copy", sinceMillis);
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param beanType The bean type of the source index
|
||||
* @param newIndex The name of the index to copy to
|
||||
* @return the number of documents copied to the new index
|
||||
*/
|
||||
long copyIndex(Class<?> beanType, String newIndex, long sinceEpochMillis);
|
||||
|
||||
/**
|
||||
* Copy from a source index to a new index taking only the documents
|
||||
* matching the given query.
|
||||
* <pre>{@code
|
||||
*
|
||||
* // predicates to select the source documents to copy
|
||||
* Query<Product> query = database.find(Product.class)
|
||||
* .where()
|
||||
* .ge("whenModified", new Timestamp(since))
|
||||
* .ge("name", "A")
|
||||
* .lt("name", "D")
|
||||
* .query();
|
||||
*
|
||||
* // copy from the source index to "product_copy" index
|
||||
* long copyCount = documentStore.copyIndex(query, "product_copy", 1000);
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param query The query to select the source documents to copy
|
||||
* @param newIndex The target index to copy the documents to
|
||||
* @param bulkBatchSize The ElasticSearch bulk batch size, if 0 uses the default.
|
||||
* @return The number of documents copied to the new index.
|
||||
*/
|
||||
long copyIndex(Query<?> query, String newIndex, int bulkBatchSize);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package io.ebean;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import io.avaje.lang.NonNullApi;
|
||||
import io.avaje.lang.Nullable;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
@@ -42,7 +42,7 @@ import java.util.stream.Stream;
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@NullMarked
|
||||
@NonNullApi
|
||||
public interface DtoQuery<T> extends CancelableQuery {
|
||||
|
||||
/**
|
||||
@@ -140,17 +140,6 @@ public interface DtoQuery<T> extends CancelableQuery {
|
||||
* Bind the named multi-value array parameter which we would use with Postgres ANY.
|
||||
* <p>
|
||||
* For Postgres this binds an ARRAY rather than expands into multiple bind values.
|
||||
* <pre>{@code
|
||||
*
|
||||
* String sql = "select id, name from o_customer where id = any(:idList)";
|
||||
*
|
||||
* var ids = List.of(1, 2, 3);
|
||||
*
|
||||
* List<CustomerDto> list2 = DB.findDto(CustomerDto.class, sql)
|
||||
* .setArrayParameter("idList", ids)
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
DtoQuery<T> setArrayParameter(String name, Collection<?> values);
|
||||
|
||||
|
||||
@@ -5,8 +5,6 @@ import java.util.List;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* @deprecated migrate to using {@link PagedList#emptyList()} only.
|
||||
* <p>
|
||||
* An empty PagedList.
|
||||
* <p>
|
||||
* For use in application code when we need to return a PagedList but don't want to
|
||||
@@ -19,8 +17,7 @@ import java.util.concurrent.Future;
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public final class EmptyPagedList<T> implements PagedList<T> {
|
||||
public class EmptyPagedList<T> implements PagedList<T> {
|
||||
|
||||
@Override
|
||||
public void loadCount() {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.search.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -625,31 +623,6 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
Expression raw(String raw);
|
||||
|
||||
/**
|
||||
* Create a Text Match expression (currently doc store/Elastic only).
|
||||
*/
|
||||
Expression textMatch(String propertyName, String search, Match options);
|
||||
|
||||
/**
|
||||
* Create a Text Multi match expression (currently doc store/Elastic only).
|
||||
*/
|
||||
Expression textMultiMatch(String query, MultiMatch options);
|
||||
|
||||
/**
|
||||
* Create a text simple query expression (currently doc store/Elastic only).
|
||||
*/
|
||||
Expression textSimple(String search, TextSimple options);
|
||||
|
||||
/**
|
||||
* Create a text query string expression (currently doc store/Elastic only).
|
||||
*/
|
||||
Expression textQueryString(String search, TextQueryString options);
|
||||
|
||||
/**
|
||||
* Create a text common terms expression (currently doc store/Elastic only).
|
||||
*/
|
||||
Expression textCommonTerms(String search, TextCommonTerms options);
|
||||
|
||||
/**
|
||||
* And - join two expressions with a logical and.
|
||||
*/
|
||||
@@ -693,12 +666,4 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
<T> Junction<T> junction(Junction.Type type, Query<T> query, ExpressionList<T> parent);
|
||||
|
||||
/**
|
||||
* Add the expressions to the given expression list.
|
||||
*
|
||||
* @param where The expression list to add the expressions to
|
||||
* @param expressions The expressions that are parsed
|
||||
* @param params Bind parameters to match ? or ?1 bind positions.
|
||||
*/
|
||||
<T> void where(ExpressionList<T> where, String expressions, Object[] params);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
package io.ebean;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import io.ebean.search.*;
|
||||
import io.avaje.lang.NonNullApi;
|
||||
import io.avaje.lang.Nullable;
|
||||
|
||||
import jakarta.persistence.NonUniqueResultException;
|
||||
import java.sql.Connection;
|
||||
@@ -31,7 +30,7 @@ import java.util.function.Predicate;
|
||||
*
|
||||
* @see Query#where()
|
||||
*/
|
||||
@NullMarked
|
||||
@NonNullApi
|
||||
public interface ExpressionList<T> {
|
||||
|
||||
/**
|
||||
@@ -53,6 +52,14 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
Query<T> orderById(boolean orderById);
|
||||
|
||||
/**
|
||||
* @deprecated migrate to {@link #orderBy(String)}
|
||||
*/
|
||||
@Deprecated(since = "13.19", forRemoval = true)
|
||||
default ExpressionList<T> order(String orderByClause) {
|
||||
return orderBy(orderByClause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the order by clause replacing the existing order by clause if there is
|
||||
* one.
|
||||
@@ -63,6 +70,14 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> orderBy(String orderBy);
|
||||
|
||||
/**
|
||||
* @deprecated migrate to {@link #orderBy()}.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
default OrderBy<T> order() {
|
||||
return orderBy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the OrderBy so that you can append an ascending or descending
|
||||
* property to the order by clause.
|
||||
@@ -90,11 +105,6 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
Query<T> asOf(Timestamp asOf);
|
||||
|
||||
/**
|
||||
* Execute the query against the draft set of tables.
|
||||
*/
|
||||
Query<T> asDraft();
|
||||
|
||||
/**
|
||||
* Convert the query to a DTO bean query.
|
||||
* <p>
|
||||
@@ -205,6 +215,18 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
int delete();
|
||||
|
||||
/**
|
||||
* 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>
|
||||
*
|
||||
* @return the number of rows that were deleted.
|
||||
*/
|
||||
int delete(Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute as a update query.
|
||||
*
|
||||
@@ -213,6 +235,14 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
int update();
|
||||
|
||||
/**
|
||||
* Execute as a update query with the given transaction.
|
||||
*
|
||||
* @return the number of rows that were updated.
|
||||
* @see UpdateQuery
|
||||
*/
|
||||
int update(Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the query returning true if a row is found.
|
||||
* <p>
|
||||
@@ -313,7 +343,7 @@ public interface ExpressionList<T> {
|
||||
* List<String> names =
|
||||
* DB.find(Customer.class)
|
||||
* .select("name")
|
||||
* .orderBy().asc("name")
|
||||
* .order().asc("name")
|
||||
* .findSingleAttributeList();
|
||||
*
|
||||
* }</pre>
|
||||
@@ -326,7 +356,7 @@ public interface ExpressionList<T> {
|
||||
* .setDistinct(true)
|
||||
* .select("name")
|
||||
* .where().eq("status", Customer.Status.NEW)
|
||||
* .orderBy().asc("name")
|
||||
* .order().asc("name")
|
||||
* .setMaxRows(100)
|
||||
* .findSingleAttributeList();
|
||||
*
|
||||
@@ -471,28 +501,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
|
||||
*
|
||||
* DB.find(Customer.class)
|
||||
* .where()
|
||||
* .eq("name", "Rob")
|
||||
* .filterMany("orders", "status = ?", Status.NEW)
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param manyProperty The many property
|
||||
* @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.
|
||||
@@ -544,19 +552,6 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
Query<T> setDistinct(boolean distinct);
|
||||
|
||||
/**
|
||||
* Set the index(es) to search for a document store which uses partitions.
|
||||
* <p>
|
||||
* For example, when executing a query against ElasticSearch with daily indexes we can
|
||||
* explicitly specify the indexes to search against.
|
||||
* </p>
|
||||
*
|
||||
* @param indexName The index or indexes to search against
|
||||
* @return This query
|
||||
* @see Query#setDocIndexName(String)
|
||||
*/
|
||||
Query<T> setDocIndexName(String indexName);
|
||||
|
||||
/**
|
||||
* Set the first row to fetch.
|
||||
*
|
||||
@@ -640,14 +635,6 @@ public interface ExpressionList<T> {
|
||||
return setUseQueryCache(enabled ? CacheMode.ON : CacheMode.OFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if this query should execute against the doc store.
|
||||
* <p>
|
||||
* When setting this you may also consider disabling lazy loading.
|
||||
* </p>
|
||||
*/
|
||||
Query<T> setUseDocStore(boolean useDocsStore);
|
||||
|
||||
/**
|
||||
* Set true if you want to disable lazy loading.
|
||||
* <p>
|
||||
@@ -656,16 +643,6 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
Query<T> setDisableLazyLoading(boolean disableLazyLoading);
|
||||
|
||||
/**
|
||||
* Disable read auditing for this query.
|
||||
* <p>
|
||||
* This is intended to be used when the query is not a user initiated query and instead
|
||||
* part of the internal processing in an application to load a cache or document store etc.
|
||||
* In these cases we don't want the query to be part of read auditing.
|
||||
* </p>
|
||||
*/
|
||||
Query<T> setDisableReadAuditing();
|
||||
|
||||
/**
|
||||
* Set a label on the query (to help identify query execution statistics).
|
||||
*/
|
||||
@@ -685,14 +662,6 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> where();
|
||||
|
||||
/**
|
||||
* Add the expressions to this expression list.
|
||||
*
|
||||
* @param expressions The expressions that are parsed and added to this expression list
|
||||
* @param params Bind parameters to match ? or ?1 bind positions.
|
||||
*/
|
||||
ExpressionList<T> where(String expressions, Object... params);
|
||||
|
||||
/**
|
||||
* Path exists - for the given path in a JSON document.
|
||||
* <pre>{@code
|
||||
@@ -1587,47 +1556,6 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> rawOrEmpty(String raw, Collection<?> values);
|
||||
|
||||
/**
|
||||
* Add a match expression.
|
||||
*
|
||||
* @param propertyName The property name for the match
|
||||
* @param search The search value
|
||||
*/
|
||||
ExpressionList<T> match(String propertyName, String search);
|
||||
|
||||
/**
|
||||
* Add a match expression with options.
|
||||
*
|
||||
* @param propertyName The property name for the match
|
||||
* @param search The search value
|
||||
*/
|
||||
ExpressionList<T> match(String propertyName, String search, Match options);
|
||||
|
||||
/**
|
||||
* Add a multi-match expression.
|
||||
*/
|
||||
ExpressionList<T> multiMatch(String search, String... properties);
|
||||
|
||||
/**
|
||||
* Add a multi-match expression using options.
|
||||
*/
|
||||
ExpressionList<T> multiMatch(String search, MultiMatch options);
|
||||
|
||||
/**
|
||||
* Add a simple query string expression.
|
||||
*/
|
||||
ExpressionList<T> textSimple(String search, TextSimple options);
|
||||
|
||||
/**
|
||||
* Add a query string expression.
|
||||
*/
|
||||
ExpressionList<T> textQueryString(String search, TextQueryString options);
|
||||
|
||||
/**
|
||||
* Add common terms expression.
|
||||
*/
|
||||
ExpressionList<T> textCommonTerms(String search, TextCommonTerms options);
|
||||
|
||||
/**
|
||||
* And - join two expressions with a logical and.
|
||||
*/
|
||||
@@ -1671,7 +1599,7 @@ public interface ExpressionList<T> {
|
||||
* .eq("status", Customer.Status.ACTIVE)
|
||||
* .gt("id", 0)
|
||||
* .endAnd()
|
||||
* .orderBy().asc("name")
|
||||
* .order().asc("name")
|
||||
* .findList();
|
||||
* }</pre>
|
||||
*/
|
||||
@@ -1692,7 +1620,7 @@ public interface ExpressionList<T> {
|
||||
* .or()
|
||||
* .eq("status", Customer.Status.ACTIVE)
|
||||
* .isNull("anniversary")
|
||||
* .orderBy().asc("name")
|
||||
* .order().asc("name")
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
@@ -1712,7 +1640,7 @@ public interface ExpressionList<T> {
|
||||
* .eq("status", Customer.Status.ACTIVE)
|
||||
* .gt("id", 0)
|
||||
* .endAnd()
|
||||
* .orderBy().asc("name")
|
||||
* .order().asc("name")
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
@@ -1746,7 +1674,7 @@ public interface ExpressionList<T> {
|
||||
* .gt("id", 1)
|
||||
* .eq("anniversary", onAfter)
|
||||
* .endNot()
|
||||
* .orderBy()
|
||||
* .order()
|
||||
* .asc("name")
|
||||
* .findList();
|
||||
*
|
||||
@@ -1770,42 +1698,6 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
Junction<T> disjunction();
|
||||
|
||||
/**
|
||||
* Start a list of expressions that will be joined by MUST.
|
||||
* <p>
|
||||
* This automatically makes the query a useDocStore(true) query that
|
||||
* will execute against the document store (ElasticSearch etc).
|
||||
* </p>
|
||||
* <p>
|
||||
* This is logically similar to and().
|
||||
* </p>
|
||||
*/
|
||||
Junction<T> must();
|
||||
|
||||
/**
|
||||
* Start a list of expressions that will be joined by SHOULD.
|
||||
* <p>
|
||||
* This automatically makes the query a useDocStore(true) query that
|
||||
* will execute against the document store (ElasticSearch etc).
|
||||
* </p>
|
||||
* <p>
|
||||
* This is logically similar to or().
|
||||
* </p>
|
||||
*/
|
||||
Junction<T> should();
|
||||
|
||||
/**
|
||||
* Start a list of expressions that will be joined by MUST NOT.
|
||||
* <p>
|
||||
* This automatically makes the query a useDocStore(true) query that
|
||||
* will execute against the document store (ElasticSearch etc).
|
||||
* </p>
|
||||
* <p>
|
||||
* This is logically similar to not().
|
||||
* </p>
|
||||
*/
|
||||
Junction<T> mustNot();
|
||||
|
||||
/**
|
||||
* End a junction returning the parent expression list.
|
||||
* <p>
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package io.ebean;
|
||||
|
||||
import java.time.Clock;
|
||||
|
||||
/**
|
||||
* The extended API for Database.
|
||||
*/
|
||||
public interface ExtendedServer {
|
||||
|
||||
/**
|
||||
* Deprecated but no yet determined suitable replacement (to support testing only change of clock).
|
||||
* <p>
|
||||
* 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);
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.ebean;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import io.avaje.lang.NonNullApi;
|
||||
import io.ebean.service.SpiFetchGroupQuery;
|
||||
|
||||
/**
|
||||
@@ -61,7 +61,7 @@ import io.ebean.service.SpiFetchGroupQuery;
|
||||
*
|
||||
* @param <T> The bean type the Fetch group can be applied to
|
||||
*/
|
||||
@NullMarked
|
||||
@NonNullApi
|
||||
public interface FetchGroup<T> {
|
||||
|
||||
/**
|
||||
@@ -84,7 +84,7 @@ public interface FetchGroup<T> {
|
||||
* @return The FetchGroup with the given select clause
|
||||
*/
|
||||
static <T> FetchGroup<T> of(Class<T> cls, String select) {
|
||||
return XBootstrapService.fetchGroupOf(cls, select);
|
||||
return XServiceProvider.fetchGroupOf(cls, select);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,14 +108,14 @@ public interface FetchGroup<T> {
|
||||
* @return The FetchGroupBuilder with the given select clause which we will add fetch clauses to
|
||||
*/
|
||||
static <T> FetchGroupBuilder<T> of(Class<T> cls) {
|
||||
return XBootstrapService.fetchGroupOf(cls);
|
||||
return XServiceProvider.fetchGroupOf(cls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a query to be used by query beans for constructing FetchGroup.
|
||||
*/
|
||||
static <T> SpiFetchGroupQuery<T> queryFor(Class<T> beanType) {
|
||||
return XBootstrapService.fetchGroupQueryFor(beanType);
|
||||
return XServiceProvider.fetchGroupQueryFor(beanType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.ebean;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import io.avaje.lang.NonNullApi;
|
||||
|
||||
/**
|
||||
* Builds a FetchGroup by adding fetch clauses.
|
||||
@@ -23,7 +23,7 @@ import org.jspecify.annotations.NullMarked;
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@NullMarked
|
||||
@NonNullApi
|
||||
public interface FetchGroupBuilder<T> {
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.ebean;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import io.avaje.lang.NonNullApi;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -79,7 +79,7 @@ import java.util.Set;
|
||||
*
|
||||
* @param <T> the entity bean type
|
||||
*/
|
||||
@NullMarked
|
||||
@NonNullApi
|
||||
public interface Filter<T> {
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package io.ebean;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import io.avaje.lang.NonNullApi;
|
||||
import io.avaje.lang.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -35,7 +35,7 @@ import java.util.List;
|
||||
* public List<Customer> findNew() {
|
||||
* return query().where()
|
||||
* .eq("status", Customer.Status.NEW)
|
||||
* .orderBy("name")
|
||||
* .order("name")
|
||||
* .findList()
|
||||
* }
|
||||
* }
|
||||
@@ -60,7 +60,7 @@ import java.util.List;
|
||||
* @see BeanRepository
|
||||
* @see BeanFinder
|
||||
*/
|
||||
@NullMarked
|
||||
@NonNullApi
|
||||
public class Finder<I, T> {
|
||||
|
||||
/**
|
||||
@@ -213,11 +213,4 @@ public class Finder<I, T> {
|
||||
return db().findNative(type, nativeSql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a query using the ORM query language.
|
||||
*/
|
||||
public Query<T> query(String ormQuery) {
|
||||
return db().createQuery(type, ormQuery);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
package io.ebean;
|
||||
|
||||
import jakarta.persistence.PersistenceException;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
/**
|
||||
* FutureMap represents the result of a background query execution that will
|
||||
* return a map of entities.
|
||||
* <p>
|
||||
* It extends the java.util.concurrent.Future with the ability to cancel the
|
||||
* query, check if it is finished and get the resulting list waiting for the
|
||||
* query to finish (ie. the standard features of java.util.concurrent.Future).
|
||||
* </p>
|
||||
* <p>
|
||||
* A simple example:
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // create a query to find all orders
|
||||
* Query<Long,Order> query = DB.find(Order.class)
|
||||
* .setMapKey("id");
|
||||
*
|
||||
* // execute the query in a background thread
|
||||
* // immediately returning the futureMap
|
||||
* FutureMap<Long,Order> futureMap = query.findFutureMap();
|
||||
*
|
||||
* // do something else ...
|
||||
*
|
||||
* if (!futureMap.isDone()){
|
||||
* // we can cancel the query execution. This will cancel
|
||||
* // the underlying query if that is supported by the JDBC
|
||||
* // driver and database
|
||||
* futureMap.cancel(true);
|
||||
* }
|
||||
*
|
||||
* if (!futureMap.isCancelled()){
|
||||
* // wait for the query to finish and return the map
|
||||
* Map<Long,Order> map = futureMap.get();
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
public interface FutureMap<K, T> extends Future<Map<K, T>> {
|
||||
|
||||
/**
|
||||
* Return the query that is being executed by a background thread.
|
||||
*/
|
||||
Query<T> getQuery();
|
||||
|
||||
/**
|
||||
* Same as {@link #get()} but wraps InterruptedException and ExecutionException in the
|
||||
* unchecked PersistenceException.
|
||||
*
|
||||
* @return The query list result
|
||||
* @throws PersistenceException when a InterruptedException or ExecutionException occurs.
|
||||
*/
|
||||
Map<K, T> getUnchecked();
|
||||
|
||||
/**
|
||||
* Same as {@link #get(long, TimeUnit)} but wraps InterruptedException
|
||||
* and ExecutionException in the unchecked PersistenceException.
|
||||
*
|
||||
* @return The query list result
|
||||
* @throws TimeoutException if the wait timed out
|
||||
* @throws PersistenceException if a InterruptedException or ExecutionException occurs.
|
||||
*/
|
||||
Map<K, T> getUnchecked(long timeout, TimeUnit unit) throws TimeoutException;
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package io.ebean;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import io.avaje.lang.Nullable;
|
||||
|
||||
/**
|
||||
* Options to be used with insert such as ON CONFLICT DO UPDATE | NOTHING.
|
||||
|
||||
@@ -61,7 +61,7 @@ package io.ebean;
|
||||
* .eq("status", Customer.Status.ACTIVE)
|
||||
* .gt("id", 0)
|
||||
* .endAnd()
|
||||
* .orderBy().asc("name");
|
||||
* .order().asc("name");
|
||||
*
|
||||
* q.findList();
|
||||
* String s = q.getGeneratedSql();
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
package io.ebean;
|
||||
|
||||
/**
|
||||
* Thrown when trying to access a property that isn't loaded on an entity
|
||||
* that is unmodifiable or has disabled lazy loading.
|
||||
* <p>
|
||||
* On a normal mutable entity accessing the property would invoke lazy loading. On
|
||||
* a unmodifiable entity with lazy loading disabled, accessing an unloaded property
|
||||
* throws this LazyInitialisationException instead.
|
||||
*/
|
||||
public class LazyInitialisationException extends BeanAccessException {
|
||||
|
||||
/**
|
||||
* Create specifying the property that was being accessed.
|
||||
*/
|
||||
public LazyInitialisationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,4 @@ public interface ModifyAwareType {
|
||||
*/
|
||||
void setMarkedDirty(boolean markedDirty);
|
||||
|
||||
default Object freeze() {
|
||||
return this; // throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,11 +8,13 @@ import java.util.Objects;
|
||||
/**
|
||||
* Represents an Order By for a Query.
|
||||
* <p>
|
||||
* Is an ordered list of OrderBy.Property objects each specifying a property and
|
||||
* Is a ordered list of OrderBy.Property objects each specifying a property and
|
||||
* whether it is ascending or descending order.
|
||||
* </p>
|
||||
* <p>
|
||||
* Typically, you will not construct an OrderBy yourself but use one that exists
|
||||
* Typically you will not construct an OrderBy yourself but use one that exists
|
||||
* on the Query object.
|
||||
* </p>
|
||||
*/
|
||||
public class OrderBy<T> implements Serializable {
|
||||
|
||||
@@ -23,22 +25,8 @@ public class OrderBy<T> implements Serializable {
|
||||
private final List<Property> list;
|
||||
|
||||
/**
|
||||
* Create an OrderBy parsing the given order by clause.
|
||||
* <p>
|
||||
* The order by clause follows SQL order by clause with comma's between each
|
||||
* property and optionally "asc" or "desc" to represent ascending or
|
||||
* descending order respectively.
|
||||
*/
|
||||
public static <P> OrderBy<P> of(String orderByClause) {
|
||||
return new OrderBy<>(orderByClause);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method will be removed from public API.
|
||||
* <p>
|
||||
* Create an empty OrderBy with no associated query.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public OrderBy() {
|
||||
this.list = new ArrayList<>(3);
|
||||
}
|
||||
@@ -48,17 +36,20 @@ public class OrderBy<T> implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated migrate to {@link OrderBy#of(String)}.
|
||||
* Create an orderBy parsing the order by clause.
|
||||
* <p>
|
||||
* The order by clause follows SQL order by clause with comma's between each
|
||||
* property and optionally "asc" or "desc" to represent ascending or
|
||||
* descending order respectively.
|
||||
* </p>
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public OrderBy(String orderByClause) {
|
||||
this(null, orderByClause);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method will be removed from public API.
|
||||
* Construct with a given query and order by clause.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public OrderBy(Query<T> query, String orderByClause) {
|
||||
this.query = query;
|
||||
this.list = new ArrayList<>(3);
|
||||
@@ -119,11 +110,8 @@ public class OrderBy<T> implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method will become internal only API.
|
||||
* <p>
|
||||
* Return a copy of this OrderBy with the path trimmed.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public OrderBy<T> copyWithTrim(String path) {
|
||||
List<Property> newList = new ArrayList<>(list.size());
|
||||
for (Property aList : list) {
|
||||
@@ -198,15 +186,15 @@ public class OrderBy<T> implements Serializable {
|
||||
if (list.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
var append = new StringAppend();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
Property property = list.get(i);
|
||||
if (i > 0) {
|
||||
append.append(", ");
|
||||
sb.append(", ");
|
||||
}
|
||||
property.toStringFormat(append);
|
||||
sb.append(property.toStringFormat());
|
||||
}
|
||||
return append.toString();
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -243,55 +231,6 @@ public class OrderBy<T> implements Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the order by clause.
|
||||
*/
|
||||
public interface Append {
|
||||
|
||||
/**
|
||||
* Append a property expression.
|
||||
*/
|
||||
Append property(String property);
|
||||
|
||||
/**
|
||||
* Append a literal.
|
||||
*/
|
||||
Append append(String literal);
|
||||
|
||||
/**
|
||||
* Parse and append an expression.
|
||||
*/
|
||||
Append parse(String expression);
|
||||
}
|
||||
|
||||
private static final class StringAppend implements Append {
|
||||
|
||||
private final StringBuilder builder = new StringBuilder();
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Append property(String property) {
|
||||
builder.append(property);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Append append(String literal) {
|
||||
builder.append(literal);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Append parse(String raw) {
|
||||
builder.append(raw);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A property and its ascending descending order.
|
||||
*/
|
||||
@@ -370,25 +309,36 @@ public class OrderBy<T> implements Serializable {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return property;
|
||||
return toStringFormat();
|
||||
}
|
||||
|
||||
public void toStringFormat(Append append) {
|
||||
if (collation != null) {
|
||||
if (collation.contains("${}")) {
|
||||
// this is a complex collation, e.g. DB2 - we must replace the property
|
||||
append.parse(collation.replace("${}", property));
|
||||
public String toStringFormat() {
|
||||
if (nulls == null && collation == null) {
|
||||
if (ascending) {
|
||||
return property;
|
||||
} else {
|
||||
append.property(property).append(" collate ").append(collation);
|
||||
return property + " desc";
|
||||
}
|
||||
} else {
|
||||
append.property(property);
|
||||
}
|
||||
if (!ascending) {
|
||||
append.append(" desc");
|
||||
}
|
||||
if (nulls != null) {
|
||||
append.append(" ").append(nulls).append(" ").append(highLow);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (collation != null) {
|
||||
if (collation.contains("${}")) {
|
||||
// this is a complex collation, e.g. DB2 - we must replace the property
|
||||
sb.append(collation.replace("${}", property));
|
||||
} else {
|
||||
sb.append(property);
|
||||
sb.append(" collate ").append(collation);
|
||||
}
|
||||
} else {
|
||||
sb.append(property);
|
||||
}
|
||||
if (!ascending) {
|
||||
sb.append(' ').append("desc");
|
||||
}
|
||||
if (nulls != null) {
|
||||
sb.append(' ').append(nulls).append(' ').append(highLow);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import java.util.concurrent.Future;
|
||||
*
|
||||
* PagedList<Order> pagedList = DB.find(Order.class)
|
||||
* .where().eq("status", Order.Status.NEW)
|
||||
* .orderBy().asc("id")
|
||||
* .order().asc("id")
|
||||
* .setFirstRow(0)
|
||||
* .setMaxRows(50)
|
||||
* .findPagedList();
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
package io.ebean;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Used to specify Paging on a Query as an alternative to setting each of the
|
||||
* maxRows, firstRow and orderBy clause via:
|
||||
* {@link Query#setMaxRows(int)} + {@link Query#setFirstRow(int)} + {@link Query#setOrderBy(OrderBy)}.
|
||||
* <p>
|
||||
* Example use:
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* var orderBy = OrderBy.of("lastName desc nulls first, firstName asc");
|
||||
* var paging = Paging.of(0, 100, orderBy);
|
||||
*
|
||||
* new QCustomer()
|
||||
* .name.isNotNull()
|
||||
* .setPaging(paging)
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
public interface Paging {
|
||||
|
||||
/**
|
||||
* Create a Paging with the given page index size and orderBy.
|
||||
*
|
||||
* @param pageIndex the page index starting from zero
|
||||
* @param pageSize the page size (effectively max rows)
|
||||
* @param orderBy order by for the query result
|
||||
*/
|
||||
static Paging of(int pageIndex, int pageSize, @Nullable OrderBy<?> orderBy) {
|
||||
return DPaging.build(pageIndex, pageSize, orderBy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Paging with a raw order by clause.
|
||||
*
|
||||
* @param pageIndex the page index starting from zero
|
||||
* @param pageSize the page size (effectively max rows)
|
||||
* @param orderByClause raw order by clause for ordering the query result
|
||||
*/
|
||||
static Paging of(int pageIndex, int pageSize, @Nullable String orderByClause) {
|
||||
return of(pageIndex, pageSize, OrderBy.of(orderByClause));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Paging that will use the id property for ordering.
|
||||
*
|
||||
* @param pageIndex the page index starting from zero
|
||||
* @param pageSize the page size (effectively max rows)
|
||||
*/
|
||||
static Paging of(int pageIndex, int pageSize) {
|
||||
return DPaging.build(pageIndex, pageSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a Paging that will not apply any pagination to a query.
|
||||
*/
|
||||
static Paging ofNone() {
|
||||
return DPaging.NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the page index.
|
||||
*/
|
||||
int pageIndex();
|
||||
|
||||
/**
|
||||
* Return the page size.
|
||||
*/
|
||||
int pageSize();
|
||||
|
||||
/**
|
||||
* Return the order by.
|
||||
*/
|
||||
OrderBy<?> orderBy();
|
||||
|
||||
/**
|
||||
* Return a Paging using the given page index.
|
||||
*/
|
||||
Paging withPage(int pageIndex);
|
||||
|
||||
/**
|
||||
* Return a Paging using the given order by clause.
|
||||
*/
|
||||
Paging withOrderBy(String orderByClause);
|
||||
|
||||
}
|
||||
@@ -30,7 +30,7 @@ import java.util.Objects;
|
||||
* .where()
|
||||
* .eq("store", "def")
|
||||
* .inPairs(pairs) // IN clause with 'pairs' of values
|
||||
* .orderBy("sku desc")
|
||||
* .order("sku desc")
|
||||
*
|
||||
* // query expressions cover the natural key properties
|
||||
* // so we can choose to hit the L2 bean cache if we want
|
||||
|
||||
@@ -13,21 +13,21 @@ public interface ProfileLocation {
|
||||
* Create and return a new ProfileLocation.
|
||||
*/
|
||||
static ProfileLocation create() {
|
||||
return XBootstrapService.profileLocationFactory().create();
|
||||
return XServiceProvider.profileLocationFactory().create();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a new ProfileLocation with line number.
|
||||
*/
|
||||
static ProfileLocation createWithLine() {
|
||||
return XBootstrapService.profileLocationFactory().createWithLine();
|
||||
return XServiceProvider.profileLocationFactory().createWithLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a new ProfileLocation with a given lineNumber and label.
|
||||
*/
|
||||
static ProfileLocation create(String label) {
|
||||
return XBootstrapService.profileLocationFactory().create(label);
|
||||
return XServiceProvider.profileLocationFactory().create(label);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,998 +0,0 @@
|
||||
package io.ebean;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Build and execute an ORM query.
|
||||
*
|
||||
* @param <SELF> The type of the builder
|
||||
* @param <T> The entity bean type
|
||||
*/
|
||||
public interface QueryBuilder<SELF extends QueryBuilder<SELF, T>, T> extends QueryBuilderProjection<SELF, T> {
|
||||
|
||||
/**
|
||||
* Set root table alias.
|
||||
*/
|
||||
SELF alias(String alias);
|
||||
|
||||
/**
|
||||
* Apply changes to the query using a function.
|
||||
*
|
||||
* @param apply Function that applies changes to the query.
|
||||
*/
|
||||
SELF also(Consumer<SELF> apply);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
SELF alsoIf(BooleanSupplier predicate, Consumer<SELF> apply);
|
||||
|
||||
/**
|
||||
* Perform an 'As of' query using history tables to return the object graph
|
||||
* as of a time in the past.
|
||||
* <p>
|
||||
* To perform this query the DB must have underlying history tables.
|
||||
*
|
||||
* @param asOf the date time in the past at which you want to view the data
|
||||
*/
|
||||
SELF asOf(Timestamp asOf);
|
||||
|
||||
/**
|
||||
* Execute the query against the draft set of tables.
|
||||
*/
|
||||
SELF asDraft();
|
||||
|
||||
/**
|
||||
* Convert the query to a DTO bean query.
|
||||
* <p>
|
||||
* We effectively use the underlying ORM query to build the SQL and then execute
|
||||
* and map it into DTO beans.
|
||||
*/
|
||||
<D> DtoQuery<D> asDto(Class<D> dtoClass);
|
||||
|
||||
/**
|
||||
* Convert the query to a UpdateQuery.
|
||||
* <p>
|
||||
* Typically this is used with query beans to covert a query bean
|
||||
* query into an UpdateQuery like the examples below.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* int rowsUpdated = new QCustomer()
|
||||
* .name.startsWith("Rob")
|
||||
* .asUpdate()
|
||||
* .set("active", false)
|
||||
* .update();;
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* int rowsUpdated = new QContact()
|
||||
* .notes.note.startsWith("Make Inactive")
|
||||
* .email.endsWith("@foo.com")
|
||||
* .customer.id.equalTo(42)
|
||||
* .asUpdate()
|
||||
* .set("inactive", true)
|
||||
* .setRaw("email = lower(email)")
|
||||
* .update();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
UpdateQuery<T> asUpdate();
|
||||
|
||||
/**
|
||||
* Return a copy of the query.
|
||||
* <p>
|
||||
* This is so that you can use a Query as a "prototype" for creating other
|
||||
* query instances. You could create a Query with various where expressions
|
||||
* and use that as a "prototype" - using this copy() method to create a new
|
||||
* instance that you can then add other expressions then execute.
|
||||
* </p>
|
||||
*/
|
||||
SELF copy();
|
||||
|
||||
/**
|
||||
* Execute the query using the given transaction.
|
||||
*/
|
||||
SELF usingTransaction(Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the query using the given connection.
|
||||
*/
|
||||
SELF usingConnection(Connection connection);
|
||||
|
||||
/**
|
||||
* Execute the query using the given database.
|
||||
*/
|
||||
SELF usingDatabase(Database database);
|
||||
|
||||
/**
|
||||
* Ensure that the master DataSource is used if there is a read only data source
|
||||
* being used (that is using a read replica database potentially with replication lag).
|
||||
* <p>
|
||||
* When the database is configured with a read-only DataSource via
|
||||
* say {@link io.ebean.config.DatabaseConfig#setReadOnlyDataSource(DataSource)} then
|
||||
* by default when a query is run without an active transaction, it uses the read-only data
|
||||
* source. We we use {@code usingMaster()} to instead ensure that the query is executed
|
||||
* against the master data source.
|
||||
*/
|
||||
SELF usingMaster();
|
||||
|
||||
/**
|
||||
* Set the base table to use for this query.
|
||||
* <p>
|
||||
* Typically this is used when a table has partitioning and we wish to specify a specific
|
||||
* partition/table to query against.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* QOrder()
|
||||
* .setBaseTable("order_2019_05")
|
||||
* .status.equalTo(Status.NEW)
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
SELF setBaseTable(String baseTable);
|
||||
|
||||
/**
|
||||
* Specify the PersistenceContextScope to use for this query.
|
||||
* <p>
|
||||
* When this is not set the 'default' configured on {@link io.ebean.config.DatabaseConfig#setPersistenceContextScope(PersistenceContextScope)}
|
||||
* is used - this value defaults to {@link PersistenceContextScope#TRANSACTION}.
|
||||
* <p>
|
||||
* Note that the same persistence Context is used for subsequent lazy loading and query join queries.
|
||||
* <p>
|
||||
* Note that #findEach uses a 'per object graph' PersistenceContext so this scope is ignored for
|
||||
* queries executed as #findIterate, #findEach, #findEachWhile.
|
||||
*
|
||||
* @param scope The scope to use for this query and subsequent lazy loading.
|
||||
*/
|
||||
SELF setPersistenceContextScope(PersistenceContextScope scope);
|
||||
|
||||
/**
|
||||
* Explicitly specify whether to use AutoTune for this query.
|
||||
* <p>
|
||||
* If you do not call this method on a query the "Implicit AutoTune mode" is
|
||||
* used to determine if AutoTune should be used for a given query.
|
||||
* <p>
|
||||
* AutoTune can add additional fetch paths to the query and specify which
|
||||
* properties are included for each path. If you have explicitly defined some
|
||||
* fetch paths AutoTune will not remove them.
|
||||
*/
|
||||
SELF setAutoTune(boolean autoTune);
|
||||
|
||||
/**
|
||||
* Execute the query allowing properties with invalid JSON to be collected and not fail the query.
|
||||
* <pre>{@code
|
||||
*
|
||||
* // fetch a bean with JSON content
|
||||
* EBasicJsonList bean= DB.find(EBasicJsonList.class)
|
||||
* .setId(42)
|
||||
* .setAllowLoadErrors() // collect errors into bean state if we have invalid JSON
|
||||
* .findOne();
|
||||
*
|
||||
*
|
||||
* // get the invalid JSON errors from the bean state
|
||||
* Map<String, Exception> errors = server().getBeanState(bean).getLoadErrors();
|
||||
*
|
||||
* // If this map is not empty tell we have invalid JSON
|
||||
* // and should try and fix the JSON content or inform the user
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
SELF setAllowLoadErrors();
|
||||
|
||||
/**
|
||||
* Set the default lazy loading batch size to use.
|
||||
* <p>
|
||||
* When lazy loading is invoked on beans loaded by this query then this sets the
|
||||
* batch size used to load those beans.
|
||||
*
|
||||
* @param lazyLoadBatchSize the number of beans to lazy load in a single batch
|
||||
*/
|
||||
SELF setLazyLoadBatchSize(int lazyLoadBatchSize);
|
||||
|
||||
/**
|
||||
* Set a label on the query.
|
||||
* <p>
|
||||
* This label can be used to help identify query performance metrics but we can also use
|
||||
* profile location enhancement on Finders so for some that would be a better option.
|
||||
*/
|
||||
SELF 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 *\/ }
|
||||
*/
|
||||
SELF setHint(String hint);
|
||||
|
||||
/**
|
||||
* Set the index(es) to search for a document store which uses partitions.
|
||||
* <p>
|
||||
* For example, when executing a query against ElasticSearch with daily indexes we can
|
||||
* explicitly specify the indexes to search against.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // explicitly specify the indexes to search
|
||||
* query.setDocIndexName("logstash-2016.11.5,logstash-2016.11.6")
|
||||
*
|
||||
* // search today's index
|
||||
* query.setDocIndexName("$today")
|
||||
*
|
||||
* // search the last 3 days
|
||||
* query.setDocIndexName("$last-3")
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* If the indexName is specified with ${daily} e.g. "logstash-${daily}" ... then we can use
|
||||
* $today and $last-x as the search docIndexName like the examples below.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // search today's index
|
||||
* query.setDocIndexName("$today")
|
||||
*
|
||||
* // search the last 3 days
|
||||
* query.setDocIndexName("$last-3")
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param indexName The index or indexes to search against
|
||||
* @return This query
|
||||
*/
|
||||
SELF setDocIndexName(String indexName);
|
||||
|
||||
/**
|
||||
* Execute the query including soft deleted rows.
|
||||
* <p>
|
||||
* This means that Ebean will not add any predicates to the query for filtering out
|
||||
* soft deleted rows. You can still add your own predicates for the deleted properties
|
||||
* and effectively you have full control over the query to include or exclude soft deleted
|
||||
* rows as needed for a given use case.
|
||||
*/
|
||||
SELF setIncludeSoftDeletes();
|
||||
|
||||
/**
|
||||
* Disable read auditing for this query.
|
||||
* <p>
|
||||
* This is intended to be used when the query is not a user initiated query and instead
|
||||
* part of the internal processing in an application to load a cache or document store etc.
|
||||
* In these cases we don't want the query to be part of read auditing.
|
||||
*/
|
||||
SELF setDisableReadAuditing();
|
||||
|
||||
/**
|
||||
* Set true if you want to disable lazy loading.
|
||||
* <p>
|
||||
* That is, once the object graph is returned further lazy loading is disabled.
|
||||
*/
|
||||
SELF setDisableLazyLoading(boolean disableLazyLoading);
|
||||
|
||||
/**
|
||||
* Set whether this query uses DISTINCT.
|
||||
*/
|
||||
SELF setDistinct(boolean distinct);
|
||||
|
||||
/**
|
||||
* Restrict the query to only return subtypes of the given inherit type.
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<Animal> animals =
|
||||
* new QAnimal()
|
||||
* .name.startsWith("Fluffy")
|
||||
* .setInheritType(Cat.class)
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
SELF setInheritType(Class<? extends T> type);
|
||||
|
||||
/**
|
||||
* Set the first row to return for this query.
|
||||
*
|
||||
* @param firstRow the first row to include in the query result.
|
||||
*/
|
||||
SELF setFirstRow(int firstRow);
|
||||
|
||||
/**
|
||||
* Set the maximum number of rows to return in the query.
|
||||
*
|
||||
* @param maxRows the maximum number of rows to return in the query.
|
||||
*/
|
||||
SELF setMaxRows(int maxRows);
|
||||
|
||||
SELF setPaging(Paging paging);
|
||||
|
||||
/**
|
||||
* Set RawSql to use for this query.
|
||||
*/
|
||||
SELF setRawSql(RawSql rawSql);
|
||||
|
||||
/**
|
||||
* Extended version for setDistinct in conjunction with "findSingleAttributeList";
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<CountedValue<Order.Status>> orderStatusCount =
|
||||
*
|
||||
* DB.find(Order.class)
|
||||
* .select("status")
|
||||
* .where()
|
||||
* .gt("orderDate", LocalDate.now().minusMonths(3))
|
||||
*
|
||||
* // fetch as single attribute with a COUNT
|
||||
* .setCountDistinct(CountDistinctOrder.COUNT_DESC_ATTR_ASC)
|
||||
* .findSingleAttributeList();
|
||||
*
|
||||
* for (CountedValue<Order.Status> entry : orderStatusCount) {
|
||||
* System.out.println(" count:" + entry.getCount()+" orderStatus:" + entry.getValue() );
|
||||
* }
|
||||
*
|
||||
* // produces
|
||||
*
|
||||
* count:3 orderStatus:NEW
|
||||
* count:1 orderStatus:SHIPPED
|
||||
* count:1 orderStatus:COMPLETE
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
SELF setCountDistinct(CountDistinctOrder orderBy);
|
||||
|
||||
/**
|
||||
* Set the property to use as keys for a map.
|
||||
* <p>
|
||||
* If no property is set then the id property is used.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // Assuming sku is unique for products...
|
||||
*
|
||||
* Map<String,Product> productMap = DB.find(Product.class)
|
||||
* .setMapKey("sku") // sku map keys...
|
||||
* .findMap();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param mapKey the property to use as keys for a map.
|
||||
*/
|
||||
SELF setMapKey(String mapKey);
|
||||
|
||||
/**
|
||||
* Set to true if this query should execute against the doc store.
|
||||
* <p>
|
||||
* When setting this you may also consider disabling lazy loading.
|
||||
*/
|
||||
SELF setUseDocStore(boolean useDocStore);
|
||||
|
||||
/**
|
||||
* When set to true when you want the returned beans to be unmodifiable read only.
|
||||
* <p>
|
||||
* This means that the returning graph can't be mutated via setters, all the collections
|
||||
* are unmodifiable collections, lazy loading is disabled and that the query uses
|
||||
* {@link PersistenceContextScope#QUERY}.
|
||||
*/
|
||||
SELF setUnmodifiable(boolean unmodifiable);
|
||||
|
||||
/**
|
||||
* Set a timeout on this query.
|
||||
* <p>
|
||||
* This will typically result in a call to setQueryTimeout() on a
|
||||
* preparedStatement. If the timeout occurs an exception will be thrown - this
|
||||
* will be a SQLException wrapped up in a PersistenceException.
|
||||
* </p>
|
||||
*
|
||||
* @param secs the query timeout limit in seconds. Zero means there is no limit.
|
||||
*/
|
||||
SELF setTimeout(int secs);
|
||||
|
||||
/**
|
||||
* A hint which for JDBC translates to the Statement.fetchSize().
|
||||
* <p>
|
||||
* Gives the JDBC driver a hint as to the number of rows that should be
|
||||
* fetched from the database when more rows are needed for ResultSet.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that internally findEach and findEachWhile will set the fetch size
|
||||
* if it has not already as these queries expect to process a lot of rows.
|
||||
* If we didn't then Postgres and MySql for example would eagerly pull back
|
||||
* all the row data and potentially consume a lot of memory in the process.
|
||||
* </p>
|
||||
* <p>
|
||||
* As findEach and findEachWhile automatically set the fetch size we don't have
|
||||
* to do so generally but we might still wish to for tuning a specific use case.
|
||||
* </p>
|
||||
*/
|
||||
SELF setBufferFetchSizeHint(int fetchSize);
|
||||
|
||||
/**
|
||||
* Set the mode to use the bean cache when executing this query.
|
||||
* <p>
|
||||
* By default, "find by id" and "find by natural key" will use the bean cache
|
||||
* when bean caching is enabled. Setting this to false means that the query
|
||||
* will not use the bean cache and instead hit the database.
|
||||
* <p>
|
||||
* By default, findList() with natural keys will not use the bean cache. In that
|
||||
* case we need to explicitly use the bean cache.
|
||||
*/
|
||||
SELF setBeanCacheMode(CacheMode beanCacheMode);
|
||||
|
||||
/**
|
||||
* Set the {@link CacheMode} to use the query for executing this query.
|
||||
*/
|
||||
SELF setUseQueryCache(CacheMode cacheMode);
|
||||
|
||||
/**
|
||||
* Set this to false to not use the bean cache.
|
||||
* <p>
|
||||
* This method is now superseded by {@link #setBeanCacheMode(CacheMode)}
|
||||
* which provides more explicit options controlled bean cache use.
|
||||
* <p>
|
||||
* This method is likely to be deprecated in the future with migration
|
||||
* over to setUseBeanCache().
|
||||
*/
|
||||
default SELF setUseCache(boolean useCache) {
|
||||
return setBeanCacheMode(useCache ? CacheMode.ON : CacheMode.OFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls {@link #setUseQueryCache(CacheMode)} with <code>ON</code> or <code>OFF</code>.
|
||||
*/
|
||||
default SELF setUseQueryCache(boolean enabled) {
|
||||
return setUseQueryCache(enabled ? CacheMode.ON : CacheMode.OFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
SELF orderBy(String orderByClause);
|
||||
|
||||
/**
|
||||
* Set an OrderBy object to replace any existing OrderBy clause.
|
||||
*/
|
||||
SELF setOrderBy(OrderBy<T> orderBy);
|
||||
|
||||
/**
|
||||
* Controls, if paginated queries should always append an 'order by id' statement at the end to
|
||||
* guarantee a deterministic sort result. This may affect performance.
|
||||
* If this is not enabled, and an orderBy is set on the query, it's up to the programmer that
|
||||
* this query provides a deterministic result.
|
||||
*/
|
||||
SELF orderById(boolean orderById);
|
||||
|
||||
/**
|
||||
* Execute the query with the given lock type and WAIT.
|
||||
* <p>
|
||||
* Note that <code>forUpdate()</code> is the same as
|
||||
* <code>withLock(LockType.UPDATE)</code>.
|
||||
* <p>
|
||||
* Provides us with the ability to explicitly use Postgres
|
||||
* SHARE, KEY SHARE, NO KEY UPDATE and UPDATE row locks.
|
||||
*/
|
||||
SELF withLock(Query.LockType lockType);
|
||||
|
||||
/**
|
||||
* Execute the query with the given lock type and lock wait.
|
||||
* <p>
|
||||
* Note that <code>forUpdateNoWait()</code> is the same as
|
||||
* <code>withLock(LockType.UPDATE, LockWait.NOWAIT)</code>.
|
||||
* <p>
|
||||
* Provides us with the ability to explicitly use Postgres
|
||||
* SHARE, KEY SHARE, NO KEY UPDATE and UPDATE row locks.
|
||||
*/
|
||||
SELF withLock(Query.LockType lockType, Query.LockWait lockWait);
|
||||
|
||||
/**
|
||||
* Execute using "for update" clause which results in the DB locking the record.
|
||||
* <p>
|
||||
* The same as <code>withLock(LockType.UPDATE, LockWait.WAIT)</code>.
|
||||
*/
|
||||
SELF forUpdate();
|
||||
|
||||
/**
|
||||
* Execute using "for update" clause with "no wait" option.
|
||||
* <p>
|
||||
* This is typically a Postgres and Oracle only option at this stage.
|
||||
* <p>
|
||||
* The same as <code>withLock(LockType.UPDATE, LockWait.NOWAIT)</code>.
|
||||
*/
|
||||
SELF forUpdateNoWait();
|
||||
|
||||
/**
|
||||
* Execute using "for update" clause with "skip locked" option.
|
||||
* <p>
|
||||
* This is typically a Postgres and Oracle only option at this stage.
|
||||
* <p>
|
||||
* The same as <code>withLock(LockType.UPDATE, LockWait.SKIPLOCKED)</code>.
|
||||
*/
|
||||
SELF forUpdateSkipLocked();
|
||||
|
||||
/**
|
||||
* Returns the set of properties or paths that are unknown (do not map to known properties or paths).
|
||||
* <p>
|
||||
* Validate the query checking the where and orderBy expression paths to confirm if
|
||||
* they represent valid properties or paths for the given bean type.
|
||||
*/
|
||||
Set<String> validate();
|
||||
|
||||
/**
|
||||
* Return the sql that was generated for executing this query.
|
||||
* <p>
|
||||
* This is only available after the query has been executed and provided only
|
||||
* for informational purposes.
|
||||
*/
|
||||
String getGeneratedSql();
|
||||
|
||||
/**
|
||||
* Return the type of beans being queried.
|
||||
*/
|
||||
Class<T> getBeanType();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return the number of beans/rows that were deleted.
|
||||
*/
|
||||
int delete();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* <h2>Example using a query bean:</h2>
|
||||
* <pre>{@code
|
||||
*
|
||||
* boolean userExists =
|
||||
* new QContact()
|
||||
* .email.equalTo("rob@foo.com")
|
||||
* .exists();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h2>Example:</h2>
|
||||
* <pre>{@code
|
||||
*
|
||||
* boolean userExists = query()
|
||||
* .where().eq("email", "rob@foo.com")
|
||||
* .exists();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @return True if the query finds a matching row in the database
|
||||
*/
|
||||
boolean exists();
|
||||
|
||||
/**
|
||||
* Execute the query returning either a single bean or null (if no matching
|
||||
* bean is found).
|
||||
* <p>
|
||||
* If more than 1 row is found for this query then a PersistenceException is
|
||||
* thrown.
|
||||
* <p>
|
||||
* This is useful when your predicates dictate that your query should only
|
||||
* return 0 or 1 results.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // assuming the sku of products is unique...
|
||||
* Product product =
|
||||
* new QProduct()
|
||||
* .sku.equalTo("aa113")
|
||||
* .findOne();
|
||||
* ...
|
||||
* }</pre>
|
||||
* <p>
|
||||
* It is also useful with finding objects by their id when you want to specify
|
||||
* further join information to optimise the query.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // Fetch order 42 and additionally fetch join its order details...
|
||||
* Order order =
|
||||
* new QOrder()
|
||||
* .fetch("details") // eagerly load the order details
|
||||
* .id.equalTo(42)
|
||||
* .findOne();
|
||||
*
|
||||
* // the order details were eagerly loaded
|
||||
* List<OrderDetail> details = order.getDetails();
|
||||
* ...
|
||||
* }</pre>
|
||||
*/
|
||||
@Nullable
|
||||
T findOne();
|
||||
|
||||
/**
|
||||
* Execute the query returning an optional bean.
|
||||
*/
|
||||
Optional<T> findOneOrEmpty();
|
||||
|
||||
/**
|
||||
* Execute the query returning the list of objects.
|
||||
* <p>
|
||||
* This query will execute against the EbeanServer that was used to create it.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<Customer> customers =
|
||||
* new QCustomer()
|
||||
* .name.ilike("rob%")
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @see Query#findList()
|
||||
*/
|
||||
List<T> findList();
|
||||
|
||||
/**
|
||||
* 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>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // use try with resources to ensure Stream is closed
|
||||
*
|
||||
* try (Stream<Customer> stream = query.findStream()) {
|
||||
* stream
|
||||
* .map(...)
|
||||
* .collect(...);
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
Stream<T> findStream();
|
||||
|
||||
/**
|
||||
* Execute the query returning the set of objects.
|
||||
* <p>
|
||||
* This query will execute against the EbeanServer that was used to create it.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* Set<Customer> customers =
|
||||
* new QCustomer()
|
||||
* .name.ilike("rob%")
|
||||
* .findSet();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @see Query#findSet()
|
||||
*/
|
||||
Set<T> findSet();
|
||||
|
||||
/**
|
||||
* Execute the query returning the list of Id's.
|
||||
* <p>
|
||||
* This query will execute against the EbeanServer that was used to create it.
|
||||
*
|
||||
* @see Query#findIds()
|
||||
*/
|
||||
<A> List<A> findIds();
|
||||
|
||||
/**
|
||||
* Execute the query returning a map of the objects.
|
||||
* <p>
|
||||
* This query will execute against the EbeanServer that was used to create it.
|
||||
* <p>
|
||||
* You can use setMapKey() or asMapKey() to specify the property to be used as keys
|
||||
* on the map. If one is not specified then the id property is used.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* Map<String, Product> map =
|
||||
* new QProduct()
|
||||
* .sku.asMapKey()
|
||||
* .findMap();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @see Query#findMap()
|
||||
*/
|
||||
<K> Map<K, T> findMap();
|
||||
|
||||
/**
|
||||
* Execute the query iterating over the results.
|
||||
* <p>
|
||||
* Note that findIterate (and findEach and findEachWhile) uses a "per graph"
|
||||
* persistence context scope and adjusts jdbc fetch buffer size for large
|
||||
* queries. As such it is better to use findList for small queries.
|
||||
* <p>
|
||||
* Remember that with {@link QueryIterator} you must call {@link QueryIterator#close()}
|
||||
* when you have finished iterating the results (typically in a finally block).
|
||||
* <p>
|
||||
* findEach() and findEachWhile() are preferred to findIterate() as they ensure
|
||||
* the jdbc statement and resultSet are closed at the end of the iteration.
|
||||
* <p>
|
||||
* This query will execute against the EbeanServer that was used to create it.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* Query<Customer> query =
|
||||
* new QCustomer()
|
||||
* .status.equalTo(Customer.Status.NEW)
|
||||
* .orderBy()
|
||||
* id.asc()
|
||||
* .query();
|
||||
*
|
||||
* try (QueryIterator<Customer> it = query.findIterate()) {
|
||||
* while (it.hasNext()) {
|
||||
* Customer customer = it.next();
|
||||
* // do something with customer ...
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
QueryIterator<T> findIterate();
|
||||
|
||||
/**
|
||||
* Execute the query returning a list of values for a single property.
|
||||
* <p>
|
||||
* <h3>Example</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<String> names =
|
||||
* new QCustomer()
|
||||
* .setDistinct(true)
|
||||
* .select(name)
|
||||
* .findSingleAttributeList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @return the list of values for the selected property
|
||||
*/
|
||||
<A> List<A> findSingleAttributeList();
|
||||
|
||||
/**
|
||||
* Execute the query returning a single value or null for a single property.
|
||||
* <p>
|
||||
* <h3>Example</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* LocalDate maxDate =
|
||||
* new QCustomer()
|
||||
* .select("max(startDate)")
|
||||
* .findSingleAttribute();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @return a single value or null for the selected property
|
||||
*/
|
||||
@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();
|
||||
|
||||
/**
|
||||
* Execute the query returning a hashset of values for a single property.
|
||||
*/
|
||||
<A> Set<A> findSingleAttributeSet();
|
||||
|
||||
/**
|
||||
* Execute the query processing the beans one at a time.
|
||||
* <p>
|
||||
* This method is appropriate to process very large query results as the
|
||||
* beans are consumed one at a time and do not need to be held in memory
|
||||
* (unlike #findList #findSet etc)
|
||||
* <p>
|
||||
* Note that internally Ebean can inform the JDBC driver that it is expecting larger
|
||||
* resultSet and specifically for MySQL this hint is required to stop it's JDBC driver
|
||||
* from buffering the entire resultSet. As such, for smaller resultSets findList() is
|
||||
* generally preferable.
|
||||
* <p>
|
||||
* Compared with #findEachWhile this will always process all the beans where as
|
||||
* #findEachWhile provides a way to stop processing the query result early before
|
||||
* all the beans have been read.
|
||||
* <p>
|
||||
* This method is functionally equivalent to findIterate() but instead of using an
|
||||
* iterator uses the Consumer interface which is better suited to use with closures.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* new QCustomer()
|
||||
* .status.equalTo(Status.NEW)
|
||||
* .orderBy().id.asc()
|
||||
* .findEach((Customer customer) -> {
|
||||
*
|
||||
* // do something with customer
|
||||
* System.out.println("-- visit " + customer);
|
||||
* });
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param consumer the consumer used to process the queried beans.
|
||||
*/
|
||||
void findEach(Consumer<T> consumer);
|
||||
|
||||
/**
|
||||
* Execute findEach streaming query batching the results for consuming.
|
||||
* <p>
|
||||
* This query execution will stream the results and is suited to consuming
|
||||
* large numbers of results from the database.
|
||||
* <p>
|
||||
* Typically, we use this batch consumer when we want to do further processing on
|
||||
* the beans and want to do that processing in batch form, for example - 100 at
|
||||
* a time.
|
||||
*
|
||||
* @param batch The number of beans processed in the batch
|
||||
* @param consumer Process the batch of beans
|
||||
*/
|
||||
void findEach(int batch, Consumer<List<T>> consumer);
|
||||
|
||||
/**
|
||||
* Execute the query using callbacks to a visitor to process the resulting
|
||||
* beans one at a time.
|
||||
* <p>
|
||||
* This method is functionally equivalent to findIterate() but instead of using an
|
||||
* iterator uses the Predicate interface which is better suited to use with closures.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* new QCustomer()
|
||||
* .status.equalTo(Status.NEW)
|
||||
* .orderBy().id.asc()
|
||||
* .findEachWhile((Customer customer) -> {
|
||||
*
|
||||
* // do something with customer
|
||||
* System.out.println("-- visit " + customer);
|
||||
*
|
||||
* // return true to continue processing or false to stop
|
||||
* return (customer.getId() < 40);
|
||||
* });
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param consumer the consumer used to process the queried beans.
|
||||
*/
|
||||
void findEachWhile(Predicate<T> consumer);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
List<Version<T>> findVersions();
|
||||
|
||||
/**
|
||||
* Return versions of a @History entity bean between a start and end timestamp.
|
||||
* <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.
|
||||
*/
|
||||
List<Version<T>> findVersionsBetween(Timestamp start, Timestamp end);
|
||||
|
||||
/**
|
||||
* Return the count of entities this query should return.
|
||||
* <p>
|
||||
* This is the number of 'top level' or 'root level' entities.
|
||||
*/
|
||||
int findCount();
|
||||
|
||||
/**
|
||||
* 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).
|
||||
*
|
||||
* @return a Future object for the row count query
|
||||
*/
|
||||
FutureRowCount<T> findFutureCount();
|
||||
|
||||
/**
|
||||
* 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).
|
||||
*
|
||||
* @return a Future object for the list of Id's
|
||||
*/
|
||||
FutureIds<T> findFutureIds();
|
||||
|
||||
/**
|
||||
* Execute find list query in a background thread.
|
||||
* <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.
|
||||
*
|
||||
* @return a Future object for the list result of the query
|
||||
*/
|
||||
FutureList<T> findFutureList();
|
||||
|
||||
/**
|
||||
* Execute find map query in a background thread.
|
||||
* <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.
|
||||
*
|
||||
* @return a Future object for the map result of the query
|
||||
*/
|
||||
<K> FutureMap<K,T> findFutureMap();
|
||||
|
||||
/**
|
||||
* 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>
|
||||
* If maxRows is not set on the query prior to calling findPagedList() then a
|
||||
* PersistenceException is thrown.
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* PagedList<Order> pagedList =
|
||||
* new QOrder()
|
||||
* .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
|
||||
*/
|
||||
PagedList<T> findPagedList();
|
||||
|
||||
}
|
||||
@@ -1,249 +0,0 @@
|
||||
package io.ebean;
|
||||
|
||||
/**
|
||||
* Builder for ORM Query projection (the select and fetch part).
|
||||
*
|
||||
* @param <SELF> The builder type
|
||||
* @param <T> The entity bean type
|
||||
*/
|
||||
public interface QueryBuilderProjection<SELF extends QueryBuilderProjection<SELF, T>, T> {
|
||||
|
||||
/**
|
||||
* Apply the path properties replacing the select and fetch clauses.
|
||||
* <p>
|
||||
* This is typically used when the FetchPath is applied to both the query and the JSON output.
|
||||
*/
|
||||
SELF apply(FetchPath fetchPath);
|
||||
|
||||
/**
|
||||
* Specify the properties to fetch on the root level entity bean in comma delimited format.
|
||||
* <p>
|
||||
* The Id property is automatically included in the properties to fetch unless setDistinct(true)
|
||||
* is set on the query.
|
||||
* </p>
|
||||
* <p>
|
||||
* Use {@link #fetch(String, String)} to specify specific properties to fetch
|
||||
* on other non-root level paths of the object graph.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<Customer> customers = DB.find(Customer.class)
|
||||
* // Only fetch the customer id, name and status.
|
||||
* // This is described as a "Partial Object"
|
||||
* .select("name, status")
|
||||
* .where.ilike("name", "rob%")
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param fetchProperties the properties to fetch for this bean (* = all properties).
|
||||
*/
|
||||
SELF select(String fetchProperties);
|
||||
|
||||
/**
|
||||
* Set DISTINCT ON clause. This is a Postgres only SQL feature.
|
||||
*
|
||||
* @param distinctOn The properties to include in the DISTINCT ON clause.
|
||||
*/
|
||||
SELF distinctOn(String distinctOn);
|
||||
|
||||
/**
|
||||
* Apply the fetchGroup which defines what part of the object graph to load.
|
||||
*/
|
||||
SELF select(FetchGroup<T> fetchGroup);
|
||||
|
||||
/**
|
||||
* Specify a path to fetch eagerly including specific properties.
|
||||
* <p>
|
||||
* Ebean will endeavour to fetch this path using a SQL join. If Ebean determines that it can
|
||||
* not use a SQL join (due to maxRows or because it would result in a cartesian product) Ebean
|
||||
* will automatically convert this fetch query into a "query join" - i.e. use fetchQuery().
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // query orders...
|
||||
* List<Order> orders = DB.find(Order.class)
|
||||
* // fetch the customer...
|
||||
* // ... getting the customers name and phone number
|
||||
* .fetch("customer", "name, phoneNumber")
|
||||
*
|
||||
* // ... also fetch the customers billing address (* = all properties)
|
||||
* .fetch("customer.billingAddress", "*")
|
||||
* .findList();
|
||||
* }</pre>
|
||||
* <p>
|
||||
* If columns is null or "*" then all columns/properties for that path are fetched.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // fetch customers (their id, name and status)
|
||||
* List<Customer> customers = DB.find(Customer.class)
|
||||
* .select("name, status")
|
||||
* .fetch("contacts", "firstName,lastName,email")
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param path the property path we wish to fetch eagerly.
|
||||
* @param fetchProperties properties of the associated bean that you want to include in the
|
||||
* fetch (* means all properties, null also means all properties).
|
||||
*/
|
||||
SELF fetch(String path, String fetchProperties);
|
||||
|
||||
/**
|
||||
* Fetch the path and properties using a "query join" (separate SQL query).
|
||||
* <p>
|
||||
* This is the same as:
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* fetch(path, fetchProperties, FetchConfig.ofQuery())
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* This would be used instead of a fetch() when we use a separate SQL query to fetch this
|
||||
* part of the object graph rather than a SQL join.
|
||||
* <p>
|
||||
* We might typically get a performance benefit when the path to fetch is a OneToMany
|
||||
* or ManyToMany, the 'width' of the 'root bean' is wide and the cardinality of the many
|
||||
* is high.
|
||||
*
|
||||
* @param path the property path we wish to fetch eagerly.
|
||||
* @param fetchProperties properties of the associated bean that you want to include in the
|
||||
* fetch (* means all properties, null also means all properties).
|
||||
*/
|
||||
SELF fetchQuery(String path, String fetchProperties);
|
||||
|
||||
/**
|
||||
* Fetch the path and properties using L2 bean cache.
|
||||
*
|
||||
* @param path The path of the beans we are fetching from L2 cache.
|
||||
* @param fetchProperties The properties that should be loaded.
|
||||
*/
|
||||
SELF fetchCache(String path, String fetchProperties);
|
||||
|
||||
/**
|
||||
* Fetch the path and properties lazily (via batch lazy loading).
|
||||
* <p>
|
||||
* This is the same as:
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* fetch(path, fetchProperties, FetchConfig.ofLazy())
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* The reason for using fetchLazy() is to either:
|
||||
* <ul>
|
||||
* <li>Control/tune what is fetched as part of lazy loading</li>
|
||||
* <li>Make use of the L2 cache, build this part of the graph from L2 cache</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param path the property path we wish to fetch lazily.
|
||||
* @param fetchProperties properties of the associated bean that you want to include in the
|
||||
* fetch (* means all properties, null also means all properties).
|
||||
*/
|
||||
SELF fetchLazy(String path, String fetchProperties);
|
||||
|
||||
/**
|
||||
* Additionally specify a FetchConfig to use a separate query or lazy loading
|
||||
* to load this path.
|
||||
* <pre>{@code
|
||||
*
|
||||
* // fetch customers (their id, name and status)
|
||||
* List<Customer> customers = DB.find(Customer.class)
|
||||
* .select("name, status")
|
||||
* .fetch("contacts", "firstName,lastName,email", FetchConfig.ofLazy(10))
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param path the property path we wish to fetch eagerly.
|
||||
*/
|
||||
SELF fetch(String path, String fetchProperties, FetchConfig fetchConfig);
|
||||
|
||||
/**
|
||||
* Specify a path to fetch eagerly including all its properties.
|
||||
* <p>
|
||||
* Ebean will endeavour to fetch this path using a SQL join. If Ebean determines that it can
|
||||
* not use a SQL join (due to maxRows or because it would result in a cartesian product) Ebean
|
||||
* will automatically convert this fetch query into a "query join" - i.e. use fetchQuery().
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // fetch customers (their id, name and status)
|
||||
* List<Customer> customers = DB.find(Customer.class)
|
||||
* // eager fetch the contacts
|
||||
* .fetch("contacts")
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param path the property path we wish to fetch eagerly.
|
||||
*/
|
||||
SELF fetch(String path);
|
||||
|
||||
/**
|
||||
* Fetch the path eagerly using a "query join" (separate SQL query).
|
||||
* <p>
|
||||
* This is the same as:
|
||||
* <pre>{@code
|
||||
*
|
||||
* fetch(path, FetchConfig.ofQuery())
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* This would be used instead of a fetch() when we use a separate SQL query to fetch this
|
||||
* part of the object graph rather than a SQL join.
|
||||
* <p>
|
||||
* We might typically get a performance benefit when the path to fetch is a OneToMany
|
||||
* or ManyToMany, the 'width' of the 'root bean' is wide and the cardinality of the many
|
||||
* is high.
|
||||
*
|
||||
* @param path the property path we wish to fetch eagerly
|
||||
*/
|
||||
SELF fetchQuery(String path);
|
||||
|
||||
/**
|
||||
* Fetch the path eagerly using L2 cache.
|
||||
*/
|
||||
SELF fetchCache(String path);
|
||||
|
||||
/**
|
||||
* Fetch the path lazily (via batch lazy loading).
|
||||
* <p>
|
||||
* This is the same as:
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* fetch(path, FetchConfig.ofLazy())
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* The reason for using fetchLazy() is to either:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>Control/tune what is fetched as part of lazy loading</li>
|
||||
* <li>Make use of the L2 cache, build this part of the graph from L2 cache</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param path the property path we wish to fetch lazily.
|
||||
*/
|
||||
SELF fetchLazy(String path);
|
||||
|
||||
/**
|
||||
* Additionally specify a JoinConfig to specify a "query join" and or define
|
||||
* the lazy loading query.
|
||||
* <pre>{@code
|
||||
*
|
||||
* // fetch customers (their id, name and status)
|
||||
* List<Customer> customers = DB.find(Customer.class)
|
||||
* // lazy fetch contacts with a batch size of 100
|
||||
* .fetch("contacts", FetchConfig.ofLazy(100))
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
SELF fetch(String path, FetchConfig fetchConfig);
|
||||
|
||||
}
|
||||
@@ -25,7 +25,7 @@ import java.util.Iterator;
|
||||
*
|
||||
* Query<Customer> query = database.find(Customer.class)
|
||||
* .where().gt("id", 0)
|
||||
* .orderBy("id")
|
||||
* .order("id")
|
||||
* .setMaxRows(2);
|
||||
*
|
||||
* QueryIterator<Customer> it = query.findIterate();
|
||||
|
||||
@@ -111,7 +111,7 @@ package io.ebean;
|
||||
* .fetch("order.customer", "name")
|
||||
* .where().gt("order.id", 0)
|
||||
* .having().gt("totalAmount", 20)
|
||||
* .orderBy().desc("totalAmount")
|
||||
* .order().desc("totalAmount")
|
||||
* .setMaxRows(10)
|
||||
* .findList();
|
||||
*
|
||||
|
||||
@@ -22,14 +22,14 @@ public interface RawSqlBuilder {
|
||||
* resultSet.
|
||||
*/
|
||||
static RawSql resultSet(ResultSet resultSet, String... propertyNames) {
|
||||
return XBootstrapService.rawSql().resultSet(resultSet, propertyNames);
|
||||
return XServiceProvider.rawSql().resultSet(resultSet, propertyNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a SqlRow based on the resultSet with dbTrueValue and binaryOptimizedUUID options.
|
||||
*/
|
||||
static SqlRow sqlRow(ResultSet resultSet, final String dbTrueValue, boolean binaryOptimizedUUID) throws SQLException {
|
||||
return XBootstrapService.rawSql().sqlRow(resultSet, dbTrueValue, binaryOptimizedUUID);
|
||||
return XServiceProvider.rawSql().sqlRow(resultSet, dbTrueValue, binaryOptimizedUUID);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,7 +38,7 @@ public interface RawSqlBuilder {
|
||||
* this query.
|
||||
*/
|
||||
static RawSqlBuilder unparsed(String sql) {
|
||||
return XBootstrapService.rawSql().unparsed(sql);
|
||||
return XServiceProvider.rawSql().unparsed(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,7 +55,7 @@ public interface RawSqlBuilder {
|
||||
* </p>
|
||||
*/
|
||||
static RawSqlBuilder parse(String sql) {
|
||||
return XBootstrapService.rawSql().parsed(sql);
|
||||
return XServiceProvider.rawSql().parsed(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package io.ebean;
|
||||
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import io.avaje.lang.NonNullApi;
|
||||
import io.avaje.lang.Nullable;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.io.Serializable;
|
||||
import java.sql.Connection;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
@@ -40,7 +39,7 @@ import java.util.function.Predicate;
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@NullMarked
|
||||
@NonNullApi
|
||||
public interface SqlQuery extends Serializable, CancelableQuery {
|
||||
|
||||
/**
|
||||
@@ -172,7 +171,7 @@ public interface SqlQuery extends Serializable, CancelableQuery {
|
||||
* List<SqlRow> list =
|
||||
* DB.sqlQuery(sql)
|
||||
* .setParameter("Rob")
|
||||
* .setParameter(Status.NEW)
|
||||
* .setParameter("Status.NEW)
|
||||
* .findList();
|
||||
*
|
||||
* // the same as ...
|
||||
@@ -242,45 +241,11 @@ public interface SqlQuery extends Serializable, CancelableQuery {
|
||||
*/
|
||||
SqlQuery setParameter(int position, Object value);
|
||||
|
||||
/**
|
||||
* Bind the array parameter by its index position for use with Postgres ANY.
|
||||
* <p>
|
||||
* For Postgres this binds an ARRAY rather than expands into multiple bind values.
|
||||
* <pre>{@code
|
||||
*
|
||||
* String sql = "select name from customer where id = any(?)";
|
||||
*
|
||||
* List<SqlRow> list =
|
||||
* DB.sqlQuery(sql)
|
||||
* .setArrayParameter(1, List.of(1, 2, 3))
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
SqlQuery setArrayParameter(int position, Collection<?> value);
|
||||
|
||||
/**
|
||||
* Bind the named parameter value.
|
||||
*/
|
||||
SqlQuery setParameter(String name, Object value);
|
||||
|
||||
/**
|
||||
* Bind the named array parameter which we would use with Postgres ANY.
|
||||
* <p>
|
||||
* For Postgres this binds an ARRAY rather than expands into multiple bind values.
|
||||
* <pre>{@code
|
||||
*
|
||||
* String sql = "select name from customer where id = any(:idList)";
|
||||
*
|
||||
* List<SqlRow> list =
|
||||
* DB.sqlQuery(sql)
|
||||
* .setArrayParameter("idList", List.of(1, 2, 3))
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
SqlQuery setArrayParameter(String name, Collection<?> value);
|
||||
|
||||
/**
|
||||
* Set the index of the first row of the results to return.
|
||||
*/
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.annotation.DocStoreMode;
|
||||
import io.ebean.annotation.PersistBatch;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.config.DocStoreConfig;
|
||||
|
||||
import jakarta.persistence.PersistenceException;
|
||||
import java.sql.Connection;
|
||||
@@ -211,29 +209,6 @@ public interface Transaction extends AutoCloseable {
|
||||
*/
|
||||
boolean isActive();
|
||||
|
||||
/**
|
||||
* Set the behavior for document store updates on this transaction.
|
||||
* <p>
|
||||
* For example, set the mode to DocStoreEvent.IGNORE for this transaction and
|
||||
* then any changes via this transaction are not sent to the doc store. This
|
||||
* would be used when doing large bulk inserts into the database and we want
|
||||
* to control how that is sent to the document store.
|
||||
* </p>
|
||||
*/
|
||||
void setDocStoreMode(DocStoreMode mode);
|
||||
|
||||
/**
|
||||
* Set the batch size to use for sending messages to the document store.
|
||||
* <p>
|
||||
* You might set this if you know the changes in this transaction result in especially large or
|
||||
* especially small payloads and want to adjust the batch size to match.
|
||||
* </p>
|
||||
* <p>
|
||||
* Setting this overrides the default of {@link DocStoreConfig#getBulkBatchSize()}
|
||||
* </p>
|
||||
*/
|
||||
void setDocStoreBatchSize(int batchSize);
|
||||
|
||||
/**
|
||||
* Explicitly turn off or on the cascading nature of save() and delete(). This
|
||||
* gives the developer exact control over what beans are saved and deleted
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
package io.ebean;
|
||||
|
||||
/**
|
||||
* Attempted to modify a read only entity.
|
||||
*/
|
||||
public class UnmodifiableEntityException extends BeanAccessException {
|
||||
private static final long serialVersionUID = 1;
|
||||
|
||||
/**
|
||||
* Create with no message.
|
||||
*/
|
||||
public UnmodifiableEntityException() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create with message.
|
||||
*/
|
||||
public UnmodifiableEntityException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.metric.MetricFactory;
|
||||
import io.ebean.service.*;
|
||||
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
/**
|
||||
* Bootstrap internal services.
|
||||
*/
|
||||
public final class XBootstrapService {
|
||||
|
||||
private static final SpiContainerFactory containerFactory;
|
||||
private static final SpiRawSqlService rawSqlService;
|
||||
private static final SpiProfileLocationFactory profileLocationFactory;
|
||||
private static final SpiFetchGroupService fetchGroupService;
|
||||
private static final MetricFactory metricFactory;
|
||||
private static final SpiJsonService jsonService;
|
||||
static {
|
||||
SpiContainerFactory _factory = null;
|
||||
SpiRawSqlService _raw = null;
|
||||
SpiProfileLocationFactory _profile = null;
|
||||
SpiFetchGroupService _fetch = null;
|
||||
MetricFactory _metric = null;
|
||||
SpiJsonService _json = null;
|
||||
for (BootstrapService extension : ServiceLoader.load(BootstrapService.class)) {
|
||||
if (extension instanceof SpiContainerFactory) {
|
||||
_factory = (SpiContainerFactory)extension;
|
||||
} else if (extension instanceof SpiRawSqlService) {
|
||||
_raw = (SpiRawSqlService)extension;
|
||||
} else if (extension instanceof SpiProfileLocationFactory) {
|
||||
_profile = (SpiProfileLocationFactory)extension;
|
||||
} else if (extension instanceof SpiFetchGroupService) {
|
||||
_fetch = (SpiFetchGroupService)extension;
|
||||
} else if (extension instanceof MetricFactory) {
|
||||
_metric = (MetricFactory)extension;
|
||||
} else if (extension instanceof SpiJsonService) {
|
||||
_json = (SpiJsonService)extension;
|
||||
}
|
||||
}
|
||||
containerFactory = _factory;
|
||||
rawSqlService = _raw;
|
||||
profileLocationFactory = _profile;
|
||||
fetchGroupService = _fetch;
|
||||
metricFactory = _metric;
|
||||
jsonService = _json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the MetricFactory found in boostrap service loading.
|
||||
*/
|
||||
public static MetricFactory metricFactory() {
|
||||
return metricFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the SpiJsonService found in boostrap service loading.
|
||||
*/
|
||||
public static SpiJsonService jsonService() {
|
||||
return jsonService;
|
||||
}
|
||||
|
||||
static SpiContainerFactory containerFactory() {
|
||||
return containerFactory;
|
||||
}
|
||||
|
||||
static SpiRawSqlService rawSql() {
|
||||
return rawSqlService;
|
||||
}
|
||||
|
||||
static SpiProfileLocationFactory profileLocationFactory() {
|
||||
return profileLocationFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the FetchGroup with the given select clause.
|
||||
*/
|
||||
static <T> FetchGroup<T> fetchGroupOf(Class<T> cls, String select) {
|
||||
return fetchGroupService.of(cls, select);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the FetchGroupBuilder with the given select clause.
|
||||
*/
|
||||
static <T> FetchGroupBuilder<T> fetchGroupOf(Class<T> cls) {
|
||||
return fetchGroupService.of(cls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the FetchGroup Query for building fetch groups via query beans.
|
||||
*/
|
||||
static <T> SpiFetchGroupQuery<T> fetchGroupQueryFor(Class<T> cls) {
|
||||
return fetchGroupService.queryFor(cls);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.service.SpiFetchGroupQuery;
|
||||
import io.ebean.service.SpiFetchGroupService;
|
||||
import io.ebean.service.SpiProfileLocationFactory;
|
||||
import io.ebean.service.SpiRawSqlService;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
/**
|
||||
* Lookup internal services.
|
||||
*/
|
||||
final class XServiceProvider {
|
||||
|
||||
private static SpiRawSqlService rawSqlService = initRawSql();
|
||||
|
||||
private static SpiProfileLocationFactory profileLocationFactory = initProfileLocation();
|
||||
|
||||
private static SpiFetchGroupService fetchGroupService = initSpiFetchGroupService();
|
||||
|
||||
private static SpiFetchGroupService initSpiFetchGroupService() {
|
||||
return loadFirstService(SpiFetchGroupService.class);
|
||||
}
|
||||
|
||||
private static SpiRawSqlService initRawSql() {
|
||||
return loadFirstService(SpiRawSqlService.class);
|
||||
}
|
||||
|
||||
private static SpiProfileLocationFactory initProfileLocation() {
|
||||
return loadFirstService(SpiProfileLocationFactory.class);
|
||||
}
|
||||
|
||||
private static <T> T loadFirstService(Class<T> cls) {
|
||||
Iterator<T> loader = ServiceLoader.load(cls).iterator();
|
||||
if (loader.hasNext()) {
|
||||
return loader.next();
|
||||
}
|
||||
throw new IllegalStateException("No service implementation found for " + cls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the RawSqlService implementation.
|
||||
*/
|
||||
static SpiRawSqlService rawSql() {
|
||||
return rawSqlService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the RawSqlService implementation.
|
||||
*/
|
||||
static SpiProfileLocationFactory profileLocationFactory() {
|
||||
return profileLocationFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the FetchGroup with the given select clause.
|
||||
*/
|
||||
static <T> FetchGroup<T> fetchGroupOf(Class<T> cls, String select) {
|
||||
return fetchGroupService.of(cls, select);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the FetchGroupBuilder with the given select clause.
|
||||
*/
|
||||
static <T> FetchGroupBuilder<T> fetchGroupOf(Class<T> cls) {
|
||||
return fetchGroupService.of(cls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the FetchGroup Query for building fetch groups via query beans.
|
||||
*/
|
||||
static <T> SpiFetchGroupQuery<T> fetchGroupQueryFor(Class<T> cls) {
|
||||
return fetchGroupService.queryFor(cls);
|
||||
}
|
||||
}
|
||||
@@ -119,6 +119,18 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
|
||||
*/
|
||||
void setLoader(BeanCollectionLoader beanLoader);
|
||||
|
||||
/**
|
||||
* Set to true if you want the BeanCollection to be treated as read only. This
|
||||
* means no elements can be added or removed etc.
|
||||
*/
|
||||
void setReadOnly(boolean readOnly);
|
||||
|
||||
/**
|
||||
* Return true if the collection should be treated as readOnly and no elements
|
||||
* can be added or removed etc.
|
||||
*/
|
||||
boolean isReadOnly();
|
||||
|
||||
/**
|
||||
* Add the bean to the collection. This is disallowed for BeanMap.
|
||||
*/
|
||||
@@ -225,7 +237,7 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
|
||||
boolean wasTouched();
|
||||
|
||||
/**
|
||||
* Freeze the collection returning an unmodifiable version.
|
||||
* Return a shallow copy of this collection that is modifiable.
|
||||
*/
|
||||
Object freeze();
|
||||
BeanCollection<E> shallowCopy();
|
||||
}
|
||||
|
||||
@@ -148,6 +148,18 @@ public interface EntityBeanIntercept extends Serializable {
|
||||
*/
|
||||
boolean isLoadedFromCache();
|
||||
|
||||
/**
|
||||
* Return true if the bean should be treated as readOnly. If a setter method
|
||||
* is called when it is readOnly an Exception is thrown.
|
||||
*/
|
||||
boolean isReadOnly();
|
||||
|
||||
/**
|
||||
* Set the readOnly status. If readOnly then calls to setter methods through
|
||||
* an exception.
|
||||
*/
|
||||
void setReadOnly(boolean readOnly);
|
||||
|
||||
/**
|
||||
* Set the bean to be updated when persisted (for merge).
|
||||
*/
|
||||
@@ -540,9 +552,4 @@ public interface EntityBeanIntercept extends Serializable {
|
||||
* Update the 'next' mutable info returning the content that was obtained via dirty detection.
|
||||
*/
|
||||
String mutableNext(int propertyIndex);
|
||||
|
||||
/**
|
||||
* Return true if this entity bean should be frozen. Used to handle recursive freezing.
|
||||
*/
|
||||
boolean freeze();
|
||||
}
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
package io.ebean.bean;
|
||||
|
||||
/**
|
||||
* Common base features for EntityBeanIntercept.
|
||||
*/
|
||||
abstract class InterceptBase implements EntityBeanIntercept {
|
||||
|
||||
final EntityBean owner;
|
||||
boolean fullyLoadedBean;
|
||||
|
||||
/**
|
||||
* Create with a given entity.
|
||||
*/
|
||||
InterceptBase(Object ownerBean) {
|
||||
this.owner = (EntityBean) ownerBean;
|
||||
}
|
||||
|
||||
/**
|
||||
* EXPERIMENTAL - Constructor only for use by serialization frameworks.
|
||||
*/
|
||||
InterceptBase() {
|
||||
this.owner = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final EntityBean owner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isFullyLoadedBean() {
|
||||
return fullyLoadedBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setFullyLoadedBean(boolean fullyLoadedBean) {
|
||||
this.fullyLoadedBean = fullyLoadedBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String property(int propertyIndex) {
|
||||
if (propertyIndex == -1) {
|
||||
return null;
|
||||
}
|
||||
return owner._ebean_getPropertyName(propertyIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int findProperty(String propertyName) {
|
||||
final String[] names = owner._ebean_getPropertyNames();
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
if (names[i].equals(propertyName)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final StringBuilder loadedPropertyKey() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final int len = propertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (isLoadedProperty(i)) {
|
||||
sb.append(i).append(',');
|
||||
}
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
}
|
||||
@@ -1,44 +1,37 @@
|
||||
package io.ebean.bean;
|
||||
|
||||
import io.ebean.LazyInitialisationException;
|
||||
import io.ebean.UnmodifiableEntityException;
|
||||
import io.ebean.ValuePair;
|
||||
|
||||
import java.util.*;
|
||||
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, dirty state, original values
|
||||
* required for updates such as per property changed, loaded, dirty state, original values
|
||||
* bean state etc.
|
||||
*/
|
||||
public final class InterceptReadOnly extends InterceptBase {
|
||||
public class InterceptReadOnly implements EntityBeanIntercept {
|
||||
|
||||
private final boolean[] loaded;
|
||||
private boolean frozen;
|
||||
private final EntityBean owner;
|
||||
|
||||
/**
|
||||
* Create with a given entity.
|
||||
*/
|
||||
public InterceptReadOnly(Object ownerBean) {
|
||||
super(ownerBean);
|
||||
this.loaded = new boolean[owner._ebean_getPropertyNames().length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean freeze() {
|
||||
if (frozen) {
|
||||
return false;
|
||||
} else {
|
||||
frozen = true;
|
||||
return true;
|
||||
}
|
||||
this.owner = (EntityBean) ownerBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InterceptReadOnly{frozen:" + frozen + " loaded:" + loadedPropertyNames() + '}';
|
||||
return "InterceptReadOnly{" + owner + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityBean owner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -101,13 +94,18 @@ public final class InterceptReadOnly extends InterceptBase {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFullyLoadedBean() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFullyLoadedBean(boolean fullyLoadedBean) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPartial() {
|
||||
for (boolean flag : loaded) {
|
||||
if (!flag) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -138,14 +136,7 @@ public final class InterceptReadOnly extends InterceptBase {
|
||||
|
||||
@Override
|
||||
public boolean hasIdOnly(int idIndex) {
|
||||
for (int i = 0; i < loaded.length; i++) {
|
||||
if (i == idIndex) {
|
||||
if (!loaded[i]) return false;
|
||||
} else if (loaded[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -168,6 +159,16 @@ public final class InterceptReadOnly extends InterceptBase {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadOnly(boolean readOnly) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setForceUpdate(boolean forceUpdate) {
|
||||
|
||||
@@ -233,38 +234,44 @@ public final class InterceptReadOnly extends InterceptBase {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int findProperty(String propertyName) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String property(int propertyIndex) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int propertyLength() {
|
||||
return loaded.length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPropertyLoaded(String propertyName, boolean loaded) {
|
||||
final int position = findProperty(propertyName);
|
||||
if (position == -1) {
|
||||
throw new IllegalArgumentException("Property not found - " + propertyName);
|
||||
}
|
||||
this.loaded[position] = loaded;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPropertyUnloaded(int propertyIndex) {
|
||||
loaded[propertyIndex] = false;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoadedProperty(int propertyIndex) {
|
||||
loaded[propertyIndex] = true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoadedPropertyAll() {
|
||||
Arrays.fill(loaded, true);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoadedProperty(int propertyIndex) {
|
||||
return loaded[propertyIndex];
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -314,16 +321,7 @@ public final class InterceptReadOnly extends InterceptBase {
|
||||
|
||||
@Override
|
||||
public Set<String> loadedPropertyNames() {
|
||||
if (fullyLoadedBean) {
|
||||
return null;
|
||||
}
|
||||
final Set<String> props = new LinkedHashSet<>();
|
||||
for (int i = 0; i < loaded.length; i++) {
|
||||
if (loaded[i]) {
|
||||
props.add(property(i));
|
||||
}
|
||||
}
|
||||
return props;
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -371,11 +369,14 @@ public final class InterceptReadOnly extends InterceptBase {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuilder loadedPropertyKey() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] loaded() {
|
||||
final boolean[] ret = new boolean[loaded.length];
|
||||
System.arraycopy(loaded, 0, ret, 0, ret.length);
|
||||
return ret;
|
||||
return new boolean[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -400,7 +401,7 @@ public final class InterceptReadOnly extends InterceptBase {
|
||||
|
||||
@Override
|
||||
public void initialisedMany(int propertyIndex) {
|
||||
loaded[propertyIndex] = true;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -415,14 +416,12 @@ public final class InterceptReadOnly extends InterceptBase {
|
||||
|
||||
@Override
|
||||
public void preGetter(int propertyIndex) {
|
||||
if (!loaded[propertyIndex]) {
|
||||
throw new LazyInitialisationException("Property not loaded: " + property(propertyIndex));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetterMany(boolean interceptField, int propertyIndex, Object oldValue, Object newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -437,57 +436,57 @@ public final class InterceptReadOnly extends InterceptBase {
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, Object oldValue, Object newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, boolean oldValue, boolean newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, int oldValue, int newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, long oldValue, long newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, double oldValue, double newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, float oldValue, float newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, short oldValue, short newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, char oldValue, char newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, byte oldValue, byte newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, char[] oldValue, char[] newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preSetter(boolean intercept, int propertyIndex, byte[] oldValue, byte[] newValue) {
|
||||
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
* This provides the mechanisms to support deferred fetching of reference beans
|
||||
* and oldValues generation for concurrency checking.
|
||||
*/
|
||||
public final class InterceptReadWrite extends InterceptBase {
|
||||
public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
|
||||
private static final long serialVersionUID = -3664031775464862649L;
|
||||
|
||||
@@ -56,6 +56,10 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
private String ebeanServerName;
|
||||
private boolean deletedFromCollection;
|
||||
|
||||
/**
|
||||
* The actual entity bean that 'owns' this intercept.
|
||||
*/
|
||||
private final EntityBean owner;
|
||||
private EntityBean embeddedOwner;
|
||||
private int embeddedOwnerIndex;
|
||||
/**
|
||||
@@ -63,6 +67,7 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
*/
|
||||
private int state;
|
||||
private boolean forceUpdate;
|
||||
private boolean readOnly;
|
||||
private boolean dirty;
|
||||
/**
|
||||
* Flag set to disable lazy loading.
|
||||
@@ -72,6 +77,7 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
* Flag set when lazy loading failed due to the underlying bean being deleted in the DB.
|
||||
*/
|
||||
private boolean lazyLoadFailure;
|
||||
private boolean fullyLoadedBean;
|
||||
private boolean loadedFromCache;
|
||||
private final byte[] flags;
|
||||
private Object[] origValues;
|
||||
@@ -95,7 +101,7 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
* Create with a given entity.
|
||||
*/
|
||||
public InterceptReadWrite(Object ownerBean) {
|
||||
super(ownerBean);
|
||||
this.owner = (EntityBean) ownerBean;
|
||||
this.flags = new byte[owner._ebean_getPropertyNames().length];
|
||||
}
|
||||
|
||||
@@ -103,20 +109,16 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
* EXPERIMENTAL - Constructor only for use by serialization frameworks.
|
||||
*/
|
||||
public InterceptReadWrite() {
|
||||
super();
|
||||
this.owner = null;
|
||||
this.flags = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean freeze() {
|
||||
throw new UnsupportedOperationException("never expected");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InterceptReadWrite@" + hashCode() + "{state=" + state +
|
||||
(dirty ? " dirty;" : "") +
|
||||
(forceUpdate ? " forceUpdate;" : "") +
|
||||
(readOnly ? " readOnly;" : "") +
|
||||
(disableLazyLoad ? " disableLazyLoad;" : "") +
|
||||
(lazyLoadFailure ? " lazyLoadFailure;" : "") +
|
||||
(fullyLoadedBean ? " fullyLoadedBean;" : "") +
|
||||
@@ -129,6 +131,11 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityBean owner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceContext persistenceContext() {
|
||||
return persistenceContext;
|
||||
@@ -193,6 +200,16 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
this.ebeanServerName = beanLoader.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFullyLoadedBean() {
|
||||
return fullyLoadedBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFullyLoadedBean(boolean fullyLoadedBean) {
|
||||
this.fullyLoadedBean = fullyLoadedBean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPartial() {
|
||||
for (byte flag : flags) {
|
||||
@@ -281,6 +298,16 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
return loadedFromCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadOnly(boolean readOnly) {
|
||||
this.readOnly = readOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setForceUpdate(boolean forceUpdate) {
|
||||
this.forceUpdate = forceUpdate;
|
||||
@@ -384,6 +411,25 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
return origValues[propertyIndex];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int findProperty(String propertyName) {
|
||||
final String[] names = owner._ebean_getPropertyNames();
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
if (names[i].equals(propertyName)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String property(int propertyIndex) {
|
||||
if (propertyIndex == -1) {
|
||||
return null;
|
||||
}
|
||||
return owner._ebean_getPropertyName(propertyIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int propertyLength() {
|
||||
return flags.length;
|
||||
@@ -622,6 +668,18 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuilder loadedPropertyKey() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final int len = propertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (isLoadedProperty(i)) {
|
||||
sb.append(i).append(',');
|
||||
}
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean[] loaded() {
|
||||
final boolean[] ret = new boolean[flags.length];
|
||||
@@ -650,7 +708,7 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
if (database == null) {
|
||||
throw new PersistenceException(ebeanServerName == null ? "No registered default server" : "Database [" + ebeanServerName + "] is not registered");
|
||||
}
|
||||
// For stand-alone reference bean or after deserialisation lazy load
|
||||
// For stand alone reference bean or after deserialisation lazy load
|
||||
// using the ebeanServer. Synchronise only on the bean.
|
||||
loadBeanInternal(loadProperty, database.pluginApi().beanLoader());
|
||||
return;
|
||||
@@ -787,12 +845,18 @@ public final class InterceptReadWrite extends InterceptBase {
|
||||
if (state == STATE_NEW) {
|
||||
setLoadedProperty(propertyIndex);
|
||||
} else {
|
||||
if (readOnly) {
|
||||
throw new IllegalStateException("This bean is readOnly");
|
||||
}
|
||||
setChangeLoaded(propertyIndex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChangedPropertyValue(int propertyIndex, boolean setDirtyState, Object origValue) {
|
||||
if (readOnly) {
|
||||
throw new IllegalStateException("This bean is readOnly");
|
||||
}
|
||||
setChangedProperty(propertyIndex);
|
||||
if (setDirtyState) {
|
||||
setOriginalValue(propertyIndex, origValue);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.ebean.cache;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -11,11 +10,11 @@ import java.util.Set;
|
||||
* the query cache entry is treated as invalid.
|
||||
* </p>
|
||||
*/
|
||||
public final class QueryCacheEntry {
|
||||
public class QueryCacheEntry {
|
||||
|
||||
private final Object value;
|
||||
private final Set<String> dependentTables;
|
||||
private final Instant timestamp;
|
||||
private final long timestamp;
|
||||
|
||||
/**
|
||||
* Create with dependent tables and timestamp.
|
||||
@@ -24,7 +23,7 @@ public final class QueryCacheEntry {
|
||||
* @param dependentTables The extra tables the query is dependent on (joins to)
|
||||
* @param timestamp The timestamp that the query uses to check for modifications
|
||||
*/
|
||||
public QueryCacheEntry(Object value, Set<String> dependentTables, Instant timestamp) {
|
||||
public QueryCacheEntry(Object value, Set<String> dependentTables, long timestamp) {
|
||||
this.value = value;
|
||||
this.dependentTables = dependentTables;
|
||||
this.timestamp = timestamp;
|
||||
@@ -33,21 +32,21 @@ public final class QueryCacheEntry {
|
||||
/**
|
||||
* Return the actual query result.
|
||||
*/
|
||||
public Object value() {
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the tables the query result is dependent on.
|
||||
*/
|
||||
public Set<String> dependentTables() {
|
||||
public Set<String> getDependentTables() {
|
||||
return dependentTables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the timestamp used to check for modifications on the dependent tables.
|
||||
*/
|
||||
public Instant timestamp() {
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package io.ebean.cache;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import io.avaje.lang.Nullable;
|
||||
import io.ebean.meta.MetricVisitor;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
@@ -17,6 +17,7 @@ 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).
|
||||
@@ -54,6 +55,7 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
this.ebeanServerName = loader.name();
|
||||
this.ownerBean = ownerBean;
|
||||
this.propertyName = propertyName;
|
||||
this.readOnly = ownerBean != null && ownerBean._ebean_getIntercept().isReadOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -101,6 +103,22 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
this.ebeanServerName = loader.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReadOnly() {
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadOnly(boolean readOnly) {
|
||||
this.readOnly = readOnly;
|
||||
}
|
||||
|
||||
void checkReadOnly() {
|
||||
if (readOnly) {
|
||||
throw new IllegalStateException("This collection is in ReadOnly mode");
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Support for modify additions deletions etc - ManyToMany
|
||||
// ---------------------------------------------------------
|
||||
@@ -194,4 +212,14 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
return modifyHolder != null && modifyHolder.wasTouched();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all relevant properties for a clone. See {@link #shallowCopy()}
|
||||
*/
|
||||
protected void setFromOriginal(AbstractBeanCollection<E> other) {
|
||||
this.disableLazyLoad = other.disableLazyLoad;
|
||||
this.ebeanServerName = other.ebeanServerName;
|
||||
this.loader = other.loader;
|
||||
this.ownerBean = other.ownerBean;
|
||||
this.propertyName = other.propertyName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebean.common;
|
||||
|
||||
import io.ebean.bean.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@@ -38,17 +39,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
super(loader, ownerBean, propertyName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<E> freeze() {
|
||||
if (list == null) {
|
||||
return null;
|
||||
} else if (list.isEmpty()) {
|
||||
return List.of();
|
||||
} else {
|
||||
return Collections.unmodifiableList(list);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toString(ToStringBuilder builder) {
|
||||
builder.addCollection(list);
|
||||
@@ -233,6 +223,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public void add(int index, E element) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
modifyAddition(element);
|
||||
@@ -247,6 +238,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public boolean add(E bean) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
if (list.add(bean)) {
|
||||
@@ -261,6 +253,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends E> beans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
// all elements in c are added (no contains checking)
|
||||
@@ -271,6 +264,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, Collection<? extends E> beans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
// all elements in c are added (no contains checking)
|
||||
@@ -281,6 +275,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
checkReadOnly();
|
||||
// TODO: when clear() and not initialised could be more clever
|
||||
// and fetch just the Id's
|
||||
initClear();
|
||||
@@ -325,6 +320,9 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
init();
|
||||
if (readOnly) {
|
||||
return new ReadOnlyListIterator<>(list.listIterator());
|
||||
}
|
||||
if (modifyListening) {
|
||||
return new ModifyIterator<>(this, list.iterator());
|
||||
}
|
||||
@@ -340,6 +338,9 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
@Override
|
||||
public ListIterator<E> listIterator() {
|
||||
init();
|
||||
if (readOnly) {
|
||||
return new ReadOnlyListIterator<>(list.listIterator());
|
||||
}
|
||||
if (modifyListening) {
|
||||
return new ModifyListIterator<>(this, list.listIterator());
|
||||
}
|
||||
@@ -349,6 +350,9 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
@Override
|
||||
public ListIterator<E> listIterator(int index) {
|
||||
init();
|
||||
if (readOnly) {
|
||||
return new ReadOnlyListIterator<>(list.listIterator(index));
|
||||
}
|
||||
if (modifyListening) {
|
||||
return new ModifyListIterator<>(this, list.listIterator(index));
|
||||
}
|
||||
@@ -364,6 +368,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public E remove(int index) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
E o = list.remove(index);
|
||||
@@ -375,6 +380,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public boolean remove(Object bean) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
boolean isRemove = list.remove(bean);
|
||||
@@ -388,6 +394,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> beans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
boolean changed = false;
|
||||
@@ -405,6 +412,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> retainBeans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
boolean changed = false;
|
||||
@@ -425,6 +433,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public E set(int index, E element) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
E o = list.set(index, element);
|
||||
@@ -444,6 +453,9 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
@Override
|
||||
public List<E> subList(int fromIndex, int toIndex) {
|
||||
init();
|
||||
if (readOnly) {
|
||||
return Collections.unmodifiableList(list.subList(fromIndex, toIndex));
|
||||
}
|
||||
if (modifyListening) {
|
||||
return new ModifyList<>(this, list.subList(fromIndex, toIndex));
|
||||
}
|
||||
@@ -463,4 +475,67 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
return list.toArray(array);
|
||||
}
|
||||
|
||||
private static final class ReadOnlyListIterator<E> implements ListIterator<E>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 3097271091406323699L;
|
||||
|
||||
private final ListIterator<E> i;
|
||||
|
||||
ReadOnlyListIterator(ListIterator<E> i) {
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(E o) {
|
||||
throw new IllegalStateException("This collection is in ReadOnly mode");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new IllegalStateException("This collection is in ReadOnly mode");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(E o) {
|
||||
throw new IllegalStateException("This collection is in ReadOnly mode");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return i.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPrevious() {
|
||||
return i.hasPrevious();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
return i.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextIndex() {
|
||||
return i.nextIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E previous() {
|
||||
return i.previous();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int previousIndex() {
|
||||
return i.previousIndex();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollection<E> shallowCopy() {
|
||||
BeanList<E> copy = new BeanList<>(new CopyOnFirstWriteList<>(list));
|
||||
copy.setFromOriginal(this);
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,11 +37,6 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
super(ebeanServer, ownerBean, propertyName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<K, E> freeze() {
|
||||
return map == null ? null : Collections.unmodifiableMap(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toString(ToStringBuilder builder) {
|
||||
if (map == null || map.isEmpty()) {
|
||||
@@ -222,6 +217,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
checkReadOnly();
|
||||
initClear();
|
||||
if (modifyListening) {
|
||||
// add all beans to the removal list
|
||||
@@ -247,6 +243,9 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
@Override
|
||||
public Set<Entry<K, E>> entrySet() {
|
||||
init();
|
||||
if (readOnly) {
|
||||
return Collections.unmodifiableSet(map.entrySet());
|
||||
}
|
||||
return modifyListening ? new ModifyEntrySet<>(this, map.entrySet()) : map.entrySet();
|
||||
}
|
||||
|
||||
@@ -265,11 +264,15 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
init();
|
||||
if (readOnly) {
|
||||
return Collections.unmodifiableSet(map.keySet());
|
||||
}
|
||||
return modifyListening ? new ModifyKeySet<>(this, map.keySet()) : map.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E put(K key, E value) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
E oldBean = map.put(key, value);
|
||||
@@ -286,6 +289,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
|
||||
@Override
|
||||
public void putAll(Map<? extends K, ? extends E> puts) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
for (Entry<? extends K, ? extends E> entry : puts.entrySet()) {
|
||||
@@ -302,16 +306,17 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
|
||||
@Override
|
||||
public void addBean(E bean) {
|
||||
throw new UnsupportedOperationException("Method not allowed on Map. Please use List instead.");
|
||||
throw new IllegalStateException("Method not allowed on Map. Please use List instead.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeBean(E bean) {
|
||||
throw new UnsupportedOperationException("Method not allowed on Map. Please use List instead.");
|
||||
throw new IllegalStateException("Method not allowed on Map. Please use List instead.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public E remove(Object key) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
E o = map.remove(key);
|
||||
@@ -330,6 +335,16 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
@Override
|
||||
public Collection<E> values() {
|
||||
init();
|
||||
if (readOnly) {
|
||||
return Collections.unmodifiableCollection(map.values());
|
||||
}
|
||||
return modifyListening ? new ModifyCollection<>(this, map.values()) : map.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollection<E> shallowCopy() {
|
||||
BeanMap<K, E> copy = new BeanMap<>(new LinkedHashMap<>(map));
|
||||
copy.setFromOriginal(this);
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@ package io.ebean.common;
|
||||
import io.ebean.bean.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Set capable of lazy loading and modification aware.
|
||||
@@ -35,11 +38,6 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
super(loader, ownerBean, propertyName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<E> freeze() {
|
||||
return set == null ? null : Collections.unmodifiableSet(set);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toString(ToStringBuilder builder) {
|
||||
builder.addCollection(set);
|
||||
@@ -213,6 +211,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
|
||||
@Override
|
||||
public boolean add(E bean) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
if (set.add(bean)) {
|
||||
@@ -227,6 +226,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends E> beans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
boolean changed = false;
|
||||
@@ -244,6 +244,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
checkReadOnly();
|
||||
initClear();
|
||||
if (modifyListening) {
|
||||
for (E bean : set) {
|
||||
@@ -274,6 +275,9 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
init();
|
||||
if (readOnly) {
|
||||
return new ReadOnlyIterator<>(set.iterator());
|
||||
}
|
||||
if (modifyListening) {
|
||||
return new ModifyIterator<>(this, set.iterator());
|
||||
}
|
||||
@@ -282,6 +286,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
|
||||
@Override
|
||||
public boolean remove(Object bean) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
if (set.remove(bean)) {
|
||||
@@ -295,6 +300,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> beans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
boolean changed = false;
|
||||
@@ -311,6 +317,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> beans) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
if (modifyListening) {
|
||||
boolean changed = false;
|
||||
@@ -348,4 +355,36 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
return set.toArray(array);
|
||||
}
|
||||
|
||||
private static final class ReadOnlyIterator<E> implements Iterator<E>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 2577697326745352605L;
|
||||
|
||||
private final Iterator<E> it;
|
||||
|
||||
ReadOnlyIterator(Iterator<E> it) {
|
||||
this.it = it;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return it.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
return it.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new IllegalStateException("This collection is in ReadOnly mode");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanCollection<E> shallowCopy() {
|
||||
BeanSet<E> copy = new BeanSet<>(new LinkedHashSet<>(set));
|
||||
copy.setFromOriginal(this);
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
package io.ebean.common;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
/**
|
||||
* List that copies itself on first write access. Needed to keep memory footprint low and the ability
|
||||
* to modify lists from cache.
|
||||
*
|
||||
* @author Roland Praml, FOCONIS AG
|
||||
*/
|
||||
public final class CopyOnFirstWriteList<E> extends AbstractList<E> implements List<E>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
/**
|
||||
* The underlying List implementation.
|
||||
*/
|
||||
private List<E> list;
|
||||
|
||||
public CopyOnFirstWriteList(List<E> list) {
|
||||
super();
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
private volatile boolean copied = false;
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return list.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return list.contains(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return list.toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T[] toArray(T[] a) {
|
||||
return list.toArray(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(E e) {
|
||||
checkCopyOnWrite();
|
||||
return list.add(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
checkCopyOnWrite();
|
||||
return list.remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
return list.containsAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends E> c) {
|
||||
checkCopyOnWrite();
|
||||
return list.addAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, Collection<? extends E> c) {
|
||||
checkCopyOnWrite();
|
||||
return list.addAll(index, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
checkCopyOnWrite();
|
||||
return list.removeAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
checkCopyOnWrite();
|
||||
return list.retainAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceAll(UnaryOperator<E> operator) {
|
||||
checkCopyOnWrite();
|
||||
list.replaceAll(operator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeIf(Predicate<? super E> filter) {
|
||||
checkCopyOnWrite();
|
||||
return list.removeIf(filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(Comparator<? super E> c) {
|
||||
checkCopyOnWrite();
|
||||
list.sort(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
if (!copied) {
|
||||
list = new ArrayList<>();
|
||||
copied = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return list.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return list.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E get(int index) {
|
||||
return list.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E set(int index, E element) {
|
||||
checkCopyOnWrite();
|
||||
return list.set(index, element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int index, E element) {
|
||||
checkCopyOnWrite();
|
||||
list.add(index, element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public E remove(int index) {
|
||||
checkCopyOnWrite();
|
||||
return list.remove(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(Object o) {
|
||||
return list.indexOf(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lastIndexOf(Object o) {
|
||||
return list.lastIndexOf(o);
|
||||
}
|
||||
|
||||
private void checkCopyOnWrite() {
|
||||
if (!copied) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (!copied) {
|
||||
list = new ArrayList<>(list);
|
||||
copied = true;
|
||||
}
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
package io.ebean.config;
|
||||
|
||||
import io.ebean.plugin.Lookups;
|
||||
|
||||
/**
|
||||
* Helper to find classes taking into account the context class loader.
|
||||
*/
|
||||
@@ -75,8 +73,9 @@ public class ClassLoadConfig {
|
||||
*/
|
||||
public Object newInstance(String className) {
|
||||
try {
|
||||
return Lookups.newDefaultInstance(forName(className));
|
||||
} catch (Throwable e) {
|
||||
Class<?> cls = forName(className);
|
||||
return cls.getDeclaredConstructor().newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException("Error constructing " + className, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@ import io.ebean.event.*;
|
||||
import io.ebean.event.changelog.ChangeLogListener;
|
||||
import io.ebean.event.changelog.ChangeLogPrepare;
|
||||
import io.ebean.event.changelog.ChangeLogRegister;
|
||||
import io.ebean.event.readaudit.ReadAuditLogger;
|
||||
import io.ebean.event.readaudit.ReadAuditPrepare;
|
||||
import io.ebean.meta.MetricNamingMatch;
|
||||
import io.ebean.util.StringHelper;
|
||||
import jakarta.persistence.EnumType;
|
||||
@@ -129,7 +127,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
* When true then include a sql comment in generated SELECT queries with the query
|
||||
* label or profile location label.
|
||||
*/
|
||||
private boolean includeLabelInSql = true;
|
||||
private boolean includeLabelInSql;
|
||||
|
||||
/**
|
||||
* Interesting classes such as entities, embedded, ScalarTypes,
|
||||
@@ -143,16 +141,6 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
*/
|
||||
private List<String> packages = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Configuration for the ElasticSearch integration.
|
||||
*/
|
||||
private DocStoreConfig docStoreConfig = new DocStoreConfig();
|
||||
|
||||
/**
|
||||
* Set to true when the Database only uses Document store.
|
||||
*/
|
||||
private boolean docStoreOnly;
|
||||
|
||||
/**
|
||||
* This is used to populate @WhoCreated, @WhoModified and
|
||||
* support other audit features (who executed a query etc).
|
||||
@@ -251,7 +239,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
/**
|
||||
* The default batch size for lazy loading
|
||||
*/
|
||||
private int lazyLoadBatchSize = 100;
|
||||
private int lazyLoadBatchSize = 10;
|
||||
|
||||
/**
|
||||
* The default batch size for 'query joins'.
|
||||
@@ -311,7 +299,6 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
private boolean skipDataSourceCheck;
|
||||
|
||||
private boolean readOnlyDatabase;
|
||||
private boolean shutdownHook = true;
|
||||
|
||||
/**
|
||||
* The data source (if programmatically provided).
|
||||
@@ -428,8 +415,6 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
private ChangeLogListener changeLogListener;
|
||||
private ChangeLogRegister changeLogRegister;
|
||||
private boolean changeLogAsync = true;
|
||||
private ReadAuditLogger readAuditLogger;
|
||||
private ReadAuditPrepare readAuditPrepare;
|
||||
private EncryptKeyManager encryptKeyManager;
|
||||
private EncryptDeployManager encryptDeployManager;
|
||||
private Encryptor encryptor;
|
||||
@@ -482,7 +467,6 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
* Time to live for query plans - defaults to 5 minutes.
|
||||
*/
|
||||
private int queryPlanTTLSeconds = 60 * 5;
|
||||
private String queryPlanExplain;
|
||||
|
||||
/**
|
||||
* Set to true to globally disable L2 caching (typically for performance testing).
|
||||
@@ -1004,28 +988,6 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadAuditLogger getReadAuditLogger() {
|
||||
return readAuditLogger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseConfig setReadAuditLogger(ReadAuditLogger readAuditLogger) {
|
||||
this.readAuditLogger = readAuditLogger;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReadAuditPrepare getReadAuditPrepare() {
|
||||
return readAuditPrepare;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseConfig setReadAuditPrepare(ReadAuditPrepare readAuditPrepare) {
|
||||
this.readAuditPrepare = readAuditPrepare;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProfilingConfig getProfilingConfig() {
|
||||
return profilingConfig;
|
||||
@@ -1300,28 +1262,6 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDocStoreOnly() {
|
||||
return docStoreOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseConfig setDocStoreOnly(boolean docStoreOnly) {
|
||||
this.docStoreOnly = docStoreOnly;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DocStoreConfig getDocStoreConfig() {
|
||||
return docStoreConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseConfig setDocStoreConfig(DocStoreConfig docStoreConfig) {
|
||||
this.docStoreConfig = docStoreConfig;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DbConstraintNaming getConstraintNaming() {
|
||||
return platformConfig.getConstraintNaming();
|
||||
@@ -1366,17 +1306,6 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
return readOnlyDatabase;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseBuilder shutdownHook(boolean shutdownHook) {
|
||||
this.shutdownHook = shutdownHook;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shutdownHook() {
|
||||
return shutdownHook;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataSource getDataSource() {
|
||||
return dataSource;
|
||||
@@ -2105,13 +2034,6 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
readOnlyDataSourceConfig.loadSettings(p.properties, name + "-ro");
|
||||
}
|
||||
|
||||
/**
|
||||
* This is broken out to allow overridden behaviour.
|
||||
*/
|
||||
protected void loadDocStoreSettings(PropertiesWrapper p) {
|
||||
docStoreConfig.loadSettings(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is broken out to allow overridden behaviour.
|
||||
*/
|
||||
@@ -2143,13 +2065,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
}
|
||||
loadDataSourceSettings(p);
|
||||
|
||||
if (docStoreConfig == null) {
|
||||
docStoreConfig = new DocStoreConfig();
|
||||
}
|
||||
loadDocStoreSettings(p);
|
||||
|
||||
defaultServer = p.getBoolean("defaultServer", defaultServer);
|
||||
shutdownHook = p.getBoolean("shutdownHook", shutdownHook);
|
||||
readOnlyDatabase = p.getBoolean("readOnlyDatabase", readOnlyDatabase);
|
||||
autoPersistUpdates = p.getBoolean("autoPersistUpdates", autoPersistUpdates);
|
||||
loadModuleInfo = p.getBoolean("loadModuleInfo", loadModuleInfo);
|
||||
@@ -2165,8 +2081,6 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
queryPlanCapturePeriodSecs = p.getLong("queryPlan.capturePeriodSecs", queryPlanCapturePeriodSecs);
|
||||
queryPlanCaptureMaxTimeMillis = p.getLong("queryPlan.captureMaxTimeMillis", queryPlanCaptureMaxTimeMillis);
|
||||
queryPlanCaptureMaxCount = p.getInt("queryPlan.captureMaxCount", queryPlanCaptureMaxCount);
|
||||
queryPlanExplain = p.get("queryPlan.explain", queryPlanExplain);
|
||||
docStoreOnly = p.getBoolean("docStoreOnly", docStoreOnly);
|
||||
disableL2Cache = p.getBoolean("disableL2Cache", disableL2Cache);
|
||||
localOnlyL2Cache = p.getBoolean("localOnlyL2Cache", localOnlyL2Cache);
|
||||
enabledL2Regions = p.get("enabledL2Regions", enabledL2Regions);
|
||||
@@ -2417,17 +2331,6 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
|
||||
return queryPlanTTLSeconds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQueryPlanExplain() {
|
||||
return queryPlanExplain;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseBuilder queryPlanExplain(String queryPlanExplain) {
|
||||
this.queryPlanExplain = queryPlanExplain;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseConfig setQueryPlanTTLSeconds(int queryPlanTTLSeconds) {
|
||||
this.queryPlanTTLSeconds = queryPlanTTLSeconds;
|
||||
|
||||
@@ -1,320 +0,0 @@
|
||||
package io.ebean.config;
|
||||
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.annotation.DocStoreMode;
|
||||
|
||||
/**
|
||||
* Configuration for the Document store integration (e.g. ElasticSearch).
|
||||
*/
|
||||
public class DocStoreConfig {
|
||||
|
||||
/**
|
||||
* True when the Document store integration is active/on.
|
||||
*/
|
||||
protected boolean active;
|
||||
|
||||
/**
|
||||
* Set to true means Ebean will generate mapping files on startup.
|
||||
*/
|
||||
protected boolean generateMapping;
|
||||
|
||||
/**
|
||||
* When true the Document store should drop and re-create document indexes.
|
||||
*/
|
||||
protected boolean dropCreate;
|
||||
|
||||
/**
|
||||
* When true the Document store should create any document indexes that don't already exist.
|
||||
*/
|
||||
protected boolean create;
|
||||
|
||||
/**
|
||||
* The URL of the Document store. For example: http://localhost:9200.
|
||||
*/
|
||||
protected String url;
|
||||
|
||||
/**
|
||||
* Credential that be used for authentication to document store.
|
||||
*/
|
||||
protected String username;
|
||||
|
||||
/**
|
||||
* Password credential that be used for authentication to document store.
|
||||
*/
|
||||
protected String password;
|
||||
|
||||
/**
|
||||
* Set to true such that the client allows connections to invalid/self signed SSL certificates.
|
||||
*/
|
||||
protected boolean allowAllCertificates;
|
||||
|
||||
/**
|
||||
* The default mode used by indexes.
|
||||
*/
|
||||
protected DocStoreMode persist = DocStoreMode.UPDATE;
|
||||
|
||||
/**
|
||||
* The default batch size to use for the Bulk API calls.
|
||||
*/
|
||||
protected int bulkBatchSize = 1000;
|
||||
|
||||
/**
|
||||
* Resource path for the Document store mapping files.
|
||||
*/
|
||||
protected String mappingPath;
|
||||
|
||||
/**
|
||||
* Suffix used for mapping files.
|
||||
*/
|
||||
protected String mappingSuffix;
|
||||
|
||||
/**
|
||||
* Location of resources that mapping files are generated into.
|
||||
*/
|
||||
protected String pathToResources = "src/main/resources";
|
||||
|
||||
/**
|
||||
* Return true if the Document store (ElasticSearch) integration is active.
|
||||
*/
|
||||
public boolean isActive() {
|
||||
String systemValue = System.getProperty("ebean.docstore.active");
|
||||
if (systemValue != null) {
|
||||
return Boolean.parseBoolean(systemValue);
|
||||
}
|
||||
return active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true to make the Document store (ElasticSearch) integration active.
|
||||
*/
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the URL to the Document store.
|
||||
*/
|
||||
public String getUrl() {
|
||||
String systemValue = System.getProperty("ebean.docstore.url");
|
||||
if (systemValue != null) {
|
||||
return systemValue;
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the user credential for connecting to the document store.
|
||||
*/
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user credential for connecting to the document store.
|
||||
*/
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the password credential for connecting to the document store.
|
||||
*/
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the password credential for connecting to the document store.
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the URL to the Document store.
|
||||
* <p>
|
||||
* For a local ElasticSearch server this would be: http://localhost:9200
|
||||
*/
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if Ebean should generate mapping files on server startup.
|
||||
*/
|
||||
public boolean isGenerateMapping() {
|
||||
String systemValue = System.getProperty("ebean.docstore.generateMapping");
|
||||
if (systemValue != null) {
|
||||
return Boolean.parseBoolean(systemValue);
|
||||
}
|
||||
return generateMapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if Ebean should generate mapping files on server startup.
|
||||
*/
|
||||
public void setGenerateMapping(boolean generateMapping) {
|
||||
this.generateMapping = generateMapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the document store should recreate mapped indexes.
|
||||
*/
|
||||
public boolean isDropCreate() {
|
||||
String systemValue = System.getProperty("ebean.docstore.dropCreate");
|
||||
if (systemValue != null) {
|
||||
return Boolean.parseBoolean(systemValue);
|
||||
}
|
||||
return dropCreate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if the document store should recreate mapped indexes.
|
||||
*/
|
||||
public void setDropCreate(boolean dropCreate) {
|
||||
this.dropCreate = dropCreate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create true if the document store should create mapped indexes that don't yet exist.
|
||||
* This is only used if dropCreate is false.
|
||||
*/
|
||||
public boolean isCreate() {
|
||||
String systemValue = System.getProperty("ebean.docstore.create");
|
||||
if (systemValue != null) {
|
||||
return Boolean.parseBoolean(systemValue);
|
||||
}
|
||||
return create;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if the document store should create mapped indexes that don't yet exist.
|
||||
* This is only used if dropCreate is false.
|
||||
*/
|
||||
public void setCreate(boolean create) {
|
||||
this.create = create;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the client allows connections to invalid/self signed SSL certificates.
|
||||
*/
|
||||
public boolean isAllowAllCertificates() {
|
||||
return allowAllCertificates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true such that the client allows connections to invalid/self signed SSL certificates.
|
||||
*/
|
||||
public void setAllowAllCertificates(boolean allowAllCertificates) {
|
||||
this.allowAllCertificates = allowAllCertificates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default batch size to use for calls to the Bulk API.
|
||||
*/
|
||||
public int getBulkBatchSize() {
|
||||
return bulkBatchSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default batch size to use for calls to the Bulk API.
|
||||
* <p>
|
||||
* The batch size can be set on a transaction via {@link Transaction#setDocStoreBatchSize(int)}.
|
||||
* </p>
|
||||
*/
|
||||
public void setBulkBatchSize(int bulkBatchSize) {
|
||||
this.bulkBatchSize = bulkBatchSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mapping path.
|
||||
*/
|
||||
public String getMappingPath() {
|
||||
return mappingPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mapping path.
|
||||
*/
|
||||
public void setMappingPath(String mappingPath) {
|
||||
this.mappingPath = mappingPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mapping suffix.
|
||||
*/
|
||||
public String getMappingSuffix() {
|
||||
return mappingSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mapping suffix.
|
||||
*/
|
||||
public void setMappingSuffix(String mappingSuffix) {
|
||||
this.mappingSuffix = mappingSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the relative file system path to resources when generating mapping files.
|
||||
*/
|
||||
public String getPathToResources() {
|
||||
return pathToResources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the relative file system path to resources when generating mapping files.
|
||||
*/
|
||||
public void setPathToResources(String pathToResources) {
|
||||
this.pathToResources = pathToResources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default behavior for when Insert, Update and Delete events occur on beans that have an associated
|
||||
* Document store.
|
||||
*/
|
||||
public DocStoreMode getPersist() {
|
||||
return persist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default behavior for when Insert, Update and Delete events occur on beans that have an associated
|
||||
* Document store.
|
||||
* <ul>
|
||||
* <li>DocStoreEvent.UPDATE - build and send message to Bulk API</li>
|
||||
* <li>DocStoreEvent.QUEUE - add an entry with the index type and id only into a queue for later processing</li>
|
||||
* <li>DocStoreEvent.IGNORE - ignore. Most likely used when some scheduled batch job handles updating the index</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* You might choose to use QUEUE if that particular index data is updating very frequently or the cost of indexing
|
||||
* is expensive. Setting it to QUEUE can mean many changes can be batched together potentially coalescing multiple
|
||||
* updates for an index entry into a single update.
|
||||
* </p>
|
||||
* <p>
|
||||
* You might choose to use IGNORE when you have your own external process for updating the indexes. In this case
|
||||
* you don't want Ebean to do anything when the data changes.
|
||||
* </p>
|
||||
*/
|
||||
public void setPersist(DocStoreMode persist) {
|
||||
this.persist = persist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load settings specified in properties files.
|
||||
*/
|
||||
public void loadSettings(PropertiesWrapper properties) {
|
||||
|
||||
active = properties.getBoolean("docstore.active", active);
|
||||
url = properties.get("docstore.url", url);
|
||||
username = properties.get("docstore.username", url);
|
||||
password = properties.get("docstore.password", url);
|
||||
persist = properties.getEnum(DocStoreMode.class, "docstore.persist", persist);
|
||||
bulkBatchSize = properties.getInt("docstore.bulkBatchSize", bulkBatchSize);
|
||||
generateMapping = properties.getBoolean("docstore.generateMapping", generateMapping);
|
||||
dropCreate = properties.getBoolean("docstore.dropCreate", dropCreate);
|
||||
create = properties.getBoolean("docstore.create", create);
|
||||
allowAllCertificates = properties.getBoolean("docstore.allowAllCertificates", allowAllCertificates);
|
||||
mappingPath = properties.get("docstore.mappingPath", mappingPath);
|
||||
mappingSuffix = properties.get("docstore.mappingSuffix", mappingSuffix);
|
||||
pathToResources = properties.get("docstore.pathToResources", pathToResources);
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package io.ebean.config;
|
||||
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
|
||||
/**
|
||||
* Provides a Lookup instance for accessing entity/dto fields.
|
||||
*/
|
||||
public interface LookupProvider {
|
||||
|
||||
/**
|
||||
* Return the Lookup.
|
||||
*/
|
||||
Lookup provideLookup();
|
||||
|
||||
}
|
||||
@@ -1,29 +1,50 @@
|
||||
package io.ebean.config;
|
||||
|
||||
import io.ebean.ProfileLocation;
|
||||
import io.ebean.bean.ObjectGraphNode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The data for the slow query.
|
||||
* Slow query event.
|
||||
*/
|
||||
public interface SlowQueryEvent {
|
||||
public class SlowQueryEvent {
|
||||
|
||||
private final String sql;
|
||||
|
||||
private final long timeMillis;
|
||||
|
||||
private final int rowCount;
|
||||
|
||||
private final ObjectGraphNode originNode;
|
||||
|
||||
/**
|
||||
* Construct with the SQL and execution time in millis.
|
||||
*/
|
||||
public SlowQueryEvent(String sql, long timeMillis, int rowCount, ObjectGraphNode originNode) {
|
||||
this.sql = sql;
|
||||
this.timeMillis = timeMillis;
|
||||
this.rowCount = rowCount;
|
||||
this.originNode = originNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the SQL for the slow query.
|
||||
*/
|
||||
String getSql();
|
||||
public String getSql() {
|
||||
return sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the execution time in millis.
|
||||
*/
|
||||
long getTimeMillis();
|
||||
public long getTimeMillis() {
|
||||
return timeMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the total row count associated with the query.
|
||||
*/
|
||||
int getRowCount();
|
||||
public int getRowCount() {
|
||||
return rowCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the origin point for the root query.
|
||||
@@ -32,20 +53,7 @@ public interface SlowQueryEvent {
|
||||
* shows the code that invoked the query.
|
||||
* </p>
|
||||
*/
|
||||
ObjectGraphNode getOriginNode();
|
||||
|
||||
/**
|
||||
* Return the bind parameters.
|
||||
*/
|
||||
List<Object> getBindParams();
|
||||
|
||||
/**
|
||||
* Return the label.
|
||||
*/
|
||||
String getLabel();
|
||||
|
||||
/**
|
||||
* Return the profile location.
|
||||
*/
|
||||
ProfileLocation getProfileLocation();
|
||||
public ObjectGraphNode getOriginNode() {
|
||||
return originNode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,22 @@ public final class AnsiSqlRowsLimiter implements SqlLimiter {
|
||||
|
||||
@Override
|
||||
public SqlLimitResponse limit(SqlLimitRequest request) {
|
||||
final var ansiSql = request.ansiOffsetRows();
|
||||
final var sql = request.getDbPlatform().completeSql(ansiSql, request.getOrmQuery());
|
||||
String dbSql = request.getDbSql();
|
||||
StringBuilder sb = new StringBuilder(50 + dbSql.length());
|
||||
sb.append("select ");
|
||||
if (request.isDistinct()) {
|
||||
sb.append("distinct ");
|
||||
}
|
||||
sb.append(dbSql);
|
||||
int firstRow = request.getFirstRow();
|
||||
if (firstRow > 0) {
|
||||
sb.append(" offset ").append(firstRow).append(" rows");
|
||||
}
|
||||
int maxRows = request.getMaxRows();
|
||||
if (maxRows > 0) {
|
||||
sb.append(" fetch next ").append(maxRows).append(" rows only");
|
||||
}
|
||||
String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
|
||||
return new SqlLimitResponse(sql);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,7 +167,6 @@ public class DatabasePlatform {
|
||||
* findIterate() and findVisit().
|
||||
*/
|
||||
protected boolean forwardOnlyHintOnFindIterate;
|
||||
protected boolean autoCommitFalseOnFindIterate;
|
||||
|
||||
/**
|
||||
* If set then use the CONCUR_UPDATABLE hint when creating ResultSets.
|
||||
@@ -529,10 +528,6 @@ public class DatabasePlatform {
|
||||
this.forwardOnlyHintOnFindIterate = forwardOnlyHintOnFindIterate;
|
||||
}
|
||||
|
||||
public boolean autoCommitFalseOnFindIterate() {
|
||||
return autoCommitFalseOnFindIterate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the ResultSet CONCUR_UPDATABLE Hint should be used on
|
||||
* createNativeSqlTree() PreparedStatements.
|
||||
@@ -785,5 +780,4 @@ public class DatabasePlatform {
|
||||
public String inlineSqlHint(String hint) {
|
||||
return "/*+ " + hint + " */ ";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -172,6 +172,7 @@ public class DbPlatformType implements ExtraDbTypes {
|
||||
* </p>
|
||||
*/
|
||||
public String renderType(int deployLength, int deployScale, boolean strict) {
|
||||
|
||||
int len = deployLength != 0 ? deployLength : defaultLength;
|
||||
if (len > maxLength) {
|
||||
return fallback.renderType(deployLength, deployScale, strict);
|
||||
@@ -181,6 +182,7 @@ public class DbPlatformType implements ExtraDbTypes {
|
||||
if ((canHaveLength || !strict) && len > 0) {
|
||||
renderLengthScale(len, deployScale, sb);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,16 +7,23 @@ public final class LimitOffsetSqlLimiter implements SqlLimiter {
|
||||
|
||||
@Override
|
||||
public SqlLimitResponse limit(SqlLimitRequest request) {
|
||||
final var buffer = request.selectDistinctOnSql();
|
||||
String dbSql = request.getDbSql();
|
||||
StringBuilder sb = new StringBuilder(50 + dbSql.length());
|
||||
sb.append("select ");
|
||||
if (request.isDistinct()) {
|
||||
sb.append("distinct ");
|
||||
}
|
||||
sb.append(dbSql);
|
||||
int maxRows = request.getMaxRows();
|
||||
if (maxRows > 0) {
|
||||
buffer.append(" limit ").append(maxRows);
|
||||
sb.append(" limit ").append(maxRows);
|
||||
}
|
||||
int firstRow = request.getFirstRow();
|
||||
if (firstRow > 0) {
|
||||
buffer.append(" offset ").append(firstRow);
|
||||
sb.append(" offset ").append(firstRow);
|
||||
}
|
||||
return new SqlLimitResponse(request.getDbPlatform().completeSql(buffer.toString(), request.getOrmQuery()));
|
||||
String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
|
||||
return new SqlLimitResponse(sql);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
|
||||
if (newIds.isEmpty()) {
|
||||
throw new PersistenceException("Always expecting more than 1 row from " + sql);
|
||||
}
|
||||
connection.commit();
|
||||
|
||||
return newIds;
|
||||
|
||||
} catch (SQLException e) {
|
||||
|
||||
@@ -8,21 +8,6 @@ import io.ebean.Query;
|
||||
*/
|
||||
public interface SqlLimitRequest {
|
||||
|
||||
/**
|
||||
* Return ANSI SQL Offset and next rows.
|
||||
*/
|
||||
String ansiOffsetRows();
|
||||
|
||||
/**
|
||||
* Create and return buffer including the select distinct clause.
|
||||
*/
|
||||
StringBuilder selectDistinct();
|
||||
|
||||
/**
|
||||
* Create and return buffer including the select distinct on clause.
|
||||
*/
|
||||
StringBuilder selectDistinctOnSql();
|
||||
|
||||
/**
|
||||
* Return true if the query uses distinct.
|
||||
*/
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user