Compare commits

..
Author SHA1 Message Date
Rob Bygrave 93ae5f2b7c ToMany collections that are not loaded on freeze are marked unloaded
They are marked as unloaded which means accessing the collection will
throw a PersistenceException.

e.g. customer.getOrders() will throw PersistenceException rather than
return an empty list.
2024-01-30 22:32:49 +13:00
Rob Bygrave bc302b19db Experimental Feature - Freeze and detach beans (and attach)
- Frozen beans as ReadOnly + Unmodifiable collections
- Add Transaction.freezeAndDetach() returning FrozenBeans
- Add Transaction.attach( FrozenBeans )

- InterceptReadOnly now supports lazy loading
- Query.setReadOnly(true) now uses InterceptReadOnly [when it used to ALSO require Query.setDisableLazyLoading(true)}
- Add EntityBeanIntercept.errorOnLazyLoad (such that lazy loading on frozen bean is an error)

- BeanList, BeanSet, BeanMap are now freezable
- ModifyAwareList Set and Map are now freezable
2024-01-30 20:40:18 +13:00
Rob Bygrave f34e7b6003 Version 13.26.0 2024-01-20 22:01:30 +13:00
Rob BygraveandGitHub 089dd8e364 Merge pull request #3311 from ebean-orm/feature/findSingleAttributeOrEmpty
enh: Add findSingleAttributeOrEmpty() returning Optional
2024-01-19 15:23:27 +13:00
Rob Bygrave 44770382fb enh: Add findSingleAttributeOrEmpty() returning Optional 2024-01-19 10:41:54 +13:00
Rob BygraveandGitHub 2a62d413cc Merge pull request #3308 from Incanus3/fix/querybean_or_with_exists
fix TQRootBean.exists() when used with .or()
2024-01-19 08:29:29 +13:00
Rob Bygrave 0046d983cb Adjust test such that table alias does not clash
The .raw("contact.customer_id = customer.id") clashes as "customer.id" is
a logical path from contact
2024-01-19 08:14:58 +13:00
Jakub Kaláb 2e1b52d7d4 WIP: fix TQRootBean.exists() when used with .or() 2024-01-18 11:32:34 +01:00
Rob BygraveandGitHub 09d5163396 Merge pull request #3307 from ebean-orm/feature/bump-avaje-config-310
Bump avaje-config to version 3.10
2024-01-18 22:30:42 +13:00
Rob Bygrave a6a38b9a92 Bump avaje-config to version 3.10 2024-01-18 22:30:09 +13:00
Rob BygraveandGitHub bd4521b240 Merge pull request #3306 from ebean-orm/feature/querybean-deprecated
Add forRemoval=true for existing Deprecated methods in query beans
2024-01-18 22:28:23 +13:00
Rob Bygrave 8a7379879b Add forRemoval=true for existing Deprecated methods in query beans 2024-01-18 20:15:57 +13:00
Rob BygraveandGitHub b78dd6f79a Merge pull request #3304 from ebean-orm/feature/3296-querybean-copy
#3296 Add copy() method to query beans
2024-01-15 22:38:30 +13:00
Rob Bygrave 4ebb5fd112 #3296 Add copy() method to query beans 2024-01-15 22:30:17 +13:00
Rob Bygrave 487368976f Tidy SimpleQueryBeanWriter internals 2024-01-15 22:03:17 +13:00
Rob Bygrave c6defceec9 Add additional test for filterMany() with fetch() 2024-01-15 21:02:47 +13:00
Rob BygraveandGitHub 8ed3b765ec Merge pull request #3299 from ebean-orm/feature/3294-warnings
#3294 Suppress compiler warnings on generated query bean `filterMany()`
2023-12-22 08:33:31 +13:00
Rob BygraveandGitHub fcbcc53e27 Merge pull request #3298 from ebean-orm/feature/add-usingConnection-dtoQuery
Add usingConnection() to DtoQuery and SqlQuery
2023-12-22 08:25:48 +13:00
Rob Bygrave b377e1a618 #3294 Suppress compiler warnings on generated query bean filterMany() 2023-12-22 08:24:54 +13:00
Rob Bygrave a0f612ed71 Add usingConnection() to DtoQuery and SqlQuery
For the case where we have a java.sql.Connection and wish
to execute a DtoQuery or SqlQuery using that connection.
2023-12-21 21:24:02 +13:00
Rob Bygrave 47e97a77a8 Version 13.25.2 2023-12-07 20:18:40 +13:00
Rob Bygrave e8d3f50bb4 Bump ebean-agent to 13.25.2 2023-12-07 19:57:55 +13:00
110 changed files with 1384 additions and 876 deletions
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-clickhouse</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-db2</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-hana</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mariadb</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mysql</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-nuodb</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-oracle</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -22,13 +22,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
@@ -47,19 +47,19 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgis-types</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlite</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlserver</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
@@ -41,7 +41,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jackson-mapper</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
@@ -60,13 +60,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-all</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</parent>
<artifactId>composites</artifactId>
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</parent>
<name>ebean api</name>
@@ -39,7 +39,7 @@
<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-config</artifactId>
<version>3.9</version>
<version>3.10</version>
</dependency>
<dependency>
@@ -3,6 +3,8 @@ package io.ebean;
import io.avaje.lang.NonNullApi;
import io.avaje.lang.Nullable;
import javax.sql.DataSource;
import java.sql.Connection;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
@@ -206,14 +208,19 @@ public interface DtoQuery<T> extends CancelableQuery {
*/
DtoQuery<T> usingTransaction(Transaction transaction);
/**
* Execute the query using the given connection.
*/
DtoQuery<T> usingConnection(Connection connection);
/**
* Ensure that the master DataSource is used if there is a read only data source
* being used (that is using a read replica database potentially with replication lag).
* <p>
* When the database is configured with a read-only DataSource via
* say {@link io.ebean.config.DatabaseConfig#setReadOnlyDataSource(DataSource)} then
* say {@link io.ebean.DatabaseBuilder#readOnlyDataSource(DataSource)} then
* by default when a query is run without an active transaction, it uses the read-only data
* source. We we use {@code usingMaster()} to instead ensure that the query is executed
* source. We use {@code usingMaster()} to instead ensure that the query is executed
* against the master data source.
*/
DtoQuery<T> usingMaster();
@@ -16,4 +16,9 @@ public interface ModifyAwareType {
*/
void setMarkedDirty(boolean markedDirty);
/**
* Return a unmodifiable version of this type.
*/
Object freeze();
}
+21 -2
View File
@@ -702,9 +702,9 @@ public interface Query<T> extends CancelableQuery {
* 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
* say {@link io.ebean.DatabaseBuilder#readOnlyDataSource(DataSource)} then
* by default when a query is run without an active transaction, it uses the read-only data
* source. We we use {@code usingMaster()} to instead ensure that the query is executed
* source. We use {@code usingMaster()} to instead ensure that the query is executed
* against the master data source.
*/
Query<T> usingMaster();
@@ -970,6 +970,25 @@ public interface Query<T> extends CancelableQuery {
@Nullable
<A> A findSingleAttribute();
/**
* Execute the query returning a single optional attribute value.
* <p>
* <h3>Example</h3>
* <pre>{@code
*
* Optional<String> maybeName =
* new QCustomer()
* .select(name)
* .id.eq(42)
* .status.eq(NEW)
* .findSingleAttributeOrEmpty();
*
* }</pre>
*
* @return an optional value for the selected property
*/
<A> Optional<A> findSingleAttributeOrEmpty();
/**
* Return true if this is countDistinct query.
*/
@@ -3,7 +3,9 @@ package io.ebean;
import io.avaje.lang.NonNullApi;
import io.avaje.lang.Nullable;
import javax.sql.DataSource;
import java.io.Serializable;
import java.sql.Connection;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
@@ -45,14 +47,19 @@ public interface SqlQuery extends Serializable, CancelableQuery {
*/
SqlQuery usingTransaction(Transaction transaction);
/**
* Execute the query using the given connection.
*/
SqlQuery usingConnection(Connection connection);
/**
* Ensure that the master DataSource is used if there is a read only data source
* being used (that is using a read replica database potentially with replication lag).
* <p>
* When the database is configured with a read-only DataSource via
* say {@link io.ebean.config.DatabaseConfig#setReadOnlyDataSource(DataSource)} then
* say {@link io.ebean.DatabaseBuilder#readOnlyDataSource(DataSource)}then
* by default when a query is run without an active transaction, it uses the read-only data
* source. We we use {@code usingMaster()} to instead ensure that the query is executed
* source. We use {@code usingMaster()} to instead ensure that the query is executed
* against the master data source.
*/
SqlQuery usingMaster();
@@ -2,6 +2,7 @@ package io.ebean;
import io.ebean.annotation.DocStoreMode;
import io.ebean.annotation.PersistBatch;
import io.ebean.bean.FrozenBeans;
import io.ebean.config.DatabaseConfig;
import io.ebean.config.DocStoreConfig;
@@ -54,6 +55,24 @@ public interface Transaction extends AutoCloseable {
*/
int SERIALIZABLE = java.sql.Connection.TRANSACTION_SERIALIZABLE;
/**
* Experimental Feature - Freeze the beans in the persistence context and detach them.
*/
@Deprecated(since = "Experimental Feature")
default FrozenBeans freezeAndDetach() {
throw new UnsupportedOperationException();
}
/**
* Experimental Feature - Attach frozen beans to the persistence context so that they can be
* used with ORM queries (with the persistence context acting like a cache).
*/
@Deprecated(since = "Experimental Feature")
default void attach(FrozenBeans frozenBeans) {
throw new UnsupportedOperationException();
}
/**
* Register a TransactionCallback with this transaction.
*/
@@ -35,6 +35,11 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
ALL
}
/**
* Return a unmodifiable collection of the underlying entities.
*/
Object freeze();
/**
* Set the disableLazyLoad state.
*/
@@ -552,4 +552,16 @@ public interface EntityBeanIntercept extends Serializable {
* Update the 'next' mutable info returning the content that was obtained via dirty detection.
*/
String mutableNext(int propertyIndex);
/**
* Set that lazy loading if invoked throws a PersistenceException.
*/
void errorOnLazyLoad(boolean lazyLoadAsError);
/**
* Freeze the intercept so that it is readOnly.
* Lazy loading and mutation of the bean is not allowed.
*/
void freeze();
}
@@ -0,0 +1,9 @@
package io.ebean.bean;
import java.io.Serializable;
/**
* Holds entity beans that are frozen.
*/
public interface FrozenBeans extends Serializable {
}
@@ -0,0 +1,343 @@
package io.ebean.bean;
import io.ebean.DB;
import io.ebean.Database;
import jakarta.persistence.EntityNotFoundException;
import jakarta.persistence.PersistenceException;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* Base EntityBeanIntercept that supports partial loaded state and lazy loading.
*/
abstract class InterceptBase implements EntityBeanIntercept {
/**
* Flag for loaded property.
*/
static final byte FLAG_LOADED_PROP = 1;
/**
* The actual entity bean that 'owns' this intercept.
*/
protected final EntityBean owner;
protected final byte[] flags;
protected boolean readOnly;
protected boolean disableLazyLoad;
protected boolean errorOnLazyLoad;
private final ReentrantLock lock = new ReentrantLock();
private String ebeanServerName;
private transient BeanLoader beanLoader;
private transient PersistenceContext persistenceContext;
/**
* Flag set when lazy loading failed due to the underlying bean being deleted in the DB.
*/
protected boolean lazyLoadFailure;
protected boolean fullyLoadedBean;
protected int lazyLoadProperty = -1;
protected Object ownerId;
/**
* Create with a given entity.
*/
InterceptBase(Object ownerBean) {
this.owner = (EntityBean) ownerBean;
this.flags = new byte[owner._ebean_getPropertyNames().length];
}
/**
* EXPERIMENTAL - Constructor only for use by serialization frameworks.
*/
InterceptBase() {
this.owner = null;
this.flags = null;
}
public void freeze() {
this.errorOnLazyLoad = true;
this.readOnly = true;
this.beanLoader = null;
this.persistenceContext = null;
}
@Override
public final EntityBean owner() {
return owner;
}
@Override
public final Object ownerId() {
return ownerId;
}
@Override
public final void setOwnerId(Object ownerId) {
this.ownerId = ownerId;
}
@Override
public final void setBeanLoader(BeanLoader beanLoader) {
this.beanLoader = beanLoader;
this.ebeanServerName = beanLoader.name();
}
@Override
public final void setBeanLoader(BeanLoader beanLoader, PersistenceContext ctx) {
this.beanLoader = beanLoader;
this.persistenceContext = ctx;
this.ebeanServerName = beanLoader.name();
}
@Override
public final PersistenceContext persistenceContext() {
return persistenceContext;
}
@Override
public final void setPersistenceContext(PersistenceContext persistenceContext) {
this.persistenceContext = persistenceContext;
}
@Override
public final boolean isFullyLoadedBean() {
return fullyLoadedBean;
}
@Override
public final void setFullyLoadedBean(boolean fullyLoadedBean) {
this.fullyLoadedBean = fullyLoadedBean;
}
@Override
public final boolean isPartial() {
for (byte flag : flags) {
if ((flag & FLAG_LOADED_PROP) == 0) {
return true;
}
}
return false;
}
@Override
public final boolean hasIdOnly(int idIndex) {
for (int i = 0; i < flags.length; i++) {
if (i == idIndex) {
if ((flags[i] & FLAG_LOADED_PROP) == 0) return false;
} else if ((flags[i] & FLAG_LOADED_PROP) != 0) {
return false;
}
}
return true;
}
@Override
public final boolean isReadOnly() {
return readOnly;
}
@Override
public final void setReadOnly(boolean readOnly) {
this.readOnly = readOnly;
}
@Override
public final void setLazyLoadFailure(Object ownerId) {
this.lazyLoadFailure = true;
this.ownerId = ownerId;
}
@Override
public final boolean isLazyLoadFailure() {
return lazyLoadFailure;
}
@Override
public final boolean isDisableLazyLoad() {
return disableLazyLoad;
}
@Override
public final void setDisableLazyLoad(boolean disableLazyLoad) {
this.disableLazyLoad = disableLazyLoad;
}
@Override
public final void errorOnLazyLoad(boolean errorOnLazyLoad) {
this.errorOnLazyLoad = errorOnLazyLoad;
}
@Override
public final void setEmbeddedLoaded(Object embeddedBean) {
if (embeddedBean instanceof EntityBean) {
((EntityBean) embeddedBean)._ebean_getIntercept().setLoaded();
}
}
@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 String property(int propertyIndex) {
if (propertyIndex == -1) {
return null;
}
return owner._ebean_getPropertyName(propertyIndex);
}
@Override
public final int propertyLength() {
return flags.length;
}
@Override
public final void setPropertyLoaded(String propertyName, boolean loaded) {
final int position = findProperty(propertyName);
if (position == -1) {
throw new IllegalArgumentException("Property " + propertyName + " not found");
}
if (loaded) {
flags[position] |= FLAG_LOADED_PROP;
} else {
flags[position] &= ~FLAG_LOADED_PROP;
}
}
@Override
public final void setPropertyUnloaded(int propertyIndex) {
flags[propertyIndex] &= ~FLAG_LOADED_PROP;
}
@Override
public final void initialisedMany(int propertyIndex) {
flags[propertyIndex] |= FLAG_LOADED_PROP;
}
@Override
public final void setLoadedProperty(int propertyIndex) {
flags[propertyIndex] |= FLAG_LOADED_PROP;
}
@Override
public final void setLoadedPropertyAll() {
for (int i = 0; i < flags.length; i++) {
flags[i] |= FLAG_LOADED_PROP;
}
}
@Override
public final boolean isLoadedProperty(int propertyIndex) {
return (flags[propertyIndex] & FLAG_LOADED_PROP) != 0;
}
@Override
public final Set<String> loadedPropertyNames() {
if (fullyLoadedBean) {
return null;
}
final Set<String> props = new LinkedHashSet<>();
for (int i = 0; i < flags.length; i++) {
if ((flags[i] & FLAG_LOADED_PROP) != 0) {
props.add(property(i));
}
}
return props;
}
@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;
}
@Override
public final boolean[] loaded() {
final boolean[] ret = new boolean[flags.length];
for (int i = 0; i < ret.length; i++) {
ret[i] = (flags[i] & FLAG_LOADED_PROP) != 0;
}
return ret;
}
@Override
public final int lazyLoadPropertyIndex() {
return lazyLoadProperty;
}
@Override
public final String lazyLoadProperty() {
return property(lazyLoadProperty);
}
@Override
public final void loadBean(int loadProperty) {
lock.lock();
try {
if (errorOnLazyLoad) {
throw new PersistenceException("Lazy loading not allowed on this bean");
}
if (beanLoader == null) {
final Database database = DB.byName(ebeanServerName);
if (database == null) {
throw new PersistenceException(ebeanServerName == null ? "No registered default server" : "Database [" + ebeanServerName + "] is not registered");
}
// For stand alone reference bean or after deserialisation lazy load
// using the ebeanServer. Synchronise only on the bean.
loadBeanInternal(loadProperty, database.pluginApi().beanLoader());
return;
}
} finally {
lock.unlock();
}
final Lock lock = beanLoader.lock();
try {
// Lazy loading using LoadBeanContext which supports batch loading
// Synchronise on the beanLoader (a 'node' of the LoadBeanContext 'tree')
loadBeanInternal(loadProperty, beanLoader);
} finally {
lock.unlock();
}
}
@Override
public final void loadBeanInternal(int loadProperty, BeanLoader loader) {
if ((flags[loadProperty] & FLAG_LOADED_PROP) != 0) {
// race condition where multiple threads calling preGetter concurrently
return;
}
if (lazyLoadFailure) {
// failed when batch lazy loaded by another bean in the batch
throw new EntityNotFoundException("(Lazy) loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted. BeanLoader: " + beanLoader);
}
if (lazyLoadProperty == -1) {
lazyLoadProperty = loadProperty;
loader.loadBean(this);
if (lazyLoadFailure) {
// failed when lazy loading this bean
throw new EntityNotFoundException("Lazy loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted. BeanLoader: " + beanLoader);
}
// bean should be loaded and intercepting now. setLoaded() has
// been called by the lazy loading mechanism
}
}
}
@@ -10,55 +10,110 @@ import java.util.Set;
* EntityBeanIntercept optimised for read only use.
* <p>
* For the read only use this intercept doesn't need to hold any state that is normally
* required for updates such as per property changed, loaded, dirty state, original values
* required for updates such as per property changed, dirty state, original values
* bean state etc.
*/
public class InterceptReadOnly implements EntityBeanIntercept {
private final EntityBean owner;
public final class InterceptReadOnly extends InterceptBase {
/**
* Create with a given entity.
*/
public InterceptReadOnly(Object ownerBean) {
this.owner = (EntityBean) ownerBean;
super(ownerBean);
}
@Override
public String toString() {
return "InterceptReadOnly{" + owner + '}';
public void preGetId() {
// do nothing
}
@Override
public EntityBean owner() {
return owner;
public void preGetter(int propertyIndex) {
if (disableLazyLoad) {
return;
}
if (!isLoadedProperty(propertyIndex)) {
loadBean(propertyIndex);
}
}
private void preSetter(int propertyIndex) {
if (readOnly) {
throw new IllegalStateException("This bean is readOnly");
}
setLoadedProperty(propertyIndex);
}
@Override
public PersistenceContext persistenceContext() {
return null;
public void preSetterMany(boolean interceptField, int propertyIndex, Object oldValue, Object newValue) {
preSetter(propertyIndex);
}
@Override
public void setPersistenceContext(PersistenceContext persistenceContext) {
public void preSetter(boolean intercept, int propertyIndex, Object oldValue, Object newValue) {
preSetter(propertyIndex);
}
@Override
public void preSetter(boolean intercept, int propertyIndex, boolean oldValue, boolean newValue) {
preSetter(propertyIndex);
}
@Override
public void preSetter(boolean intercept, int propertyIndex, int oldValue, int newValue) {
preSetter(propertyIndex);
}
@Override
public void preSetter(boolean intercept, int propertyIndex, long oldValue, long newValue) {
preSetter(propertyIndex);
}
@Override
public void preSetter(boolean intercept, int propertyIndex, double oldValue, double newValue) {
preSetter(propertyIndex);
}
@Override
public void preSetter(boolean intercept, int propertyIndex, float oldValue, float newValue) {
preSetter(propertyIndex);
}
@Override
public void preSetter(boolean intercept, int propertyIndex, short oldValue, short newValue) {
preSetter(propertyIndex);
}
@Override
public void preSetter(boolean intercept, int propertyIndex, char oldValue, char newValue) {
preSetter(propertyIndex);
}
@Override
public void preSetter(boolean intercept, int propertyIndex, byte oldValue, byte newValue) {
preSetter(propertyIndex);
}
@Override
public void preSetter(boolean intercept, int propertyIndex, char[] oldValue, char[] newValue) {
preSetter(propertyIndex);
}
@Override
public void preSetter(boolean intercept, int propertyIndex, byte[] oldValue, byte[] newValue) {
preSetter(propertyIndex);
}
// ------------------------------------------------------------------------------------
// The following method have "Do Nothing" behaviour as not interested in mutation state
// ------------------------------------------------------------------------------------
@Override
public void setNodeUsageCollector(NodeUsageCollector usageCollector) {
}
@Override
public Object ownerId() {
return null;
}
@Override
public void setOwnerId(Object ownerId) {
}
@Override
public Object embeddedOwner() {
return null;
@@ -84,31 +139,6 @@ public class InterceptReadOnly implements EntityBeanIntercept {
}
@Override
public void setBeanLoader(BeanLoader beanLoader, PersistenceContext ctx) {
}
@Override
public void setBeanLoader(BeanLoader beanLoader) {
}
@Override
public boolean isFullyLoadedBean() {
return false;
}
@Override
public void setFullyLoadedBean(boolean fullyLoadedBean) {
}
@Override
public boolean isPartial() {
return false;
}
@Override
public boolean isDirty() {
return false;
@@ -134,11 +164,6 @@ public class InterceptReadOnly implements EntityBeanIntercept {
return false;
}
@Override
public boolean hasIdOnly(int idIndex) {
return false;
}
@Override
public boolean isReference() {
return false;
@@ -159,16 +184,6 @@ public class InterceptReadOnly implements EntityBeanIntercept {
return false;
}
@Override
public boolean isReadOnly() {
return true;
}
@Override
public void setReadOnly(boolean readOnly) {
}
@Override
public void setForceUpdate(boolean forceUpdate) {
@@ -199,31 +214,6 @@ public class InterceptReadOnly implements EntityBeanIntercept {
}
@Override
public void setLazyLoadFailure(Object ownerId) {
}
@Override
public boolean isLazyLoadFailure() {
return false;
}
@Override
public boolean isDisableLazyLoad() {
return false;
}
@Override
public void setDisableLazyLoad(boolean disableLazyLoad) {
}
@Override
public void setEmbeddedLoaded(Object embeddedBean) {
}
@Override
public boolean isEmbeddedNewOrDirty(Object embeddedBean) {
return false;
@@ -234,45 +224,6 @@ public class InterceptReadOnly implements EntityBeanIntercept {
return null;
}
@Override
public int findProperty(String propertyName) {
return 0;
}
@Override
public String property(int propertyIndex) {
return null;
}
@Override
public int propertyLength() {
return 0;
}
@Override
public void setPropertyLoaded(String propertyName, boolean loaded) {
}
@Override
public void setPropertyUnloaded(int propertyIndex) {
}
@Override
public void setLoadedProperty(int propertyIndex) {
}
@Override
public void setLoadedPropertyAll() {
}
@Override
public boolean isLoadedProperty(int propertyIndex) {
return false;
}
@Override
public boolean isChangedProperty(int propertyIndex) {
@@ -319,11 +270,6 @@ public class InterceptReadOnly implements EntityBeanIntercept {
}
@Override
public Set<String> loadedPropertyNames() {
return Collections.emptySet();
}
@Override
public boolean[] dirtyProperties() {
return new boolean[0];
@@ -369,61 +315,11 @@ public class InterceptReadOnly implements EntityBeanIntercept {
}
@Override
public StringBuilder loadedPropertyKey() {
return null;
}
@Override
public boolean[] loaded() {
return new boolean[0];
}
@Override
public int lazyLoadPropertyIndex() {
return 0;
}
@Override
public String lazyLoadProperty() {
return null;
}
@Override
public void loadBean(int loadProperty) {
}
@Override
public void loadBeanInternal(int loadProperty, BeanLoader loader) {
}
@Override
public void initialisedMany(int propertyIndex) {
}
@Override
public void preGetterCallback(int propertyIndex) {
}
@Override
public void preGetId() {
}
@Override
public void preGetter(int propertyIndex) {
}
@Override
public void preSetterMany(boolean interceptField, int propertyIndex, Object oldValue, Object newValue) {
}
@Override
public void setChangedPropertyValue(int propertyIndex, boolean setDirtyState, Object origValue) {
@@ -434,61 +330,6 @@ public class InterceptReadOnly implements EntityBeanIntercept {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, Object oldValue, Object newValue) {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, boolean oldValue, boolean newValue) {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, int oldValue, int newValue) {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, long oldValue, long newValue) {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, double oldValue, double newValue) {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, float oldValue, float newValue) {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, short oldValue, short newValue) {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, char oldValue, char newValue) {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, byte oldValue, byte newValue) {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, char[] oldValue, char[] newValue) {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, byte[] oldValue, byte[] newValue) {
}
@Override
public void setOldValue(int propertyIndex, Object oldValue) {
@@ -1,11 +1,7 @@
package io.ebean.bean;
import io.ebean.DB;
import io.ebean.Database;
import io.ebean.ValuePair;
import jakarta.persistence.EntityNotFoundException;
import jakarta.persistence.PersistenceException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@@ -13,8 +9,6 @@ import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URL;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* This is the object added to every entity bean using byte code enhancement.
@@ -22,7 +16,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 implements EntityBeanIntercept {
public final class InterceptReadWrite extends InterceptBase {
private static final long serialVersionUID = -3664031775464862649L;
@@ -30,10 +24,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
private static final int STATE_REFERENCE = 1;
private static final int STATE_LOADED = 2;
/**
* Used when a bean is partially loaded.
*/
private static final byte FLAG_LOADED_PROP = 1;
private static final byte FLAG_CHANGED_PROP = 2;
private static final byte FLAG_CHANGEDLOADED_PROP = 3;
/**
@@ -47,43 +37,21 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
*/
private static final byte FLAG_MUTABLE_HASH_SET = 16;
private final ReentrantLock lock = new ReentrantLock();
private transient NodeUsageCollector nodeUsageCollector;
private transient PersistenceContext persistenceContext;
private transient BeanLoader beanLoader;
private transient PreGetterCallback preGetterCallback;
private String ebeanServerName;
private boolean deletedFromCollection;
/**
* The actual entity bean that 'owns' this intercept.
*/
private final EntityBean owner;
private EntityBean embeddedOwner;
private int embeddedOwnerIndex;
/**
* One of NEW, REF, UPD.
* One of NEW, REF, LOADED.
*/
private int state;
private boolean deletedFromCollection;
private boolean forceUpdate;
private boolean readOnly;
private boolean dirty;
/**
* Flag set to disable lazy loading.
*/
private boolean disableLazyLoad;
/**
* 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;
private Exception[] loadErrors;
private int lazyLoadProperty = -1;
private Object ownerId;
private int sortOrder;
/**
@@ -101,49 +69,14 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
* Create with a given entity.
*/
public InterceptReadWrite(Object ownerBean) {
this.owner = (EntityBean) ownerBean;
this.flags = new byte[owner._ebean_getPropertyNames().length];
super(ownerBean);
}
/**
* EXPERIMENTAL - Constructor only for use by serialization frameworks.
*/
public InterceptReadWrite() {
this.owner = null;
this.flags = null;
}
@Override
public String toString() {
return "InterceptReadWrite@" + hashCode() + "{state=" + state +
(dirty ? " dirty;" : "") +
(forceUpdate ? " forceUpdate;" : "") +
(readOnly ? " readOnly;" : "") +
(disableLazyLoad ? " disableLazyLoad;" : "") +
(lazyLoadFailure ? " lazyLoadFailure;" : "") +
(fullyLoadedBean ? " fullyLoadedBean;" : "") +
(loadedFromCache ? " loadedFromCache;" : "") +
", pc=" + System.identityHashCode(persistenceContext) +
", flags=" + Arrays.toString(flags) +
(lazyLoadProperty > -1 ? (", lazyLoadProperty=" + lazyLoadProperty) : "") +
", loader=" + beanLoader +
(ownerId != null ? (", ownerId=" + ownerId) : "") +
'}';
}
@Override
public EntityBean owner() {
return owner;
}
@Override
public PersistenceContext persistenceContext() {
return persistenceContext;
}
@Override
public void setPersistenceContext(PersistenceContext persistenceContext) {
this.persistenceContext = persistenceContext;
super();
}
@Override
@@ -151,16 +84,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
this.nodeUsageCollector = usageCollector;
}
@Override
public Object ownerId() {
return ownerId;
}
@Override
public void setOwnerId(Object ownerId) {
this.ownerId = ownerId;
}
@Override
public Object embeddedOwner() {
return embeddedOwner;
@@ -187,39 +110,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
this.embeddedOwnerIndex = embeddedOwnerIndex;
}
@Override
public void setBeanLoader(BeanLoader beanLoader, PersistenceContext ctx) {
this.beanLoader = beanLoader;
this.persistenceContext = ctx;
this.ebeanServerName = beanLoader.name();
}
@Override
public void setBeanLoader(BeanLoader beanLoader) {
this.beanLoader = beanLoader;
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) {
if ((flag & FLAG_LOADED_PROP) == 0) {
return true;
}
}
return false;
}
@Override
public boolean isDirty() {
if (dirty) {
@@ -257,18 +147,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
return isNew() || isDirty();
}
@Override
public boolean hasIdOnly(int idIndex) {
for (int i = 0; i < flags.length; i++) {
if (i == idIndex) {
if ((flags[i] & FLAG_LOADED_PROP) == 0) return false;
} else if ((flags[i] & FLAG_LOADED_PROP) != 0) {
return false;
}
}
return true;
}
@Override
public boolean isReference() {
return state == STATE_REFERENCE;
@@ -298,16 +176,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
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;
@@ -356,34 +224,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
this.lazyLoadProperty = -1;
}
@Override
public void setLazyLoadFailure(Object ownerId) {
this.lazyLoadFailure = true;
this.ownerId = ownerId;
}
@Override
public boolean isLazyLoadFailure() {
return lazyLoadFailure;
}
@Override
public boolean isDisableLazyLoad() {
return disableLazyLoad;
}
@Override
public void setDisableLazyLoad(boolean disableLazyLoad) {
this.disableLazyLoad = disableLazyLoad;
}
@Override
public void setEmbeddedLoaded(Object embeddedBean) {
if (embeddedBean instanceof EntityBean) {
((EntityBean) embeddedBean)._ebean_getIntercept().setLoaded();
}
}
@Override
public boolean isEmbeddedNewOrDirty(Object embeddedBean) {
if (embeddedBean == null) {
@@ -411,65 +251,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
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;
}
@Override
public void setPropertyLoaded(String propertyName, boolean loaded) {
final int position = findProperty(propertyName);
if (position == -1) {
throw new IllegalArgumentException("Property " + propertyName + " not found");
}
if (loaded) {
flags[position] |= FLAG_LOADED_PROP;
} else {
flags[position] &= ~FLAG_LOADED_PROP;
}
}
@Override
public void setPropertyUnloaded(int propertyIndex) {
flags[propertyIndex] &= ~FLAG_LOADED_PROP;
}
@Override
public void setLoadedProperty(int propertyIndex) {
flags[propertyIndex] |= FLAG_LOADED_PROP;
}
@Override
public void setLoadedPropertyAll() {
for (int i = 0; i < flags.length; i++) {
flags[i] |= FLAG_LOADED_PROP;
}
}
@Override
public boolean isLoadedProperty(int propertyIndex) {
return (flags[propertyIndex] & FLAG_LOADED_PROP) != 0;
}
@Override
public boolean isChangedProperty(int propertyIndex) {
return (flags[propertyIndex] & FLAG_CHANGED_PROP) != 0;
@@ -530,20 +311,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
setDirty(true);
}
@Override
public Set<String> loadedPropertyNames() {
if (fullyLoadedBean) {
return null;
}
final Set<String> props = new LinkedHashSet<>();
for (int i = 0; i < flags.length; i++) {
if ((flags[i] & FLAG_LOADED_PROP) != 0) {
props.add(property(i));
}
}
return props;
}
@Override
public boolean[] dirtyProperties() {
final int len = propertyLength();
@@ -668,86 +435,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
}
}
@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];
for (int i = 0; i < ret.length; i++) {
ret[i] = (flags[i] & FLAG_LOADED_PROP) != 0;
}
return ret;
}
@Override
public int lazyLoadPropertyIndex() {
return lazyLoadProperty;
}
@Override
public String lazyLoadProperty() {
return property(lazyLoadProperty);
}
@Override
public void loadBean(int loadProperty) {
lock.lock();
try {
if (beanLoader == null) {
final Database database = DB.byName(ebeanServerName);
if (database == null) {
throw new PersistenceException(ebeanServerName == null ? "No registered default server" : "Database [" + ebeanServerName + "] is not registered");
}
// For stand alone reference bean or after deserialisation lazy load
// using the ebeanServer. Synchronise only on the bean.
loadBeanInternal(loadProperty, database.pluginApi().beanLoader());
return;
}
} finally {
lock.unlock();
}
final Lock lock = beanLoader.lock();
try {
// Lazy loading using LoadBeanContext which supports batch loading
// Synchronise on the beanLoader (a 'node' of the LoadBeanContext 'tree')
loadBeanInternal(loadProperty, beanLoader);
} finally {
lock.unlock();
}
}
@Override
public void loadBeanInternal(int loadProperty, BeanLoader loader) {
if ((flags[loadProperty] & FLAG_LOADED_PROP) != 0) {
// race condition where multiple threads calling preGetter concurrently
return;
}
if (lazyLoadFailure) {
// failed when batch lazy loaded by another bean in the batch
throw new EntityNotFoundException("(Lazy) loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted. BeanLoader: " + beanLoader);
}
if (lazyLoadProperty == -1) {
lazyLoadProperty = loadProperty;
loader.loadBean(this);
if (lazyLoadFailure) {
// failed when lazy loading this bean
throw new EntityNotFoundException("Lazy loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted. BeanLoader: " + beanLoader);
}
// bean should be loaded and intercepting now. setLoaded() has
// been called by the lazy loading mechanism
}
}
/**
* Helper method to check if two objects are equal.
*/
@@ -808,11 +495,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
}
}
@Override
public void initialisedMany(int propertyIndex) {
flags[propertyIndex] |= FLAG_LOADED_PROP;
}
@Override
public void preGetterCallback(int propertyIndex) {
PreGetterCallback preGetterCallback = this.preGetterCallback;
@@ -1076,4 +758,16 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
final MutableValueNext next = mutableNext[propertyIndex];
return next != null ? next.content() : null;
}
@Override
public void freeze() {
super.freeze();
// not allowed to be used for updates
this.dirty = false;
this.forceUpdate = false;
this.deletedFromCollection = false;
this.origValues = null;
this.nodeUsageCollector = null;
this.embeddedOwner = null;
}
}
@@ -44,6 +44,12 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
builder.addCollection(list);
}
@Override
public Object freeze() {
// null -> illegal to access reference collection
return list == null ? null : Collections.unmodifiableList(list);
}
@Override
public void reset(EntityBean ownerBean, String propertyName) {
this.ownerBean = ownerBean;
@@ -37,6 +37,12 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
super(ebeanServer, ownerBean, propertyName);
}
@Override
public Object freeze() {
// null -> illegal to access reference collection
return map == null ? null : Collections.unmodifiableMap(map);
}
@Override
public void toString(ToStringBuilder builder) {
if (map == null || map.isEmpty()) {
@@ -3,10 +3,7 @@ package io.ebean.common;
import io.ebean.bean.*;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.*;
/**
* Set capable of lazy loading and modification aware.
@@ -43,6 +40,12 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
builder.addCollection(set);
}
@Override
public Object freeze() {
// null -> illegal to access reference collection
return set == null ? null : Collections.unmodifiableSet(set);
}
@Override
public void reset(EntityBean ownerBean, String propertyName) {
this.ownerBean = ownerBean;
+26 -26
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</parent>
<name>ebean bom</name>
@@ -89,25 +89,25 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
@@ -125,13 +125,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jackson-mapper</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-ddl-generator</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
@@ -155,37 +155,37 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>querybean-generator</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>kotlin-querybean-generator</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-redis</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-spring-txn</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<!-- platforms -->
@@ -193,79 +193,79 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-clickhouse</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-db2</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-h2</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-hana</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-mariadb</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-mysql</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-nuodb</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-oracle</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgres</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgis</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgis-types</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-sqlite</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-sqlserver</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</parent>
<artifactId>ebean-core-type</artifactId>
@@ -16,7 +16,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
+6 -6
View File
@@ -3,7 +3,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</parent>
<artifactId>ebean-core</artifactId>
@@ -22,7 +22,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
@@ -46,7 +46,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
@@ -159,21 +159,21 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlserver</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>test</scope>
</dependency>
@@ -1,8 +1,11 @@
package io.ebeaninternal.api;
import io.ebean.bean.FrozenBeans;
import io.ebean.bean.EntityBean;
import io.ebean.bean.PersistenceContext;
import java.util.List;
import java.util.Map;
/**
* SPI extension to PersistenceContext.
@@ -14,4 +17,14 @@ public interface SpiPersistenceContext extends PersistenceContext {
*/
List<Object> dirtyBeans(SpiBeanTypeManager manager);
/**
* Return all the entities from this persistence context.
*/
Map<Class<?>, List<EntityBean>> detach();
/**
* Attach all the cached entities into this persistence context.
*/
void attach(FrozenBeans cachedBeans);
}
@@ -3,6 +3,7 @@ package io.ebeaninternal.api;
import io.ebean.ProfileLocation;
import io.ebean.TransactionCallback;
import io.ebean.annotation.DocStoreMode;
import io.ebean.bean.FrozenBeans;
import io.ebean.event.changelog.BeanChange;
import io.ebean.event.changelog.ChangeSet;
import io.ebeaninternal.server.core.PersistDeferredRelationship;
@@ -223,6 +224,16 @@ public abstract class SpiTransactionProxy implements SpiTransaction {
transaction.register(callback);
}
@Override
public FrozenBeans freezeAndDetach() {
return transaction.freezeAndDetach();
}
@Override
public void attach(FrozenBeans frozenBeans) {
transaction.attach(frozenBeans);
}
@Override
public boolean isReadOnly() {
return transaction.isReadOnly();
@@ -23,4 +23,8 @@ public final class ModifyAwareFlag implements ModifyAwareType, Serializable {
this.markedDirty = markedDirty;
}
@Override
public Object freeze() {
throw new UnsupportedOperationException();
}
}
@@ -3,12 +3,7 @@ package io.ebeaninternal.json;
import io.ebean.ModifyAwareType;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Objects;
import java.util.*;
/**
* Modify aware wrapper of a list.
@@ -52,6 +47,11 @@ public final class ModifyAwareList<E> implements List<E>, ModifyAwareType, Seria
return list.hashCode();
}
@Override
public List<E> freeze() {
return Collections.unmodifiableList(list);
}
@Override
public boolean isMarkedDirty() {
return owner.isMarkedDirty();
@@ -3,11 +3,7 @@ package io.ebeaninternal.json;
import io.ebean.ModifyAwareType;
import java.io.Serializable;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.*;
/**
* Map that is wraps an underlying map for the purpose of detecting changes.
@@ -51,6 +47,11 @@ public final class ModifyAwareMap<K, V> implements Map<K, V>, ModifyAwareType, S
return map.hashCode();
}
@Override
public Map<K, V> freeze() {
return Collections.unmodifiableMap(map);
}
@Override
public boolean isMarkedDirty() {
return owner.isMarkedDirty();
@@ -3,10 +3,7 @@ package io.ebeaninternal.json;
import io.ebean.ModifyAwareType;
import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;
import java.util.Objects;
import java.util.Set;
import java.util.*;
/**
* Wraps a Set for the purposes of detecting modifications.
@@ -33,6 +30,11 @@ public final class ModifyAwareSet<E> implements Set<E>, ModifyAwareType, Seriali
this.set = underlying;
}
@Override
public Set<E> freeze() {
return Collections.unmodifiableSet(set);
}
@Override
public boolean isMarkedDirty() {
return owner.isMarkedDirty();
@@ -687,6 +687,16 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
}
}
public void freeze(EntityBean entityBean) {
for (BeanProperty beanProperty : propertiesMutable) {
beanProperty.freeze(entityBean);
}
for (BeanPropertyAssocMany<?> many : propertiesMany) {
many.freeze(entityBean);
}
entityBean._ebean_getIntercept().freeze();
}
public void metricPersistBatch(PersistRequest.Type type, long startNanos, int size) {
iudMetrics.addBatch(type, startNanos, size);
}
@@ -1,11 +1,9 @@
package io.ebeaninternal.server.deploy;
import com.fasterxml.jackson.core.JsonToken;
import io.ebean.ModifyAwareType;
import io.ebean.ValuePair;
import io.ebean.bean.EntityBean;
import io.ebean.bean.EntityBeanIntercept;
import io.ebean.bean.MutableValueInfo;
import io.ebean.bean.PersistenceContext;
import io.ebean.bean.*;
import io.ebean.config.EncryptKey;
import io.ebean.config.dbplatform.DbEncryptFunction;
import io.ebean.config.dbplatform.DbPlatformType;
@@ -1498,4 +1496,15 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
desc.registerColumn(dbColumn, path);
}
}
/**
* Freeze mutable types (like DbArray).
*/
public void freeze(EntityBean entityBean) {
Object value = getValue(entityBean);
if (value instanceof ModifyAwareType) {
ModifyAwareType bc = (ModifyAwareType) value;
setValue(entityBean, bc.freeze());
}
}
}
@@ -1133,4 +1133,17 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
return false;
}
}
@Override
public void freeze(EntityBean entityBean) {
Object value = getValue(entityBean);
if (value instanceof BeanCollection) {
BeanCollection<?> bc = (BeanCollection<?>) value;
setValue(entityBean, bc.freeze());
if (bc.isReference()) {
// make it an error to access the collection (no lazy loading allowed)
entityBean._ebean_getIntercept().setPropertyUnloaded(propertyIndex);
}
}
}
}
@@ -305,6 +305,11 @@ final class DefaultFetchGroupQuery<T> implements SpiFetchGroupQuery<T>, SpiQuery
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
}
@Override
public <A> Optional<A> findSingleAttributeOrEmpty() {
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
}
@Override
public boolean isCountDistinct() {
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
@@ -31,7 +31,7 @@ class SqlTreeLoadBean implements SqlTreeLoad {
final boolean readId;
private final boolean readIdNormal;
private final boolean disableLazyLoad;
private final boolean readOnlyNoIntercept;
private final boolean readOnly;
private final InheritInfo inheritInfo;
final String prefix;
private final Map<String, String> pathMap;
@@ -54,7 +54,7 @@ class SqlTreeLoadBean implements SqlTreeLoad {
this.readId = node.readId;
this.readIdNormal = readId && !temporalVersions;
this.disableLazyLoad = node.disableLazyLoad;
this.readOnlyNoIntercept = disableLazyLoad && node.readOnly;
this.readOnly = node.readOnly;
this.partialObject = node.partialObject;
this.properties = node.properties;
this.pathMap = node.pathMap;
@@ -162,7 +162,7 @@ class SqlTreeLoadBean implements SqlTreeLoad {
void initBeanType() throws SQLException {
localDesc = desc;
localBean = desc.createEntityBean2(readOnlyNoIntercept);
localBean = desc.createEntityBean2(readOnly);
localIdBinder = idBinder;
}
@@ -302,7 +302,7 @@ class SqlTreeLoadBean implements SqlTreeLoad {
boolean forceNewReference = queryMode == Mode.REFRESH_BEAN;
for (STreePropertyAssocMany many : localDesc.propsMany()) {
if (many != loadingChildProperty) {
if (readOnlyNoIntercept) {
if (disableLazyLoad && readOnly) {
many.createEmptyReference(localBean);
} else {
// create a proxy for the many (deferred fetching)
@@ -9,8 +9,10 @@ import io.ebeaninternal.api.*;
import io.ebeaninternal.server.dto.DtoBeanDescriptor;
import io.ebeaninternal.server.dto.DtoMappingRequest;
import io.ebeaninternal.server.dto.DtoQueryPlan;
import io.ebeaninternal.server.transaction.ExternalJdbcTransaction;
import javax.annotation.Nullable;
import java.sql.Connection;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
@@ -86,6 +88,12 @@ public final class DefaultDtoQuery<T> extends AbstractQuery implements SpiDtoQue
return this;
}
@Override
public DtoQuery<T> usingConnection(Connection connection) {
this.transaction = new ExternalJdbcTransaction(connection);
return this;
}
@Override
public DtoQuery<T> usingMaster() {
this.useMaster = true;
@@ -1161,7 +1161,7 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
// add the rawSql statement - if any
if (orderByIsEmpty()) {
if (rawSql != null && rawSql.getSql() != null) {
order(rawSql.getSql().getOrderBy());
orderBy(rawSql.getSql().getOrderBy());
}
}
if (checkPagingOrderBy()) {
@@ -1517,7 +1517,6 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
}
@Override
@SuppressWarnings("unchecked")
public final <A> List<A> findSingleAttributeList() {
return server.findSingleAttributeList(this);
}
@@ -1533,6 +1532,11 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
return !list.isEmpty() ? list.get(0) : null;
}
@Override
public final <A> Optional<A> findSingleAttributeOrEmpty() {
return Optional.ofNullable(findSingleAttribute());
}
@Override
public final T findOne() {
return server.findOne(this);
@@ -7,7 +7,9 @@ import io.ebeaninternal.api.BindParams;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.SpiSqlQuery;
import io.ebeaninternal.api.SpiTransaction;
import io.ebeaninternal.server.transaction.ExternalJdbcTransaction;
import java.sql.Connection;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
@@ -50,6 +52,12 @@ public final class DefaultRelationalQuery extends AbstractQuery implements SpiSq
return this;
}
@Override
public SqlQuery usingConnection(Connection connection) {
this.transaction = new ExternalJdbcTransaction(connection);
return this;
}
@Override
public SqlQuery usingMaster() {
this.useMaster = true;
@@ -0,0 +1,23 @@
package io.ebeaninternal.server.transaction;
import io.ebean.bean.FrozenBeans;
import io.ebean.bean.EntityBean;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
final class DFrozenBeans implements FrozenBeans {
private static final long serialVersionUID = 1L;
private final Map<Class<?>, Map<Object, EntityBean>> beans;
DFrozenBeans(Map<Class<?>, Map<Object, EntityBean>> beans) {
this.beans = Collections.unmodifiableMap(beans);
}
Set<Map.Entry<Class<?>, Map<Object, EntityBean>>> entries() {
return beans.entrySet();
}
}
@@ -1,5 +1,6 @@
package io.ebeaninternal.server.transaction;
import io.ebean.bean.FrozenBeans;
import io.ebean.bean.EntityBean;
import io.ebeaninternal.api.SpiBeanType;
import io.ebeaninternal.api.SpiBeanTypeManager;
@@ -44,6 +45,33 @@ public final class DefaultPersistenceContext implements SpiPersistenceContext {
public DefaultPersistenceContext() {
}
public void attach(FrozenBeans other) {
lock.lock();
try {
DFrozenBeans otherContext = (DFrozenBeans) other;
for (Map.Entry<Class<?>, Map<Object, EntityBean>> entry : otherContext.entries()) {
classContext(entry.getKey()).attach(entry.getValue());
}
} finally {
lock.unlock();
}
}
@Override
public Map<Class<?>, List<EntityBean>> detach() {
lock.lock();
try {
expungeStaleEntries();
Map<Class<?>, List<EntityBean>> result = new LinkedHashMap<>();
for (Map.Entry<Class<?>, ClassContext> entry : typeCache.entrySet()) {
result.put(entry.getKey(), entry.getValue().beans());
}
return result;
} finally {
lock.unlock();
}
}
@Override
public void beginIterate() {
lock.lock();
@@ -247,6 +275,23 @@ public final class DefaultPersistenceContext implements SpiPersistenceContext {
return "size:" + map.size() + " (" + weakCount + " weak)";
}
List<EntityBean> beans() {
List<EntityBean> beans = new ArrayList<>(map.size());
for (Object value : map.values()) {
if (value instanceof BeanRef) {
value = ((BeanRef) value).get();
}
if (value != null) {
beans.add((EntityBean) value);
}
}
return beans;
}
void attach(Map<Object, EntityBean> value) {
map.putAll(value);
}
private Object get(Object id) {
Object ret = map.get(id);
if (ret instanceof BeanRef) {
@@ -3,6 +3,7 @@ package io.ebeaninternal.server.transaction;
import io.ebean.ProfileLocation;
import io.ebean.TransactionCallback;
import io.ebean.annotation.DocStoreMode;
import io.ebean.bean.FrozenBeans;
import io.ebean.config.DatabaseConfig;
import io.ebean.event.changelog.BeanChange;
import io.ebean.event.changelog.ChangeSet;
@@ -130,6 +131,16 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
}
}
@Override
public FrozenBeans freezeAndDetach() {
return manager.freezeAndDetach(persistenceContext);
}
@Override
public void attach(FrozenBeans frozenBeans) {
persistenceContext.attach(frozenBeans);
}
@Override
public final void setLabel(String label) {
this.label = label;
@@ -6,6 +6,8 @@ import io.ebean.ProfileLocation;
import io.ebean.TxScope;
import io.ebean.annotation.PersistBatch;
import io.ebean.annotation.TxType;
import io.ebean.bean.FrozenBeans;
import io.ebean.bean.EntityBean;
import io.ebean.cache.ServerCacheNotification;
import io.ebean.cache.ServerCacheNotify;
import io.ebean.config.CurrentTenantProvider;
@@ -22,6 +24,7 @@ import io.ebeaninternal.api.*;
import io.ebeaninternal.api.TransactionEventTable.TableIUD;
import io.ebeaninternal.server.cache.CacheChangeSet;
import io.ebeaninternal.server.cluster.ClusterManager;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.BeanDescriptorManager;
import io.ebeaninternal.server.profile.TimedProfileLocation;
import io.ebeaninternal.server.profile.TimedProfileLocationRegistry;
@@ -33,7 +36,9 @@ import jakarta.persistence.PersistenceException;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -637,4 +642,21 @@ public class TransactionManager implements SpiTransactionManager {
}
}
public FrozenBeans freezeAndDetach(SpiPersistenceContext persistenceContext) {
Map<Class<?>, Map<Object, EntityBean>> allBeans = new HashMap<>();
for (Map.Entry<Class<?>, List<EntityBean>> entry : persistenceContext.detach().entrySet()) {
allBeans.put(entry.getKey(), freezeBeanMap(entry));
}
return new DFrozenBeans(allBeans);
}
private Map<Object, EntityBean> freezeBeanMap(Map.Entry<Class<?>, List<EntityBean>> entry) {
BeanDescriptor<?> descriptor = beanDescriptorManager.descriptor(entry.getKey());
Map<Object, EntityBean> beanMap = new HashMap<>();
for (EntityBean entityBean : entry.getValue()) {
descriptor.freeze(entityBean);
beanMap.put(descriptor.getId(entityBean), entityBean);
}
return beanMap;
}
}
@@ -1,6 +0,0 @@
package io.ebeaninternal.server.type;
public interface ModifyAwareType {
boolean isDirty();
}
+4 -4
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</parent>
<name>ebean ddl generation</name>
@@ -28,14 +28,14 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>provided</scope>
</dependency>
@@ -65,7 +65,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-all</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>test</scope>
</dependency>
+2 -2
View File
@@ -3,7 +3,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -14,7 +14,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>provided</scope>
</dependency>
+5 -5
View File
@@ -4,14 +4,14 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</parent>
<name>ebean postgis types</name>
<artifactId>ebean-postgis-types</artifactId>
<properties>
<postgis.jdbc.version>2021.1.0</postgis.jdbc.version>
<postgis.jdbc.version>2.5.1</postgis.jdbc.version>
</properties>
<dependencies>
@@ -19,14 +19,14 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<!-- provided scope -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>provided</scope>
</dependency>
@@ -62,7 +62,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>test</scope>
</dependency>
@@ -2,9 +2,9 @@ package io.ebean.postgis;
import io.ebean.core.type.DataBinder;
import io.ebeaninternal.server.type.GeoTypeBinder;
import net.postgis.jdbc.PGgeometryLW;
import net.postgis.jdbc.geometry.Geometry;
import org.geolatte.geom.codec.Wkt;
import org.postgis.Geometry;
import org.postgis.PGgeometryLW;
import java.sql.SQLException;
@@ -18,15 +18,15 @@ class PostgisGeoTypeBinder implements GeoTypeBinder {
@Override
public void bind(DataBinder binder, int dataType, Object data) throws SQLException {
if (data instanceof Geometry) {
binder.setObject(new PGgeometryLW((Geometry) data));
} else if (withGeolatte) {
binder.setObject(new PGgeometryLW(toWktString(data)));
}
if (data instanceof Geometry) {
binder.setObject(new PGgeometryLW((Geometry) data));
} else if (withGeolatte) {
binder.setObject(new PGgeometryLW(toWktString(data)));
}
}
private String toWktString(Object data) {
org.geolatte.geom.Geometry<?> geoLatte = (org.geolatte.geom.Geometry<?>) data;
org.geolatte.geom.Geometry<?> geoLatte = (org.geolatte.geom.Geometry<?>)data;
return Wkt.newEncoder(Wkt.Dialect.POSTGIS_EWKT_1).encode(geoLatte);
}
}
@@ -6,11 +6,11 @@ import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
import io.ebean.core.type.ScalarType;
import net.postgis.jdbc.geometry.Geometry;
import net.postgis.jdbc.geometry.GeometryBuilder;
import net.postgis.jdbc.geometry.binary.BinaryParser;
import net.postgis.jdbc.PGgeometry;
import net.postgis.jdbc.PGgeometryLW;
import org.postgis.Geometry;
import org.postgis.GeometryBuilder;
import org.postgis.PGgeometry;
import org.postgis.PGgeometryLW;
import org.postgis.binary.BinaryParser;
import org.postgresql.util.PGobject;
import java.io.DataInput;
@@ -1,7 +1,7 @@
package io.ebean.postgis;
import io.ebean.config.dbplatform.ExtraDbTypes;
import net.postgis.jdbc.geometry.LineString;
import org.postgis.LineString;
import java.sql.SQLException;
@@ -1,7 +1,7 @@
package io.ebean.postgis;
import io.ebean.config.dbplatform.ExtraDbTypes;
import net.postgis.jdbc.geometry.MultiLineString;
import org.postgis.MultiLineString;
import java.sql.SQLException;
@@ -1,7 +1,7 @@
package io.ebean.postgis;
import io.ebean.config.dbplatform.ExtraDbTypes;
import net.postgis.jdbc.geometry.MultiPoint;
import org.postgis.MultiPoint;
import java.sql.SQLException;
@@ -1,7 +1,7 @@
package io.ebean.postgis;
import io.ebean.config.dbplatform.ExtraDbTypes;
import net.postgis.jdbc.geometry.MultiPolygon;
import org.postgis.MultiPolygon;
import java.sql.SQLException;
@@ -1,7 +1,7 @@
package io.ebean.postgis;
import io.ebean.config.dbplatform.ExtraDbTypes;
import net.postgis.jdbc.geometry.Point;
import org.postgis.Point;
import java.sql.SQLException;
@@ -1,7 +1,7 @@
package io.ebean.postgis;
import io.ebean.config.dbplatform.ExtraDbTypes;
import net.postgis.jdbc.geometry.Polygon;
import org.postgis.Polygon;
import java.sql.SQLException;
@@ -8,8 +8,8 @@ import io.ebean.core.type.DocPropertyType;
import io.ebean.core.type.ScalarType;
import org.geolatte.geom.Geometry;
import org.geolatte.geom.codec.Wkt;
import net.postgis.jdbc.PGgeometry;
import net.postgis.jdbc.PGgeometryLW;
import org.postgis.PGgeometry;
import org.postgis.PGgeometryLW;
import java.io.DataInput;
import java.io.DataOutput;
@@ -61,7 +61,7 @@ abstract class ScalarTypeGeoLatteBase<T extends Geometry> implements ScalarType<
return null;
}
if (object instanceof PGgeometry) {
net.postgis.jdbc.geometry.Geometry geometry = ((PGgeometry) object).getGeometry();
org.postgis.Geometry geometry = ((PGgeometry) object).getGeometry();
return (T) Wkt.newDecoder(Wkt.Dialect.POSTGIS_EWKT_1).decode(geometry.toString());
}
throw new IllegalStateException("Received object of type " + object.getClass().getCanonicalName());
@@ -1,8 +1,8 @@
package org.example.domain;
import io.ebean.annotation.Cache;
import net.postgis.jdbc.geometry.Point;
import net.postgis.jdbc.geometry.Polygon;
import org.postgis.Point;
import org.postgis.Polygon;
import jakarta.persistence.Entity;
import jakarta.persistence.Table;
@@ -1,11 +1,11 @@
package org.example.domain;
import net.postgis.jdbc.geometry.LineString;
import net.postgis.jdbc.geometry.MultiLineString;
import net.postgis.jdbc.geometry.MultiPoint;
import net.postgis.jdbc.geometry.MultiPolygon;
import net.postgis.jdbc.geometry.Point;
import net.postgis.jdbc.geometry.Polygon;
import org.postgis.LineString;
import org.postgis.MultiLineString;
import org.postgis.MultiPoint;
import org.postgis.MultiPolygon;
import org.postgis.Point;
import org.postgis.Polygon;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
@@ -2,8 +2,8 @@ package org.example.domain;
import io.ebean.DB;
import org.junit.jupiter.api.Test;
import net.postgis.jdbc.geometry.Point;
import net.postgis.jdbc.geometry.Polygon;
import org.postgis.Point;
import org.postgis.Polygon;
import java.sql.SQLException;
@@ -2,12 +2,12 @@ package org.example.domain;
import io.ebean.DB;
import org.junit.jupiter.api.Test;
import net.postgis.jdbc.geometry.LineString;
import net.postgis.jdbc.geometry.MultiLineString;
import net.postgis.jdbc.geometry.MultiPoint;
import net.postgis.jdbc.geometry.MultiPolygon;
import net.postgis.jdbc.geometry.Point;
import net.postgis.jdbc.geometry.Polygon;
import org.postgis.LineString;
import org.postgis.MultiLineString;
import org.postgis.MultiPoint;
import org.postgis.MultiPolygon;
import org.postgis.Point;
import org.postgis.Polygon;
import java.sql.SQLException;
import java.util.List;
@@ -181,7 +181,7 @@ public class TestQuery {
.find(MyBean.class)
.where()
.raw("st_distance(wgs84Point, ?) < 0.011", toWkt(geolatteClosePoint))
.raw("st_distance(wgs84Point, ?) < 0.011", new net.postgis.jdbc.geometry.Point(toWkt(geolatteClosePoint)))
.raw("st_distance(wgs84Point, ?) < 0.011", new org.postgis.Point(toWkt(geolatteClosePoint)))
.findOne()
);
@@ -190,7 +190,7 @@ public class TestQuery {
.find(MyBean.class)
.where()
.raw("st_distance(wgs84Point, ?) < 0.009", toWkt(geolatteClosePoint))
.raw("st_distance(wgs84Point, ?) < 0.009", new net.postgis.jdbc.geometry.Point(toWkt(geolatteClosePoint)))
.raw("st_distance(wgs84Point, ?) < 0.009", new org.postgis.Point(toWkt(geolatteClosePoint)))
.findOne()
);
@@ -199,7 +199,7 @@ public class TestQuery {
.find(MyBean.class)
.where()
.raw("ST_Within(wgs84Point, ST_GeomFromText(?))", toWkt(enclosingPolygon))
.raw("ST_Within(wgs84Point, ?)", new net.postgis.jdbc.geometry.Polygon(toWkt(enclosingPolygon)))
.raw("ST_Within(wgs84Point, ?)", new org.postgis.Polygon(toWkt(enclosingPolygon)))
.findOne()
);
@@ -207,7 +207,7 @@ public class TestQuery {
DB.find(MyBean.class)
.where()
.raw("wgs84Point = ST_PointN(ST_GeomFromText(?), 2)", toWkt(lineString))
.raw("wgs84Point = ST_PointN(?, 2)", new net.postgis.jdbc.geometry.LineString(toWkt(lineString)))
.raw("wgs84Point = ST_PointN(?, 2)", new org.postgis.LineString(toWkt(lineString)))
.findOne()
);
@@ -215,7 +215,7 @@ public class TestQuery {
DB.find(OtherBeanGeoLatte.class)
.where()
.raw("wgs84Point = ST_PointN(ST_LineFromMultiPoint(ST_GeomFromText(?)), 2)", toWkt(multiPoint))
.raw("wgs84Point = ST_PointN(ST_LineFromMultiPoint(?), 2)", new net.postgis.jdbc.geometry.MultiPoint(toWkt(multiPoint)))
.raw("wgs84Point = ST_PointN(ST_LineFromMultiPoint(?), 2)", new org.postgis.MultiPoint(toWkt(multiPoint)))
.findOne()
);
@@ -223,7 +223,7 @@ public class TestQuery {
DB.find(OtherBeanGeoLatte.class)
.where()
.raw("wgs84Point = ST_PointN(ST_LineFromMultiPoint(ST_GeomFromText(?)), 2)", toWkt(multiPoint))
.raw("wgs84Point = ST_PointN(ST_LineFromMultiPoint(?), 2)", new net.postgis.jdbc.geometry.MultiPoint(toWkt(multiPoint)))
.raw("wgs84Point = ST_PointN(ST_LineFromMultiPoint(?), 2)", new org.postgis.MultiPoint(toWkt(multiPoint)))
.findOne()
);
@@ -232,7 +232,7 @@ public class TestQuery {
.find(MyBean.class)
.where()
.raw("ST_Within(wgs84Point, ST_GeomFromText(?))", toWkt(multiPolygon))
.raw("ST_Within(wgs84Point, ?)", new net.postgis.jdbc.geometry.MultiPolygon(toWkt(multiPolygon)))
.raw("ST_Within(wgs84Point, ?)", new org.postgis.MultiPolygon(toWkt(multiPolygon)))
.findOne()
);
@@ -240,7 +240,7 @@ public class TestQuery {
DB.find(OtherBeanGeoLatte.class)
.where()
.raw("ST_Intersects(wgs84Point, ST_GeomFromText(?))", toWkt(multiLineString))
.raw("ST_Intersects(wgs84Point, ?)", new net.postgis.jdbc.geometry.MultiLineString(toWkt(multiLineString)))
.raw("ST_Intersects(wgs84Point, ?)", new org.postgis.MultiLineString(toWkt(multiLineString)))
.findOne()
);
}
@@ -15,4 +15,4 @@ ebean:
image: ghcr.io/baosystems/postgis:15
# extensions: postgis
# url: jdbc:postgresql_lwgis://localhost:6432/mygisapp
driver: net.postgis.jdbc.DriverWrapperLW
# driver: org.postgis.DriverWrapperLW
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</parent>
<name>ebean querybean</name>
@@ -17,7 +17,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>provided</scope>
</dependency>
@@ -63,14 +63,14 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-ddl-generator</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>test</scope>
</dependency>
@@ -84,7 +84,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>querybean-generator</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>provided</scope>
</dependency>
@@ -32,7 +32,7 @@ public abstract class PBaseString<R, T> extends PBaseComparable<R, T> {
* @param value the equal to bind value
* @return the root query bean instance
*/
@Deprecated
@Deprecated(forRemoval = true)
public final R equalToType(T value) {
expr().eq(_name, value);
return _root;
@@ -46,7 +46,7 @@ public abstract class PBaseString<R, T> extends PBaseComparable<R, T> {
* @param value the equal to bind value
* @return the root query bean instance
*/
@Deprecated
@Deprecated(forRemoval = true)
public final R notEqualToType(T value) {
expr().ne(_name, value);
return _root;
@@ -745,7 +745,7 @@ public abstract class TQRootBean<T, R> {
* Add EXISTS sub-query predicate.
*/
public R exists(Query<?> subQuery) {
query.where().exists(subQuery);
peekExprList().exists(subQuery);
return root;
}
@@ -753,7 +753,7 @@ public abstract class TQRootBean<T, R> {
* Add NOT EXISTS sub-query predicate.
*/
public R notExists(Query<?> subQuery) {
query.where().notExists(subQuery);
peekExprList().notExists(subQuery);
return root;
}
@@ -764,7 +764,7 @@ public abstract class TQRootBean<T, R> {
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
public final R exists(String sqlSubQuery, Object... bindValues) {
query().where().exists(sqlSubQuery, bindValues);
peekExprList().exists(sqlSubQuery, bindValues);
return root;
}
@@ -775,7 +775,7 @@ public abstract class TQRootBean<T, R> {
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
*/
public final R notExists(String sqlSubQuery, Object... bindValues) {
query().where().notExists(sqlSubQuery, bindValues);
peekExprList().notExists(sqlSubQuery, bindValues);
return root;
}
@@ -1275,7 +1275,7 @@ public abstract class TQRootBean<T, R> {
/**
* @deprecated migrate to {@link #orderBy()}.
*/
@Deprecated(since = "13.19")
@Deprecated(since = "13.19", forRemoval = true)
public R order() {
return root;
}
@@ -1295,7 +1295,7 @@ public abstract class TQRootBean<T, R> {
/**
* @deprecated migrate to {@link #orderBy(String)}
*/
@Deprecated(since = "13.19")
@Deprecated(since = "13.19", forRemoval = true)
public R order(String orderByClause) {
return orderBy(orderByClause);
}
@@ -1867,6 +1867,28 @@ public abstract class TQRootBean<T, R> {
return query.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
*/
@Nullable
public <A> Optional<A> findSingleAttributeOrEmpty() {
return query.findSingleAttributeOrEmpty();
}
/**
* Execute the query processing the beans one at a time.
* <p>
@@ -1,8 +1,9 @@
package org.example.domain;
import io.ebean.annotation.DbArray;
import jakarta.persistence.*;
import org.example.domain.finder.ContactFinder;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.time.ZonedDateTime;
@@ -17,6 +18,11 @@ import java.util.Map;
@Table(name = "be_contact")
public class Contact extends BaseModel {
/**
* Convenience Finder for 'active record' style.
*/
public static final ContactFinder find = new ContactFinder();
@DbArray
List<@Size(max=20) String> phoneNumbers = new ArrayList<>();
@@ -0,0 +1,18 @@
package org.example.domain.finder;
import io.ebean.Finder;
import org.example.domain.Contact;
import org.example.domain.query.QContact;
/**
*/
public class ContactFinder extends Finder<Long, Contact> {
public ContactFinder() {
super(Contact.class);
}
public QContact typed() {
return new QContact();
}
}
@@ -1,6 +1,8 @@
package org.querytest;
import org.example.domain.Contact;
import org.example.domain.Customer;
import org.example.domain.query.QCustomer;
import org.junit.jupiter.api.Test;
import java.time.LocalDate;
@@ -9,6 +11,8 @@ import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
public class QCustomerAndOrTest {
@Test
@@ -55,6 +59,30 @@ public class QCustomerAndOrTest {
}
@Test
public void testOrWithExists() {
QCustomer query = Customer.find.typed()
.alias("_cust")
.or()
.name.eq("Superman")
.exists(Contact.find.typed()
.alias("contact")
.firstName.eq("Superman")
.raw("contact.customer_id = _cust.id")
.query()
)
.endOr()
.select(QCustomer.alias().id);
query.findList();
assertThat(query.getGeneratedSql()).isEqualTo(
"select _cust.id from be_customer _cust where (" +
"_cust.name = ? or exists (select 1 from be_contact contact where " +
"contact.first_name = ? and contact.customer_id = _cust.id))"
);
}
private Date fiveDaysAgo() {
LocalDateTime fiveDaysAgo = LocalDate.now().atStartOfDay().minusDays(5);
return new Date(fiveDaysAgo.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
@@ -63,6 +63,25 @@ public class QCustomerTest {
}
@Test
public void copy() {
var origin = new QCustomer()
.setDistinct(true)
.status.equalTo(Customer.Status.BAD);
var copy1 = origin.copy().name.isNotNull();
var q1 = copy1.query();
copy1.findList();
assertThat(q1.getGeneratedSql()).contains("from be_customer t0 where t0.status = ? and t0.name is not null");
var copy2 = origin.copy().version.ge(1L);
var q2 = copy2.query();
copy2.findList();
assertThat(q2.getGeneratedSql()).contains("from be_customer t0 where t0.status = ? and t0.version >= ?");
}
@Test
public void findSingleAttribute() {
@@ -1050,6 +1069,32 @@ public class QCustomerTest {
assertThat(maxDate).isNotNull();
}
@Test
public void findSingleAttributeOrEmpty() {
Customer cust = new Customer();
cust.setName("MaybeIExist yeah");
cust.setStatus(Customer.Status.GOOD);
cust.setRegistered(new Date());
cust.save();
Optional<String> customerName = new QCustomer()
.select(name)
.status.eq(Customer.Status.GOOD)
.name.startsWith("MaybeIExist")
.findSingleAttributeOrEmpty();
assertThat(customerName).isPresent();
Optional<String> customerName2 = new QCustomer()
.select(name)
.status.eq(Customer.Status.GOOD)
.name.eq("NahIDoNotExist")
.findSingleAttributeOrEmpty();
assertThat(customerName2).isEmpty();
}
@Test
public void testFetchByScalarValue() {
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</parent>
<artifactId>ebean-redis</artifactId>
@@ -22,28 +22,28 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>test</scope>
</dependency>
@@ -57,7 +57,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>querybean-generator</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>provided</scope>
</dependency>
+3 -3
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</parent>
<artifactId>ebean-spring-txn</artifactId>
@@ -28,7 +28,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>provided</scope>
</dependency>
@@ -77,7 +77,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>test</scope>
</dependency>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</parent>
<name>ebean test</name>
@@ -33,20 +33,20 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-ddl-generator</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
@@ -149,14 +149,14 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jackson-mapper</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-all</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>test</scope>
</dependency>
@@ -73,9 +73,26 @@ public class TestQueryUsingConnection extends BaseTestCase {
assertThat(count).isEqualTo(otherCount + 1);
assertThat(otherCount).isEqualTo(masterCount);
}
}
@IgnorePlatform({Platform.SQLSERVER, Platform.COCKROACH})
@Test
public void dtoQueryUsingConnection() {
ResetBasicData.reset();
try (Transaction transaction = DB.createTransaction()) {
final CountryDto dto = DB.findDto(CountryDto.class, "select code, name from o_country where code=?")
.usingConnection(transaction.connection())
.setParameter("NZ")
.findOne();
assertThat(dto).isNotNull();
assertEquals("NZ", dto.code);
transaction.rollback();
}
}
public static class CountryDto {
final String code;
final String name;
@@ -35,6 +35,11 @@ public class PlainBeanDirtyAware implements ModifyAwareType {
return markedDirty;
}
@Override
public Object freeze() {
return this;
}
@Override
public void setMarkedDirty(boolean markedDirty) {
this.markedDirty = markedDirty;
@@ -355,6 +355,24 @@ public class TestQueryFilterMany extends BaseTestCase {
assertSql(sql.get(1)).contains(" and lower(t0.title) like");
}
@Test
public void testFetchAndFilterMany() {
ResetBasicData.reset();
LoggedSql.start();
DB.find(Customer.class)
.fetch("contacts")
.filterMany("contacts.notes").istartsWith("title", "foo")
.findList();
List<String> sql = LoggedSql.stop();
assertThat(sql.size()).isEqualTo(2);
assertSql(sql.get(0)).contains(" from o_customer t0 left join contact t1 on t1.customer_id = t0.id");
platformAssertIn(sql.get(1), " from contact_note t0 where (t0.contact_id)");
assertSql(sql.get(1)).contains(" and lower(t0.title) like");
}
@Test
public void testFilterManyUsingExpression() {
@@ -1,5 +1,7 @@
package org.tests.query;
import io.ebean.Transaction;
import io.ebean.bean.FrozenBeans;
import io.ebean.bean.EntityBean;
import io.ebean.bean.EntityBeanIntercept;
import io.ebean.bean.InterceptReadOnly;
@@ -7,23 +9,150 @@ import io.ebean.xtest.BaseTestCase;
import io.ebean.DB;
import io.ebean.Query;
import org.junit.jupiter.api.Test;
import org.tests.model.basic.Customer;
import org.tests.model.basic.ResetBasicData;
import org.tests.model.basic.*;
import java.io.*;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static org.assertj.core.api.Assertions.assertThat;
public class TestQueryOrderById extends BaseTestCase {
private Set<Integer> cachedCustomerIds;
@Test
void cachedBeanContext_attach() {
ResetBasicData.reset();
FrozenBeans cachedBeanContext = testSerialiseCachedBeans(buildCachedBeans());
testSerialiseCustomer(cachedCustomers.get(0));
try (Transaction txn = DB.beginTransaction()) {
txn.attach(cachedBeanContext);
List<Order> orders = DB.find(Order.class)
.findList();
for (Order order : orders) {
Customer customer = order.getCustomer();
if (cachedCustomerIds.contains(customer.getId())) {
// Illegal to access customer.orders as that was not loaded and no lazy loading is allowed
// List<Order> orders1 = customer.getOrders();
// assertThat(orders1).isEmpty();
// assertThat(orders1).isSameAs(Collections.EMPTY_LIST);
List<Contact> contacts = customer.getContacts();
assertThat(contacts).isNotNull();
// customer.setContacts(new ArrayList<>());
// customer.setName("modified");
Address billingAddress = customer.getBillingAddress();
if (billingAddress != null) {
String line1 = billingAddress.getLine1();
Country country = billingAddress.getCountry();
}
Address shippingAddress = customer.getShippingAddress();
// if (shippingAddress != null) {
// // shippingAddress.getCountry();
// }
}
}
}
}
private static FrozenBeans testSerialiseCachedBeans(FrozenBeans source) {
try {
ByteArrayOutputStream os = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(source);
oos.close();
byte[] byteArray = os.toByteArray();
var is = new ByteArrayInputStream(byteArray);
ObjectInputStream ois = new ObjectInputStream(is);
FrozenBeans result = (FrozenBeans)ois.readObject();
assertThat(result).isNotNull();
return result;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static void testSerialiseCustomer(Customer source) {
try {
ByteArrayOutputStream os = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(source);
oos.close();
byte[] byteArray = os.toByteArray();
var is = new ByteArrayInputStream(byteArray);
ObjectInputStream ois = new ObjectInputStream(is);
Customer customer = (Customer)ois.readObject();
assertThat(customer.getId()).isEqualTo(source.getId());
assertThat(customer.getName()).isEqualTo(source.getName());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private List<Customer> cachedCustomers;
private FrozenBeans buildCachedBeans() {
try (Transaction txn = DB.beginTransaction()) {
List<Customer> list = DB.find(Customer.class)
.setReadOnly(true)
//.setDisableLazyLoading(true)
.orderBy("id")
.setMaxRows(3)
.findList();
// perform some lazy loading if we desire
for (Customer customer : list) {
customer.getContacts().size();
Address billingAddress = customer.getBillingAddress();
if (billingAddress != null) {
Country country = billingAddress.getCountry();
if (country != null) {
country.getName();
}
}
}
// can selectively use DisableLazyLoad which is "lazy loading is NO-operation"
//for (Customer customer : list) {
// DB.beanState(customer).setDisableLazyLoad(true);
//}
cachedCustomerIds = list.stream()
.map(BasicDomain::getId)
.collect(Collectors.toSet());
cachedCustomers = list;
return txn.freezeAndDetach();
}
}
@Test
public void orderById_default_expectNotOrderById() {
ResetBasicData.reset();
Query<Customer> query = DB.find(Customer.class)
.select("id,name")
.order("id")
.orderBy("id")
.setFirstRow(1)
.setMaxRows(5);
@@ -20,6 +20,7 @@ import org.tests.o2m.OmBasicParent;
import java.sql.Date;
import java.time.LocalDate;
import java.util.List;
import java.util.Optional;
import static org.assertj.core.api.Assertions.assertThat;
@@ -139,6 +140,32 @@ class TestQuerySingleAttribute extends BaseTestCase {
assertThat(name).isNotNull();
}
@Test
void findSingleAttributeOrEmpty() {
ResetBasicData.reset();
Query<Customer> query = DB.find(Customer.class)
.select("name")
.where().eq("name", "Rob").query();
Optional<String> name = query.findSingleAttributeOrEmpty();
assertThat(sqlOf(query)).contains("select t0.name from o_customer t0");
assertThat(name).isPresent().contains("Rob");
}
@Test
void findSingleAttributeOrEmpty_when_empty() {
ResetBasicData.reset();
Query<Customer> query = DB.find(Customer.class)
.select("name")
.where().eq("name", "I_Do_Not_ExistO!").query();
Optional<String> name = query.findSingleAttributeOrEmpty();
assertThat(name).isEmpty();
}
@Test
void findSingleAttributeList_with_join_column() {
ResetBasicData.reset();
@@ -265,6 +265,33 @@ class SqlQueryTests extends BaseTestCase {
assertThat(custDtos).isNotEmpty();
}
@Test
void queryUsingConnection() throws SQLException {
ResetBasicData.reset();
boolean h2 = isH2();
String sql = h2 ? "select id, name||session_id(), status from o_customer where name is not null"
: "select id, name, status from o_customer where name is not null";
try (Transaction txn = DB.createTransaction()) {
String h2SessionId = h2 ? h2SessionId(txn) : null;
AtomicInteger counter = new AtomicInteger();
DB.sqlQuery(sql)
.usingConnection(txn.connection())
.mapTo(CUST_MAPPER)
.findEach(custDto -> {
counter.incrementAndGet();
assertThat(custDto.name).isNotNull();
if (h2) {
assertThat(custDto.name).endsWith(h2SessionId);
}
});
assertThat(counter.get()).isGreaterThan(0);
}
}
@Test
void queryUsingTransaction() throws SQLException {
ResetBasicData.reset();
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</parent>
<name>kotlin querybean generator</name>
@@ -21,7 +21,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>test</scope>
</dependency>
@@ -35,7 +35,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>test</scope>
</dependency>
@@ -56,14 +56,14 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-ddl-generator</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<scope>test</scope>
</dependency>
@@ -94,6 +94,13 @@ class KotlinLangAdapter implements LangAdapter {
writer.append(" * Private constructor for FetchGroup building.").eol();
writer.append(" */").eol();
writer.append(" private constructor(fetchGroupQuery: Query<%s>) : super(fetchGroupQuery)", shortName).eol();
writer.eol();
writer.append(" /** Return a copy of the query. */").eol();
writer.append(" fun copy() : Q%s {", shortName).eol();
writer.append(" return Q%s(query().copy())", shortName).eol();
writer.append(" }").eol();
writer.eol();
}
@Override
+14 -14
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -15,67 +15,67 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-clickhouse</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-db2</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-hana</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-hsqldb</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mysql</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mariadb</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-nuodb</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-oracle</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlanywhere</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlite</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlserver</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -15,7 +15,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -15,7 +15,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -15,7 +15,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<!-- Provided scope so that the H2HistoryTrigger can live in Ebean core
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -15,7 +15,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -15,7 +15,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+3 -3
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -15,13 +15,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mysql</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -15,7 +15,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -15,7 +15,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
<relativePath>../..</relativePath>
</parent>
@@ -15,7 +15,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</dependency>
</dependencies>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.25.1-jakarta</version>
<version>13.26.0-jakarta</version>
</parent>
<artifactId>platforms</artifactId>

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