Compare commits

...
434 Commits
Author SHA1 Message Date
Rob Bygrave 69c932816a Version 16.3.0 2026-02-16 21:07:49 +13:00
Rob Bygrave a1facf527b Bump ebean-agent and avaje junit 2026-02-16 21:03:37 +13:00
Rob Bygrave ec42ebf66d Bump ebean-datasource to 10.3 (#3727)
This version has moved the connection initialisation that sets the
autoCommit mode to be after the clientInfo and any initial sql has
been executed
2026-02-16 20:24:58 +13:00
Rob Bygrave 5dede70801 Fix for #3722 Remove isSkipCacheExplicit() and use isSkipCache()
This change is to reduce PUTs causing cache pollution where
changes that are rolled back are PUT into the bean cache.

Effectively remove the isSkipCacheExplicit() feature and just
use the existing isSkipCache(). This means that skipCacheAfterWrite
is used and PUTs after a database write/insert/update/delete are
effectively skipped.
2026-02-16 19:49:56 +13:00
Rob Bygrave b2f02ecc1f Fix for #3723 FilterMany predicates added to incorrect join clause (#3725)
The change that moved the filterMany predicates to the join had an
issue that extra joins may be needed to support those predicates.

Prior to this change, the extra predicates where effectively just
added to the end of the joins, rather than as a "child" node in
the SqlTreeNode tree.

This fix is in SqlTreeBuilder, where the list of top level extra
joins are first tried to be added as a child to a parent node, and
only if we can't find the parent added at the end.
2026-02-15 21:47:17 +13:00
dependabot[bot] 15fa7cd1c2 Bump org.assertj:assertj-core from 3.27.6 to 3.27.7 in /ebean-test (#3718)
Bumps [org.assertj:assertj-core](https://github.com/assertj/assertj) from 3.27.6 to 3.27.7.
- [Release notes](https://github.com/assertj/assertj/releases)
- [Commits](https://github.com/assertj/assertj/compare/assertj-build-3.27.6...assertj-build-3.27.7)

---
updated-dependencies:
- dependency-name: org.assertj:assertj-core
  dependency-version: 3.27.7
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-15 10:02:49 +13:00
Rob Bygrave 8dced38cd5 Bump kotlin maven plugin version in build (#3724)
* Bump kotlin maven plugin version in build

* For build bump kotlin-maven-plugin version to 2.3.10
2026-02-15 09:59:16 +13:00
Rob Bygrave 7addba7c93 Version 16.2.1 2026-02-02 23:22:22 +13:00
Rob Bygrave 00b45c1642 For query usingMaster support passing a boolean (#3721)
This is to support the use case where other logic is used to determine if a query
should be "forced" to use the master data source or not, and so it's easier to
pass that as a boolean to the usingMaster() method.
2026-02-02 23:17:37 +13:00
Rob Bygrave a3d9711fe6 Version 16.2.0 2025-11-23 22:18:54 +13:00
Rob Bygrave 1239c50723 Bump ebean-agent to 16.2.0 2025-11-23 22:16:29 +13:00
Rob Bygrave d85d8449e2 #3695 Behaviour change: findSingleAttribute() to throw when multiple … (#3697)
* #3695 Behaviour change: findSingleAttribute() to throw when multiple rows returned by query

On the plus, this makes the behaviour consistent with all the other findOne() methods (ORM, DTO, SqlQuery) and this very much feels like buggy behaviour [to just get the first result and ignore any subsequent results in the ResultSet]

On the negative of merging this bug fix, any application code relying on the existing behaviour with this fix will break and throw a NonUniqueResultException at RUNTIME (not ideal). However, for these cases where the application now throws an exception, people might not be aware that they were relying on this behaviour and this exception could be useful to highlight that (a potential non-deterministic query result was being used and a potential source of bugs was being).

* Change SqlQuery + Mapper + findOne() also to throw NonUniqueResultException
2025-11-23 22:14:44 +13:00
dependabot[bot] baf71cbab3 Bump com.microsoft.sqlserver:mssql-jdbc in /ebean-test (#3694)
Bumps [com.microsoft.sqlserver:mssql-jdbc](https://github.com/Microsoft/mssql-jdbc) from 10.2.0.jre8 to 11.1.0.jre8-preview.
- [Release notes](https://github.com/Microsoft/mssql-jdbc/releases)
- [Changelog](https://github.com/microsoft/mssql-jdbc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Microsoft/mssql-jdbc/commits)

---
updated-dependencies:
- dependency-name: com.microsoft.sqlserver:mssql-jdbc
  dependency-version: 11.1.0.jre8-preview
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-23 21:01:00 +13:00
Rob Bygrave ff0ca35e54 #3701 Improve error message when missing dependency ebean-jackson-mapper (#3708) 2025-11-23 20:25:16 +13:00
Rob BygraveandRoman Parshikov 0fc9a1ac2f Bug fix and change filterMany to put predicates into JOIN clause, Fix for #3626 (#3707)
* Problem with filterMany

* Missing id

* Other test

* Fix

* Update TestQueryFilterMany.java

* #3706 Bug fix and change filterMany to put predicates into JOIN clause, Fix for #3626

* Fix tests for Postgres, Oracle, Sql Server

---------

Co-authored-by: Roman Parshikov <promansew@gmail.com>
2025-11-23 20:20:13 +13:00
Rob Bygrave f7b4edb193 Merge pull request #3704 from ebean-orm/feature/bump-test-deps-bytebuddy
Bump test dependencies byte buddy and assertj
2025-11-20 09:35:09 +13:00
robin.bygrave 284c8d4d21 Bump test dependencies byte buddy and assertj 2025-11-20 09:23:39 +13:00
Rob Bygrave 59a5c5f9bd Bump dependency avaje-config to 4.2 (#3699) 2025-11-11 07:59:40 +13:00
Rob Bygrave 5b04d6eca3 #3551 Log warning for use of mapping column to Class (#3698)
I think it was a mistake for Ebean to support Class<?> from a security perspective. Instead, Ebean should just use a String <-> Varchar and leave if up to the application to take that String and convert it to a class [and then that potential Class initialisation is owned by the application code and all security considerations around that are owned by the application code].
2025-11-11 07:57:15 +13:00
Ryszard TrojnackiandRob Bygrave d5547808a2 PGvector support (#3696)
* Add pgvector-types module.

* Add missing binder definitions.
Add missing PGbit type registration.
Few tests.

* Add cached bean test.

* Prefer final classes, minor formating only

---------

Co-authored-by: Rob Bygrave <robin.bygrave@gmail.com>
2025-11-09 16:55:51 +13:00
Rob Bygrave 5606c95de5 Version 16.1.1 2025-10-22 22:45:21 +13:00
Rob Bygrave 4c2bd408b0 Bump ebean-agent 2025-10-22 22:42:00 +13:00
Rob Bygrave db76d5c27c Test only - add Postgres JSONB raw() expression example 2025-10-22 22:03:09 +13:00
Rob Bygrave f92c2f8c14 Test only - add test for string id InsertOnConflict 2025-10-22 22:02:40 +13:00
Rob Bygrave 51c3065419 3683 - Add AggregateFormulaContext to support group_concat etc (#3691)
- Add AggregateFormulaContext with ability to override the default via DatabaseBuilder
- Add group_concat, string_agg, listagg to set of known aggregation functions
2025-10-21 22:54:55 +13:00
Rob Bygrave e46dd66292 Test only - bump to Postgres 17 for PostgresReadOnlyDatabaseTest 2025-10-21 20:55:52 +13:00
Rob Bygrave 3e1451bee7 Merge branch 'master' of github.com:ebean-orm/ebean 2025-10-21 20:54:23 +13:00
Rob Bygrave 4ac3c4ddb1 3682 @Aggregation is applied to query if entity also has a @lob column (#3689)
* Version 16.1.0

* #3682 @Aggregation is applied to query if entity also has a @Lob column

The underling issue was that Aggregation columns should have been marked as default LAZY. This impact was only hit when @Lob column are included which by default lazy fetched, and that means the default select clause determined.
2025-10-20 20:55:18 +13:00
Rob Bygrave ee8e48902b Merge branch 'master' of github.com:ebean-orm/ebean 2025-10-19 18:07:18 +13:00
Rob Bygrave c37e752ace #3681 javadoc query cache (#3687)
* Version 16.1.0

* Improve javadoc for Query setUseQueryCache() and unmodifiable

Since 16.x a query using the query cache returns unmodifiable object graphs.
2025-10-14 20:04:38 +13:00
Rob Bygrave c9a6f822ac Version 16.1.0 2025-09-19 18:48:28 +12:00
Rob Bygrave 2231ef9fd1 Bump ebean-agent to 16.1.0 with Java 25 support (#3680)
Note that the IntelliJ plugin has been updated and published. It should be public in a few days.
2025-09-19 16:25:24 +12:00
Rob Bygrave 3ff1905318 Bump ebean-test-containers to 7.15 with updated ClickHouse support 2025-09-19 16:25:00 +12:00
Rob Bygrave 9b4fecff96 Add support for AutoCommit true transactions (#3679)
* Add support for AutoCommit true transactions

* Update DocStoreTransactionManager
2025-09-19 16:22:59 +12:00
Rob Bygrave 6f356fd55e #3674 Add @Nullable to Query getId(), getForUpdateLockWait(), getForUpdateLockType() (#3675)
These methods return nullable results, add JSpecify `@Nullable` to correctly indicate this.
2025-09-06 17:22:13 +12:00
Rob Bygrave 591f260f5b Retain filterMany expression when select fetchGroup applied after filterMany (#3673) 2025-09-02 22:35:43 +12:00
Rob Bygrave b361b10571 Version 16.0.1 2025-09-02 14:09:03 +12:00
Rob Bygrave c0e4e548ee Update the kotlin-maven-plugin for tests and use EA maven profile (#3671)
* Update the kotlin-maven-plugin for tests

* Add a profile for EA that excludes kotlin-querybean-generator

* For build workflow use maven profile "default"

To ensure the kotlin-querybean-generator, test modules run

* For build workflow use maven profile "default"

To ensure the kotlin-querybean-generator, test modules run
2025-09-02 14:04:59 +12:00
Rob Bygrave 92f3245919 Bump ebean-agent to 16.0.1 2025-09-02 13:37:45 +12:00
Rob Bygrave 59c2290916 Bump ebean-migration dependency, fix for setting dbSchema on migrations (#3670)
Ref: https://github.com/ebean-orm/ebean-migration/pull/163
2025-09-02 12:52:41 +12:00
Rob Bygrave 1135eb3f99 #3665 Fix for delete() Skips Bean due to Hash Collision (#3669)
Change the underlying storage of deleting beans to be by type by id so:

  private Map<Class<?>, Set<Object>> deletingBeans;
2025-08-31 22:32:27 +12:00
Rob Bygrave 1dccdff7bf #3664 Fix / support for extra JoinColumns on ManyToOne (#3668)
* #3664 Fix / support for extra JoinColumns on ManyToOne

Allows for extra JoinColumns on ManyToOne. The extra JoinColumn(s) are
expected to be useful for the case of table partitioning where the extra
join column is used to partition the table. In the test case, the partition
column would be the org_id column and common to both tables (same partition key).

* #3664 Fix / support for extra JoinColumns on ManyToOne

Allows for extra JoinColumns on ManyToOne. The extra JoinColumn(s) are
expected to be useful for the case of table partitioning where the extra
join column is used to partition the table. In the test case, the partition
column would be the org_id column and common to both tables (same partition key).

* #3664 Extend test

* #3664 Tidy up test
2025-08-31 12:52:17 +12:00
Rob Bygrave 5f74a53e3e #3666 Fix for NPE with filterMany() containing or() (#3667)
For FilterMany with QueryBeans, it creates a queryBean to build the filterMany predicates with. This query bean needed 2 changes for this fix:

1. Needs to set it's internal "root" such that it supports chaining (required for or() etc)
2. The ExpressionFactory needs to be explicitly passed to the expression list (rather than get it from the query which is actually null in this case).
2025-08-31 10:08:07 +12:00
Rob Bygrave 1f9e652ea9 Version 16.0.0 2025-08-25 08:21:49 +12:00
Rob Bygrave 4e592c97ff Update how to deploy 2025-08-05 23:30:18 +12:00
Rob Bygrave 760d19a10d Update how to deploy 2025-08-05 23:16:42 +12:00
Rob Bygrave d2693c3ff2 Version 16.0.0-RC4 2025-08-05 23:15:20 +12:00
Rob Bygrave 3324b2bda4 Use autocommit false with findIterate for Postgres (#3662)
* Use autocommit false with findIterate for Postgres

* Use autocommit false with findIterate for Postgres

* Use autocommit false with FindDto queries for Postgres

* Use autocommit false with SqlQuery findIterate queries for Postgres

* Ensure that TransactionFactory.createReadOnlyTransaction() returns an ImplicitReadOnlyTransaction

This change changes TransactionFactoryTenant.createReadOnlyTransaction() to return a ImplicitReadOnlyTransaction, as that is now used to support Postgres use of cursors with findIterate style queries.
2025-08-05 23:03:28 +12:00
Rob Bygrave 1b5e066562 #3654 Fix querybean-generator compiler warning for unclaimed annotations (#3655)
warning: No processor claimed any of these annotations: /io.ebean.typequery.TypeQueryBean,/io.ebean.typequery.Generated

This fix is required when the compiler is run with -Werror specified

An alternative workaround is to use compiler arg -Xlint:-processing rather than -Xlint:all
2025-07-16 20:34:56 +12:00
Rob Bygrave 104e4ec756 Bump ebean-test-containers to 7.14 - Yugabyte read committed support enabled by default (#3651) 2025-07-14 09:03:39 +12:00
Rob Bygrave 74a2967a6e Tests Yugabyte - comment out the TestQueryForUpdate using repeatable read
... as its noise there is anyone else reads the logs
2025-07-12 09:38:06 +12:00
Rob Bygrave e693b12a97 Tests DB2 - ignore TestRawExpressionInterpolation for DB2 2025-07-12 09:30:16 +12:00
Rob Bygrave 48fb9b34bb Tests Yugabyte - faster test using forUpdate 2025-07-12 09:18:01 +12:00
Rob Bygrave f64400400a Tests Oracle - ignore the TestRawExpressionInterpolation for Oracle 2025-07-12 09:09:34 +12:00
Rob Bygrave d7cc081942 Tests Yugabyte - see if everything else passes 2025-07-12 09:04:02 +12:00
Rob Bygrave 3351548b60 Fix use of JSpecify Nullable annotation in query bean generation 2025-07-11 23:45:31 +12:00
Rob Bygrave 8d9858f57a Test only - Update logging for test TestQueryForUpdate 2025-07-11 23:35:03 +12:00
Rob Bygrave 9b520bc176 Bump avaje-config to 4.1 2025-07-11 23:22:16 +12:00
Rob Bygrave 44fd8e3a56 Adjust TestQueryForUpdate for Yugabyte - use markAsDirty on repeatable read test 2025-07-11 23:11:45 +12:00
Rob Bygrave 6910016c4d Adjust TestQueryForUpdate for Yugabyte - use markAsDirty
To see if the update has an impact on the 2nd thread waiting
2025-07-11 22:58:02 +12:00
Rob Bygrave 5f8a3c0591 Adjust TestQueryForUpdate for Yugabyte - check repeatable read isolation level 2025-07-11 22:05:31 +12:00
Rob Bygrave 0ae6956c1c Bump ebean-datasource 10.1 with support for initialConnections (#3650)
So in a K8s deployment, this adds support for having an initial number of connections to create initially (higher that min connections). This allows for a smoother deployment, by effectively having initially more connections than min in order to immediately take production load, and then over time trim back down towards the min connections.

So in k8s I am setting min, initial and max connections, where initial connections is high enough to take full production load straight after readiness true.
2025-07-11 21:26:58 +12:00
Rob Bygrave 2e9c5d8548 Merge branch 'query-cache-oom-for-too-large-beans' 2025-07-11 21:19:21 +12:00
Rob Bygrave 93edc840b3 Add a test that hits the new branch of code 2025-07-11 21:18:00 +12:00
Josiah NoelandRob Bygrave 34311785fa Fix Jackson NCDF Error (#3639)
* fix jackson NCDF error

split jackson SPI impl into it's own module

* Restore format

* Restore format

* Trim up dependencies

* Rename module to ebean-core-json

---------

Co-authored-by: Rob Bygrave <robin.bygrave@gmail.com>
2025-07-11 20:53:25 +12:00
Rob Bygrave 63929f8ff3 Bump test Yugabyte version to 2.20.11.0-b34 2025-07-11 20:26:12 +12:00
Jonas Fröhler d918c5117f no import changes 2025-07-01 09:05:48 +02:00
Jonas Fröhler dd845a7b0c Fix imports 2025-07-01 09:02:26 +02:00
Jonas Fröhler df0e4d57f0 Clean up 2025-06-27 12:17:19 +02:00
Jonas Fröhler 9c7fa25d49 Query Cache OOM test and potential draft for the fix 2025-06-27 12:14:01 +02:00
Rob Bygrave e82c1a4140 Version 16.0.0-rc3 2025-05-26 21:00:32 +12:00
Rob Bygrave 389bf48e3e Merge pull request #3636 from ebean-orm/feature/explicit-shutdownHook
Add DatabaseBuilder.shutdownHook option (programmatic disabling registration of JVM shutdown hook)
2025-05-26 17:24:25 +12:00
Rob Bygrave 3b3b44543e Bump ebean-test-containers, programmatically get DatabaseBuilder from test container 2025-05-26 17:23:27 +12:00
Rob Bygrave 297f334da5 Add DatabaseBuilder.shutdownHook option (programmatic disabling registration of JVM shutdown hook) 2025-05-26 17:21:15 +12:00
Rob Bygrave 78c7439445 test only - rename TestRawExpressionInterpolation 2025-05-15 08:00:52 +12:00
Rob Bygrave 2043ba6411 Merge pull request #3634 from ebean-orm/feature/native-image-otherTypes
[native-image] Modify querybean-generator to include AttributeConverters in generated reflect-config.json
2025-05-14 20:49:52 +12:00
Rob Bygrave 437c58001b [native-image] Modify querybean-generator to include AttributeConverters in generated reflect-config.json 2025-05-14 20:48:07 +12:00
Rob Bygrave 0e812efa7e Merge branch 'master' of github.com:ebean-orm/ebean 2025-05-14 20:27:56 +12:00
Rob Bygrave 80d4d21986 Merge pull request #3632 from FOCONIS/reorg-args-placeholder
Db2: Reorg args placeholder
2025-05-06 20:44:00 +12:00
Noemi Praml fe66b8c242 fix DbMigrationTest 2025-05-06 09:49:18 +02:00
Noemi Praml 206b2b2d3b migrations 2025-05-06 08:06:48 +02:00
Noemi Praml c0bc3faea0 fix test 2025-05-06 08:06:40 +02:00
Noemi Praml 3d07e7d804 add: reorgARgs Placeholder 2025-05-06 08:00:58 +02:00
Rob Bygrave fc124e8318 Tidy pom only 2025-04-30 00:02:30 +12:00
Rob Bygrave f4fd4f4b09 Version 16.0.0-RC2 2025-04-30 00:01:52 +12:00
Rob Bygrave 16f5311885 Bump parent pom to 5.1 for new maven central deploy 2025-04-29 23:41:48 +12:00
Rob Bygrave 75a0675977 Merge pull request #3630 from ebean-orm/feature/fix-ea-build-kotlin
Fix EA build, Kotlin not supporting 25-EA release
2025-04-29 23:37:10 +12:00
Rob Bygrave 80ebf4a1ee Fix EA build, Kotlin not supporting 25-EA release
It barfs trying to parse the 25-EA version, means the kotlin-querybean-generator fails the build for the Java Early Release versions.

With this, it will skip the kotlin modules for the Java Early Access release builds.
2025-04-29 23:36:22 +12:00
Rob Bygrave 4185beb5aa Merge pull request #3629 from ebean-orm/feature/bump-datasource-10
Bump ebean-datasource to 10.0 (Virtual Threads support via MR Jar)
2025-04-29 23:17:54 +12:00
Rob Bygrave 79908c0164 Bump ebean-datasource to 10.0 (Virtual Threads support via MR Jar)
Note that this still supports Java 11.

The 10.0 version of ebean-datasource uses Multi-Version jar such that if running using Java 21+ then it will use Virtual Threads for the background Heartbeat validation and also background closing of connections.
2025-04-29 23:09:49 +12:00
Rob Bygrave b5a16f42ca #3626 Add tests for bean property name instead of db column 2025-04-23 22:33:18 +12:00
Gonçalo Andrade a320a132b3 Fix incorrect usage of bean property name instead of corresponding column 2025-04-22 14:51:38 +01:00
Rob Bygrave 9e84e93511 Merge pull request #3621 from FOCONIS/new-db-versions
New db versions + testcontainers 7.8
2025-04-17 23:18:05 +12:00
Noemi Praml 6fb40c71ef update StartDb2 2025-04-16 15:22:08 +02:00
Noemi Praml 202b9ae94a update to testcontainers 7.8 2025-04-16 14:52:21 +02:00
Noemi Praml d79b452378 new db2 version 2025-04-16 14:19:11 +02:00
Noemi Praml 78a408dd10 new sqlserver version 2025-04-16 14:19:11 +02:00
Noemi Praml 6af974e432 new mariadb version 2025-04-16 14:19:11 +02:00
Rob Bygrave 04a8475291 Merge pull request #3623 from ebean-orm/feature/readOnly-DataSource-mark-nullable
Explicitly mark Database.readOnlyDataSource() as @Nullable
2025-04-15 22:25:06 +12:00
Rob Bygrave c56345f92e Explicitly mark Database.readOnlyDataSource() as @Nullable
Using JSpecify @Nullable on the return for Database.readOnlyDataSource()
2025-04-15 22:24:14 +12:00
Rob Bygrave ed0a46955e Explicitly mark Database.readOnlyDataSource() as @Nullable
Using JSpecify @Nullable on the return for Database.readOnlyDataSource()
2025-04-15 22:22:08 +12:00
Rob Bygrave 3c4b04a893 Version 16.0.0-rc1 2025-04-09 23:18:27 +12:00
Rob Bygrave ee403bdb83 Merge pull request #3620 from ebean-orm/feature/bump-ebean-agent
Bump the ebean-agent to 14.12.0, support for Lombok SuperBuilder
2025-04-09 23:02:46 +12:00
Rob Bygrave b18abe2221 Bump the ebean-agent to 14.12.0, support for Lombok SuperBuilder 2025-04-09 22:52:39 +12:00
Rob Bygrave d68f372d99 Merge pull request #3619 from ebean-orm/feature/column-length-255
For Postgres @Column(length=255) means varchar(255)
2025-04-09 20:22:56 +12:00
Rob Bygrave c8f769aa2a For Postgres @Column(length=255) means varchar(255)
The `@Column` length defaults to 0 rather than 255, this allows us to detect when it has been explicitly set and thus for Postgres we can now have:

@Column(length=255) mapping to -> varchar(255)
@Column mapping to -> varchar
2025-04-09 20:07:56 +12:00
Rob Bygrave bde626fd45 Merge pull request #3618 from ebean-orm/feature/bump-datasource-95
Bump ebean-datasource to 9.5
2025-04-09 20:04:23 +12:00
Rob Bygrave b828b73b2c Bump ebean-datasource to 9.5
When using DataSourceBuilder for both main and readOnly datasource, the maxConnections for the readOnly will default to the main pool maxConnections.
2025-04-09 20:02:14 +12:00
Rob Bygrave 2795a8578f Merge pull request #3616 from ebean-orm/feature/lazyLoadBatch-100
Increase default lazyLoadBatchSize from 10 to 100
2025-04-04 21:15:23 +13:00
Rob Bygrave bd0a3c2303 Increase default lazyLoadBatchSize from 10 to 100 2025-04-04 21:14:47 +13:00
Rob Bygrave 21e50e9d00 Merge pull request #3615 from ebean-orm/feature/3612-redis-exception
#3612 Catch all RedisException (rather than only IOException)
2025-04-04 20:47:44 +13:00
Rob Bygrave 88a47bf0a9 #3612 Catch all RedisException (rather than only IOException) 2025-04-04 20:45:59 +13:00
Rob Bygrave d9a45245f4 Version 16.0.0-beta1 2025-04-03 19:35:14 +13:00
Rob Bygrave 7be72df788 Merge pull request #3570 from ebean-orm/feature/improved-readOnly-immutable
Unmodifiable - Improved read only immutable entity beans / graphs
2025-04-02 22:24:19 +13:00
Rob Bygrave 42685335e3 Version 14.11.0 2025-04-01 21:32:48 +13:00
Rob Bygrave 478a2be405 Merge pull request #3611 from ebean-orm/feature/fix-native-image-mappedSuper
Fix NPE with native-image with @MappedSuperclass
2025-04-01 20:45:17 +13:00
Rob Bygrave ebcac9a503 Fix NPE with native-image with @MappedSuperclass
@MappedSuperclass was excluded from the generated reflect-config.json, this PR fixes that.

The missing reflect-config entry for MappedSuperclass means that with native-image the @Id property isn't found when its on a MappedSuperclass, and that ended up as a NPE in BeanPropertyAssocOne.
2025-04-01 20:29:26 +13:00
Rob Bygrave 996239c29f Merge pull request #3610 from ebean-orm/feature/configure-explain
Add support to configure EXPLAIN options for query plan capture
2025-04-01 08:07:46 +13:00
Rob Bygrave caf2772fb3 Put Postgres explain back to default format text for now 2025-04-01 08:07:04 +13:00
Rob Bygrave 1482c4c84f Add support to configure EXPLAIN options for query plan capture
e.g. DatabaseBuilder.queryPlanExplain("explain (verbose)")

Also changes Postgres default explain to be:
explain (analyze, costs, verbose, buffers, format json)
2025-03-31 23:41:16 +13:00
Rob Bygrave 792d52b794 Merge pull request #3609 from ebean-orm/feature/queryPlanInit
Change QueryPlanInit to support thresholdMicros per hash
2025-03-30 21:41:53 +13:00
Rob Bygrave aa4ea4904f Change QueryPlanInit to support thresholdMicros per hash
Effectively means that we can provide a thresholdMicros per query plan hash [for the plans that we want collected]
2025-03-30 21:35:20 +13:00
Rob Bygrave bab839fb38 Change QueryPlanInit to support thresholdMicros per hash
Effectively means that we can provide a thresholdMicros per query plan hash [for the plans that we want collected]
2025-03-30 18:33:13 +13:00
Rob Bygrave dde2567ccd Merge pull request #3608 from ebean-orm/feature/bump-postgres-16
Test only - align sqlserver test configuration
2025-03-26 22:50:48 +13:00
Rob Bygrave 7e4d070b75 Test only - update sqlserver test docker image to 2017-CU31-ubuntu-18.04 2025-03-26 22:50:22 +13:00
Rob Bygrave 3151e3f82b Test only - align sqlserver test configuration 2025-03-26 22:41:00 +13:00
Rob Bygrave c630aaff0e Merge pull request #3607 from ebean-orm/feature/bump-postgres-16
Test only - align mariadb test configuration
2025-03-26 22:37:34 +13:00
Rob Bygrave 67ec848f15 Test only - align mariadb test configuration 2025-03-26 22:37:09 +13:00
Rob Bygrave 57f0734381 Test only - align mariadb test configuration 2025-03-26 22:32:18 +13:00
Rob Bygrave cbd5bf23c9 Merge pull request #3606 from ebean-orm/feature/bump-postgres-16
Test only - align mysql and db2 test configuration
2025-03-26 22:31:51 +13:00
Rob Bygrave 5dc664a63f Test only - align mysql and db2 test configuration 2025-03-26 22:27:35 +13:00
Rob Bygrave d9b53677f2 Merge pull request #3605 from ebean-orm/feature/bump-postgres-16
Test only - add logging for datasource to BaseTestCase
2025-03-26 22:17:56 +13:00
Rob Bygrave f55c2cf3b6 Test only - add logging for datasource to BaseTestCase 2025-03-26 22:14:24 +13:00
Rob Bygrave c98def7ab7 Merge pull request #3604 from ebean-orm/feature/bump-postgres-16
Test only - add logging for datasource to BaseTestCase
2025-03-26 22:06:58 +13:00
Rob Bygrave 705e158a70 Test only - add logging for datasource to BaseTestCase 2025-03-26 22:06:35 +13:00
Rob Bygrave 569e782e99 Merge pull request #3603 from ebean-orm/feature/bump-postgres-16
Update Postgres and Postgis test containers to default to 16
2025-03-26 22:05:59 +13:00
Rob Bygrave 265b92fb12 Update Postgres and Postgis test containers to default to 16 2025-03-26 21:43:08 +13:00
Rob Bygrave 74311fad0a Update test postgres docker image to 16 2025-03-26 21:34:31 +13:00
Rob Bygrave 1eded5682a Merge pull request #3599 from ebean-orm/feature/bump-datasource-dependency2
Bump ebean-datasource dependency to 9.3
2025-03-21 18:42:53 +13:00
Rob Bygrave ff21bfe1de Bump ebean-datasource dependency to 9.3 2025-03-21 00:35:41 +13:00
Rob Bygrave 86db7fadfd Merge pull request #3598 from ebean-orm/feature/tidy-QueryCacheEntry
Tidy QueryCacheEntry, final class and use accessors
2025-03-20 23:58:56 +13:00
Rob Bygrave e48b327967 Tidy QueryCacheEntry, final class and use accessors 2025-03-20 23:57:56 +13:00
Rob Bygrave 964b3ccf8e Merge pull request #3597 from ebean-orm/feature/3515-extend
#3515 Bug in QueryCache invalidation
2025-03-20 23:55:10 +13:00
Rob Bygrave eb6906ad2b #3515 Bug in QueryCache invalidation
Effectively the bug fix is in SqlTreeNodeRoot.dependentTables() to include the baseTable in the set of dependent tables
2025-03-20 23:47:21 +13:00
Rob Bygrave 86e5ea3627 Merge pull request #3596 from ebean-orm/feature/tidy-future-queries
Change findFuture queries such that they can use the read only DataSource
2025-03-19 23:06:38 +13:00
Rob Bygrave 3a5e8290e0 Change findFuture queries such that they can use the read only DataSource
Prior to this change they made an explicit transaction if one was needed, and this would always use the Main DataSource.

With this change, when there is no transaction assigned to the query and no active transaction, then the find future query will use the ReadOnly DataSource if it has been configured (e.g. ReadOnly DataSource might point to a read replica database instance).
2025-03-19 23:00:19 +13:00
Rob Bygrave 929604e33d Merge pull request #3593 from LeComptoirDesPharmacies/feature/findFutureMap
Add feature findFutureMap
2025-03-19 22:12:06 +13:00
Rob Bygrave 2eed68ad61 Merge pull request #3595 from ebean-orm/feature/bump-avaje-config2
Bump avaje-config dependency to 4.0
2025-03-19 20:57:13 +13:00
Rob Bygrave f705560b8b Bump avaje-config dependency to 4.0 2025-03-19 20:56:40 +13:00
Rob Bygrave 6d791c7b50 Add BeanAccessException extends UnsupportedOperationException
And:

LazyInitialisationException extends BeanAccessException ...
UnmodifiableEntityException extends BeanAccessException ...
2025-03-18 22:54:34 +13:00
Rob Bygrave 1afe42f4c6 Merge branch 'master' into feature/improved-readOnly-immutable 2025-03-18 22:43:00 +13:00
Rob Bygrave 4e7f3c13a0 Merge pull request #3592 from ebean-orm/feature/improved-readOnly-immutable-part2
Remove readOnly, migrate to unmodifiable (or use normal mutable)
2025-03-18 22:41:12 +13:00
Thomas a35db6bdee Add feature findFutureMap 2025-03-18 09:19:15 +01:00
Rob Bygrave d7366dec0f Tidy readOnly removal 2025-03-18 20:59:04 +13:00
Rob Bygrave ceee1d7489 Remove readOnly from Query 2025-03-18 20:49:26 +13:00
Rob Bygrave 1b23319fa4 Remove readOnly from EntityBeanIntercept and BeanCollection 2025-03-18 20:32:22 +13:00
Rob Bygrave 6f726973ea Remove most internal use of readOnly 2025-03-18 19:53:13 +13:00
Rob Bygrave 82284b19d5 Bean cache sharable instances as unmodifiable + bean cache queries can also be unmodifiable
Entities without *any* relationships can support "sharable instances" with bean caching. This change restores that and uses unmodifiable instances (rather than the old ReadOnly).

Currently, for a query to get shared instances it now needs to explicitly use setUnmodifiable(true) where as before it defaulted to shared instances so that is a behaviour change.

Additionally, bean cache queries were not honouring setUnmodifiable(true) and with these changes they now do.
2025-03-16 23:19:54 +13:00
Rob Bygrave 798d01abd1 LazyInitialisationException, plus javadoc 2025-03-16 21:12:25 +13:00
Rob Bygrave 5136a5a708 Support unmodifiable Embedded and EmbeddedId 2025-03-13 22:52:45 +13:00
Rob Bygrave fa25d7cc8a Using Query Cache now implies unmodifiable
- Query Cache now holds unmodifiable collections
- Can no longer have readOnly=false with queryCache=true
- Reference beans now also honor unmodifiable
- Effectively no longer does bean cache lookup for reference beans (which it defaulted to when cacheSharableBeans true, e.g. Country entity bean)
2025-03-11 23:50:34 +13:00
Rob Bygrave c13e09257c Version 14.10.0 2025-03-11 21:26:00 +13:00
Rob Bygrave ed65433640 Merge pull request #3574 from ebean-orm/feature/3459-postgres-varchar
#3459 Postgres varchar default to no length (aka text)
2025-03-11 20:01:26 +13:00
Rob Bygrave 08890e9d5a Merge pull request #3590 from ebean-orm/feature/3580-lookwriter-logWarn
Adjust LookupWriter to log at WARN rather than ERROR due to Quarkus dev mode
2025-03-10 23:56:19 +13:00
Rob Bygrave 4273c4af6a Adjust LookupWriter to log at WARN rather than ERROR due to Quarkus dev mode
Die to Quarkus dev mode (#3541 #3582) we want to log FilerException at WARN level rather than ERROR. This is because Quarkus dev mode will invoke the annotation processor more than usual, so we expect to fail with the FilerException.
2025-03-10 23:42:38 +13:00
Rob Bygrave 51424d9eea Merge pull request #3580 from SentryMan/feature/lookup-generation
[querybean-generator] Generate lookup for modules
2025-03-10 23:31:35 +13:00
Rob Bygrave cf2ab33903 Merge pull request #3589 from ebean-orm/feature/bump-ebean-agent-dependency
Bump ebean-agent to 14.10.0
2025-03-10 23:28:05 +13:00
Rob Bygrave 90d8b4fb04 Bump ebean-agent to 14.10.0 2025-03-10 23:27:02 +13:00
Rob Bygrave ff4eeff264 Merge pull request #3588 from ebean-orm/feature/3586-querybean-gen
[query bean generation] #3586 public constructor for Embedded bean
2025-03-10 08:02:03 +13:00
Rob Bygrave 64ba343e35 [query bean generation] #3586 public constructor for Embedded bean 2025-03-10 07:59:33 +13:00
Rob Bygrave af3c59c0fd Merge pull request #3587 from ebean-orm/feature/bump-test-containers-77
Bump ebean-test-containers dependency - improved SQL Server handling
2025-03-10 07:40:31 +13:00
Rob Bygrave ae55d28026 Bump ebean-test-containers dependency - improved SQL Server handling
Improvments around collation changes that end up making SQL Server startup flaky
2025-03-10 07:40:02 +13:00
Rob Bygrave ddffc8eee2 Merge pull request #3581 from apflieger/#3573-initfields-prevent-secondary-query
OneToMany initialisation via List.of() - was Tests only - new test on multiple many joins
2025-03-10 07:30:40 +13:00
Rob Bygrave 7f1a3a46cf #3581 ebean-agent 14.10.0 handling for OneToMany initialisation 2025-03-10 07:12:20 +13:00
Rob Bygrave a59f75a468 Merge pull request #3585 from nedge/feature/Create_test_entities
Simple Test Entities in preparation for type scoped loading
2025-03-05 08:06:39 +13:00
Eddie Mc Greal 6f1c66ecd6 Simple Test Entities in preparation for type scoped loading 2025-03-04 14:17:08 +01:00
Rob Bygrave 25f6fb6d6f test only - Almost fix the model for test_manyNonRoot_RootHasNoMany
The test was using field access??? when that isn't valid unless we specifically turn on enhancement to support that.

Using proper method access though stops the test from failing.
2025-03-03 21:42:15 +13:00
Rob Bygrave 852def8536 test only - use assertThat hasSize instead of assertEquals for test_manyNonRoot_RootHasNoMany 2025-03-03 21:34:22 +13:00
Rob Bygrave dfb29fd75f Merge pull request #3578 from mkurz/fix_3577
Work around `mysqldump` bug by moving comment one line up
2025-03-03 21:26:40 +13:00
Rob Bygrave 80c3501197 Merge pull request #3583 from ebean-orm/feature/revert-3541-3582
[querybean-generator] #3582 - Revert #3541 "FilerException trying to write EntityClassRegister with Quarkus dev mode / hot reload "
2025-03-03 21:25:39 +13:00
Rob Bygrave b4ff5748fc Merge pull request #3579 from FOCONIS/rollbac-or-commit-before-close
Rollback/Commit raw connections before close
2025-03-03 21:25:12 +13:00
Rob Bygrave 64f01f0543 [querybean-generator] #3582 - Revert #3541 "FilerException trying to write EntityClassRegister with Quarkus dev mode / hot reload "
This reverts commit 69c25309 and applies the required "Fix" in the initModuleInfoBean() method to catch FilerException and log it at WARN level
2025-03-03 20:49:19 +13:00
Arnaud Pflieger fee6e0f480 Tests only - new test on multiple many joins
This test reproduce the problem of #3573
The field initialization `= List.of();` prevents eager secondary query.
2025-02-28 12:20:18 +01:00
Josiah Noel 50b44c4529 Update LookupWriter.java 2025-02-28 00:29:03 -05:00
Josiah Noel f0c2ba0e28 [Feature] Generate lookup for modules
Generate Lookup Class for modular projects
2025-02-27 20:47:16 -05:00
Roland Praml 7643dc9b22 Rollback/Commit raw transactions before close 2025-02-27 10:56:41 +01:00
Matthias Kurz c49a1b3d71 Work around mysqldump bug by moving comment one line up
It seems like mysqldump just adds ;; to the last line and does not
check if that line is a comment. To work around that it's good enough
to move the comment one line up - as long as the END does not end with ;
(which here it does not so that is ok)
2025-02-26 15:36:20 +01:00
Rob Bygrave 11e783938c Merge pull request #3576 from ebean-orm/feature/bump-ebean-test-containers
#3511 bump ebean-test-containers dependency
2025-02-26 23:18:43 +13:00
Rob Bygrave 3845861e24 test only - Fix tests due to automatic inline comment included in generated sql like:
select /* TestQueryDefaultBatchSize.test_findEach_details__lazy */ t0.order_id, t0.id,

select /* TestQueryDefaultBatchSize.test_findEach_details__lazy */ t0.order_id
2025-02-26 23:15:51 +13:00
Rob Bygrave d04181865c test only - update TestOrderByWithMany which is flaky 2025-02-26 23:10:55 +13:00
Rob Bygrave 00d7db31d6 test only - update TestQueryFindIterate which is flaky 2025-02-26 23:07:53 +13:00
Rob Bygrave 6880b5673a #3511 bump ebean-test-containers dependency
ebean-test-containers version 7.6 supports extraDb for MySql and MariaDb, resolving #3511 with extraDb configuration for each extra schema/database required with MySql or MariaDb.
2025-02-26 22:24:05 +13:00
Rob Bygrave e18b59a9dd Remove deprecated ExtendedServer.setClock() migrate to DatabaseBuilder.clock() (#3566)
So we can no longer dynamically change the Clock being used and instead for testing purposes need to create the Database with a test clock instance as needed.

Refer to the ExtendedServerTest for an example
2025-02-26 22:16:12 +13:00
Rob Bygrave cc48dced09 #3572 DDL support for non-nullable JoinColumn column (#3575) 2025-02-26 21:13:50 +13:00
Rob Bygrave b13bdc95be #3459 Postgres varchar default to no length (aka text)
Change Postgres platform to default a String to varchar [with no length defined] rather than varchar(255)
2025-02-26 18:53:08 +13:00
Rob Bygrave 0a5c3ced21 Test only - update TestQueryMultiManyOrder sql asserts
No effective change.
2025-02-26 00:59:57 +13:00
Rob Bygrave 8ff5f7f72a Recursive freeze on entity beans
Noting that the freeze needs to occur after secondary queries have executed
2025-02-26 00:00:07 +13:00
Rob Bygrave 71944bb8fa Rename flags -> loaded, add message with property name to UnmodifiableEntityException 2025-02-23 22:25:46 +13:00
Rob Bygrave 24888fc01e Change InterceptReadWrite to use UnmodifiableEntityException
Add unmodified to DefaultOrmQuery query plan description
Fix incorrect merge conflict
2025-02-21 22:24:48 +13:00
Rob Bygrave 645d5bb613 Merge branch 'master' into feature/improved-readOnly-immutable 2025-02-21 22:08:38 +13:00
Rob Bygrave 4a6f1a39e0 Add UnloadedPropertyException and UnmodifiableEntityException, change existing use of IllegalStateException
- Adds new exceptions UnloadedPropertyException and UnmodifiableEntityException
- Change InterceptReadOnly to use these exception instead of IllegalStateException
- Change collections BeanSet, BeanList, BeanMap from using IllegalStateException to UnsupportedOperationException [to bring these in line with JDK unmodifiable collections]
2025-02-21 22:05:49 +13:00
Rob Bygrave 40637bd68c Allow OneToOne to map to ManyToOne (#3569) 2025-02-19 20:00:15 +13:00
Rob BygraveandJonas Pöhler 8dd438be61 #3564 Fix for nested transaction with batch-mode does not flush (#3565)
* ADD: Testcase for showing nested transaction with batch-mode not flushing batch on commit

* Update test only - TestNestedTransaction.test_txn_nestedWithInnerBatch()

Update the test to show that we desire the nested transaction changes to be "visible" after a commit regardless of flushOnQuery etc

* #3564 Fix for nested transaction with batch-mode does not flush

- Adds flush() into ScopeTrans.commitTransaction()
- Related fixes in DefaultServer execute() and executeCall() where it was performing extra unnecessary nesting on PersistenceException

* Touch

---------

Co-authored-by: Jonas Pöhler <jonas.poehler@foconis.de>
2025-02-18 07:33:48 +13:00
Rob Bygrave 5e1ad29c5d Build - add workflow_dispatch trigger to main build 2025-02-17 07:46:20 +13:00
Rob Bygrave 9eeb137907 Tests only - update test-kotlin dependency 2025-02-17 07:33:56 +13:00
Rob Bygrave 578a041c9e Version 14.9.0 2025-02-12 19:56:14 +13:00
Rob Bygrave b0b2a0d320 Bump ebean-agent to 14.9.0 with module path support for @Transactional 2025-02-12 19:36:48 +13:00
Josiah NoelandRob Bygrave de81dfc067 Feature: Add a MethodHandles.Lookup SPI (#3535)
* ServiceLoad lookups

* remove more reflection

* address comments

* Update DefaultTypeManager.java

* Javadoc and format changes

---------

Co-authored-by: Rob Bygrave <robin.bygrave@gmail.com>
2025-02-12 19:30:05 +13:00
Rob Bygrave 2bd53cb52b Merge pull request #3560 from ebean-orm/feature/3533-aop-transactional
#3533 Support @Transactional on module path
2025-02-12 18:53:57 +13:00
Rob Bygrave a6d792de64 Merge pull request #3563 from ebean-orm/feature/remove-deprecated-queryOrder
Remove deprecated order() migrate to orderBy()
2025-02-12 18:52:53 +13:00
Rob Bygrave c73d83ef33 Merge pull request #3562 from ebean-orm/feature/remove-deprecated-queryUpdTxn
Remove deprecated query.update(txn) & query.delete(txn)
2025-02-12 18:52:18 +13:00
Rob Bygrave 9f1b4ba758 Remove deprecated order() migrate to orderBy() 2025-02-12 18:47:16 +13:00
Rob Bygrave 1f7117da25 Merge pull request #3561 from ebean-orm/feature/remove-deprecated-servletContextListener
Remove deprecated ServletContextListener
2025-02-12 18:43:55 +13:00
Rob Bygrave f0ceab43bf Remove deprecated query.update(txn) & query.delete(txn)
Migrate to query.usingTransaction(txn)
2025-02-12 18:42:23 +13:00
Rob Bygrave 1107e4ea4c Remove deprecated ServletContextListener 2025-02-12 18:38:17 +13:00
Rob Bygrave 4dd8a5dfea Merge pull request #3558 from ebean-orm/feature/3557-filterMany-removal
#3557 [Query beans] Remove deprecated filterMany(String expressions, Object... params) from generated query beans
2025-02-12 18:01:39 +13:00
Rob Bygrave 195edf0355 Merge pull request #3514 from ebean-orm/feature/querybean-txn-ctor
Remove deprecated QueryBean constructor that takes transaction, migrate to query.usingTransaction()
2025-02-12 18:01:03 +13:00
Rob Bygrave e9c438adab Merge branch 'master' into feature/querybean-txn-ctor 2025-02-12 15:05:57 +13:00
Rob Bygrave e45cf5fab9 #3533 Bump ebean-agent to use the new AOPTransactionScope 2025-02-12 00:27:07 +13:00
Rob Bygrave 1bf9d1dd4f Merge pull request #3559 from ebean-orm/feature/findCount-noId
FindCount on entity bean without @Id + platform wants column alias
2025-02-12 00:01:24 +13:00
Rob Bygrave 657920c4a2 #3533 Support @Transactional on module path
As HelpScopeTrans isn't in an exported package it's use fails with an error in module path. This adds AOPTransactionScope in the exported package io.ebean.plugin and moves the required methods from SpiEbeanServer to SpiServer to support this move.

This also requires an associate change in ebean-agent to support this feature which will be in ebean-agent 14.9.0.
2025-02-11 23:57:18 +13:00
Rob Bygrave 6c47107436 FindCount on entity bean without @Id + platform wants column alias
Internally in CQueryBuilder only use query.setSelectId(); for findCount when the entity bean has a @Id property [which it doesn't strictly need and likely won't have for view based entities]
2025-02-11 23:04:02 +13:00
Rob Bygrave 88cf4e001a #3557 [Query beans] Remove deprecated filterMany(String expressions, Object... params) from generated query beans, migrate to filterManyRaw() 2025-02-11 22:06:20 +13:00
Rob Bygrave 7f1fcbcf92 Merge pull request #3556 from ebean-orm/feature/test-containers-bump
Bump ebean-test-containers to 7.5
2025-02-10 21:55:18 +13:00
Rob Bygrave 95d5d5e467 Bump ebean-test-containers to 7.5 2025-02-10 21:54:54 +13:00
Rob Bygrave 2dde23d577 Merge pull request #3555 from ebean-orm/feature/3503-kotlin-querybean-gen-DbMap
#3503 - Fix kotlin-querybean-generator for use of @DbMap
2025-02-10 14:01:09 +13:00
Rob Bygrave 1ec26d13f9 #3503 - Fix kotlin-querybean-generator for use of @DbMap 2025-02-10 11:35:44 +13:00
Rob Bygrave bb1b55e897 Reduce frequency of running yugabyte CI test 2025-02-09 22:45:10 +13:00
Rob Bygrave fb07447df4 Fix test only - test-kotlin bump kotlin-querybean-generator version 2025-02-09 22:43:02 +13:00
Rob Bygrave ad18b6573c Version 14.8.2 2025-02-09 22:07:28 +13:00
Rob Bygrave 11632c3a6e Merge pull request #3554 from ebean-orm/feature/3536-kotlin-querybean-generator
#3536 kotlin-querybean-generator update for filterMany() changes
2025-02-09 21:37:38 +13:00
Rob Bygrave b066f9c072 #3536 kotlin-querybean-generator update for filterMany() changes
Brings the kotlin-querybean-generator up to date with the [java] querybean-generator in terms of how it has specific "associated beans" for ToOne and ToMany type relationships
2025-02-09 21:24:51 +13:00
Rob Bygrave 1e38ed9efc Test only, add Embedded bean as an inner class for querybean-generation 2025-02-09 21:19:39 +13:00
Roland Praml 2d48dd2fef Pass create/configOptions to DB2 test container (#3550)
This allows to pass collation/pagesize settings via the
`ebean.test.createOptions=` property to the container
2025-02-08 19:47:20 +13:00
Rob Bygrave 60aa899a34 #3552 Column alias required for SQL Server + findCount + distinct (#3553)
* #3552 Column alias required for SQL Server + findCount + distinct

- Modifies CQueryBuilder with the main fix which is to use the database platform selectCountWithColumnAlias for all distinct queries [and later disable it for single column case]

- Modifies SqlTreeBuilder because we need to NOT use the column alias for the count distinct SINGLE COLUMN case. So change here to:
  - build the root SqlTreeNode first as part of constructor
  - use rootNode.isSingleProperty() to NOT use column alias for the single column case
  - Hence need to initialise DefaultDbSqlContext AFTER the root SqlTreeNode

  - Modifies DefaultDbSqlContext with no effective change, just columnIndex++ ONLY when we are actually using column alias

 - Modifies H2Platform to also use selectCountWithColumnAlias true

* #3552 selectCountWithColumnAlias true for MariaDB and MySql

Plus fix TestRowCount for Oracle platform
2025-02-08 19:33:03 +13:00
Rob Bygrave c38c75fdec Merge pull request #3549 from ebean-orm/feature/3546
#3546 Reduce compiler warning on query bean generated code
2025-01-28 23:34:23 +13:00
Rob Bygrave cf275f4edd #3546 Reduce compiler warning on query bean generated code
This method is effectively internal and called by generated code that also is Deprecated(forRemoval = true)
2025-01-28 23:31:23 +13:00
Rob Bygrave 121f4afed8 #3545 Support @SQL entity with a OneToOne with EmbeddedId
- @Sql entity
- Has a OneToOne or ManyToOne to a bean that uses @EmbeddedId
2025-01-28 23:26:09 +13:00
Rob Bygrave c8621c3a29 Put back the querybean-generator version 2025-01-16 21:42:02 +13:00
Rob Bygrave f83da15d5e Merge pull request #3542 from ebean-orm/feature/3542-quarkus
[querybean-generator] FilerException trying to write EntityClassRegister with Quarkus dev mode / hot reload #3541
2025-01-16 16:46:46 +13:00
Rob Bygrave 52729d9802 Missing import and adjust warning message 2025-01-16 16:40:43 +13:00
Rob Bygrave 69c25309da [querybean-generator] FilerException trying to write EntityClassRegister with Quarkus dev mode / hot reload #3541
Drop to log at WARN level when we catch FilerException such that Quarkus dev mode / hot reload works
2025-01-16 16:31:52 +13:00
Rob Bygrave 723a12fd66 #3538 Restoring batchMode etc with nested transaction scopes
This change is a simplification such that these batch attributes are always stored and restored for nested ScopeTrans.

There are no expensive side effects of doing it this way.

This fixes issues where the batch attributes are changed after the ScopeTrans is created (like the test for this PR).
2025-01-16 08:15:22 +13:00
Noemi Praml 5cf74f1ee9 Add: failing Unittest 2025-01-08 14:43:49 +01:00
Rob Bygrave 2c18b4fe97 Version 14.8.1 2024-12-20 15:34:07 +13:00
Rob Bygrave 9c9fb70999 Bump ebean agent to align 2024-12-20 15:24:08 +13:00
Rob Bygrave 18e6374a60 Merge pull request #3532 from ebean-orm/feature/sql-play-ebean
#3408 play-ebean inline sql comment in test generated scripts
2024-12-20 14:59:54 +13:00
Rob Bygrave 3fea5ce93d #3408 play-ebean inline sql comment in test generated scripts 2024-12-20 14:58:10 +13:00
Rob Bygrave 43675468ae Merge pull request #3523 from FOCONIS/streaming-tests
set defaultFetchBuffer in findEach/findList in SQL and DTO Queries
2024-12-19 11:04:01 +13:00
Rob Bygrave 1c038f4629 Merge pull request #3408 from mkurz/meta_datastored-procedures-DDL
Add metadata to stored procedures for 3rd party libs
2024-12-19 10:47:14 +13:00
Rob Bygrave 49b6f3dec9 Merge pull request #3530 from SentryMan/fix/dto-lookup
FIX: IllegalAccessError on modular DTO queries
2024-12-19 09:07:45 +13:00
Josiah Noel 346e30217a Merge remote-tracking branch 'upstream/master' into fix/dto-lookup 2024-12-18 14:56:15 -05:00
Rob Bygrave 5dc165debf Fix test TestLazyJoin2 2024-12-19 08:42:37 +13:00
Josiah Noel d5cb7c3ff1 fix illegal access error on modular dtos
When using a dto query on a JPMS application, I get an IllegalAccessError even though I export and open my package.
2024-12-18 00:20:08 -05:00
Roland Praml 4d08dce033 set defaultFetchBuffer in findEach/findList in relational/orm Queries 2024-11-27 17:05:15 +01:00
Roland Praml beef4407e3 Add failing testcase 2024-11-27 17:02:15 +01:00
Matthias Kurz e99f922de6 Add metadata to stored procedures for 3rd party libs
This way a third party can parse the meta data and knows how
to handle the bodies of a stored procedure
2024-11-26 23:36:30 +01:00
Rob Bygrave 1fef4f7c11 Add explicit query.setUnmodifiable(true) [for readOnly=true + disableLazyLoad=true]
Although this is ok, makes me think that another option is just to have query.setReadOnly(true)
to mean ... readOnly + disableLazyLoad + error reading unloaded property or collection. As in,
readOnly true without these extra things does not that good [as in the existing readOnly does
not seem very good/safe/useful to use].
2024-11-20 23:01:59 +13:00
Rob Bygrave 103e8323f2 Merge pull request #3519 from FOCONIS/no-codechange-test-cleanup
No productive code change: cleanup basic test data
2024-11-07 21:32:35 +13:00
Noemi Praml 59ed0bb015 fix delete contacts 2024-11-05 14:04:32 +01:00
Noemi Praml c0eb896e1f No productive code change: cleanup basic test data (#114)
* Erste Tests bereinigt

* fix

* noch mehr Tests bereinigt

* modify output

* reformat
2024-11-05 13:16:47 +01:00
Noemi Praml 3ab3f81fa3 Add failing concurrent test 2024-10-31 08:21:37 +01:00
Rob Bygrave ddb4b9d3e5 Remove deprecated QueryBean constructor that takes transaction, migrate to query.usingTransaction()
Remove the constructor for QueryBean that takes transaction. Migrate code to use query.usingTransaction() instead.
2024-10-31 18:22:43 +13:00
Rob Bygrave 7035b4c74c tests only: Update versions in test / test-kotlin maven plugin and apt 2024-10-31 18:19:36 +13:00
Rob Bygrave 85a575e353 Merge pull request #3513 from ebean-orm/feature/bump-parent-javadoc
Bump java11-oss parent and tidy javadoc
2024-10-31 17:14:52 +13:00
robin.bygrave eb05be286c Bump java11-oss parent and tidy javadoc 2024-10-31 14:55:43 +13:00
Rob Bygrave 9f5a77fdaa Merge pull request #3509 from FOCONIS/javadoc-fixes
RFC: Fix some javadoc issues
2024-10-31 14:47:46 +13:00
Roland Praml 42ee75f212 RFC: Fix some javadoc issues 2024-10-25 08:46:34 +02:00
Rob Bygrave 4610dbb26e Version 14.8.0 2024-10-25 14:28:58 +13:00
Rob Bygrave b26382f99c Merge pull request #3507 from ebean-orm/feature/agent-1480
Bump ebean-agent to 14.8.0
2024-10-25 14:18:20 +13:00
Rob Bygrave 2fba89f846 Bump ebean-agent to 14.8.0
This ebean agent is required to support the fluid QueryBuilder API change.
2024-10-25 14:17:46 +13:00
Rob Bygrave e4f13da868 Merge branch 'dynamic-property-group-by' 2024-10-24 16:13:01 +13:00
Rob Bygrave 32cd081fce #3504 Tidy test only and final method 2024-10-24 16:12:45 +13:00
Rob Bygrave e6f92eaceb ReadOnly Immutable query WIP 2024-10-24 16:02:50 +13:00
Rob Bygrave f6da332998 Add test for TestReflectiveModificationUpdate 2024-10-24 08:37:02 +13:00
Alexander Wagner d8f321d87b Fix: dynamic property group by with alias 2024-10-22 13:24:12 +02:00
Rob Bygrave c868d8a23b Fix test for Postgres TestDistinctOnQuery 2024-10-22 19:00:52 +13:00
Rob Bygrave d77c14d866 Fix test for Postgres TestDistinctOnQuery 2024-10-22 08:14:01 +13:00
Rob Bygrave 423d906848 Merge pull request #3499 from ebean-orm/feature/3489
Potentially breaking change: Throw PersistenceException for unknown property in select clause
2024-10-18 19:25:46 +13:00
Rob Bygrave 100d33cc94 Potentially breaking change: Throw PersistenceException for unknown property in select clause 2024-10-18 19:12:53 +13:00
Rob Bygrave 20cf6a9c00 Merge pull request #3498 from ebean-orm/feature/migrate-avaje-lang-to-jspecify
Migrate to JSpecify NullMarked/Nullable from avaje.lang NonNullApi/Nullable
2024-10-18 16:56:19 +13:00
Rob Bygrave e2c12268f7 Merge branch 'master' into feature/migrate-avaje-lang-to-jspecify 2024-10-18 16:52:53 +13:00
Rob Bygrave 937f6296e1 Merge pull request #3497 from ebean-orm/feature/fluid-self-querybuilder
Fix SELF of QueryBuilder, QueryBean, IQueryBean for fluid use
2024-10-18 16:48:26 +13:00
Rob Bygrave 24749567d2 Migrate to JSpecify NullMarked/Nullable from avaje.lang NonNullApi/Nullable 2024-10-18 16:46:41 +13:00
Rob Bygrave 7045240778 Merge branch 'transaction-readonly' 2024-10-18 16:27:18 +13:00
Rob Bygrave 6ceea85b94 Move markNotQueryOnly() into init transaction methods of PersistRequest 2024-10-18 16:26:49 +13:00
Rob Bygrave e04ac50800 Fix SELF of QueryBuilder, QueryBean, IQueryBean for fluid use
Currently, the SELF response type of QueryBuilder returns as Object when really we want it to return the SELF generic type of QueryBuilder, QueryBean, IQueryBean etc

Note that this change requires an updated ebean-agent
2024-10-18 16:18:39 +13:00
Noemi Praml a452fc0e21 call request.markNotQueryOnly 2024-10-17 16:30:42 +02:00
Noemi Praml 4438d5db7d Fixes in DefaultPersister 2024-10-17 16:19:19 +02:00
Noemi Praml 9ca6fa31e5 more tests 2024-10-17 16:19:03 +02:00
Rob Bygrave e0a00bea34 Merge pull request #3496 from mumbler6/fix-flaky
fixed flaky test in ToStringBuilderTest.java
2024-10-17 21:36:15 +13:00
mumbler6 b24b549298 fixed flaky test in ToStringBuilderTest.java 2024-10-15 22:41:51 -05:00
Rob Bygrave 51d0f4efcc Fix test TestOrderedList for Postgres ANY 2024-10-15 22:14:45 +13:00
Noemi Praml e08985d7c5 suggested solution 2024-10-14 16:53:48 +02:00
Noemi Praml 4f984ff2d4 add: failing test 2024-10-14 16:53:00 +02:00
Rob Bygrave b6843c6db0 Version 14.7.0 2024-10-10 23:48:29 +13:00
Rob Bygrave 57782c05b5 Update ebean-agent to 14.7.0 (Updates to ASM 9.7.1) 2024-10-10 23:46:37 +13:00
Rob Bygrave a2ee8b61f8 Merge pull request #3487 from FOCONIS/batch-ordering-bug
Bug: Batch ordering - Regression introduced in version 13.26.1, insertAll() leaves batchMode=true enabled ... when it should not
2024-10-10 22:31:15 +13:00
Rob Bygrave 1225a2776f Merge pull request #3485 from FOCONIS/ordercolumn-cache-queries
Fix orderBy for cached many requests
2024-10-10 22:30:23 +13:00
Rob Bygrave a499c8c26a Merge pull request #3493 from ebean-orm/feature/3490
#3490 filterMany generates invalid sql when the many side uses @EmbeddedId to model composite primary key
2024-10-10 22:27:58 +13:00
Rob Bygrave 8e627c756f #3490 filterMany generates invalid sql when the many side uses @EmbeddedId to model composite primary key 2024-10-10 22:24:24 +13:00
Rob Bygrave 45cc78bb0a #3490 filterMany generates invalid sql when the many side uses @EmbeddedId to model composite primary key 2024-10-10 22:11:20 +13:00
Rob Bygrave 38a8e95b36 #3491 Update javadocs and SqlQuery Postgres ANY tests 2024-10-10 20:08:03 +13:00
Rob Bygrave bca381104b Merge pull request #3491 from ajcamilo/master
Add setArrayParameter to SqlQuery
2024-10-10 20:07:08 +13:00
André Camilo 7e0c6795ff add setArrayParameter to SqlQuery 2024-10-09 13:24:52 +01:00
Roland Praml 8b4804be22 Fix: after DB.inserAll, transaction may stay in batchmode 2024-10-08 13:16:37 +02:00
Roland Praml a8418a3d75 Created test for batch escalation 2024-10-08 13:16:32 +02:00
Rob Bygrave bb0f63e38a Merge pull request #3488 from ebean-orm/dependabot/maven/ebean-test/commons-io-commons-io-2.14.0
Bump commons-io:commons-io from 2.7 to 2.14.0 in /ebean-test
2024-10-08 18:28:32 +13:00
Rob Bygrave 978ed26b78 Update ebean-agent 14.6.1 for #3484 2024-10-08 18:23:46 +13:00
Rob Bygrave 5cfa7295f8 Update tests for test-kotlin with latest agent 2024-10-08 18:17:08 +13:00
Noemi Praml 88d8b4fb5e Fix orderBy for cached many requests 2024-10-07 15:04:46 +02:00
dependabot[bot] 93155d3c8f Bump commons-io:commons-io from 2.7 to 2.14.0 in /ebean-test
Bumps commons-io:commons-io from 2.7 to 2.14.0.

---
updated-dependencies:
- dependency-name: commons-io:commons-io
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-03 18:46:07 +00:00
Rob Bygrave 6d5f740337 TestQueryPaging example to H2 and Postgres due to use of nulls first
nulls first isn't supports by mysql
2024-09-20 21:21:57 +12:00
Rob Bygrave bd06b57144 Add valhalla EA build 2024-09-18 20:49:40 +12:00
Rob Bygrave 77383f4d29 Version 14.6.0 2024-09-17 22:23:13 +12:00
Rob Bygrave 29fcbbfe97 Bump ebean-agent to 14.6.0 2024-09-17 22:09:44 +12:00
Rob Bygrave d9e0a35efb Merge pull request #3481 from ebean-orm/feature/boostrap-service
Use io.ebean.service.BootstrapService as common marker interface for service loading bootstrapped services
2024-09-17 22:03:52 +12:00
Rob Bygrave 0c01ecbac7 Merge pull request #3478 from ebean-orm/feature/3462
#3462 Add Paging as alternative to maxRows + firstRow + orderBy
2024-09-17 22:03:13 +12:00
Rob Bygrave 5095583cc8 Merge pull request #3473 from ebean-orm/feature/3455-query-beans-improvement
#3455 - Improve query beans such that filterMany() expressions are only on ToMany relationships
2024-09-17 22:02:40 +12:00
Rob Bygrave 92f04a2353 Use io.ebean.service.BootstrapService as common marker interface for service loading bootstrapped services 2024-09-17 21:58:19 +12:00
Rob Bygrave acbce35182 Merge pull request #3480 from ebean-orm/feature/emptylist
Change EmptyPagedList to be deprecated from public use
2024-09-16 21:07:40 +12:00
Rob Bygrave d6165f4b17 Change EmptyPagedList to be deprecated from public use
This should never have been public really
2024-09-16 20:58:40 +12:00
Rob Bygrave 95656360a9 Mark OrderBy constructors as deprecated
The plan is to migrate OrderBy into an interface
2024-09-15 19:21:17 +12:00
Rob Bygrave 65d7df5488 #3462 Add Paging as alternative to maxRows + firstRow + orderBy
Paging is an alternative to specifying the maxRows + firstRow + orderBy on a query.

Example:
```java

    var orderBy = OrderBy.of("lastName desc nulls first, firstName asc");
    var paging = Paging.of(0, 100, orderBy);

    DB.find(Contact.class)
      .setPaging(paging)
      .where().startsWith("lastName", "foo")
      .findList();
```
2024-09-12 22:54:35 +12:00
Rob Bygrave 12648cd37d Fix test TestQueryFilterMany 2024-09-12 20:31:37 +12:00
Rob Bygrave edbd13c075 Version 14.5.2 2024-09-11 20:58:13 +12:00
Rob Bygrave 0964980a69 Merge pull request #3474 from ebean-orm/feature/3453
#3453 - Different filterMany behavior when no matches found
2024-09-11 20:27:50 +12:00
Rob Bygrave dc7d349366 #3453 - Different filterMany behavior when no matches found 2024-09-10 23:11:44 +12:00
Rob Bygrave a2e66bcb89 #3455 - Improve query beans such that filterMany() expressions are only on ToMany relationships
Use protected helper methods on TQAssocBean for the filterMany() methods generated onto AssocMany beans.
2024-09-10 00:24:41 +12:00
Rob Bygrave 4d79815779 #3455 - Improve query beans such that filterMany() expressions are only on ToMany relationships
Changes the query bean code generation for "Associated beans" to have separate AssocOne and AssocMany for *ToOne and *ToMany relationships.

Moves the filterMany() expressions such that they are only available on the *ToMany relationships.
2024-09-09 23:26:13 +12:00
Rob Bygrave cbac00a89f Merge pull request #3472 from ebean-orm/feature/3461-take-2
#3461 - Add also() for query beans
2024-09-09 22:18:40 +12:00
Rob Bygrave 33b2c398f6 #3461 - Add also() for query beans 2024-09-09 22:13:04 +12:00
Rob Bygrave 416f50e782 Merge pull request #3471 from ebean-orm/feature/bump-agent
Bump ebean-agent, will support future improvement to query beans with…
2024-09-09 21:59:20 +12:00
Rob Bygrave 2e8a6ceb53 Bump ebean-agent, will support future improvement to query beans with AssocOne AssocMany 2024-09-09 21:54:09 +12:00
Rob Bygrave f0fd9003ad Version 14.5.1 2024-09-02 22:03:55 +12:00
Rob Bygrave dfeffb7c5e Bump ebean-agent, no effective change 2024-09-02 21:50:21 +12:00
Rob Bygrave 4b0fcb1d29 Merge pull request #3469 from ebean-orm/feature/orderBy2
#3466 - Duplicated entities in findMany when a ManyToOne relation is fetched
2024-09-02 20:53:42 +12:00
Rob Bygrave a7fe5d2b84 #3466 - Duplicated entities in findMany when a ManyToOne relation is fetched (Postgresql)
Internally in OrmQueryDetail.markQueryJoins() the SpiQueryManyJoin is determined and returned. This change uses this and effectively removes the code from OrmQueryRequest.determineMany() and BeanDescriptor.manyProperty() which was the source of this issue (performing a similar task but not correctly taking the full path into account and hence the source of this bug).
2024-09-02 19:28:11 +12:00
Rob Bygrave 30327fe33e Improve existing test asserts around order by clause (#3467) 2024-09-02 08:25:19 +12:00
Rob Bygrave 1e013331d4 Improve existing test asserts around order by clause 2024-09-02 08:19:02 +12:00
Rob Bygrave f8964707d9 #3463 - Ignore queryBean.select(null) calls (#3464) 2024-08-27 21:01:51 +12:00
Rob Bygrave 86c7de2de8 ebean-test: Modify postgis platform to support both net.postgis and og.postgis (#3449)
* ebean-test: Modify postgis platform to support both net.postgis and org.postgis

Use Class.forName() to test existence of net.postgis.jdbc.DriverWrapperLW and if available use that driver rather than the older org.postgis.DriverWrapperLW one.

Also support explicitly specifying the driver to use via test property - ebean.test.postgis.driver

* Update test for net postgis to use a separate container

* Remove NetPostgisSetup as PostgisSetup handles both cases now
2024-08-27 20:44:03 +12:00
Michael Benz 53b4d94933 Update README.md fixing broken Foconis logo (#3457)
Updated the Foconis AG logo with the new Foconis Analytics URL which was broken because of a deep link to a Yoomla logo that is no longer available.
2024-08-27 20:40:36 +12:00
Rob Bygrave b0ec23e53c Update tests to ensure ResetBasicData.reset() was called early 2024-08-04 18:59:46 +12:00
Rob Bygrave 20caae532c Adjust ResetBasicData with more output 2024-08-04 18:15:22 +12:00
Rob Bygrave 4369481c1a Adjust ResetBasicData with more output 2024-08-04 18:11:36 +12:00
Rob Bygrave c94426b6b4 Update tests config for ebean-net-postgis-types 2024-07-22 22:01:42 +12:00
Rob Bygrave b2ff32e88c Update tests config for ebean-net-postgis-types 2024-07-22 21:47:48 +12:00
Rob Bygrave 3bd8dfa7bf Update tests config for ebean-net-postgis-types 2024-07-22 20:12:27 +12:00
Rob Bygrave 0e7abdd137 Version 14.5.0 2024-07-22 08:33:34 +12:00
Ryszard Trojnacki 9135f2cd3e New Postgis types / Java modules (#3448)
* Added modules `ebean-net-postgis-types`, `ebean-net-postgis` for new `net.postgis` geometry types without support for GeoLatte.

* Added missing `uses` entry in `module-info.java` for `io.ebean.api`.
2024-07-22 07:31:30 +12:00
Rob Bygrave 6785d5703e Update tests for DB2 forUpdate() 2024-07-17 08:01:26 +12:00
Rob Bygrave 0a95ac7fa0 Update tests for DB2 forUpdate() 2024-07-16 22:18:29 +12:00
Rob Bygrave bbd5636689 #3444 - DBName with hyphens creates invalid code (#3447) 2024-07-16 20:22:08 +12:00
Noemi Praml 9f0eaef3d8 Db2 forupdate fix (#3446)
* ADD failing test for db2

* ADD: possible fix
2024-07-16 19:37:20 +12:00
Rob Bygrave a5d2a574d3 #3433 - Put test back from desc -> description as desc as a column name isn't widely supported by other databases 2024-07-08 21:54:35 +12:00
Rob Bygrave 6e7adbb8e4 #3433 - Entity property called desc used with query order by desc generates bad sql (#3438) 2024-07-04 00:05:01 +12:00
Rob Bygrave 8913bead89 [ebean-migration] #3434 - Connection is closed error running migration with MySql and Hikari (#3437) 2024-07-02 23:47:14 +12:00
Rob Bygrave cdf1cd8487 [ebean-redis] Fix for #3432 empty value for natural keys (#3436) 2024-07-02 22:06:57 +12:00
Rob Bygrave 2582c4b653 Bump to ebean-agent 14.5.0/15.5.0 with ASM 9.7 for JDK 22 and 23 support (#3435) 2024-07-02 18:08:08 +12:00
Rob Bygrave a9e3e2ea43 Version 14.4.0 2024-06-26 22:33:04 +12:00
Rob Bygrave 834ce971b3 Bump ebean-agent, no functional change 2024-06-26 22:19:58 +12:00
Rob Bygrave 5c27f89677 Change includeLabelInSql to default to true (#3431)
To disable this use ebean.includeLabelInSql=false or set this via
`DatabaseBuilder.includeLabelInSql(false)``
2024-06-26 20:32:19 +12:00
Rob Bygrave bfbbb7e7a7 Bump ebean-datasource dependency to 9.0 with automatic Lambda mode detection (#3430)
* Bump ebean-datasource dependency to 9.0 with automatic Lambda mode detection

ebean-datasource 9.0 automatically detects when it is running in AWS Lambda
and will set validateOnHeartbeat to false. In Lambda we don't want to validate
connections in background threads that can suspend in Lambda.
2024-06-26 20:27:49 +12:00
Rob Bygrave a8947c7d2f Bump ebean-migration dependency to 14.1.0 with fastMode enabled by default (#3429)
ebean-migration 14.1.0 defaults fastMode to true. This means that it first
runs a fast check that all migrations have been run. If that does not succeed
for any reason it runs the normal migration process.
2024-06-26 20:15:21 +12:00
Rob Bygrave d5401efb08 #3423 JtaTransactionManager keeps reference to already closed scope (and Transaction/connection ThreadLocal) when JtaTxnListener#afterCompletion is called by a different thread (#3424)
Bugfix for "Long/slow transaction reaper" in Wildfire that can close/rollback a transaction in a different thread. Fix is to use active flag to inactivate the transaction and detect that case in JtaTransactionManager.getCurrentTransaction()
2024-06-21 07:57:31 +12:00
Rob Bygrave 925ceaf441 Update build actions/setup-java@v4 2024-06-14 21:47:43 +12:00
Rob Bygrave c5fea13ca5 Update build actions/setup-java@v4 2024-06-14 21:42:06 +12:00
Rob Bygrave 6fa3759786 Add 23 to build 2024-06-14 21:34:54 +12:00
Rob Bygrave 1c5288b6ec Version 14.3.1 2024-06-10 19:26:40 +12:00
Rob Bygrave b485fb7440 Bump ebean-agent to 14.3.1 2024-06-10 19:02:41 +12:00
Rob Bygrave b07f909dd3 Bump parent pom to 4.2 with EA changes to annotation processing (#3417)
* Bump parent pom to 4.2 with EA changes to annotation processing

Annotation processing needs to be explicitly on in JDK 24 EA builds

* Bump bytebuddy version in ebean-test and use experimental=true for EA builds

* Use parent pom 4.3 with bytebuddy.experimental=true by default for surefire
2024-06-10 18:36:40 +12:00
Rob Bygrave fa92e7a4b7 Merge pull request #3416 from ebean-orm/feature/querybean-gen-suppresswarnings
Change QueryBean to use protected constructors, suppress warning on generated query beans
2024-06-10 12:39:53 +12:00
Rob Bygrave 1823ef288a Change QueryBean to use protected constructors, suppress warning on generated query beans 2024-06-07 22:48:04 +12:00
Rob Bygrave 7b2128b02f Merge pull request #3415 from ebean-orm/feature/3412
#3412 Use existing/parent transaction with fetch query on ToMany paths
2024-06-07 22:31:24 +12:00
Rob Bygrave 3c84a902e8 Followup for #3412 - Refactor DefaultBeanLoader move query creation logic into LoadBeanRequest
Move the query creation, using transaction and configure into LoadBeanRequest. This code then looks more like that of LoadManyRequest.
2024-06-07 22:26:48 +12:00
Rob Bygrave 3ce95c34cb #3412 Use existing/parent transaction with fetch query on ToMany paths
Fix such that LoadManyRequest uses the parent requests transaction rather
than obtain a new read only transaction to perform the fetch query.
2024-06-07 22:16:02 +12:00
Rob Bygrave d817dcb549 Merge pull request #3413 from ebean-orm/feature/fix-logging-naturalKey
Fix logging message for naturalKey MPUT to include the natural key properties
2024-05-31 21:57:24 +12:00
Rob Bygrave 5f218e1fdb Merge pull request #3409 from kaiyaok2/fix_NIO
Fixed non-idempotent tests in `TestCacheSerialization`
2024-05-31 21:56:33 +12:00
Rob Bygrave 59daf5689a Fix logging message for naturalKey MPUT to include the natural key properties 2024-05-31 21:52:38 +12:00
kaiyaok2 44efed5cd9 fixed non-idempotent tests 2024-05-26 23:57:12 +08:00
Rob Bygrave be28314e31 Update test kotlin to use kotlin-querybean-generator 14.3.0
Fixes the test as we now use QueryBean etc rather than TQRootBean
2024-05-16 00:05:55 +12:00
Rob Bygrave 053d82b54a Version 14.3.0 2024-05-14 22:10:08 +12:00
Rob Bygrave 0141e2effa Merge pull request #3401 from ebean-orm/feature/agent-14.3.0
Bump to ebean-agent 14.3.0
2024-05-14 21:18:12 +12:00
Rob Bygrave a33bb4d4c8 Bump to ebean-agent 14.3.0 2024-05-14 21:15:13 +12:00
Rob Bygrave d0348210be Merge pull request #3398 from ebean-orm/feature/NoTimeZone
mysql: Support "NoTimeZone" to bypass MySQL JDBC use of Timezone Calendar
2024-05-01 20:30:56 +12:00
Rob Bygrave 753cf66cf0 Merge pull request #3397 from ebean-orm/feature/distinctOn
Postgres: Add support for DISTINCT ON query clause
2024-05-01 20:30:41 +12:00
Rob Bygrave 4a8b4dd5fb mysql: Support "NoTimeZone" to bypass MySQL JDBC use of Timezone Calendar
Refer #3393 #3394
2024-05-01 20:24:10 +12:00
robin.bygrave 2faf7008db #3397 DISTINCT ON subquery support 2024-05-01 20:07:16 +12:00
Rob Bygrave 76c25cbe83 Postgres: Add support for DISTINCT ON query clause - fix test ebean.properties 2024-05-01 01:04:33 +12:00
Rob Bygrave 5c36a725f4 Postgres: Add support for DISTINCT ON query clause 2024-05-01 00:50:37 +12:00
Rob Bygrave b99d4f5a51 Merge pull request #3396 from ebean-orm/feature/limitOffset-with-labelComment
Include inline sql hint and comment in limit/offset sql
2024-04-30 23:57:04 +12:00
Rob Bygrave 7d18942357 Include inline sql hint and comment in limit/offset sql 2024-04-30 23:46:36 +12:00
Rob Bygrave e51d9ba2ab Fix test test-java16 using maven.compiler.release 2024-04-14 22:26:20 +12:00
Rob Bygrave 1b1dce90ed Merge pull request #3385 from ebean-orm/feature/rename-tqrootbean
Rename TQRootBean to QueryBean
2024-04-12 22:47:07 +12:00
Rob Bygrave 405834fa45 Merge branch 'master' into feature/rename-tqrootbean 2024-04-12 22:46:55 +12:00
Rob Bygrave 7720229af9 Merge pull request #3389 from ebean-orm/feature/bump-datasource-2
Bump ebean-datasource, ebean-test-containers, ebean-agent
2024-04-12 21:51:51 +12:00
Rob Bygrave 89a294414e Bump ebean-agent 14.2.1 2024-04-12 21:49:56 +12:00
Rob Bygrave 7bbfc00b86 Bump ebean-datasource and ebean-test-containers
ebean-datasource 8.14 has experimental lambda mode
ebean-test-containers has helper method to create S3Client for Localstack
2024-04-11 23:20:37 +12:00
Rob Bygrave d6c76de0a2 Merge pull request #3387 from ebean-orm/feature/bump-parent-4_1-byteBuddy
Bump parent to 4.1 with Byte-Buddy net.bytebuddy.experimental=true
2024-04-09 21:32:32 +12:00
Rob Bygrave 36f3986689 Bump avaje junit composite and bytebuddy to 1.14.13 2024-04-09 21:06:52 +12:00
Rob Bygrave f0f4f13ec6 Bump parent to 4.1 with Byte-Buddy net.bytebuddy.experimental=true
Uses maven-surefire-plugin with:
<argLine>-XX:+EnableDynamicAgentLoading -Dnet.bytebuddy.experimental=true</argLine>
2024-04-09 21:03:59 +12:00
Rob Bygrave 08466d42e9 Fix test TestLazyLoadMany with orderBy on query 2024-04-05 22:56:05 +13:00
Rob Bygrave 1f841982a5 Rename TQRootBean to QueryBean 2024-04-05 22:08:26 +13:00
Rob Bygrave b34704a1fa Fix kotlin test to use latest kotlin-querybean-generator 2024-04-05 00:29:17 +13:00
Rob Bygrave 0128d64841 Version 14.1.0 2024-04-04 22:54:23 +13:00
Rob Bygrave 68b313f778 Update ebean-agent to 14.1.0
This version allows for removal of query bean setRoot() which is no longer needed.
2024-04-04 22:42:06 +13:00
Rob Bygrave fad32c58d8 Merge pull request #3384 from ebean-orm/feature/rename-iquerybean
Rename QueryBean interface to IQueryBean (because we want to rename TQRootBean)
2024-04-04 22:36:59 +13:00
Rob Bygrave 8f1ebdb89a Rename QueryBean interface to IQueryBean (because we want to rename TQRootBean)
We want to rename TQRootBean to QueryBean. I can't do that right now because we need to make ebean-agent aware of that first. So yes, perhaps not ideal with IQueryBean but I think it will make sense once TQRootBean is renamed to QueryBean.
2024-04-04 22:35:55 +13:00
Rob Bygrave f7703efde2 Merge pull request #3383 from ebean-orm/feature/orderById
#3379 Followup, Move orderById() to common QueryBuilder interface
2024-04-04 22:09:34 +13:00
Rob Bygrave c5ffccb649 Merge pull request #3382 from ebean-orm/fix/3381-pc-clear
Fix for #3381 - Empty OneToMany when overflowing LazyLoadBatchSize an…
2024-04-04 22:08:57 +13:00
Rob Bygrave 3e65705bf9 #3379 Followup, Move orderById() to common QueryBuilder interface
Effectively this adds it to QueryBeans (where it was missing)
2024-04-04 22:05:17 +13:00
Rob Bygrave 7469a38bbc #3375 Followup, Temporarily add back setRoot() method to allow time for IntelliJ plugin to be released
Adding this means that it will work with an old ebean-agent. It takes a few days to get a new IntelliJ plugin released and we can't wait due to wanting to release the bug fix for #3381
2024-04-04 21:53:18 +13:00
Rob Bygrave 7ea4311662 Fix for #3381 - Empty OneToMany when overflowing LazyLoadBatchSize and mixed queries
14.0.0 via #3295 introduced this bug.

 #3295 introduced a behaviour where bulk updates clear the persistence context. Now the lazy loading of a BeanCollection works with an assumption that the "parent bean" is in the persistence context (and this assumption is broken with that change for this test case). That is, the bulk update is clearing the persistence context - removing the parent bean BEFORE the lazy loading is invoked ... and that doesn't then work because the parent bean isn't in the persistence context.

 This fix means that when lazy loading many's, the parent beans are putIfAbsent into the persistence context.
2024-04-04 20:13:20 +13:00
Rob Bygrave f556e04f58 Merge pull request #3380 from ebean-orm/feature/deprecate-update-transaction
Deprecate update(transaction) and delete(transaction) - migrate to usingTransaction(transaction)
2024-04-01 20:57:58 +13:00
Rob Bygrave d9c75a60a5 Deprecate update(transaction) and delete(transaction) - migrate to usingTransaction(transaction)
Migrate to usingTransaction(transaction) to set the transaction explicitly on a delete or update query.
2024-04-01 20:35:59 +13:00
Rob Bygrave 225bec7b28 Merge pull request #3379 from ebean-orm/feature/query-builder-interface
Add QueryBuilder interface as common API for Query and QueryBean
2024-04-01 19:42:34 +13:00
Rob Bygrave da44f7e604 Add QueryBuilder interface as common API for Query and QueryBean 2024-04-01 18:58:57 +13:00
lqbandRob Bygrave e0eda4f8be #3370 LimitOffsetPagedList add getTotalCount cache (#3373)
* #3370 LimitOffsetPagedList add getTotalCount cache

* Move totalRowCount check to inside the lock

* No change, format only on LimitOffsetPagedList

---------

Co-authored-by: Rob Bygrave <robin.bygrave@gmail.com>
2024-04-01 11:08:57 +13:00
Rob Bygrave e4e780588c Merge pull request #3378 from ebean-orm/feature/QueryBean-interface
Add QueryBean interface for query beans to implement
2024-04-01 10:59:38 +13:00
Rob Bygrave 7c8f235550 Add QueryBean interface for query beans to implement 2024-04-01 10:56:25 +13:00
Rob Bygrave 9a77ec1567 Merge pull request #3377 from ebean-orm/feature/3374
querybeans: #3374 - Add copy() method to TQRootBean
2024-04-01 09:09:24 +13:00
Rob Bygrave ff426319f5 Fix deprecated annotation for kotlin-querybean-generator 2024-04-01 09:02:13 +13:00
Rob Bygrave 7f56aff9dd Bump kotlin-querybean-generator 2024-03-31 11:49:58 +13:00
Rob Bygrave cdbdd98d36 querybeans: #3374 - Add copy() method to TQRootBean 2024-03-31 11:44:32 +13:00
Rob Bygrave 7bf030f59c Merge pull request #3376 from ebean-orm/feature/querybean-txn
Deprecate Query bean constructor that takes transaction - migrate to query.usingTransaction() instead
2024-03-31 11:38:26 +13:00
Rob Bygrave 16dca28831 Deprecate Query bean constructor that takes transaction - migrate to usingTransaction()
Migrate to query.usingTransaction() instead of the constructor that takes a transaction.
2024-03-31 11:37:32 +13:00
Rob Bygrave 678b43693d Merge pull request #3372 from ebean-orm/feature/1857-SlowQueryBindCapture
#1857 Add bind values capture for SlowQueryEvent / SlowQueryListener
2024-03-31 11:34:18 +13:00
Rob Bygrave 7ab93a0cdf Merge pull request #3375 from ebean-orm/feature/tidy-tqrootbean
Update TQRootBean with final methods, remove setRoot()
2024-03-31 11:32:54 +13:00
Rob Bygrave 951f942c73 Tidy TQRootBean constructor for alias.
Note that this requires the updated ebean-agent, where it will not longer use the setRoot() method which has now been removed.
2024-03-31 11:19:39 +13:00
Rob Bygrave cf2ec4b81d Modify TQRootBean making root final
Remove the unused setRoot() method
2024-03-31 10:02:41 +13:00
Rob Bygrave 7d1745ba53 Add final modifier to TQRootBean methods
As these are never expected to be overwritten
2024-03-31 09:57:42 +13:00
Rob Bygrave 7adbdbf532 feat: For SpringJdbcTransactionManager support using CurrentTenantProvider (#3368)
Note that this only works for Multi-Tenant PARTITION mode where the TenantId is a column on the tables (rather than schema or database multi-tenancy mode).
2024-03-26 22:45:39 +13:00
Rob Bygrave 40d9c88e34 #1857 Add bind values capture for SlowQueryEvent / SlowQueryListener
- changes SqlQueryEvent into an interface.
- captures the bind values the slow query used and makes those available via SlowQueryEvent
- also makes the query label and profileLocation available via SlowQueryEvent
2024-03-25 22:52:04 +13:00
759 changed files with 14466 additions and 7996 deletions
+5 -4
View File
@@ -2,6 +2,7 @@
name: Build
on:
workflow_dispatch:
pull_request:
push:
branches: master
@@ -20,14 +21,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'zulu'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
@@ -39,5 +40,5 @@ jobs:
# - name: Maven single test
# run: mvn --batch-mode clean verify -Dtest="io.ebeaninternal.server.core.DefaultServer_getReferenceTest" -DfailIfNoTests=false
- name: Build with Maven
run: mvn -T 8 clean test
run: mvn -T 8 clean test -Pdefault
+3 -3
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+3 -3
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'zulu'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+3 -3
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: oracle-actions/setup-java@v1
with:
website: jdk.java.net
release: ${{ matrix.java_version }}
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
@@ -37,5 +37,5 @@ jobs:
- name: Maven version
run: mvn --version
- name: Build with Maven
run: mvn -T 8 test
run: mvn test -Pea
+4 -4
View File
@@ -20,19 +20,19 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
path:
~/.m2
key: build-${{ env.cache-name }}
- name: mariadb 10.6
- name: mariadb 10.11
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-mariadb.properties
+3 -3
View File
@@ -17,14 +17,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+3 -3
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'zulu'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+3 -3
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+3 -3
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'zulu'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+3 -3
View File
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+3 -3
View File
@@ -17,14 +17,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+5 -5
View File
@@ -20,19 +20,19 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
path:
~/.m2
key: build-${{ env.cache-name }}
- name: sqlserver 2017
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-sqlserver17.properties
- name: sqlserver 2022
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-sqlserver.properties
+41
View File
@@ -0,0 +1,41 @@
name: Valhalla EA
on:
workflow_dispatch:
schedule:
- cron: '39 2 * * 3'
jobs:
build:
runs-on: ${{ matrix.os }}
permissions:
contents: read
packages: write
strategy:
fail-fast: false
matrix:
java_version: [valhalla]
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v4
- name: Set up Java
uses: oracle-actions/setup-java@v1
with:
website: jdk.java.net
release: ${{ matrix.java_version }}
- name: Maven cache
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
path:
~/.m2
key: build-${{ env.cache-name }}
- name: Maven version
run: mvn --version
# - name: Prepare
# run: ./jakarta-to-valhalla.sh
- name: Build with Maven
run: mvn package
+4 -4
View File
@@ -4,7 +4,7 @@ name: Yugabyte
on:
workflow_dispatch:
schedule:
- cron: '10 3 * * *'
- cron: '10 3 * * 3'
jobs:
build:
@@ -20,14 +20,14 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: ${{ matrix.java_version }}
distribution: 'adopt'
- name: Maven cache
uses: actions/cache@v3
uses: actions/cache@v4
env:
cache-name: maven-cache
with:
+1 -6
View File
@@ -56,12 +56,7 @@ Work at the highest level of abstraction and drop down levels as needed.
<tr>
<td align="center" valign="middle">
<a href="https://www.foconis.de/" target="_blank">
<img width="222px" src="https://www.foconis.de/templates/yootheme/cache/foconis_logo_322-709da1de.png">
</a>
</td>
<td align="center" valign="middle">
<a href="https://www.payintech.com/" target="_blank">
<img width="222px" src="https://ebean.io/images/sponsor_PayinTech-logo-noir.png">
<img width="222px" src="https://group.foconis.com/download/ci/logo/png-72dpi/logo-quer/foconis-analytics-quer.png">
</a>
</td>
<td align="center" valign="middle">
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.0.2</version>
<version>16.3.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-clickhouse</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.0.2</version>
<version>16.3.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.0.2</version>
<version>16.3.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-db2</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.0.2</version>
<version>16.3.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.0.2</version>
<version>16.3.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-hana</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.0.2</version>
<version>16.3.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mariadb</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.0.2</version>
<version>16.3.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mysql</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
</dependencies>
+85
View File
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>16.3.0</version>
<relativePath>../..</relativePath>
</parent>
<name>ebean-net-postgis</name>
<description>ebean-net-postgis composite</description>
<artifactId>ebean-net-postgis</artifactId>
<properties>
<postgis.jdbc.version>2023.1.0</postgis.jdbc.version>
<postgres.jdbc.version>42.7.2</postgres.jdbc.version>
</properties>
<dependencies>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-datasource</artifactId>
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-net-postgis-types</artifactId>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgres.jdbc.version}</version>
<exclusions>
<!-- exclude unnecessary checker framework -->
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.postgis</groupId>
<artifactId>postgis-jdbc</artifactId>
<version>${postgis.jdbc.version}</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,7 @@
package io.ebean.postgis.assembly;
/**
* Nothing interesting here - required placeholder for javadoc.
*/
public class Assembly {
}
@@ -0,0 +1,10 @@
module io.ebean.postgis {
requires transitive io.ebean.api;
requires transitive io.ebean.core;
requires transitive io.ebean.datasource;
requires transitive io.ebean.querybean;
requires transitive io.ebean.platform.postgres;
// requires transitive io.ebean.postgis.types;
}
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.0.2</version>
<version>16.3.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-nuodb</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.0.2</version>
<version>16.3.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-oracle</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
</dependencies>
+85
View File
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>16.3.0</version>
<relativePath>../..</relativePath>
</parent>
<name>ebean-pgvector</name>
<description>ebean-pgvector composite</description>
<artifactId>ebean-pgvector</artifactId>
<properties>
<pgvector.version>0.1.6</pgvector.version>
<postgres.jdbc.version>42.7.2</postgres.jdbc.version>
</properties>
<dependencies>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-datasource</artifactId>
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-pgvector-types</artifactId>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgres.jdbc.version}</version>
<exclusions>
<!-- exclude unnecessary checker framework -->
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.pgvector</groupId>
<artifactId>pgvector</artifactId>
<version>${pgvector.version}</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,7 @@
package io.ebean.pgvector.assembly;
/**
* Nothing interesting here - required placeholder for javadoc.
*/
public class Assembly {
}
@@ -0,0 +1,9 @@
module io.ebean.pgvector {
requires transitive io.ebean.api;
requires transitive io.ebean.core;
requires transitive io.ebean.datasource;
requires transitive io.ebean.querybean;
requires transitive io.ebean.platform.postgres;
}
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.0.2</version>
<version>16.3.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -22,13 +22,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
@@ -47,19 +47,19 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgis-types</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.0.2</version>
<version>16.3.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.0.2</version>
<version>16.3.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlite</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.0.2</version>
<version>16.3.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlserver</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.0.2</version>
<version>16.3.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
</dependencies>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.0.2</version>
<version>16.3.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
@@ -41,7 +41,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jackson-mapper</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
@@ -60,13 +60,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-all</artifactId>
<version>14.0.2</version>
<version>16.3.0</version>
</dependency>
</dependencies>
+3 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.0.2</version>
<version>16.3.0</version>
</parent>
<artifactId>composites</artifactId>
@@ -24,6 +24,8 @@
<module>ebean-oracle</module>
<module>ebean-postgres</module>
<module>ebean-postgis</module>
<module>ebean-net-postgis</module>
<module>ebean-pgvector</module>
<!-- <module>sqlanywhere</module>-->
<module>ebean-sqlite</module>
<module>ebean-sqlserver</module>
+5 -26
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.0.2</version>
<version>16.3.0</version>
</parent>
<name>ebean api</name>
@@ -26,20 +26,16 @@
<version>1.0</version>
</dependency>
<!--
Class retention Nonnull and Nullable annotations
to assist with IDE auto-completion with Ebean API
-->
<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-lang</artifactId>
<version>1.1</version>
<groupId>org.jspecify</groupId>
<artifactId>jspecify</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-config</artifactId>
<version>3.12</version>
<version>4.2</version>
</dependency>
<dependency>
@@ -90,23 +86,6 @@
<optional>true</optional>
</dependency>
<!-- JAVAX-DEPENDENCY-START ___
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<optional>true</optional>
</dependency>
____ JAVAX-DEPENDENCY-END -->
<!-- JAKARTA-DEPENDENCY-START -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<optional>true</optional>
</dependency>
<!-- JAKARTA-DEPENDENCY-END -->
</dependencies>
<build>
@@ -1,10 +1,9 @@
package io.ebean;
import io.avaje.lang.NonNullApi;
import org.jspecify.annotations.NullMarked;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@@ -20,7 +19,7 @@ import java.util.concurrent.TimeUnit;
* This also propagates MDC context from the current thread to the
* background task if defined.
*/
@NonNullApi
@NullMarked
public interface BackgroundExecutor {
/**
@@ -0,0 +1,25 @@
package io.ebean;
/**
* Unsupported access of a property on an entity bean.
* <p>
* Attempted a lazy load operation on a bean that has disabled lazy loading
* or attempt to mutate an unmodifiable bean.
*/
public class BeanAccessException extends UnsupportedOperationException {
private static final long serialVersionUID = 1;
/**
* Create with no message.
*/
public BeanAccessException() {
super();
}
/**
* Create with message.
*/
public BeanAccessException(String message) {
super(message);
}
}
@@ -1,7 +1,7 @@
package io.ebean;
import io.avaje.lang.NonNullApi;
import io.avaje.lang.Nullable;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import java.util.List;
import java.util.Optional;
@@ -30,7 +30,7 @@ import java.util.Optional;
*
* @see BeanRepository
*/
@NonNullApi
@NullMarked
public abstract class BeanFinder<I,T> {
protected final Database database;
@@ -1,6 +1,6 @@
package io.ebean;
import io.avaje.lang.NonNullApi;
import org.jspecify.annotations.NullMarked;
import io.ebean.bean.EntityBean;
import java.util.Collection;
@@ -36,7 +36,7 @@ import java.util.Collection;
* @param <I> The ID type
* @param <T> The Bean type
*/
@NonNullApi
@NullMarked
public abstract class BeanRepository<I, T> extends BeanFinder<I, T> {
/**
@@ -89,12 +89,7 @@ public interface BeanState {
* <p>
* If a setter is called on a readOnly bean it will throw an exception.
*/
boolean isReadOnly();
/**
* Set the readOnly status for the bean.
*/
void setReadOnly(boolean readOnly);
boolean isUnmodifiable();
/**
* Advanced - Used to programmatically build a partially or fully loaded
+4 -4
View File
@@ -1,7 +1,7 @@
package io.ebean;
import io.avaje.lang.NonNullApi;
import io.avaje.lang.Nullable;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import io.ebean.annotation.TxIsolation;
import io.ebean.cache.ServerCacheManager;
import io.ebean.plugin.Property;
@@ -57,7 +57,7 @@ import java.util.concurrent.Callable;
*
* }</pre>
*/
@NonNullApi
@NullMarked
public final class DB {
private static final DbContext context = DbContext.getInstance();
@@ -605,7 +605,7 @@ public final class DB {
* // find orders and their customers
* List<Order> list = DB.find(Order.class)
* .fetch("customer")
* .order("id")
* .orderBy("id")
* .findList();
*
* // sort by customer name ascending, then by order shipDate
@@ -0,0 +1,50 @@
package io.ebean;
final class DPaging implements Paging {
static final Paging NONE = new DPaging(0, 0, null);
static Paging build(int pgIndex, int pgSize, OrderBy<?> orderBy) {
return new DPaging(pgIndex, pgSize, orderBy);
}
static Paging build(int pgIndex, int pgSize) {
return new DPaging(pgIndex, pgSize, null);
}
private final int pageNumber;
private final int pageSize;
private final OrderBy<?> orderBy;
DPaging(int pageNumber, int pageSize, OrderBy<?> orderBy) {
this.pageNumber = pageNumber;
this.pageSize = pageSize;
this.orderBy = orderBy;
}
@Override
public int pageIndex() {
return pageNumber;
}
@Override
public int pageSize() {
return pageSize;
}
@Override
public OrderBy<?> orderBy() {
return orderBy;
}
@Override
public Paging withPage(int pageNumber) {
return new DPaging(pageNumber, pageSize, orderBy);
}
@Override
public Paging withOrderBy(String orderByClause) {
return new DPaging(pageNumber, pageSize, OrderBy.of(orderByClause));
}
}
+5 -16
View File
@@ -1,7 +1,7 @@
package io.ebean;
import io.avaje.lang.NonNullApi;
import io.avaje.lang.Nullable;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import io.ebean.annotation.Platform;
import io.ebean.annotation.TxIsolation;
import io.ebean.cache.ServerCacheManager;
@@ -83,7 +83,7 @@ import java.util.concurrent.Callable;
* @see DatabaseFactory
* @see DatabaseConfig
*/
@NonNullApi
@NullMarked
public interface Database {
/**
@@ -137,6 +137,7 @@ public interface Database {
/**
* Return the associated read only DataSource for this Database instance (can be null).
*/
@Nullable
DataSource readOnlyDataSource();
/**
@@ -400,7 +401,7 @@ public interface Database {
* // find orders and their customers
* List<Order> list = database.find(Order.class)
* .fetch("customer")
* .order("id")
* .orderBy("id")
* .findList();
*
* // sort by customer name ascending, then by order shipDate
@@ -772,18 +773,6 @@ public interface Database {
*/
<T> T reference(Class<T> beanType, Object id);
/**
* Return the extended API for Database.
* <p>
* The extended API has the options for executing queries that take an explicit
* transaction as an argument.
* <p>
* Typically, we only need to use the extended API when we do NOT want to use the
* usual ThreadLocal based mechanism to obtain the current transaction but instead
* supply the transaction explicitly.
*/
ExtendedServer extended();
/**
* Either Insert or Update the bean depending on its state.
* <p>
@@ -989,6 +989,14 @@ public interface DatabaseBuilder {
@Deprecated
DatabaseBuilder setNamingConvention(NamingConvention namingConvention);
/**
* Set the AggregateFormulaContext which is used to determine if a database function
* is an aggregate function (like sum, min, max, avg etc).
* <p>
* Use this to override the default known aggregation functions.
*/
DatabaseConfig aggregateFormulaContext(AggregateFormulaContext aggregateFormulaContext);
/**
* Set to true if all DB column and table names should use quoted identifiers.
* <p>
@@ -1062,6 +1070,11 @@ public interface DatabaseBuilder {
*/
DatabaseBuilder readOnlyDatabase(boolean readOnlyDatabase);
/**
* Set to false such that the instance does not register a JVM shutdown hook.
*/
DatabaseBuilder shutdownHook(boolean shutdownHook);
/**
* Set a DataSource.
*/
@@ -1968,8 +1981,8 @@ public interface DatabaseBuilder {
DatabaseBuilder setLocalOnlyL2Cache(boolean localOnlyL2Cache);
/**
* Controls if Ebean should ignore <code>&x64;javax.validation.contstraints.NotNull</code> or
* <code>&x64;jakarta.validation.contstraints.NotNull</code>
* Controls if Ebean should ignore <code>&#64;javax.validation.contstraints.NotNull</code> or
* <code>&#64;jakarta.validation.contstraints.NotNull</code>
* with respect to generating a <code>NOT NULL</code> column.
* <p>
* Normally when Ebean sees javax NotNull annotation it means that column is defined as NOT NULL.
@@ -2019,6 +2032,11 @@ public interface DatabaseBuilder {
@Deprecated
DatabaseBuilder setQueryPlanTTLSeconds(int queryPlanTTLSeconds);
/**
* Set the EXPLAIN (with options) to use for query plan capture.
*/
DatabaseBuilder queryPlanExplain(String queryPlanExplain);
/**
* Create a new PlatformConfig based of the one held but with overridden properties by reading
* properties with the given path and prefix.
@@ -2600,6 +2618,11 @@ public interface DatabaseBuilder {
*/
NamingConvention getNamingConvention();
/**
* Return the AggregateFormulaContext.
*/
AggregateFormulaContext aggregateFormulaContext();
/**
* Return true if all DB column and table names should use quoted identifiers.
*/
@@ -2638,6 +2661,11 @@ public interface DatabaseBuilder {
*/
boolean readOnlyDatabase();
/**
* Return if a JVM shutdown hook should be registered.
*/
boolean shutdownHook();
/**
* Return the DataSource.
*/
@@ -3044,6 +3072,11 @@ public interface DatabaseBuilder {
*/
int getQueryPlanTTLSeconds();
/**
* Return the EXPLAIN (with options) to use for capturing query plans.
*/
String getQueryPlanExplain();
/**
* Return mapping locations to search for xml mapping via class path search.
*/
@@ -5,8 +5,6 @@ import io.ebean.service.SpiContainer;
import io.ebean.service.SpiContainerFactory;
import jakarta.persistence.PersistenceException;
import java.util.Iterator;
import java.util.ServiceLoader;
import java.util.concurrent.locks.ReentrantLock;
/**
@@ -157,10 +155,10 @@ public final class DatabaseFactory {
* Create the container instance using the configuration.
*/
private static SpiContainer createContainer(ContainerConfig containerConfig) {
Iterator<SpiContainerFactory> factories = ServiceLoader.load(SpiContainerFactory.class).iterator();
if (factories.hasNext()) {
return factories.next().create(containerConfig);
SpiContainerFactory factory = XBootstrapService.containerFactory();
if (factory == null) {
throw new IllegalStateException("Service loader didn't find a SpiContainerFactory?");
}
throw new IllegalStateException("Service loader didn't find a SpiContainerFactory?");
return factory.create(containerConfig);
}
}
@@ -1,7 +1,7 @@
package io.ebean;
import io.avaje.lang.NonNullApi;
import io.avaje.lang.Nullable;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import io.ebean.docstore.DocQueryContext;
import io.ebean.docstore.RawDoc;
@@ -14,7 +14,7 @@ import java.util.function.Predicate;
/**
* Document storage operations.
*/
@NonNullApi
@NullMarked
public interface DocumentStore {
/**
+26 -4
View File
@@ -1,7 +1,7 @@
package io.ebean;
import io.avaje.lang.NonNullApi;
import io.avaje.lang.Nullable;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import javax.sql.DataSource;
import java.sql.Connection;
@@ -42,7 +42,7 @@ import java.util.stream.Stream;
*
* }</pre>
*/
@NonNullApi
@NullMarked
public interface DtoQuery<T> extends CancelableQuery {
/**
@@ -140,6 +140,17 @@ public interface DtoQuery<T> extends CancelableQuery {
* Bind the named multi-value array parameter which we would use with Postgres ANY.
* <p>
* For Postgres this binds an ARRAY rather than expands into multiple bind values.
* <pre>{@code
*
* String sql = "select id, name from o_customer where id = any(:idList)";
*
* var ids = List.of(1, 2, 3);
*
* List<CustomerDto> list2 = DB.findDto(CustomerDto.class, sql)
* .setArrayParameter("idList", ids)
* .findList();
*
* }</pre>
*/
DtoQuery<T> setArrayParameter(String name, Collection<?> values);
@@ -223,5 +234,16 @@ public interface DtoQuery<T> extends CancelableQuery {
* source. We use {@code usingMaster()} to instead ensure that the query is executed
* against the master data source.
*/
DtoQuery<T> usingMaster();
default DtoQuery<T> usingMaster() {
return usingMaster(true);
}
/**
* Ensure the master DataSource is used when useMaster is true. Otherwise, the read only
* data source can be used if defined.
*
* @see #usingMaster()
*/
DtoQuery<T> usingMaster(boolean useMaster);
}
@@ -5,6 +5,8 @@ import java.util.List;
import java.util.concurrent.Future;
/**
* @deprecated migrate to using {@link PagedList#emptyList()} only.
* <p>
* An empty PagedList.
* <p>
* For use in application code when we need to return a PagedList but don't want to
@@ -17,7 +19,8 @@ import java.util.concurrent.Future;
*
* }</pre>
*/
public class EmptyPagedList<T> implements PagedList<T> {
@Deprecated(forRemoval = true)
public final class EmptyPagedList<T> implements PagedList<T> {
@Override
public void loadCount() {
@@ -1,7 +1,7 @@
package io.ebean;
import io.avaje.lang.NonNullApi;
import io.avaje.lang.Nullable;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import io.ebean.search.*;
import jakarta.persistence.NonUniqueResultException;
@@ -31,7 +31,7 @@ import java.util.function.Predicate;
*
* @see Query#where()
*/
@NonNullApi
@NullMarked
public interface ExpressionList<T> {
/**
@@ -53,14 +53,6 @@ public interface ExpressionList<T> {
*/
Query<T> orderById(boolean orderById);
/**
* @deprecated migrate to {@link #orderBy(String)}
*/
@Deprecated(since = "13.19", forRemoval = true)
default ExpressionList<T> order(String orderByClause) {
return orderBy(orderByClause);
}
/**
* Set the order by clause replacing the existing order by clause if there is
* one.
@@ -71,14 +63,6 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> orderBy(String orderBy);
/**
* @deprecated migrate to {@link #orderBy()}.
*/
@Deprecated(forRemoval = true)
default OrderBy<T> order() {
return orderBy();
}
/**
* Return the OrderBy so that you can append an ascending or descending
* property to the order by clause.
@@ -221,18 +205,6 @@ public interface ExpressionList<T> {
*/
int delete();
/**
* Execute as a delete query deleting the 'root level' beans that match the predicates
* in the query.
* <p>
* Note that if the query includes joins then the generated delete statement may not be
* optimal depending on the database platform.
* </p>
*
* @return the number of rows that were deleted.
*/
int delete(Transaction transaction);
/**
* Execute as a update query.
*
@@ -241,14 +213,6 @@ public interface ExpressionList<T> {
*/
int update();
/**
* Execute as a update query with the given transaction.
*
* @return the number of rows that were updated.
* @see UpdateQuery
*/
int update(Transaction transaction);
/**
* Execute the query returning true if a row is found.
* <p>
@@ -349,7 +313,7 @@ public interface ExpressionList<T> {
* List<String> names =
* DB.find(Customer.class)
* .select("name")
* .order().asc("name")
* .orderBy().asc("name")
* .findSingleAttributeList();
*
* }</pre>
@@ -362,7 +326,7 @@ public interface ExpressionList<T> {
* .setDistinct(true)
* .select("name")
* .where().eq("status", Customer.Status.NEW)
* .order().asc("name")
* .orderBy().asc("name")
* .setMaxRows(100)
* .findSingleAttributeList();
*
@@ -1707,7 +1671,7 @@ public interface ExpressionList<T> {
* .eq("status", Customer.Status.ACTIVE)
* .gt("id", 0)
* .endAnd()
* .order().asc("name")
* .orderBy().asc("name")
* .findList();
* }</pre>
*/
@@ -1728,7 +1692,7 @@ public interface ExpressionList<T> {
* .or()
* .eq("status", Customer.Status.ACTIVE)
* .isNull("anniversary")
* .order().asc("name")
* .orderBy().asc("name")
* .findList();
*
* }</pre>
@@ -1748,7 +1712,7 @@ public interface ExpressionList<T> {
* .eq("status", Customer.Status.ACTIVE)
* .gt("id", 0)
* .endAnd()
* .order().asc("name")
* .orderBy().asc("name")
* .findList();
*
* }</pre>
@@ -1782,7 +1746,7 @@ public interface ExpressionList<T> {
* .gt("id", 1)
* .eq("anniversary", onAfter)
* .endNot()
* .order()
* .orderBy()
* .asc("name")
* .findList();
*
@@ -1,21 +0,0 @@
package io.ebean;
import java.time.Clock;
/**
* The extended API for Database.
*/
public interface ExtendedServer {
/**
* Deprecated but no yet determined suitable replacement (to support testing only change of clock).
* <p>
* Set the Clock to use for <code>@WhenCreated</code> and <code>@WhenModified</code>.
* <p>
* Note that we only expect to change the Clock for testing purposes.
* </p>
*/
@Deprecated
void setClock(Clock clock);
}
@@ -1,6 +1,6 @@
package io.ebean;
import io.avaje.lang.NonNullApi;
import org.jspecify.annotations.NullMarked;
import io.ebean.service.SpiFetchGroupQuery;
/**
@@ -61,7 +61,7 @@ import io.ebean.service.SpiFetchGroupQuery;
*
* @param <T> The bean type the Fetch group can be applied to
*/
@NonNullApi
@NullMarked
public interface FetchGroup<T> {
/**
@@ -84,7 +84,7 @@ public interface FetchGroup<T> {
* @return The FetchGroup with the given select clause
*/
static <T> FetchGroup<T> of(Class<T> cls, String select) {
return XServiceProvider.fetchGroupOf(cls, select);
return XBootstrapService.fetchGroupOf(cls, select);
}
/**
@@ -108,14 +108,14 @@ public interface FetchGroup<T> {
* @return The FetchGroupBuilder with the given select clause which we will add fetch clauses to
*/
static <T> FetchGroupBuilder<T> of(Class<T> cls) {
return XServiceProvider.fetchGroupOf(cls);
return XBootstrapService.fetchGroupOf(cls);
}
/**
* Return a query to be used by query beans for constructing FetchGroup.
*/
static <T> SpiFetchGroupQuery<T> queryFor(Class<T> beanType) {
return XServiceProvider.fetchGroupQueryFor(beanType);
return XBootstrapService.fetchGroupQueryFor(beanType);
}
}
@@ -1,6 +1,6 @@
package io.ebean;
import io.avaje.lang.NonNullApi;
import org.jspecify.annotations.NullMarked;
/**
* Builds a FetchGroup by adding fetch clauses.
@@ -23,7 +23,7 @@ import io.avaje.lang.NonNullApi;
*
* }</pre>
*/
@NonNullApi
@NullMarked
public interface FetchGroupBuilder<T> {
/**
+2 -2
View File
@@ -1,6 +1,6 @@
package io.ebean;
import io.avaje.lang.NonNullApi;
import org.jspecify.annotations.NullMarked;
import java.util.List;
import java.util.Set;
@@ -79,7 +79,7 @@ import java.util.Set;
*
* @param <T> the entity bean type
*/
@NonNullApi
@NullMarked
public interface Filter<T> {
/**
+4 -4
View File
@@ -1,7 +1,7 @@
package io.ebean;
import io.avaje.lang.NonNullApi;
import io.avaje.lang.Nullable;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import java.util.List;
/**
@@ -35,7 +35,7 @@ import java.util.List;
* public List<Customer> findNew() {
* return query().where()
* .eq("status", Customer.Status.NEW)
* .order("name")
* .orderBy("name")
* .findList()
* }
* }
@@ -60,7 +60,7 @@ import java.util.List;
* @see BeanRepository
* @see BeanFinder
*/
@NonNullApi
@NullMarked
public class Finder<I, T> {
/**
@@ -0,0 +1,74 @@
package io.ebean;
import jakarta.persistence.PersistenceException;
import java.util.Map;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* FutureMap represents the result of a background query execution that will
* return a map of entities.
* <p>
* It extends the java.util.concurrent.Future with the ability to cancel the
* query, check if it is finished and get the resulting list waiting for the
* query to finish (ie. the standard features of java.util.concurrent.Future).
* </p>
* <p>
* A simple example:
* </p>
* <pre>{@code
*
* // create a query to find all orders
* Query<Long,Order> query = DB.find(Order.class)
* .setMapKey("id");
*
* // execute the query in a background thread
* // immediately returning the futureMap
* FutureMap<Long,Order> futureMap = query.findFutureMap();
*
* // do something else ...
*
* if (!futureMap.isDone()){
* // we can cancel the query execution. This will cancel
* // the underlying query if that is supported by the JDBC
* // driver and database
* futureMap.cancel(true);
* }
*
* if (!futureMap.isCancelled()){
* // wait for the query to finish and return the map
* Map<Long,Order> map = futureMap.get();
* ...
* }
*
* }</pre>
*/
public interface FutureMap<K, T> extends Future<Map<K, T>> {
/**
* Return the query that is being executed by a background thread.
*/
Query<T> getQuery();
/**
* Same as {@link #get()} but wraps InterruptedException and ExecutionException in the
* unchecked PersistenceException.
*
* @return The query list result
* @throws PersistenceException when a InterruptedException or ExecutionException occurs.
*/
Map<K, T> getUnchecked();
/**
* Same as {@link #get(long, TimeUnit)} but wraps InterruptedException
* and ExecutionException in the unchecked PersistenceException.
*
* @return The query list result
* @throws TimeoutException if the wait timed out
* @throws PersistenceException if a InterruptedException or ExecutionException occurs.
*/
Map<K, T> getUnchecked(long timeout, TimeUnit unit) throws TimeoutException;
}
@@ -1,6 +1,6 @@
package io.ebean;
import io.avaje.lang.Nullable;
import org.jspecify.annotations.Nullable;
/**
* Options to be used with insert such as ON CONFLICT DO UPDATE | NOTHING.
@@ -61,7 +61,7 @@ package io.ebean;
* .eq("status", Customer.Status.ACTIVE)
* .gt("id", 0)
* .endAnd()
* .order().asc("name");
* .orderBy().asc("name");
*
* q.findList();
* String s = q.getGeneratedSql();
@@ -0,0 +1,19 @@
package io.ebean;
/**
* Thrown when trying to access a property that isn't loaded on an entity
* that is unmodifiable or has disabled lazy loading.
* <p>
* On a normal mutable entity accessing the property would invoke lazy loading. On
* a unmodifiable entity with lazy loading disabled, accessing an unloaded property
* throws this LazyInitialisationException instead.
*/
public class LazyInitialisationException extends BeanAccessException {
/**
* Create specifying the property that was being accessed.
*/
public LazyInitialisationException(String message) {
super(message);
}
}
@@ -16,4 +16,7 @@ public interface ModifyAwareType {
*/
void setMarkedDirty(boolean markedDirty);
default Object freeze() {
return this; // throw new UnsupportedOperationException();
}
}
+90 -40
View File
@@ -8,13 +8,11 @@ import java.util.Objects;
/**
* Represents an Order By for a Query.
* <p>
* Is a ordered list of OrderBy.Property objects each specifying a property and
* Is an ordered list of OrderBy.Property objects each specifying a property and
* whether it is ascending or descending order.
* </p>
* <p>
* Typically you will not construct an OrderBy yourself but use one that exists
* Typically, you will not construct an OrderBy yourself but use one that exists
* on the Query object.
* </p>
*/
public class OrderBy<T> implements Serializable {
@@ -25,8 +23,22 @@ public class OrderBy<T> implements Serializable {
private final List<Property> list;
/**
* Create an OrderBy parsing the given order by clause.
* <p>
* The order by clause follows SQL order by clause with comma's between each
* property and optionally "asc" or "desc" to represent ascending or
* descending order respectively.
*/
public static <P> OrderBy<P> of(String orderByClause) {
return new OrderBy<>(orderByClause);
}
/**
* @deprecated This method will be removed from public API.
* <p>
* Create an empty OrderBy with no associated query.
*/
@Deprecated(forRemoval = true)
public OrderBy() {
this.list = new ArrayList<>(3);
}
@@ -36,20 +48,17 @@ public class OrderBy<T> implements Serializable {
}
/**
* Create an orderBy parsing the order by clause.
* <p>
* The order by clause follows SQL order by clause with comma's between each
* property and optionally "asc" or "desc" to represent ascending or
* descending order respectively.
* </p>
* @deprecated migrate to {@link OrderBy#of(String)}.
*/
@Deprecated(forRemoval = true)
public OrderBy(String orderByClause) {
this(null, orderByClause);
}
/**
* Construct with a given query and order by clause.
* @deprecated This method will be removed from public API.
*/
@Deprecated(forRemoval = true)
public OrderBy(Query<T> query, String orderByClause) {
this.query = query;
this.list = new ArrayList<>(3);
@@ -110,8 +119,11 @@ public class OrderBy<T> implements Serializable {
}
/**
* @deprecated This method will become internal only API.
* <p>
* Return a copy of this OrderBy with the path trimmed.
*/
@Deprecated(forRemoval = true)
public OrderBy<T> copyWithTrim(String path) {
List<Property> newList = new ArrayList<>(list.size());
for (Property aList : list) {
@@ -186,15 +198,15 @@ public class OrderBy<T> implements Serializable {
if (list.isEmpty()) {
return null;
}
StringBuilder sb = new StringBuilder();
var append = new StringAppend();
for (int i = 0; i < list.size(); i++) {
Property property = list.get(i);
if (i > 0) {
sb.append(", ");
append.append(", ");
}
sb.append(property.toStringFormat());
property.toStringFormat(append);
}
return sb.toString();
return append.toString();
}
@Override
@@ -231,6 +243,55 @@ public class OrderBy<T> implements Serializable {
return this;
}
/**
* Append the order by clause.
*/
public interface Append {
/**
* Append a property expression.
*/
Append property(String property);
/**
* Append a literal.
*/
Append append(String literal);
/**
* Parse and append an expression.
*/
Append parse(String expression);
}
private static final class StringAppend implements Append {
private final StringBuilder builder = new StringBuilder();
@Override
public String toString() {
return builder.toString();
}
@Override
public Append property(String property) {
builder.append(property);
return this;
}
@Override
public Append append(String literal) {
builder.append(literal);
return this;
}
@Override
public Append parse(String raw) {
builder.append(raw);
return this;
}
}
/**
* A property and its ascending descending order.
*/
@@ -309,36 +370,25 @@ public class OrderBy<T> implements Serializable {
@Override
public String toString() {
return toStringFormat();
return property;
}
public String toStringFormat() {
if (nulls == null && collation == null) {
if (ascending) {
return property;
public void toStringFormat(Append append) {
if (collation != null) {
if (collation.contains("${}")) {
// this is a complex collation, e.g. DB2 - we must replace the property
append.parse(collation.replace("${}", property));
} else {
return property + " desc";
append.property(property).append(" collate ").append(collation);
}
} else {
StringBuilder sb = new StringBuilder();
if (collation != null) {
if (collation.contains("${}")) {
// this is a complex collation, e.g. DB2 - we must replace the property
sb.append(collation.replace("${}", property));
} else {
sb.append(property);
sb.append(" collate ").append(collation);
}
} else {
sb.append(property);
}
if (!ascending) {
sb.append(' ').append("desc");
}
if (nulls != null) {
sb.append(' ').append(nulls).append(' ').append(highLow);
}
return sb.toString();
append.property(property);
}
if (!ascending) {
append.append(" desc");
}
if (nulls != null) {
append.append(" ").append(nulls).append(" ").append(highLow);
}
}
@@ -25,7 +25,7 @@ import java.util.concurrent.Future;
*
* PagedList<Order> pagedList = DB.find(Order.class)
* .where().eq("status", Order.Status.NEW)
* .order().asc("id")
* .orderBy().asc("id")
* .setFirstRow(0)
* .setMaxRows(50)
* .findPagedList();
@@ -0,0 +1,90 @@
package io.ebean;
import org.jspecify.annotations.Nullable;
/**
* Used to specify Paging on a Query as an alternative to setting each of the
* maxRows, firstRow and orderBy clause via:
* {@link Query#setMaxRows(int)} + {@link Query#setFirstRow(int)} + {@link Query#setOrderBy(OrderBy)}.
* <p>
* Example use:
*
* <pre>{@code
*
* var orderBy = OrderBy.of("lastName desc nulls first, firstName asc");
* var paging = Paging.of(0, 100, orderBy);
*
* new QCustomer()
* .name.isNotNull()
* .setPaging(paging)
* .findList();
*
* }</pre>
*/
public interface Paging {
/**
* Create a Paging with the given page index size and orderBy.
*
* @param pageIndex the page index starting from zero
* @param pageSize the page size (effectively max rows)
* @param orderBy order by for the query result
*/
static Paging of(int pageIndex, int pageSize, @Nullable OrderBy<?> orderBy) {
return DPaging.build(pageIndex, pageSize, orderBy);
}
/**
* Create a Paging with a raw order by clause.
*
* @param pageIndex the page index starting from zero
* @param pageSize the page size (effectively max rows)
* @param orderByClause raw order by clause for ordering the query result
*/
static Paging of(int pageIndex, int pageSize, @Nullable String orderByClause) {
return of(pageIndex, pageSize, OrderBy.of(orderByClause));
}
/**
* Create a Paging that will use the id property for ordering.
*
* @param pageIndex the page index starting from zero
* @param pageSize the page size (effectively max rows)
*/
static Paging of(int pageIndex, int pageSize) {
return DPaging.build(pageIndex, pageSize);
}
/**
* Return a Paging that will not apply any pagination to a query.
*/
static Paging ofNone() {
return DPaging.NONE;
}
/**
* Return the page index.
*/
int pageIndex();
/**
* Return the page size.
*/
int pageSize();
/**
* Return the order by.
*/
OrderBy<?> orderBy();
/**
* Return a Paging using the given page index.
*/
Paging withPage(int pageIndex);
/**
* Return a Paging using the given order by clause.
*/
Paging withOrderBy(String orderByClause);
}
+1 -1
View File
@@ -30,7 +30,7 @@ import java.util.Objects;
* .where()
* .eq("store", "def")
* .inPairs(pairs) // IN clause with 'pairs' of values
* .order("sku desc")
* .orderBy("sku desc")
*
* // query expressions cover the natural key properties
* // so we can choose to hit the L2 bean cache if we want
@@ -13,21 +13,21 @@ public interface ProfileLocation {
* Create and return a new ProfileLocation.
*/
static ProfileLocation create() {
return XServiceProvider.profileLocationFactory().create();
return XBootstrapService.profileLocationFactory().create();
}
/**
* Create and return a new ProfileLocation with line number.
*/
static ProfileLocation createWithLine() {
return XServiceProvider.profileLocationFactory().createWithLine();
return XBootstrapService.profileLocationFactory().createWithLine();
}
/**
* Create and return a new ProfileLocation with a given lineNumber and label.
*/
static ProfileLocation create(String label) {
return XServiceProvider.profileLocationFactory().create(label);
return XBootstrapService.profileLocationFactory().create(label);
}
/**
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,249 @@
package io.ebean;
/**
* Builder for ORM Query projection (the select and fetch part).
*
* @param <SELF> The builder type
* @param <T> The entity bean type
*/
public interface QueryBuilderProjection<SELF extends QueryBuilderProjection<SELF, T>, T> {
/**
* Apply the path properties replacing the select and fetch clauses.
* <p>
* This is typically used when the FetchPath is applied to both the query and the JSON output.
*/
SELF apply(FetchPath fetchPath);
/**
* Specify the properties to fetch on the root level entity bean in comma delimited format.
* <p>
* The Id property is automatically included in the properties to fetch unless setDistinct(true)
* is set on the query.
* </p>
* <p>
* Use {@link #fetch(String, String)} to specify specific properties to fetch
* on other non-root level paths of the object graph.
* </p>
* <pre>{@code
*
* List<Customer> customers = DB.find(Customer.class)
* // Only fetch the customer id, name and status.
* // This is described as a "Partial Object"
* .select("name, status")
* .where.ilike("name", "rob%")
* .findList();
*
* }</pre>
*
* @param fetchProperties the properties to fetch for this bean (* = all properties).
*/
SELF select(String fetchProperties);
/**
* Set DISTINCT ON clause. This is a Postgres only SQL feature.
*
* @param distinctOn The properties to include in the DISTINCT ON clause.
*/
SELF distinctOn(String distinctOn);
/**
* Apply the fetchGroup which defines what part of the object graph to load.
*/
SELF select(FetchGroup<T> fetchGroup);
/**
* Specify a path to fetch eagerly including specific properties.
* <p>
* Ebean will endeavour to fetch this path using a SQL join. If Ebean determines that it can
* not use a SQL join (due to maxRows or because it would result in a cartesian product) Ebean
* will automatically convert this fetch query into a "query join" - i.e. use fetchQuery().
* </p>
* <pre>{@code
*
* // query orders...
* List<Order> orders = DB.find(Order.class)
* // fetch the customer...
* // ... getting the customers name and phone number
* .fetch("customer", "name, phoneNumber")
*
* // ... also fetch the customers billing address (* = all properties)
* .fetch("customer.billingAddress", "*")
* .findList();
* }</pre>
* <p>
* If columns is null or "*" then all columns/properties for that path are fetched.
* </p>
* <pre>{@code
*
* // fetch customers (their id, name and status)
* List<Customer> customers = DB.find(Customer.class)
* .select("name, status")
* .fetch("contacts", "firstName,lastName,email")
* .findList();
*
* }</pre>
*
* @param path the property path we wish to fetch eagerly.
* @param fetchProperties properties of the associated bean that you want to include in the
* fetch (* means all properties, null also means all properties).
*/
SELF fetch(String path, String fetchProperties);
/**
* Fetch the path and properties using a "query join" (separate SQL query).
* <p>
* This is the same as:
* </p>
* <pre>{@code
*
* fetch(path, fetchProperties, FetchConfig.ofQuery())
*
* }</pre>
* <p>
* This would be used instead of a fetch() when we use a separate SQL query to fetch this
* part of the object graph rather than a SQL join.
* <p>
* We might typically get a performance benefit when the path to fetch is a OneToMany
* or ManyToMany, the 'width' of the 'root bean' is wide and the cardinality of the many
* is high.
*
* @param path the property path we wish to fetch eagerly.
* @param fetchProperties properties of the associated bean that you want to include in the
* fetch (* means all properties, null also means all properties).
*/
SELF fetchQuery(String path, String fetchProperties);
/**
* Fetch the path and properties using L2 bean cache.
*
* @param path The path of the beans we are fetching from L2 cache.
* @param fetchProperties The properties that should be loaded.
*/
SELF fetchCache(String path, String fetchProperties);
/**
* Fetch the path and properties lazily (via batch lazy loading).
* <p>
* This is the same as:
*
* <pre>{@code
*
* fetch(path, fetchProperties, FetchConfig.ofLazy())
*
* }</pre>
* <p>
* The reason for using fetchLazy() is to either:
* <ul>
* <li>Control/tune what is fetched as part of lazy loading</li>
* <li>Make use of the L2 cache, build this part of the graph from L2 cache</li>
* </ul>
*
* @param path the property path we wish to fetch lazily.
* @param fetchProperties properties of the associated bean that you want to include in the
* fetch (* means all properties, null also means all properties).
*/
SELF fetchLazy(String path, String fetchProperties);
/**
* Additionally specify a FetchConfig to use a separate query or lazy loading
* to load this path.
* <pre>{@code
*
* // fetch customers (their id, name and status)
* List<Customer> customers = DB.find(Customer.class)
* .select("name, status")
* .fetch("contacts", "firstName,lastName,email", FetchConfig.ofLazy(10))
* .findList();
*
* }</pre>
*
* @param path the property path we wish to fetch eagerly.
*/
SELF fetch(String path, String fetchProperties, FetchConfig fetchConfig);
/**
* Specify a path to fetch eagerly including all its properties.
* <p>
* Ebean will endeavour to fetch this path using a SQL join. If Ebean determines that it can
* not use a SQL join (due to maxRows or because it would result in a cartesian product) Ebean
* will automatically convert this fetch query into a "query join" - i.e. use fetchQuery().
* </p>
* <pre>{@code
*
* // fetch customers (their id, name and status)
* List<Customer> customers = DB.find(Customer.class)
* // eager fetch the contacts
* .fetch("contacts")
* .findList();
*
* }</pre>
*
* @param path the property path we wish to fetch eagerly.
*/
SELF fetch(String path);
/**
* Fetch the path eagerly using a "query join" (separate SQL query).
* <p>
* This is the same as:
* <pre>{@code
*
* fetch(path, FetchConfig.ofQuery())
*
* }</pre>
* <p>
* This would be used instead of a fetch() when we use a separate SQL query to fetch this
* part of the object graph rather than a SQL join.
* <p>
* We might typically get a performance benefit when the path to fetch is a OneToMany
* or ManyToMany, the 'width' of the 'root bean' is wide and the cardinality of the many
* is high.
*
* @param path the property path we wish to fetch eagerly
*/
SELF fetchQuery(String path);
/**
* Fetch the path eagerly using L2 cache.
*/
SELF fetchCache(String path);
/**
* Fetch the path lazily (via batch lazy loading).
* <p>
* This is the same as:
* </p>
* <pre>{@code
*
* fetch(path, FetchConfig.ofLazy())
*
* }</pre>
* <p>
* The reason for using fetchLazy() is to either:
* </p>
* <ul>
* <li>Control/tune what is fetched as part of lazy loading</li>
* <li>Make use of the L2 cache, build this part of the graph from L2 cache</li>
* </ul>
*
* @param path the property path we wish to fetch lazily.
*/
SELF fetchLazy(String path);
/**
* Additionally specify a JoinConfig to specify a "query join" and or define
* the lazy loading query.
* <pre>{@code
*
* // fetch customers (their id, name and status)
* List<Customer> customers = DB.find(Customer.class)
* // lazy fetch contacts with a batch size of 100
* .fetch("contacts", FetchConfig.ofLazy(100))
* .findList();
*
* }</pre>
*/
SELF fetch(String path, FetchConfig fetchConfig);
}
@@ -25,7 +25,7 @@ import java.util.Iterator;
*
* Query<Customer> query = database.find(Customer.class)
* .where().gt("id", 0)
* .order("id")
* .orderBy("id")
* .setMaxRows(2);
*
* QueryIterator<Customer> it = query.findIterate();
+1 -1
View File
@@ -111,7 +111,7 @@ package io.ebean;
* .fetch("order.customer", "name")
* .where().gt("order.id", 0)
* .having().gt("totalAmount", 20)
* .order().desc("totalAmount")
* .orderBy().desc("totalAmount")
* .setMaxRows(10)
* .findList();
*
@@ -22,14 +22,14 @@ public interface RawSqlBuilder {
* resultSet.
*/
static RawSql resultSet(ResultSet resultSet, String... propertyNames) {
return XServiceProvider.rawSql().resultSet(resultSet, propertyNames);
return XBootstrapService.rawSql().resultSet(resultSet, propertyNames);
}
/**
* Create and return a SqlRow based on the resultSet with dbTrueValue and binaryOptimizedUUID options.
*/
static SqlRow sqlRow(ResultSet resultSet, final String dbTrueValue, boolean binaryOptimizedUUID) throws SQLException {
return XServiceProvider.rawSql().sqlRow(resultSet, dbTrueValue, binaryOptimizedUUID);
return XBootstrapService.rawSql().sqlRow(resultSet, dbTrueValue, binaryOptimizedUUID);
}
/**
@@ -38,7 +38,7 @@ public interface RawSqlBuilder {
* this query.
*/
static RawSqlBuilder unparsed(String sql) {
return XServiceProvider.rawSql().unparsed(sql);
return XBootstrapService.rawSql().unparsed(sql);
}
/**
@@ -55,7 +55,7 @@ public interface RawSqlBuilder {
* </p>
*/
static RawSqlBuilder parse(String sql) {
return XServiceProvider.rawSql().parsed(sql);
return XBootstrapService.rawSql().parsed(sql);
}
/**
+50 -5
View File
@@ -1,11 +1,12 @@
package io.ebean;
import io.avaje.lang.NonNullApi;
import io.avaje.lang.Nullable;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import javax.sql.DataSource;
import java.io.Serializable;
import java.sql.Connection;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
@@ -39,7 +40,7 @@ import java.util.function.Predicate;
*
* }</pre>
*/
@NonNullApi
@NullMarked
public interface SqlQuery extends Serializable, CancelableQuery {
/**
@@ -62,7 +63,17 @@ public interface SqlQuery extends Serializable, CancelableQuery {
* source. We use {@code usingMaster()} to instead ensure that the query is executed
* against the master data source.
*/
SqlQuery usingMaster();
default SqlQuery usingMaster() {
return usingMaster(true);
}
/**
* Ensure the master DataSource is used when useMaster is true. Otherwise, the read only
* data source can be used if defined.
*
* @see #usingMaster()
*/
SqlQuery usingMaster(boolean useMaster);
/**
* Execute the query returning a list.
@@ -171,7 +182,7 @@ public interface SqlQuery extends Serializable, CancelableQuery {
* List<SqlRow> list =
* DB.sqlQuery(sql)
* .setParameter("Rob")
* .setParameter("Status.NEW)
* .setParameter(Status.NEW)
* .findList();
*
* // the same as ...
@@ -241,11 +252,45 @@ public interface SqlQuery extends Serializable, CancelableQuery {
*/
SqlQuery setParameter(int position, Object value);
/**
* Bind the array parameter by its index position for use with Postgres ANY.
* <p>
* For Postgres this binds an ARRAY rather than expands into multiple bind values.
* <pre>{@code
*
* String sql = "select name from customer where id = any(?)";
*
* List<SqlRow> list =
* DB.sqlQuery(sql)
* .setArrayParameter(1, List.of(1, 2, 3))
* .findList();
*
* }</pre>
*/
SqlQuery setArrayParameter(int position, Collection<?> value);
/**
* Bind the named parameter value.
*/
SqlQuery setParameter(String name, Object value);
/**
* Bind the named array parameter which we would use with Postgres ANY.
* <p>
* For Postgres this binds an ARRAY rather than expands into multiple bind values.
* <pre>{@code
*
* String sql = "select name from customer where id = any(:idList)";
*
* List<SqlRow> list =
* DB.sqlQuery(sql)
* .setArrayParameter("idList", List.of(1, 2, 3))
* .findList();
*
* }</pre>
*/
SqlQuery setArrayParameter(String name, Collection<?> value);
/**
* Set the index of the first row of the results to return.
*/
@@ -0,0 +1,22 @@
package io.ebean;
/**
* Attempted to modify a read only entity.
*/
public class UnmodifiableEntityException extends BeanAccessException {
private static final long serialVersionUID = 1;
/**
* Create with no message.
*/
public UnmodifiableEntityException() {
super();
}
/**
* Create with message.
*/
public UnmodifiableEntityException(String message) {
super(message);
}
}
@@ -0,0 +1,95 @@
package io.ebean;
import io.ebean.metric.MetricFactory;
import io.ebean.service.*;
import java.util.ServiceLoader;
/**
* Bootstrap internal services.
*/
public final class XBootstrapService {
private static final SpiContainerFactory containerFactory;
private static final SpiRawSqlService rawSqlService;
private static final SpiProfileLocationFactory profileLocationFactory;
private static final SpiFetchGroupService fetchGroupService;
private static final MetricFactory metricFactory;
private static final SpiJsonService jsonService;
static {
SpiContainerFactory _factory = null;
SpiRawSqlService _raw = null;
SpiProfileLocationFactory _profile = null;
SpiFetchGroupService _fetch = null;
MetricFactory _metric = null;
SpiJsonService _json = null;
for (BootstrapService extension : ServiceLoader.load(BootstrapService.class)) {
if (extension instanceof SpiContainerFactory) {
_factory = (SpiContainerFactory)extension;
} else if (extension instanceof SpiRawSqlService) {
_raw = (SpiRawSqlService)extension;
} else if (extension instanceof SpiProfileLocationFactory) {
_profile = (SpiProfileLocationFactory)extension;
} else if (extension instanceof SpiFetchGroupService) {
_fetch = (SpiFetchGroupService)extension;
} else if (extension instanceof MetricFactory) {
_metric = (MetricFactory)extension;
} else if (extension instanceof SpiJsonService) {
_json = (SpiJsonService)extension;
}
}
containerFactory = _factory;
rawSqlService = _raw;
profileLocationFactory = _profile;
fetchGroupService = _fetch;
metricFactory = _metric;
jsonService = _json;
}
/**
* Return the MetricFactory found in boostrap service loading.
*/
public static MetricFactory metricFactory() {
return metricFactory;
}
/**
* Return the SpiJsonService found in boostrap service loading.
*/
public static SpiJsonService jsonService() {
return jsonService;
}
static SpiContainerFactory containerFactory() {
return containerFactory;
}
static SpiRawSqlService rawSql() {
return rawSqlService;
}
static SpiProfileLocationFactory profileLocationFactory() {
return profileLocationFactory;
}
/**
* Return the FetchGroup with the given select clause.
*/
static <T> FetchGroup<T> fetchGroupOf(Class<T> cls, String select) {
return fetchGroupService.of(cls, select);
}
/**
* Return the FetchGroupBuilder with the given select clause.
*/
static <T> FetchGroupBuilder<T> fetchGroupOf(Class<T> cls) {
return fetchGroupService.of(cls);
}
/**
* Return the FetchGroup Query for building fetch groups via query beans.
*/
static <T> SpiFetchGroupQuery<T> fetchGroupQueryFor(Class<T> cls) {
return fetchGroupService.queryFor(cls);
}
}
@@ -1,76 +0,0 @@
package io.ebean;
import io.ebean.service.SpiFetchGroupQuery;
import io.ebean.service.SpiFetchGroupService;
import io.ebean.service.SpiProfileLocationFactory;
import io.ebean.service.SpiRawSqlService;
import java.util.Iterator;
import java.util.ServiceLoader;
/**
* Lookup internal services.
*/
final class XServiceProvider {
private static SpiRawSqlService rawSqlService = initRawSql();
private static SpiProfileLocationFactory profileLocationFactory = initProfileLocation();
private static SpiFetchGroupService fetchGroupService = initSpiFetchGroupService();
private static SpiFetchGroupService initSpiFetchGroupService() {
return loadFirstService(SpiFetchGroupService.class);
}
private static SpiRawSqlService initRawSql() {
return loadFirstService(SpiRawSqlService.class);
}
private static SpiProfileLocationFactory initProfileLocation() {
return loadFirstService(SpiProfileLocationFactory.class);
}
private static <T> T loadFirstService(Class<T> cls) {
Iterator<T> loader = ServiceLoader.load(cls).iterator();
if (loader.hasNext()) {
return loader.next();
}
throw new IllegalStateException("No service implementation found for " + cls);
}
/**
* Return the RawSqlService implementation.
*/
static SpiRawSqlService rawSql() {
return rawSqlService;
}
/**
* Return the RawSqlService implementation.
*/
static SpiProfileLocationFactory profileLocationFactory() {
return profileLocationFactory;
}
/**
* Return the FetchGroup with the given select clause.
*/
static <T> FetchGroup<T> fetchGroupOf(Class<T> cls, String select) {
return fetchGroupService.of(cls, select);
}
/**
* Return the FetchGroupBuilder with the given select clause.
*/
static <T> FetchGroupBuilder<T> fetchGroupOf(Class<T> cls) {
return fetchGroupService.of(cls);
}
/**
* Return the FetchGroup Query for building fetch groups via query beans.
*/
static <T> SpiFetchGroupQuery<T> fetchGroupQueryFor(Class<T> cls) {
return fetchGroupService.queryFor(cls);
}
}
@@ -119,18 +119,6 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
*/
void setLoader(BeanCollectionLoader beanLoader);
/**
* Set to true if you want the BeanCollection to be treated as read only. This
* means no elements can be added or removed etc.
*/
void setReadOnly(boolean readOnly);
/**
* Return true if the collection should be treated as readOnly and no elements
* can be added or removed etc.
*/
boolean isReadOnly();
/**
* Add the bean to the collection. This is disallowed for BeanMap.
*/
@@ -237,7 +225,7 @@ public interface BeanCollection<E> extends Serializable, ToStringAware {
boolean wasTouched();
/**
* Return a shallow copy of this collection that is modifiable.
* Freeze the collection returning an unmodifiable version.
*/
BeanCollection<E> shallowCopy();
Object freeze();
}
@@ -148,18 +148,6 @@ public interface EntityBeanIntercept extends Serializable {
*/
boolean isLoadedFromCache();
/**
* Return true if the bean should be treated as readOnly. If a setter method
* is called when it is readOnly an Exception is thrown.
*/
boolean isReadOnly();
/**
* Set the readOnly status. If readOnly then calls to setter methods through
* an exception.
*/
void setReadOnly(boolean readOnly);
/**
* Set the bean to be updated when persisted (for merge).
*/
@@ -552,4 +540,9 @@ public interface EntityBeanIntercept extends Serializable {
* Update the 'next' mutable info returning the content that was obtained via dirty detection.
*/
String mutableNext(int propertyIndex);
/**
* Return true if this entity bean should be frozen. Used to handle recursive freezing.
*/
boolean freeze();
}
@@ -0,0 +1,70 @@
package io.ebean.bean;
/**
* Common base features for EntityBeanIntercept.
*/
abstract class InterceptBase implements EntityBeanIntercept {
final EntityBean owner;
boolean fullyLoadedBean;
/**
* Create with a given entity.
*/
InterceptBase(Object ownerBean) {
this.owner = (EntityBean) ownerBean;
}
/**
* EXPERIMENTAL - Constructor only for use by serialization frameworks.
*/
InterceptBase() {
this.owner = null;
}
@Override
public final EntityBean owner() {
return owner;
}
@Override
public final boolean isFullyLoadedBean() {
return fullyLoadedBean;
}
@Override
public final void setFullyLoadedBean(boolean fullyLoadedBean) {
this.fullyLoadedBean = fullyLoadedBean;
}
@Override
public final String property(int propertyIndex) {
if (propertyIndex == -1) {
return null;
}
return owner._ebean_getPropertyName(propertyIndex);
}
@Override
public final int findProperty(String propertyName) {
final String[] names = owner._ebean_getPropertyNames();
for (int i = 0; i < names.length; i++) {
if (names[i].equals(propertyName)) {
return i;
}
}
return -1;
}
@Override
public final StringBuilder loadedPropertyKey() {
final StringBuilder sb = new StringBuilder();
final int len = propertyLength();
for (int i = 0; i < len; i++) {
if (isLoadedProperty(i)) {
sb.append(i).append(',');
}
}
return sb;
}
}
@@ -1,37 +1,44 @@
package io.ebean.bean;
import io.ebean.LazyInitialisationException;
import io.ebean.UnmodifiableEntityException;
import io.ebean.ValuePair;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.*;
/**
* 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 {
public final class InterceptReadOnly extends InterceptBase {
private final EntityBean owner;
private final boolean[] loaded;
private boolean frozen;
/**
* Create with a given entity.
*/
public InterceptReadOnly(Object ownerBean) {
this.owner = (EntityBean) ownerBean;
super(ownerBean);
this.loaded = new boolean[owner._ebean_getPropertyNames().length];
}
@Override
public boolean freeze() {
if (frozen) {
return false;
} else {
frozen = true;
return true;
}
}
@Override
public String toString() {
return "InterceptReadOnly{" + owner + '}';
}
@Override
public EntityBean owner() {
return owner;
return "InterceptReadOnly{frozen:" + frozen + " loaded:" + loadedPropertyNames() + '}';
}
@Override
@@ -94,18 +101,13 @@ public class InterceptReadOnly implements EntityBeanIntercept {
}
@Override
public boolean isFullyLoadedBean() {
return false;
}
@Override
public void setFullyLoadedBean(boolean fullyLoadedBean) {
}
@Override
public boolean isPartial() {
for (boolean flag : loaded) {
if (!flag) {
return true;
}
}
return false;
}
@@ -136,7 +138,14 @@ public class InterceptReadOnly implements EntityBeanIntercept {
@Override
public boolean hasIdOnly(int idIndex) {
return false;
for (int i = 0; i < loaded.length; i++) {
if (i == idIndex) {
if (!loaded[i]) return false;
} else if (loaded[i]) {
return false;
}
}
return true;
}
@Override
@@ -159,16 +168,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) {
@@ -234,44 +233,38 @@ 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;
return loaded.length;
}
@Override
public void setPropertyLoaded(String propertyName, boolean loaded) {
final int position = findProperty(propertyName);
if (position == -1) {
throw new IllegalArgumentException("Property not found - " + propertyName);
}
this.loaded[position] = loaded;
}
@Override
public void setPropertyUnloaded(int propertyIndex) {
loaded[propertyIndex] = false;
}
@Override
public void setLoadedProperty(int propertyIndex) {
loaded[propertyIndex] = true;
}
@Override
public void setLoadedPropertyAll() {
Arrays.fill(loaded, true);
}
@Override
public boolean isLoadedProperty(int propertyIndex) {
return false;
return loaded[propertyIndex];
}
@Override
@@ -321,7 +314,16 @@ public class InterceptReadOnly implements EntityBeanIntercept {
@Override
public Set<String> loadedPropertyNames() {
return Collections.emptySet();
if (fullyLoadedBean) {
return null;
}
final Set<String> props = new LinkedHashSet<>();
for (int i = 0; i < loaded.length; i++) {
if (loaded[i]) {
props.add(property(i));
}
}
return props;
}
@Override
@@ -369,14 +371,11 @@ public class InterceptReadOnly implements EntityBeanIntercept {
}
@Override
public StringBuilder loadedPropertyKey() {
return null;
}
@Override
public boolean[] loaded() {
return new boolean[0];
final boolean[] ret = new boolean[loaded.length];
System.arraycopy(loaded, 0, ret, 0, ret.length);
return ret;
}
@Override
@@ -401,7 +400,7 @@ public class InterceptReadOnly implements EntityBeanIntercept {
@Override
public void initialisedMany(int propertyIndex) {
loaded[propertyIndex] = true;
}
@Override
@@ -416,12 +415,14 @@ public class InterceptReadOnly implements EntityBeanIntercept {
@Override
public void preGetter(int propertyIndex) {
if (!loaded[propertyIndex]) {
throw new LazyInitialisationException("Property not loaded: " + property(propertyIndex));
}
}
@Override
public void preSetterMany(boolean interceptField, int propertyIndex, Object oldValue, Object newValue) {
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
}
@Override
@@ -436,57 +437,57 @@ public class InterceptReadOnly implements EntityBeanIntercept {
@Override
public void preSetter(boolean intercept, int propertyIndex, Object oldValue, Object newValue) {
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
}
@Override
public void preSetter(boolean intercept, int propertyIndex, boolean oldValue, boolean newValue) {
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
}
@Override
public void preSetter(boolean intercept, int propertyIndex, int oldValue, int newValue) {
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
}
@Override
public void preSetter(boolean intercept, int propertyIndex, long oldValue, long newValue) {
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
}
@Override
public void preSetter(boolean intercept, int propertyIndex, double oldValue, double newValue) {
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
}
@Override
public void preSetter(boolean intercept, int propertyIndex, float oldValue, float newValue) {
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
}
@Override
public void preSetter(boolean intercept, int propertyIndex, short oldValue, short newValue) {
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
}
@Override
public void preSetter(boolean intercept, int propertyIndex, char oldValue, char newValue) {
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
}
@Override
public void preSetter(boolean intercept, int propertyIndex, byte oldValue, byte newValue) {
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
}
@Override
public void preSetter(boolean intercept, int propertyIndex, char[] oldValue, char[] newValue) {
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
}
@Override
public void preSetter(boolean intercept, int propertyIndex, byte[] oldValue, byte[] newValue) {
throw new UnmodifiableEntityException("Attempting to modify " + property(propertyIndex));
}
@Override
@@ -22,7 +22,7 @@ import java.util.concurrent.locks.ReentrantLock;
* This provides the mechanisms to support deferred fetching of reference beans
* and oldValues generation for concurrency checking.
*/
public final class InterceptReadWrite implements EntityBeanIntercept {
public final class InterceptReadWrite extends InterceptBase {
private static final long serialVersionUID = -3664031775464862649L;
@@ -56,10 +56,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
private String ebeanServerName;
private boolean deletedFromCollection;
/**
* The actual entity bean that 'owns' this intercept.
*/
private final EntityBean owner;
private EntityBean embeddedOwner;
private int embeddedOwnerIndex;
/**
@@ -67,7 +63,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
*/
private int state;
private boolean forceUpdate;
private boolean readOnly;
private boolean dirty;
/**
* Flag set to disable lazy loading.
@@ -77,7 +72,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
* 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;
@@ -101,7 +95,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
* Create with a given entity.
*/
public InterceptReadWrite(Object ownerBean) {
this.owner = (EntityBean) ownerBean;
super(ownerBean);
this.flags = new byte[owner._ebean_getPropertyNames().length];
}
@@ -109,16 +103,20 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
* EXPERIMENTAL - Constructor only for use by serialization frameworks.
*/
public InterceptReadWrite() {
this.owner = null;
super();
this.flags = null;
}
@Override
public boolean freeze() {
throw new UnsupportedOperationException("never expected");
}
@Override
public String toString() {
return "InterceptReadWrite@" + hashCode() + "{state=" + state +
(dirty ? " dirty;" : "") +
(forceUpdate ? " forceUpdate;" : "") +
(readOnly ? " readOnly;" : "") +
(disableLazyLoad ? " disableLazyLoad;" : "") +
(lazyLoadFailure ? " lazyLoadFailure;" : "") +
(fullyLoadedBean ? " fullyLoadedBean;" : "") +
@@ -131,11 +129,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
'}';
}
@Override
public EntityBean owner() {
return owner;
}
@Override
public PersistenceContext persistenceContext() {
return persistenceContext;
@@ -200,16 +193,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
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) {
@@ -298,16 +281,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;
@@ -411,25 +384,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;
@@ -668,18 +622,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];
@@ -708,7 +650,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
if (database == null) {
throw new PersistenceException(ebeanServerName == null ? "No registered default server" : "Database [" + ebeanServerName + "] is not registered");
}
// For stand alone reference bean or after deserialisation lazy load
// For stand-alone reference bean or after deserialisation lazy load
// using the ebeanServer. Synchronise only on the bean.
loadBeanInternal(loadProperty, database.pluginApi().beanLoader());
return;
@@ -845,18 +787,12 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
if (state == STATE_NEW) {
setLoadedProperty(propertyIndex);
} else {
if (readOnly) {
throw new IllegalStateException("This bean is readOnly");
}
setChangeLoaded(propertyIndex);
}
}
@Override
public void setChangedPropertyValue(int propertyIndex, boolean setDirtyState, Object origValue) {
if (readOnly) {
throw new IllegalStateException("This bean is readOnly");
}
setChangedProperty(propertyIndex);
if (setDirtyState) {
setOriginalValue(propertyIndex, origValue);
@@ -1,5 +1,6 @@
package io.ebean.cache;
import java.time.Instant;
import java.util.Set;
/**
@@ -10,11 +11,11 @@ import java.util.Set;
* the query cache entry is treated as invalid.
* </p>
*/
public class QueryCacheEntry {
public final class QueryCacheEntry {
private final Object value;
private final Set<String> dependentTables;
private final long timestamp;
private final Instant timestamp;
/**
* Create with dependent tables and timestamp.
@@ -23,7 +24,7 @@ public class QueryCacheEntry {
* @param dependentTables The extra tables the query is dependent on (joins to)
* @param timestamp The timestamp that the query uses to check for modifications
*/
public QueryCacheEntry(Object value, Set<String> dependentTables, long timestamp) {
public QueryCacheEntry(Object value, Set<String> dependentTables, Instant timestamp) {
this.value = value;
this.dependentTables = dependentTables;
this.timestamp = timestamp;
@@ -32,21 +33,21 @@ public class QueryCacheEntry {
/**
* Return the actual query result.
*/
public Object getValue() {
public Object value() {
return value;
}
/**
* Return the tables the query result is dependent on.
*/
public Set<String> getDependentTables() {
public Set<String> dependentTables() {
return dependentTables;
}
/**
* Return the timestamp used to check for modifications on the dependent tables.
*/
public long getTimestamp() {
public Instant timestamp() {
return timestamp;
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
package io.ebean.cache;
import io.avaje.lang.Nullable;
import org.jspecify.annotations.Nullable;
import io.ebean.meta.MetricVisitor;
import java.util.LinkedHashMap;
@@ -17,7 +17,6 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
private static final long serialVersionUID = 3365725236140187588L;
protected final ReentrantLock lock = new ReentrantLock();
protected boolean readOnly;
protected boolean disableLazyLoad;
/**
* The Database this is associated with. (used for lazy fetch).
@@ -55,7 +54,6 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
this.ebeanServerName = loader.name();
this.ownerBean = ownerBean;
this.propertyName = propertyName;
this.readOnly = ownerBean != null && ownerBean._ebean_getIntercept().isReadOnly();
}
@Override
@@ -103,22 +101,6 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
this.ebeanServerName = loader.name();
}
@Override
public boolean isReadOnly() {
return readOnly;
}
@Override
public void setReadOnly(boolean readOnly) {
this.readOnly = readOnly;
}
void checkReadOnly() {
if (readOnly) {
throw new IllegalStateException("This collection is in ReadOnly mode");
}
}
// ---------------------------------------------------------
// Support for modify additions deletions etc - ManyToMany
// ---------------------------------------------------------
@@ -212,14 +194,4 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
return modifyHolder != null && modifyHolder.wasTouched();
}
/**
* Copies all relevant properties for a clone. See {@link #shallowCopy()}
*/
protected void setFromOriginal(AbstractBeanCollection<E> other) {
this.disableLazyLoad = other.disableLazyLoad;
this.ebeanServerName = other.ebeanServerName;
this.loader = other.loader;
this.ownerBean = other.ownerBean;
this.propertyName = other.propertyName;
}
}
@@ -2,7 +2,6 @@ package io.ebean.common;
import io.ebean.bean.*;
import java.io.Serializable;
import java.util.*;
/**
@@ -39,6 +38,17 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
super(loader, ownerBean, propertyName);
}
@Override
public List<E> freeze() {
if (list == null) {
return null;
} else if (list.isEmpty()) {
return List.of();
} else {
return Collections.unmodifiableList(list);
}
}
@Override
public void toString(ToStringBuilder builder) {
builder.addCollection(list);
@@ -223,7 +233,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
@Override
public void add(int index, E element) {
checkReadOnly();
init();
if (modifyListening) {
modifyAddition(element);
@@ -238,7 +247,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
@Override
public boolean add(E bean) {
checkReadOnly();
init();
if (modifyListening) {
if (list.add(bean)) {
@@ -253,7 +261,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
@Override
public boolean addAll(Collection<? extends E> beans) {
checkReadOnly();
init();
if (modifyListening) {
// all elements in c are added (no contains checking)
@@ -264,7 +271,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
@Override
public boolean addAll(int index, Collection<? extends E> beans) {
checkReadOnly();
init();
if (modifyListening) {
// all elements in c are added (no contains checking)
@@ -275,7 +281,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
@Override
public void clear() {
checkReadOnly();
// TODO: when clear() and not initialised could be more clever
// and fetch just the Id's
initClear();
@@ -320,9 +325,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
@Override
public Iterator<E> iterator() {
init();
if (readOnly) {
return new ReadOnlyListIterator<>(list.listIterator());
}
if (modifyListening) {
return new ModifyIterator<>(this, list.iterator());
}
@@ -338,9 +340,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
@Override
public ListIterator<E> listIterator() {
init();
if (readOnly) {
return new ReadOnlyListIterator<>(list.listIterator());
}
if (modifyListening) {
return new ModifyListIterator<>(this, list.listIterator());
}
@@ -350,9 +349,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
@Override
public ListIterator<E> listIterator(int index) {
init();
if (readOnly) {
return new ReadOnlyListIterator<>(list.listIterator(index));
}
if (modifyListening) {
return new ModifyListIterator<>(this, list.listIterator(index));
}
@@ -368,7 +364,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
@Override
public E remove(int index) {
checkReadOnly();
init();
if (modifyListening) {
E o = list.remove(index);
@@ -380,7 +375,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
@Override
public boolean remove(Object bean) {
checkReadOnly();
init();
if (modifyListening) {
boolean isRemove = list.remove(bean);
@@ -394,7 +388,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
@Override
public boolean removeAll(Collection<?> beans) {
checkReadOnly();
init();
if (modifyListening) {
boolean changed = false;
@@ -412,7 +405,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
@Override
public boolean retainAll(Collection<?> retainBeans) {
checkReadOnly();
init();
if (modifyListening) {
boolean changed = false;
@@ -433,7 +425,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
@Override
public E set(int index, E element) {
checkReadOnly();
init();
if (modifyListening) {
E o = list.set(index, element);
@@ -453,9 +444,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
@Override
public List<E> subList(int fromIndex, int toIndex) {
init();
if (readOnly) {
return Collections.unmodifiableList(list.subList(fromIndex, toIndex));
}
if (modifyListening) {
return new ModifyList<>(this, list.subList(fromIndex, toIndex));
}
@@ -475,67 +463,4 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
return list.toArray(array);
}
private static final class ReadOnlyListIterator<E> implements ListIterator<E>, Serializable {
private static final long serialVersionUID = 3097271091406323699L;
private final ListIterator<E> i;
ReadOnlyListIterator(ListIterator<E> i) {
this.i = i;
}
@Override
public void add(E o) {
throw new IllegalStateException("This collection is in ReadOnly mode");
}
@Override
public void remove() {
throw new IllegalStateException("This collection is in ReadOnly mode");
}
@Override
public void set(E o) {
throw new IllegalStateException("This collection is in ReadOnly mode");
}
@Override
public boolean hasNext() {
return i.hasNext();
}
@Override
public boolean hasPrevious() {
return i.hasPrevious();
}
@Override
public E next() {
return i.next();
}
@Override
public int nextIndex() {
return i.nextIndex();
}
@Override
public E previous() {
return i.previous();
}
@Override
public int previousIndex() {
return i.previousIndex();
}
}
@Override
public BeanCollection<E> shallowCopy() {
BeanList<E> copy = new BeanList<>(new CopyOnFirstWriteList<>(list));
copy.setFromOriginal(this);
return copy;
}
}
@@ -37,6 +37,11 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
super(ebeanServer, ownerBean, propertyName);
}
@Override
public Map<K, E> freeze() {
return map == null ? null : Collections.unmodifiableMap(map);
}
@Override
public void toString(ToStringBuilder builder) {
if (map == null || map.isEmpty()) {
@@ -217,7 +222,6 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
@Override
public void clear() {
checkReadOnly();
initClear();
if (modifyListening) {
// add all beans to the removal list
@@ -243,9 +247,6 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
@Override
public Set<Entry<K, E>> entrySet() {
init();
if (readOnly) {
return Collections.unmodifiableSet(map.entrySet());
}
return modifyListening ? new ModifyEntrySet<>(this, map.entrySet()) : map.entrySet();
}
@@ -264,15 +265,11 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
@Override
public Set<K> keySet() {
init();
if (readOnly) {
return Collections.unmodifiableSet(map.keySet());
}
return modifyListening ? new ModifyKeySet<>(this, map.keySet()) : map.keySet();
}
@Override
public E put(K key, E value) {
checkReadOnly();
init();
if (modifyListening) {
E oldBean = map.put(key, value);
@@ -289,7 +286,6 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
@Override
public void putAll(Map<? extends K, ? extends E> puts) {
checkReadOnly();
init();
if (modifyListening) {
for (Entry<? extends K, ? extends E> entry : puts.entrySet()) {
@@ -306,17 +302,16 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
@Override
public void addBean(E bean) {
throw new IllegalStateException("Method not allowed on Map. Please use List instead.");
throw new UnsupportedOperationException("Method not allowed on Map. Please use List instead.");
}
@Override
public void removeBean(E bean) {
throw new IllegalStateException("Method not allowed on Map. Please use List instead.");
throw new UnsupportedOperationException("Method not allowed on Map. Please use List instead.");
}
@Override
public E remove(Object key) {
checkReadOnly();
init();
if (modifyListening) {
E o = map.remove(key);
@@ -335,16 +330,6 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
@Override
public Collection<E> values() {
init();
if (readOnly) {
return Collections.unmodifiableCollection(map.values());
}
return modifyListening ? new ModifyCollection<>(this, map.values()) : map.values();
}
@Override
public BeanCollection<E> shallowCopy() {
BeanMap<K, E> copy = new BeanMap<>(new LinkedHashMap<>(map));
copy.setFromOriginal(this);
return copy;
}
}
@@ -3,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.
@@ -38,6 +35,11 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
super(loader, ownerBean, propertyName);
}
@Override
public Set<E> freeze() {
return set == null ? null : Collections.unmodifiableSet(set);
}
@Override
public void toString(ToStringBuilder builder) {
builder.addCollection(set);
@@ -211,7 +213,6 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
@Override
public boolean add(E bean) {
checkReadOnly();
init();
if (modifyListening) {
if (set.add(bean)) {
@@ -226,7 +227,6 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
@Override
public boolean addAll(Collection<? extends E> beans) {
checkReadOnly();
init();
if (modifyListening) {
boolean changed = false;
@@ -244,7 +244,6 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
@Override
public void clear() {
checkReadOnly();
initClear();
if (modifyListening) {
for (E bean : set) {
@@ -275,9 +274,6 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
@Override
public Iterator<E> iterator() {
init();
if (readOnly) {
return new ReadOnlyIterator<>(set.iterator());
}
if (modifyListening) {
return new ModifyIterator<>(this, set.iterator());
}
@@ -286,7 +282,6 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
@Override
public boolean remove(Object bean) {
checkReadOnly();
init();
if (modifyListening) {
if (set.remove(bean)) {
@@ -300,7 +295,6 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
@Override
public boolean removeAll(Collection<?> beans) {
checkReadOnly();
init();
if (modifyListening) {
boolean changed = false;
@@ -317,7 +311,6 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
@Override
public boolean retainAll(Collection<?> beans) {
checkReadOnly();
init();
if (modifyListening) {
boolean changed = false;
@@ -355,36 +348,4 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
return set.toArray(array);
}
private static final class ReadOnlyIterator<E> implements Iterator<E>, Serializable {
private static final long serialVersionUID = 2577697326745352605L;
private final Iterator<E> it;
ReadOnlyIterator(Iterator<E> it) {
this.it = it;
}
@Override
public boolean hasNext() {
return it.hasNext();
}
@Override
public E next() {
return it.next();
}
@Override
public void remove() {
throw new IllegalStateException("This collection is in ReadOnly mode");
}
}
@Override
public BeanCollection<E> shallowCopy() {
BeanSet<E> copy = new BeanSet<>(new LinkedHashSet<>(set));
copy.setFromOriginal(this);
return copy;
}
}
@@ -1,185 +0,0 @@
package io.ebean.common;
import java.io.Serializable;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
/**
* List that copies itself on first write access. Needed to keep memory footprint low and the ability
* to modify lists from cache.
*
* @author Roland Praml, FOCONIS AG
*/
public final class CopyOnFirstWriteList<E> extends AbstractList<E> implements List<E>, Serializable {
private static final long serialVersionUID = 1L;
private final ReentrantLock lock = new ReentrantLock();
/**
* The underlying List implementation.
*/
private List<E> list;
public CopyOnFirstWriteList(List<E> list) {
super();
this.list = list;
}
private volatile boolean copied = false;
@Override
public int size() {
return list.size();
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public boolean contains(Object o) {
return list.contains(o);
}
@Override
public Object[] toArray() {
return list.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return list.toArray(a);
}
@Override
public boolean add(E e) {
checkCopyOnWrite();
return list.add(e);
}
@Override
public boolean remove(Object o) {
checkCopyOnWrite();
return list.remove(o);
}
@Override
public boolean containsAll(Collection<?> c) {
return list.containsAll(c);
}
@Override
public boolean addAll(Collection<? extends E> c) {
checkCopyOnWrite();
return list.addAll(c);
}
@Override
public boolean addAll(int index, Collection<? extends E> c) {
checkCopyOnWrite();
return list.addAll(index, c);
}
@Override
public boolean removeAll(Collection<?> c) {
checkCopyOnWrite();
return list.removeAll(c);
}
@Override
public boolean retainAll(Collection<?> c) {
checkCopyOnWrite();
return list.retainAll(c);
}
@Override
public void replaceAll(UnaryOperator<E> operator) {
checkCopyOnWrite();
list.replaceAll(operator);
}
@Override
public boolean removeIf(Predicate<? super E> filter) {
checkCopyOnWrite();
return list.removeIf(filter);
}
@Override
public void sort(Comparator<? super E> c) {
checkCopyOnWrite();
list.sort(c);
}
@Override
public void clear() {
if (!copied) {
list = new ArrayList<>();
copied = true;
}
}
@Override
public boolean equals(Object o) {
return list.equals(o);
}
@Override
public int hashCode() {
return list.hashCode();
}
@Override
public E get(int index) {
return list.get(index);
}
@Override
public E set(int index, E element) {
checkCopyOnWrite();
return list.set(index, element);
}
@Override
public void add(int index, E element) {
checkCopyOnWrite();
list.add(index, element);
}
@Override
public E remove(int index) {
checkCopyOnWrite();
return list.remove(index);
}
@Override
public int indexOf(Object o) {
return list.indexOf(o);
}
@Override
public int lastIndexOf(Object o) {
return list.lastIndexOf(o);
}
private void checkCopyOnWrite() {
if (!copied) {
lock.lock();
try {
if (!copied) {
list = new ArrayList<>(list);
copied = true;
}
} finally {
lock.unlock();
}
}
}
}
@@ -0,0 +1,66 @@
package io.ebean.config;
import java.util.Set;
/**
* Used when parsing formulas to determine if they are aggregation formulas like
* sum, min, max, avg, count etc.
* <p>
* Ebean needs to determine if they are aggregation formulas to determine which
* properties should be included in a GROUP BY clause etc.
*/
public interface AggregateFormulaContext {
/**
* Return true if the outer function is an aggregate function (like sum, count, min, max, avg etc).
*/
boolean isAggregate(String outerFunction);
/**
* Return true if the aggregate function returns a BIGINT type.
* This is true for functions like count that return a numeric value regardless of the
* type of the property or expression inside the outer function.
*/
boolean isCount(String outerFunction);
/**
* Return true if the aggregate function returns a VARCHAR type.
* This is true for functions that return a string concatenation like group_concat etc
* regardless of the type of the property used inside the outer function.
*/
boolean isConcat(String outerFunction);
/**
* Return a builder for the AggregateFormulaContext.
*/
static Builder builder() {
return new AggregateFormulaContextBuilder();
}
/**
* A builder for the AggregateFormulaContext.
*/
interface Builder {
/**
* Override the default set of aggregation functions.
*/
Builder aggregateFunctions(Set<String> count);
/**
* Override the default set of concat functions.
*/
Builder concatFunctions(Set<String> concat);
/**
* Override the default set of count functions.
*/
Builder countFunctions(Set<String> count);
/**
* Build the AggregateFormulaContext.
*/
AggregateFormulaContext build();
}
}
@@ -0,0 +1,61 @@
package io.ebean.config;
import java.util.Set;
final class AggregateFormulaContextBuilder implements AggregateFormulaContext.Builder {
private Set<String> aggFunctions = Set.of("count", "max", "min", "avg", "sum", "group_concat", "string_agg", "listagg");
private Set<String> concat = Set.of("concat", "group_concat", "string_agg", "listagg");
private Set<String> count = Set.of("count");
@Override
public AggregateFormulaContext.Builder aggregateFunctions(Set<String> agg) {
this.aggFunctions = agg;
return this;
}
@Override
public AggregateFormulaContext.Builder concatFunctions(Set<String> concat) {
this.concat = concat;
return this;
}
@Override
public AggregateFormulaContext.Builder countFunctions(Set<String> count) {
this.count = count;
return this;
}
@Override
public AggregateFormulaContext build() {
return new FormulaContext(aggFunctions, concat, count);
}
private static final class FormulaContext implements AggregateFormulaContext {
private final Set<String> aggFunctions;
private final Set<String> concat;
private final Set<String> count;
private FormulaContext(Set<String> aggFunctions, Set<String> concat, Set<String> count) {
this.aggFunctions = aggFunctions;
this.concat = concat;
this.count = count;
}
@Override
public boolean isAggregate(String outerFunction) {
return aggFunctions.contains(outerFunction);
}
@Override
public boolean isCount(String outerFunction) {
return count.contains(outerFunction);
}
@Override
public boolean isConcat(String outerFunction) {
return concat.contains(outerFunction);
}
}
}
@@ -1,5 +1,7 @@
package io.ebean.config;
import io.ebean.plugin.Lookups;
/**
* Helper to find classes taking into account the context class loader.
*/
@@ -73,9 +75,8 @@ public class ClassLoadConfig {
*/
public Object newInstance(String className) {
try {
Class<?> cls = forName(className);
return cls.getDeclaredConstructor().newInstance();
} catch (Exception e) {
return Lookups.newDefaultInstance(forName(className));
} catch (Throwable e) {
throw new IllegalArgumentException("Error constructing " + className, e);
}
}
@@ -129,7 +129,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
* When true then include a sql comment in generated SELECT queries with the query
* label or profile location label.
*/
private boolean includeLabelInSql;
private boolean includeLabelInSql = true;
/**
* Interesting classes such as entities, embedded, ScalarTypes,
@@ -251,7 +251,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
/**
* The default batch size for lazy loading
*/
private int lazyLoadBatchSize = 10;
private int lazyLoadBatchSize = 100;
/**
* The default batch size for 'query joins'.
@@ -311,6 +311,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
private boolean skipDataSourceCheck;
private boolean readOnlyDatabase;
private boolean shutdownHook = true;
/**
* The data source (if programmatically provided).
@@ -355,6 +356,8 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
*/
private NamingConvention namingConvention = new UnderscoreNamingConvention();
private AggregateFormulaContext aggregateFormulaContext = AggregateFormulaContext.builder().build();
/**
* Behaviour of updates in JDBC batch to by default include all properties.
*/
@@ -481,6 +484,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
* Time to live for query plans - defaults to 5 minutes.
*/
private int queryPlanTTLSeconds = 60 * 5;
private String queryPlanExplain;
/**
* Set to true to globally disable L2 caching (typically for performance testing).
@@ -1277,6 +1281,17 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
return this;
}
@Override
public AggregateFormulaContext aggregateFormulaContext() {
return aggregateFormulaContext;
}
@Override
public DatabaseConfig aggregateFormulaContext(AggregateFormulaContext aggregateFormulaContext) {
this.aggregateFormulaContext = aggregateFormulaContext;
return this;
}
@Override
public boolean isAllQuotedIdentifiers() {
return platformConfig.isAllQuotedIdentifiers();
@@ -1364,6 +1379,17 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
return readOnlyDatabase;
}
@Override
public DatabaseBuilder shutdownHook(boolean shutdownHook) {
this.shutdownHook = shutdownHook;
return this;
}
@Override
public boolean shutdownHook() {
return shutdownHook;
}
@Override
public DataSource getDataSource() {
return dataSource;
@@ -2136,6 +2162,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
loadDocStoreSettings(p);
defaultServer = p.getBoolean("defaultServer", defaultServer);
shutdownHook = p.getBoolean("shutdownHook", shutdownHook);
readOnlyDatabase = p.getBoolean("readOnlyDatabase", readOnlyDatabase);
autoPersistUpdates = p.getBoolean("autoPersistUpdates", autoPersistUpdates);
loadModuleInfo = p.getBoolean("loadModuleInfo", loadModuleInfo);
@@ -2151,6 +2178,7 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
queryPlanCapturePeriodSecs = p.getLong("queryPlan.capturePeriodSecs", queryPlanCapturePeriodSecs);
queryPlanCaptureMaxTimeMillis = p.getLong("queryPlan.captureMaxTimeMillis", queryPlanCaptureMaxTimeMillis);
queryPlanCaptureMaxCount = p.getInt("queryPlan.captureMaxCount", queryPlanCaptureMaxCount);
queryPlanExplain = p.get("queryPlan.explain", queryPlanExplain);
docStoreOnly = p.getBoolean("docStoreOnly", docStoreOnly);
disableL2Cache = p.getBoolean("disableL2Cache", disableL2Cache);
localOnlyL2Cache = p.getBoolean("localOnlyL2Cache", localOnlyL2Cache);
@@ -2402,6 +2430,17 @@ public class DatabaseConfig implements DatabaseBuilder.Settings {
return queryPlanTTLSeconds;
}
@Override
public String getQueryPlanExplain() {
return queryPlanExplain;
}
@Override
public DatabaseBuilder queryPlanExplain(String queryPlanExplain) {
this.queryPlanExplain = queryPlanExplain;
return this;
}
@Override
public DatabaseConfig setQueryPlanTTLSeconds(int queryPlanTTLSeconds) {
this.queryPlanTTLSeconds = queryPlanTTLSeconds;
@@ -0,0 +1,15 @@
package io.ebean.config;
import java.lang.invoke.MethodHandles.Lookup;
/**
* Provides a Lookup instance for accessing entity/dto fields.
*/
public interface LookupProvider {
/**
* Return the Lookup.
*/
Lookup provideLookup();
}
@@ -1,50 +1,29 @@
package io.ebean.config;
import io.ebean.ProfileLocation;
import io.ebean.bean.ObjectGraphNode;
import java.util.List;
/**
* Slow query event.
* The data for the slow query.
*/
public class SlowQueryEvent {
private final String sql;
private final long timeMillis;
private final int rowCount;
private final ObjectGraphNode originNode;
/**
* Construct with the SQL and execution time in millis.
*/
public SlowQueryEvent(String sql, long timeMillis, int rowCount, ObjectGraphNode originNode) {
this.sql = sql;
this.timeMillis = timeMillis;
this.rowCount = rowCount;
this.originNode = originNode;
}
public interface SlowQueryEvent {
/**
* Return the SQL for the slow query.
*/
public String getSql() {
return sql;
}
String getSql();
/**
* Return the execution time in millis.
*/
public long getTimeMillis() {
return timeMillis;
}
long getTimeMillis();
/**
* Return the total row count associated with the query.
*/
public int getRowCount() {
return rowCount;
}
int getRowCount();
/**
* Return the origin point for the root query.
@@ -53,7 +32,20 @@ public class SlowQueryEvent {
* shows the code that invoked the query.
* </p>
*/
public ObjectGraphNode getOriginNode() {
return originNode;
}
ObjectGraphNode getOriginNode();
/**
* Return the bind parameters.
*/
List<Object> getBindParams();
/**
* Return the label.
*/
String getLabel();
/**
* Return the profile location.
*/
ProfileLocation getProfileLocation();
}
@@ -4,22 +4,8 @@ public final class AnsiSqlRowsLimiter implements SqlLimiter {
@Override
public SqlLimitResponse limit(SqlLimitRequest request) {
String dbSql = request.getDbSql();
StringBuilder sb = new StringBuilder(50 + dbSql.length());
sb.append("select ");
if (request.isDistinct()) {
sb.append("distinct ");
}
sb.append(dbSql);
int firstRow = request.getFirstRow();
if (firstRow > 0) {
sb.append(" offset ").append(firstRow).append(" rows");
}
int maxRows = request.getMaxRows();
if (maxRows > 0) {
sb.append(" fetch next ").append(maxRows).append(" rows only");
}
String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
final var ansiSql = request.ansiOffsetRows();
final var sql = request.getDbPlatform().completeSql(ansiSql, request.getOrmQuery());
return new SqlLimitResponse(sql);
}
}
@@ -167,6 +167,7 @@ public class DatabasePlatform {
* findIterate() and findVisit().
*/
protected boolean forwardOnlyHintOnFindIterate;
protected boolean autoCommitFalseOnFindIterate;
/**
* If set then use the CONCUR_UPDATABLE hint when creating ResultSets.
@@ -528,6 +529,10 @@ public class DatabasePlatform {
this.forwardOnlyHintOnFindIterate = forwardOnlyHintOnFindIterate;
}
public boolean autoCommitFalseOnFindIterate() {
return autoCommitFalseOnFindIterate;
}
/**
* Return true if the ResultSet CONCUR_UPDATABLE Hint should be used on
* createNativeSqlTree() PreparedStatements.
@@ -780,4 +785,5 @@ public class DatabasePlatform {
public String inlineSqlHint(String hint) {
return "/*+ " + hint + " */ ";
}
}
@@ -172,7 +172,6 @@ public class DbPlatformType implements ExtraDbTypes {
* </p>
*/
public String renderType(int deployLength, int deployScale, boolean strict) {
int len = deployLength != 0 ? deployLength : defaultLength;
if (len > maxLength) {
return fallback.renderType(deployLength, deployScale, strict);
@@ -182,7 +181,6 @@ public class DbPlatformType implements ExtraDbTypes {
if ((canHaveLength || !strict) && len > 0) {
renderLengthScale(len, deployScale, sb);
}
return sb.toString();
}
}
@@ -46,6 +46,11 @@ public class DbPlatformTypeMapping {
private static final DbPlatformType MULTILINESTRING = new DbPlatformType("multilinestring");
private static final DbPlatformType MULTIPOLYGON = new DbPlatformType("multipolygon");
private static final DbPlatformType VECTOR = new DbPlatformType("vector", 2000, null);
private static final DbPlatformType VECTOR_HALF = new DbPlatformType("halfvec", 4000, null);
private static final DbPlatformType VECTOR_BIT = new DbPlatformType("bit", 64000, null);
private static final DbPlatformType VECTOR_SPARSE = new DbPlatformType("sparsevec", 1000, null);
private final Map<DbType, DbPlatformType> typeMap = new EnumMap<>(DbType.class);
/**
@@ -93,6 +98,10 @@ public class DbPlatformTypeMapping {
put(DbType.MULTIPOINT, MULTIPOINT);
put(DbType.MULTILINESTRING, MULTILINESTRING);
put(DbType.MULTIPOLYGON, MULTIPOLYGON);
put(DbType.VECTOR, VECTOR);
put(DbType.VECTOR_HALF, VECTOR_HALF);
put(DbType.VECTOR_BIT, VECTOR_BIT);
put(DbType.VECTOR_SPARSE, VECTOR_SPARSE);
if (logicalTypes) {
// keep it logical for 2 layer DDL generation
@@ -51,7 +51,12 @@ public enum DbType {
JSONB(ExtraDbTypes.JSONB),
JSONCLOB(ExtraDbTypes.JSONClob),
JSONBLOB(ExtraDbTypes.JSONBlob),
JSONVARCHAR(ExtraDbTypes.JSONVarchar);
JSONVARCHAR(ExtraDbTypes.JSONVarchar),
VECTOR(ExtraDbTypes.VECTOR),
VECTOR_HALF(ExtraDbTypes.VECTOR_HALF),
VECTOR_BIT(ExtraDbTypes.VECTOR_BIT),
VECTOR_SPARSE(ExtraDbTypes.VECTOR_SPARSE);
private final int id;

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