Compare commits

..
358 Commits
Author SHA1 Message Date
Rob Bygrave 367eba8685 Version 16.4.0 2026-04-10 08:03:12 +12:00
Rob BygraveandGitHub be542635a5 Bump ebean-test-containers to 8.0 (major bump to mark the port fix) (#3742)
Docker changed and that broke how ebean-test-containers detected the
currently assigned port for a container. That was fixed in 7.18 but
thinking its a good idea to mark that relatively important bug fix
with a bump of the major version to 8.0.

Everyone using ebean-test-containers should consider updating the
ebean-test-containers dependency to 8.0 or 7.18 (both have the fix).
2026-04-10 08:00:04 +12:00
Rob BygraveandGitHub 6e9d0a91e0 Fix for @Column on timestamp defined as timestamp(255) (#3740)
As per https://github.com/ebean-orm/ebean/discussions/3720

```
  @Column
  ZonedDateTime zonedDateTime2;
```
... resulting in DDL generated as `timestamp(255)`. This is
occurring when the JPA dependency is used like:
jakarta.persistence:jakarta.persistence-api:3.2.0
rather than using the transitive dependency that ebean includes.

Workaround:
Remove the jakarta.persistence:jakarta.persistence-api:3.2.0 dependency.

Fix:
The fix here is to use a timestamp type that has a maximum precision.
When a precision/length is specified greater than the maximum precision
then the fallback type is used which is `timestamp` without any precision.
2026-04-10 00:46:34 +12:00
Rob BygraveandGitHub a99ef3ebf2 Bump ebean-datasource dependency to 10.4, resets metrics on initialisation (#3739) 2026-04-09 22:23:55 +12:00
19afa845d1 FEATURE: inTuples() expressions support for natural key cache lookup (#3732)
* `inTuples()` support for natural key cache lookup

* Simplify NaturalKeyEntryBasic.addInPairs()

---------

Co-authored-by: Rob Bygrave <robin.bygrave@gmail.com>
2026-04-09 19:46:33 +12:00
Rob BygraveandGitHub 239900cd3b Bump ebean-agent to 16.4.0 with support for Java 26 (#3738) 2026-04-09 19:15:36 +12:00
robin.bygrave 73ac39971c Update test TestErrorBindLog for DB2 2026-04-08 22:55:41 +12:00
robin.bygrave 3a876252ec Update test TestQueryJoinOnFormula, restrict platforms for specific test
Restrict the new test_findCount_formulaJoin_subqueryWithOrderBy_issue3686
to H2 and Postgres for now. Not supported on Oracle and SQL Server.
2026-04-08 22:33:06 +12:00
robin.bygrave 231b52ba88 Update test TestErrorBindLog to improve failure message 2026-04-08 22:27:46 +12:00
robin.bygrave 808019cf3d Modify tests, move setRegister(false) setDefaultServer(false) before loadFromProperties() 2026-04-08 22:15:11 +12:00
Rob Bygrave 364520455f Add some logging for test BeanPersistControllerTest 2026-04-08 08:58:38 +12:00
Rob BygraveandGitHub e92621a489 Try old ebean agent, for strange CI build issue (#3737) 2026-04-08 08:51:33 +12:00
Rob BygraveandGitHub ccd1b7b8ec Bump ebean-test-containers to 7.18 (#3736) 2026-04-08 08:31:02 +12:00
thomas-lcdpandGitHub d144273307 ebean-core#3686: use parenthesis-aware ORDER BY removal in buildRowCountQuery to avoid breaking nested subqueries (#3729) 2026-03-27 23:18:15 +13:00
Rob BygraveandGitHub 41c5ebdcd7 Bump ebean-agent with ASM 9.9.1 and Java 26 support (#3731) 2026-03-27 23:15:00 +13:00
Rob BygraveandGitHub 9e711efecb Merge pull request #3730 from ebean-orm/feature/add-docs-for-graalvm-support
Add GraalVM native image support documentation
2026-03-27 22:06:00 +13:00
robin.bygrave ef7fd76f14 Add GraalVM native image support documentation 2026-03-27 22:05:21 +13:00
robin.bygrave b7e3ddbedd Add GraalVM native image badge to README.md 2026-03-27 21:55:29 +13:00
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 BygraveandGitHub 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 BygraveandGitHub 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
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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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
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 BygraveandGitHub ff0ca35e54 #3701 Improve error message when missing dependency ebean-jackson-mapper (#3708) 2025-11-23 20:25:16 +13:00
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 BygraveandGitHub 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 BygraveandGitHub 59a5c5f9bd Bump dependency avaje-config to 4.2 (#3699) 2025-11-11 07:59:40 +13:00
Rob BygraveandGitHub 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
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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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
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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 929604e33d Merge pull request #3593 from LeComptoirDesPharmacies/feature/findFutureMap
Add feature findFutureMap
2025-03-19 22:12:06 +13:00
Rob BygraveandGitHub 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 BygraveandGitHub 1afe42f4c6 Merge branch 'master' into feature/improved-readOnly-immutable 2025-03-18 22:43:00 +13:00
Rob BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 40637bd68c Allow OneToOne to map to ManyToOne (#3569) 2025-02-19 20:00:15 +13:00
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
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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 PramlandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 PramlandNoemi 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub e2c12268f7 Merge branch 'master' into feature/migrate-avaje-lang-to-jspecify 2024-10-18 16:52:53 +13:00
Rob BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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]andGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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 BygraveandGitHub 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
653 changed files with 9596 additions and 4103 deletions
+2 -1
View File
@@ -2,6 +2,7 @@
name: Build
on:
workflow_dispatch:
pull_request:
push:
branches: master
@@ -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
+2 -2
View File
@@ -16,7 +16,7 @@ jobs:
strategy:
fail-fast: false
matrix:
java_version: [GA,EA,23]
java_version: [GA,EA]
os: [ubuntu-latest]
steps:
@@ -37,5 +37,5 @@ jobs:
- name: Maven version
run: mvn --version
- name: Build with Maven
run: mvn -T 8 test
run: mvn test -Pea
+1 -1
View File
@@ -34,5 +34,5 @@ jobs:
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
+2 -2
View File
@@ -34,5 +34,5 @@ jobs:
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
+1 -1
View File
@@ -4,7 +4,7 @@ name: Yugabyte
on:
workflow_dispatch:
schedule:
- cron: '10 3 * * *'
- cron: '10 3 * * 3'
jobs:
build:
+1 -5
View File
@@ -3,6 +3,7 @@
[![Maven Central : ebean](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/ebean-orm/ebean/blob/master/LICENSE)
[![Multi-JDK Build](https://github.com/ebean-orm/ebean/actions/workflows/multi-jdk-build.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/multi-jdk-build.yml)
[![GraalVM Native Image](https://img.shields.io/badge/GraalVM-Native%20Image%20Ready-darkgreen?logo=graalvm)](https://www.graalvm.org/)
##### Build with database platforms
[![H2Database](https://github.com/ebean-orm/ebean/actions/workflows/h2database.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/h2database.yml)
@@ -59,11 +60,6 @@ Work at the highest level of abstraction and drop down levels as needed.
<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">
<a href="https://www.payintech.com/" target="_blank">
<img width="222px" src="https://ebean.io/images/sponsor_PayinTech-logo-noir.png">
</a>
</td>
<td align="center" valign="middle">
<a href="https://www.premium-minds.com" target="_blank">
<img width="222px" src="https://ebean.io/images/logo-med-principal.png">
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.5.0</version>
<version>16.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-clickhouse</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.5.0</version>
<version>16.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.5.0</version>
<version>16.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-db2</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.5.0</version>
<version>16.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.5.0</version>
<version>16.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-hana</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.5.0</version>
<version>16.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mariadb</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.5.0</version>
<version>16.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mysql</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
</dependencies>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.5.0</version>
<version>16.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -22,13 +22,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
@@ -47,19 +47,19 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-net-postgis-types</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.5.0</version>
<version>16.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-nuodb</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.5.0</version>
<version>16.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-oracle</artifactId>
<version>14.5.0</version>
<version>16.4.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.4.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.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>16.4.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.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-pgvector-types</artifactId>
<version>16.4.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.5.0</version>
<version>16.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -22,13 +22,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
@@ -47,19 +47,19 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgis-types</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.5.0</version>
<version>16.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.5.0</version>
<version>16.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlite</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.5.0</version>
<version>16.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlserver</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.5.0</version>
<version>16.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
</dependencies>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.5.0</version>
<version>16.4.0</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
@@ -41,7 +41,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jackson-mapper</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
@@ -60,13 +60,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-all</artifactId>
<version>14.5.0</version>
<version>16.4.0</version>
</dependency>
</dependencies>
+2 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.5.0</version>
<version>16.4.0</version>
</parent>
<artifactId>composites</artifactId>
@@ -25,6 +25,7 @@
<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.5.0</version>
<version>16.4.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,21 +205,6 @@ public interface ExpressionList<T> {
*/
int delete();
/**
* @deprecated migrate to {@link #usingTransaction(Transaction)} then delete().
* <p>
* 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.
*/
@Deprecated(forRemoval = true, since = "13.1.0")
int delete(Transaction transaction);
/**
* Execute as a update query.
*
@@ -244,17 +213,6 @@ public interface ExpressionList<T> {
*/
int update();
/**
* @deprecated migrate to {@link #usingTransaction(Transaction)} then update().
* <p>
* Execute as a update query with the given transaction.
*
* @return the number of rows that were updated.
* @see UpdateQuery
*/
@Deprecated(forRemoval = true, since = "13.1.0")
int update(Transaction transaction);
/**
* Execute the query returning true if a row is found.
* <p>
@@ -355,7 +313,7 @@ public interface ExpressionList<T> {
* List<String> names =
* DB.find(Customer.class)
* .select("name")
* .order().asc("name")
* .orderBy().asc("name")
* .findSingleAttributeList();
*
* }</pre>
@@ -368,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();
*
@@ -1713,7 +1671,7 @@ public interface ExpressionList<T> {
* .eq("status", Customer.Status.ACTIVE)
* .gt("id", 0)
* .endAnd()
* .order().asc("name")
* .orderBy().asc("name")
* .findList();
* }</pre>
*/
@@ -1734,7 +1692,7 @@ public interface ExpressionList<T> {
* .or()
* .eq("status", Customer.Status.ACTIVE)
* .isNull("anniversary")
* .order().asc("name")
* .orderBy().asc("name")
* .findList();
*
* }</pre>
@@ -1754,7 +1712,7 @@ public interface ExpressionList<T> {
* .eq("status", Customer.Status.ACTIVE)
* .gt("id", 0)
* .endAnd()
* .order().asc("name")
* .orderBy().asc("name")
* .findList();
*
* }</pre>
@@ -1788,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();
}
}
+23 -11
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) {
@@ -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);
}
/**
+7 -50
View File
@@ -1,6 +1,7 @@
package io.ebean;
import io.avaje.lang.NonNullApi;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
/**
* Object relational query for finding a List, Set, Map or single entity bean.
@@ -13,7 +14,7 @@ import io.avaje.lang.NonNullApi;
* .where()
* .like("customer.name","rob%")
* .gt("orderDate",lastWeek)
* .order("customer.id, id desc")
* .orderBy("customer.id, id desc")
* .setMaxRows(50)
* .findList();
*
@@ -149,7 +150,7 @@ import io.avaje.lang.NonNullApi;
*
* @param <T> the type of Entity bean this query will fetch.
*/
@NonNullApi
@NullMarked
public interface Query<T> extends CancelableQuery, QueryBuilder<Query<T>, T> {
/**
@@ -218,29 +219,6 @@ public interface Query<T> extends CancelableQuery, QueryBuilder<Query<T>, T> {
*/
boolean isCountDistinct();
/**
* @deprecated migrate to {@link #usingTransaction(Transaction)} then delete().
* <p>
* Execute as a delete query returning the number of rows deleted using the given transaction.
* <p>
* Note that if the query includes joins then the generated delete statement may not be
* optimal depending on the database platform.
*
* @return the number of beans/rows that were deleted.
*/
@Deprecated(forRemoval = true, since = "14.1.0")
int delete(Transaction transaction);
/**
* @deprecated migrate to {@link #usingTransaction(Transaction)} then update().
* <p>
* Execute the UpdateQuery returning the number of rows updated using the given transaction.
*
* @return the number of beans/rows updated.
*/
@Deprecated(forRemoval = true, since = "14.1.0")
int update(Transaction transaction);
/**
* Execute the UpdateQuery returning the number of rows updated.
*
@@ -333,6 +311,7 @@ public interface Query<T> extends CancelableQuery, QueryBuilder<Query<T>, T> {
/**
* Return the Id value.
*/
@Nullable
Object getId();
/**
@@ -440,30 +419,6 @@ public interface Query<T> extends CancelableQuery, QueryBuilder<Query<T>, T> {
*/
Query<T> having(Expression addExpressionToHaving);
/**
* @deprecated migrate to {@link #orderBy()}.
*/
@Deprecated(since = "13.19", forRemoval = true)
default Query<T> order(String orderByClause) {
return orderBy(orderByClause);
}
/**
* @deprecated migrate to {@link #orderBy()}.
*/
@Deprecated(since = "13.19", forRemoval = true)
default OrderBy<T> order() {
return orderBy();
}
/**
* @deprecated migrate to {@link #setOrderBy(OrderBy)}.
*/
@Deprecated(since = "13.19", forRemoval = true)
default Query<T> setOrder(OrderBy<T> orderBy) {
return setOrderBy(orderBy);
}
/**
* Return the OrderBy so that you can append an ascending or descending
* property to the order by clause.
@@ -493,11 +448,13 @@ public interface Query<T> extends CancelableQuery, QueryBuilder<Query<T>, T> {
/**
* Return the "for update" wait mode to use.
*/
@Nullable
LockWait getForUpdateLockWait();
/**
* Return the lock type (strength) to use with "for update".
*/
@Nullable
LockType getForUpdateLockType();
/**
@@ -1,6 +1,6 @@
package io.ebean;
import io.avaje.lang.Nullable;
import org.jspecify.annotations.Nullable;
import javax.sql.DataSource;
import java.sql.Connection;
@@ -20,8 +20,7 @@ import java.util.stream.Stream;
* @param <SELF> The type of the builder
* @param <T> The entity bean type
*/
//public interface QueryBuilder<SELF extends QueryBuilder<SELF, T>, T> extends QueryBuilderProjection<SELF, T> {
public interface QueryBuilder<SELF, T> extends QueryBuilderProjection<SELF, T> {
public interface QueryBuilder<SELF extends QueryBuilder<SELF, T>, T> extends QueryBuilderProjection<SELF, T> {
/**
* Set root table alias.
@@ -30,12 +29,10 @@ public interface QueryBuilder<SELF, T> extends QueryBuilderProjection<SELF, T> {
/**
* Apply changes to the query using a function.
* <p>
* This can be used to apply generic features to queries.
*
* @param apply The changes to apply to the query
* @param apply Function that applies changes to the query.
*/
SELF also(Consumer<QueryBuilder<?, ?>> apply);
SELF also(Consumer<SELF> apply);
/**
* Apply changes to the query conditional on the supplied predicate.
@@ -138,7 +135,17 @@ public interface QueryBuilder<SELF, T> extends QueryBuilderProjection<SELF, T> {
* source. We we use {@code usingMaster()} to instead ensure that the query is executed
* against the master data source.
*/
SELF usingMaster();
default SELF 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()
*/
SELF usingMaster(boolean useMaster);
/**
* Set the base table to use for this query.
@@ -327,6 +334,8 @@ public interface QueryBuilder<SELF, T> extends QueryBuilderProjection<SELF, T> {
*/
SELF setMaxRows(int maxRows);
SELF setPaging(Paging paging);
/**
* Set RawSql to use for this query.
*/
@@ -389,9 +398,19 @@ public interface QueryBuilder<SELF, T> extends QueryBuilderProjection<SELF, T> {
SELF setUseDocStore(boolean useDocStore);
/**
* When set to true when you want the returned beans to be read only.
* When set to true when you want the returned beans to be unmodifiable read only.
* <p>
* This means that the returning graph can't be mutated via setters, all the collections
* are unmodifiable collections, lazy loading is disabled and that the query uses
* {@link PersistenceContextScope#QUERY}.
* <p>
* Attempting to mutate an unmodifiable bean will throw a <code>UnmodifiableEntityException</code>.
* Attempting to load an unloaded property will throw a <code>LazyInitialisationException</code>
*
* @see LazyInitialisationException
* @see UnmodifiableEntityException
*/
SELF setReadOnly(boolean readOnly);
SELF setUnmodifiable(boolean unmodifiable);
/**
* Set a timeout on this query.
@@ -438,6 +457,16 @@ public interface QueryBuilder<SELF, T> extends QueryBuilderProjection<SELF, T> {
/**
* Set the {@link CacheMode} to use the query for executing this query.
* <p>
* Since version 16.x using the query bean will set the query to use unmodifiable (see
* {@link #setUnmodifiable(boolean)}) so the returned object graph is unmodifiable
* and safe to cache by the application.
* <p>
* Attempting to mutate an unmodifiable bean will throw a <code>UnmodifiableEntityException</code>.
* Attempting to load an unloaded property will throw a <code>LazyInitialisationException</code>
*
* @see LazyInitialisationException
* @see UnmodifiableEntityException
*/
SELF setUseQueryCache(CacheMode cacheMode);
@@ -953,6 +982,16 @@ public interface QueryBuilder<SELF, T> extends QueryBuilderProjection<SELF, T> {
*/
FutureList<T> findFutureList();
/**
* Execute find map query in a background thread.
* <p>
* This query will execute in it's own PersistenceContext and using its own transaction.
* What that means is that it will not share any bean instances with other queries.
*
* @return a Future object for the map result of the query
*/
<K> FutureMap<K,T> findFutureMap();
/**
* Return a PagedList for this query using firstRow and maxRows.
* <p>
@@ -6,8 +6,7 @@ package io.ebean;
* @param <SELF> The builder type
* @param <T> The entity bean type
*/
//public interface QueryBuilderProjection<SELF extends QueryBuilderProjection<SELF, T>, T> {
public interface QueryBuilderProjection<SELF, T> {
public interface QueryBuilderProjection<SELF extends QueryBuilderProjection<SELF, T>, T> {
/**
* Apply the path properties replacing the select and fetch clauses.
@@ -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);
}
}
@@ -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();
}
@@ -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,18 @@ 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);
/**
* Timestamp with max precision of 15, and fallback to plain timestamp without precision defined.
*/
private static final DbPlatformType TIMESTAMP =
new DbPlatformType("timestamp", 0, 15,
new DbPlatformType("timestamp", false));
private final Map<DbType, DbPlatformType> typeMap = new EnumMap<>(DbType.class);
/**
@@ -82,7 +94,8 @@ public class DbPlatformTypeMapping {
put(DbType.ARRAY);
put(DbType.DATE);
put(DbType.TIME);
put(DbType.TIMESTAMP);
put(DbType.TIMESTAMP, TIMESTAMP);
put(DbType.LONGVARBINARY);
put(DbType.LONGVARCHAR);
// most commonly real maps to db float
@@ -93,6 +106,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;
@@ -74,4 +74,24 @@ public interface ExtraDbTypes {
*/
int MULTILINESTRING = 6007;
/**
* PGVector base type
*/
int VECTOR = 7000;
/**
* PGVector half precision float type
*/
int VECTOR_HALF = 7001;
/**
* PGVector binary type (bit)
*/
int VECTOR_BIT = 7002;
/**
* PGVector sparse type
*/
int VECTOR_SPARSE = 7003;
}
@@ -157,7 +157,7 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
if (newIds.isEmpty()) {
throw new PersistenceException("Always expecting more than 1 row from " + sql);
}
connection.commit();
return newIds;
} catch (SQLException e) {
@@ -1,5 +1,6 @@
package io.ebean.event;
import io.ebean.plugin.Lookups;
/**
* Helper to find classes taking into account the context class loader.
@@ -12,8 +13,8 @@ class ClassUtil {
static Object newInstance(String className) {
try {
Class<?> cls = forName(className);
return cls.getDeclaredConstructor().newInstance();
} catch (Exception e) {
return Lookups.newDefaultInstance(cls);
} catch (Throwable e) {
String msg = "Error constructing " + className;
throw new IllegalArgumentException(msg, e);
}
@@ -1,40 +0,0 @@
package io.ebean.event;
import jakarta.servlet.ServletContextEvent;
/**
* Deprecated for removal - no intention to replace. Create your own copy of this
* ServletContextListener if needed for your application.
* <p>
* Listens for webserver server starting and stopping events.
* <p>
* This should be used when the deployment is into a servlet container where the webapp
* can be shutdown or redeployed without the JVM stopping.
* </p>
* <p>
* If deployment is into a container where the JVM is completely shutdown (like spring boot,
* runnable war or when using a servlet container that only contains the single webapp and
* the JVM is shutdown then this isn't required. Instead we can just rely on the JVM shutdown
* hook that Ebean registers.
* </p>
*/
@Deprecated(forRemoval = true)
public class ServletContextListener implements jakarta.servlet.ServletContextListener {
/**
* The servlet container is stopping.
*/
@Override
public void contextDestroyed(ServletContextEvent event) {
ShutdownManager.shutdown();
}
/**
* Do nothing on startup.
*/
@Override
public void contextInitialized(ServletContextEvent event) {
}
}
@@ -97,8 +97,7 @@ public final class ShutdownManager {
private static void registerShutdownHook() {
lock.lock();
try {
String value = System.getProperty("ebean.registerShutdownHook");
if (value == null || !value.trim().equalsIgnoreCase("false")) {
if ("true".equalsIgnoreCase(System.getProperty("ebean.registerShutdownHook", "true"))) {
Runtime.getRuntime().addShutdownHook(shutdownHook);
}
} catch (IllegalStateException ex) {
@@ -1,18 +1,19 @@
package io.ebean.meta;
import java.util.HashSet;
import java.util.Set;
import java.util.*;
import static java.util.Objects.requireNonNull;
/**
* Initiate query plan collection for plans by their hash or all query plans.
*/
public class QueryPlanInit {
private final Map<String,Long> hashes = new HashMap<>();
private boolean all;
private Set<String> hashes = new HashSet<>();
private long thresholdMicros;
private long defaultThresholdMicros;
/**
* Return true if this initiates bind collection on all query plans.
@@ -29,39 +30,74 @@ public class QueryPlanInit {
}
/**
* Return the query execution time threshold which must be exceeded to initiate
* Return the default query execution time threshold which must be exceeded to initiate
* query plan collection.
*/
public long thresholdMicros() {
return thresholdMicros;
return defaultThresholdMicros;
}
/**
* Set the query execution time threshold which must be exceeded to initiate
* Set the default query execution time threshold which must be exceeded to initiate
* query plan collection.
*/
public void thresholdMicros(long thresholdMicros) {
this.thresholdMicros = thresholdMicros;
this.defaultThresholdMicros = thresholdMicros;
}
/**
* Return true if the query plan should be initiated based on it's hash.
*/
public boolean includeHash(String hash) {
return all || hashes.contains(hash);
return all || hashes.containsKey(hash);
}
/**
* Return the specific hashes that we want to collect query plans on.
*
* @param hash The hash of the query plan.
* @param thresholdMicros The threshold in micros to use.
*/
public Set<String> hashes() {
return hashes;
public void add(String hash, long thresholdMicros) {
requireNonNull(hash);
if (!"all".equals(hash)) {
hashes.put(hash, thresholdMicros);
} else {
all = true;
if (thresholdMicros > 0) {
defaultThresholdMicros = thresholdMicros;
}
}
}
/**
* Set the specific hashes that we want to collect query plans on.
* Remove a hash from this request.
*/
public void hashes(Set<String> hashes) {
this.hashes = hashes;
public void remove(String hash) {
hashes.remove(hash);
}
/**
* Return the threshold in micros to use for the given hash.
*/
public long thresholdMicros(String hash) {
Long threshold = hashes.get(hash);
return threshold == null || threshold < 1 ? defaultThresholdMicros : threshold;
}
/**
* Return true if there are no registered hashes and not collect <em>All</em> plans.
*/
public boolean isEmpty() {
return !all && hashes.isEmpty();
}
@Override
public String toString() {
return "QueryPlanInit{" +
"all=" + all +
", hashes=" + hashes +
", thresholdMicros=" + defaultThresholdMicros +
'}';
}
}
@@ -1,17 +1,19 @@
package io.ebean.metric;
import io.ebean.ProfileLocation;
import io.ebean.XBootstrapService;
import io.ebean.service.BootstrapService;
/**
* Factory to create timed metric counters.
*/
public interface MetricFactory {
public interface MetricFactory extends BootstrapService {
/**
* Return the factory instance.
*/
static MetricFactory get() {
return MetricServiceProvider.get();
return XBootstrapService.metricFactory();
}
/**
@@ -1,28 +0,0 @@
package io.ebean.metric;
import java.util.Iterator;
import java.util.ServiceLoader;
/**
* Lookup MetricFactory service.
*/
final class MetricServiceProvider {
private static final MetricFactory metricFactory = init();
private static MetricFactory init() {
Iterator<MetricFactory> loader = ServiceLoader.load(MetricFactory.class).iterator();
if (loader.hasNext()) {
return loader.next();
}
throw new IllegalStateException("MetricFactory not service loaded?");
}
/**
* Return the MetricFactory implementation.
*/
static MetricFactory get() {
return metricFactory;
}
}
@@ -0,0 +1,43 @@
package io.ebean.plugin;
import io.ebean.DB;
import io.ebean.TxScope;
/**
* Helper object to make AOP generated code simpler.
*/
public final class AOPTransactionScope {
private static boolean enabled = true;
/**
* Entering an enhanced transactional method.
*/
public static void enter(TxScope txScope) {
if (enabled) {
server().scopedTransactionEnter(txScope);
}
}
/**
* Exiting an enhanced transactional method.
*/
public static void exit(Object returnOrThrowable, int opCode) {
if (enabled) {
server().scopedTransactionExit(returnOrThrowable, opCode);
}
}
private static SpiServer server() {
return (SpiServer) DB.getDefault();
}
/**
* Defines if the @Transactional does what is supposed to do or is disabled
* (useful only unit testing)
*
* @param enabled if set to false, @Transactional will not create a transaction
*/
public static void setEnabled(boolean enabled) {
AOPTransactionScope.enabled = enabled;
}
}
@@ -0,0 +1,41 @@
package io.ebean.plugin;
import static java.util.stream.Collectors.toMap;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import java.util.Map;
import java.util.ServiceLoader;
import io.ebean.config.LookupProvider;
/**
* Provides Lookup instances using potentially module specific Lookups.
*/
public final class Lookups {
private static final Map<String, Lookup> LOOKUP_MAP =
ServiceLoader.load(LookupProvider.class).stream()
.collect(toMap(p -> p.type().getModule().getName(), p -> p.get().provideLookup()));
private static final Lookup DEFAULT_LOOKUP = MethodHandles.publicLookup();
private static final MethodType VOID = MethodType.methodType(void.class);
/**
* Return a Lookup ideally for the module associated with the given type.
*/
public static Lookup getLookup(Class<?> type) {
return LOOKUP_MAP.getOrDefault(type.getModule().getName(), DEFAULT_LOOKUP);
}
/**
* Find the default constructor and return a new instance for the given type
* potentially using a module specific Lookup instance.
*/
@SuppressWarnings("unchecked")
public static <T> T newDefaultInstance(Class<?> type) throws Throwable {
return (T) getLookup(type).findConstructor(type, VOID).invoke();
}
}
@@ -1,6 +1,7 @@
package io.ebean.plugin;
import io.ebean.Database;
import io.ebean.TxScope;
import io.ebean.bean.BeanLoader;
import io.ebean.bean.EntityBeanIntercept;
import io.ebean.DatabaseBuilder;
@@ -63,4 +64,15 @@ public interface SpiServer extends Database {
* Typically due to serialisation or multiple stateless updates.
*/
void loadBean(EntityBeanIntercept ebi);
/**
* Start an enhanced transactional method.
*/
void scopedTransactionEnter(TxScope txScope);
/**
* Handle the end of an enhanced Transactional method.
*/
void scopedTransactionExit(Object returnOrThrowable, int opCode);
}
@@ -0,0 +1,7 @@
package io.ebean.service;
/**
* Marker interface for internal services loaded at startup.
*/
public interface BootstrapService {
}

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