Compare commits

...
Author SHA1 Message Date
Rob Bygrave 3c4b04a893 Version 16.0.0-rc1 2025-04-09 23:18:27 +12:00
Rob Bygrave ee403bdb83 Merge pull request #3620 from ebean-orm/feature/bump-ebean-agent
Bump the ebean-agent to 14.12.0, support for Lombok SuperBuilder
2025-04-09 23:02:46 +12:00
Rob Bygrave b18abe2221 Bump the ebean-agent to 14.12.0, support for Lombok SuperBuilder 2025-04-09 22:52:39 +12:00
Rob Bygrave d68f372d99 Merge pull request #3619 from ebean-orm/feature/column-length-255
For Postgres @Column(length=255) means varchar(255)
2025-04-09 20:22:56 +12:00
Rob Bygrave c8f769aa2a For Postgres @Column(length=255) means varchar(255)
The `@Column` length defaults to 0 rather than 255, this allows us to detect when it has been explicitly set and thus for Postgres we can now have:

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

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

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

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

LazyInitialisationException extends BeanAccessException ...
UnmodifiableEntityException extends BeanAccessException ...
2025-03-18 22:54:34 +13:00
Rob Bygrave 1afe42f4c6 Merge branch 'master' into feature/improved-readOnly-immutable 2025-03-18 22:43:00 +13:00
Rob Bygrave 4e7f3c13a0 Merge pull request #3592 from ebean-orm/feature/improved-readOnly-immutable-part2
Remove readOnly, migrate to unmodifiable (or use normal mutable)
2025-03-18 22:41:12 +13:00
Thomas a35db6bdee Add feature findFutureMap 2025-03-18 09:19:15 +01:00
Rob Bygrave c13e09257c Version 14.10.0 2025-03-11 21:26:00 +13:00
Rob Bygrave ed65433640 Merge pull request #3574 from ebean-orm/feature/3459-postgres-varchar
#3459 Postgres varchar default to no length (aka text)
2025-03-11 20:01:26 +13:00
Rob Bygrave 08890e9d5a Merge pull request #3590 from ebean-orm/feature/3580-lookwriter-logWarn
Adjust LookupWriter to log at WARN rather than ERROR due to Quarkus dev mode
2025-03-10 23:56:19 +13:00
Rob Bygrave 4273c4af6a Adjust LookupWriter to log at WARN rather than ERROR due to Quarkus dev mode
Die to Quarkus dev mode (#3541 #3582) we want to log FilerException at WARN level rather than ERROR. This is because Quarkus dev mode will invoke the annotation processor more than usual, so we expect to fail with the FilerException.
2025-03-10 23:42:38 +13:00
Rob Bygrave 51424d9eea Merge pull request #3580 from SentryMan/feature/lookup-generation
[querybean-generator] Generate lookup for modules
2025-03-10 23:31:35 +13:00
Rob Bygrave cf2ab33903 Merge pull request #3589 from ebean-orm/feature/bump-ebean-agent-dependency
Bump ebean-agent to 14.10.0
2025-03-10 23:28:05 +13:00
Rob Bygrave 90d8b4fb04 Bump ebean-agent to 14.10.0 2025-03-10 23:27:02 +13:00
Rob Bygrave ff4eeff264 Merge pull request #3588 from ebean-orm/feature/3586-querybean-gen
[query bean generation] #3586 public constructor for Embedded bean
2025-03-10 08:02:03 +13:00
Rob Bygrave 64ba343e35 [query bean generation] #3586 public constructor for Embedded bean 2025-03-10 07:59:33 +13:00
Rob Bygrave af3c59c0fd Merge pull request #3587 from ebean-orm/feature/bump-test-containers-77
Bump ebean-test-containers dependency - improved SQL Server handling
2025-03-10 07:40:31 +13:00
Rob Bygrave ae55d28026 Bump ebean-test-containers dependency - improved SQL Server handling
Improvments around collation changes that end up making SQL Server startup flaky
2025-03-10 07:40:02 +13:00
Rob Bygrave ddffc8eee2 Merge pull request #3581 from apflieger/#3573-initfields-prevent-secondary-query
OneToMany initialisation via List.of() - was Tests only - new test on multiple many joins
2025-03-10 07:30:40 +13:00
Rob Bygrave 7f1a3a46cf #3581 ebean-agent 14.10.0 handling for OneToMany initialisation 2025-03-10 07:12:20 +13:00
Rob Bygrave a59f75a468 Merge pull request #3585 from nedge/feature/Create_test_entities
Simple Test Entities in preparation for type scoped loading
2025-03-05 08:06:39 +13:00
Eddie Mc Greal 6f1c66ecd6 Simple Test Entities in preparation for type scoped loading 2025-03-04 14:17:08 +01:00
Rob Bygrave 25f6fb6d6f test only - Almost fix the model for test_manyNonRoot_RootHasNoMany
The test was using field access??? when that isn't valid unless we specifically turn on enhancement to support that.

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

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

Refer to the ExtendedServerTest for an example
2025-02-26 22:16:12 +13:00
Rob Bygrave cc48dced09 #3572 DDL support for non-nullable JoinColumn column (#3575) 2025-02-26 21:13:50 +13:00
Rob Bygrave b13bdc95be #3459 Postgres varchar default to no length (aka text)
Change Postgres platform to default a String to varchar [with no length defined] rather than varchar(255)
2025-02-26 18:53:08 +13:00
Rob Bygrave 0a5c3ced21 Test only - update TestQueryMultiManyOrder sql asserts
No effective change.
2025-02-26 00:59:57 +13:00
Noemi Praml 3ab3f81fa3 Add failing concurrent test 2024-10-31 08:21:37 +01:00
189 changed files with 1953 additions and 865 deletions
+1 -1
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:
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-clickhouse</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-db2</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-hana</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mariadb</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mysql</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
</dependencies>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<relativePath>../..</relativePath>
</parent>
@@ -22,13 +22,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -47,19 +47,19 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-net-postgis-types</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-nuodb</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-oracle</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
</dependencies>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<relativePath>../..</relativePath>
</parent>
@@ -22,13 +22,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -47,19 +47,19 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgis-types</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlite</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlserver</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
</dependencies>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -42,13 +42,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
</dependencies>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<relativePath>../..</relativePath>
</parent>
@@ -17,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -41,7 +41,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jackson-mapper</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -60,13 +60,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-all</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
</dependencies>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</parent>
<artifactId>composites</artifactId>
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</parent>
<name>ebean api</name>
@@ -35,7 +35,7 @@
<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-config</artifactId>
<version>3.12</version>
<version>4.0</version>
</dependency>
<dependency>
@@ -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);
}
}
@@ -772,18 +772,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>
@@ -2019,6 +2019,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.
@@ -3044,6 +3049,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.
*/
@@ -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);
}
@@ -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;
}
@@ -8,7 +8,7 @@ package io.ebean;
* a unmodifiable entity with lazy loading disabled, accessing an unloaded property
* throws this LazyInitialisationException instead.
*/
public class LazyInitialisationException extends UnmodifiableEntityException {
public class LazyInitialisationException extends BeanAccessException {
/**
* Create specifying the property that was being accessed.
@@ -956,6 +956,16 @@ public interface QueryBuilder<SELF extends QueryBuilder<SELF, T>, T> extends Que
*/
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>
@@ -3,7 +3,7 @@ package io.ebean;
/**
* Attempted to modify a read only entity.
*/
public class UnmodifiableEntityException extends UnsupportedOperationException {
public class UnmodifiableEntityException extends BeanAccessException {
private static final long serialVersionUID = 1;
/**
@@ -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;
}
}
@@ -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'.
@@ -481,6 +481,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).
@@ -2151,6 +2152,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 +2404,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;
@@ -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();
}
}
@@ -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,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 +
'}';
}
}
@@ -77,6 +77,8 @@ class DatabaseConfigTest {
props.setProperty("readOnlyDatabase", "true");
props.setProperty("lengthCheck", "ON");
props.setProperty("includeLabelInSql", "false");
props.setProperty("lazyLoadBatchSize", "50");
props.setProperty("queryBatchSize", "60");
props.setProperty("queryPlan.enable", "true");
props.setProperty("queryPlan.thresholdMicros", "10000");
@@ -84,6 +86,7 @@ class DatabaseConfigTest {
props.setProperty("queryPlan.capturePeriodSecs", "42");
props.setProperty("queryPlan.captureMaxTimeMillis", "560");
props.setProperty("queryPlan.captureMaxCount", "7");
props.setProperty("queryPlan.explain", "explain (verbose)");
config.loadFromProperties(props);
@@ -99,6 +102,8 @@ class DatabaseConfigTest {
assertTrue(settings.readOnlyDatabase());
assertFalse(settings.isIncludeLabelInSql());
assertThat(settings.getLengthCheck()).isEqualTo(LengthCheck.ON);
assertThat(settings.getLazyLoadBatchSize()).isEqualTo(50);
assertThat(settings.getQueryBatchSize()).isEqualTo(60);
assertTrue(settings.isIdGeneratorAutomatic());
assertFalse(settings.getPlatformConfig().isCaseSensitiveCollation());
@@ -129,15 +134,18 @@ class DatabaseConfigTest {
assertEquals(42, settings.getQueryPlanCapturePeriodSecs());
assertEquals(560, settings.getQueryPlanCaptureMaxTimeMillis());
assertEquals(7, settings.getQueryPlanCaptureMaxCount());
assertEquals("explain (verbose)", settings.getQueryPlanExplain());
assertThat(settings.getMappingLocations()).containsExactly("classpath:/foo","bar");
config.persistBatch(PersistBatch.NONE)
.persistBatchOnCascade(PersistBatch.NONE)
.lengthCheck(LengthCheck.ON)
.lengthCheck(LengthCheck.UTF8);
.lengthCheck(LengthCheck.UTF8)
.queryPlanExplain("explain (buffers)");
assertThat(config.settings().getQueryPlanExplain()).isEqualTo("explain (buffers)");
Properties props1 = new Properties();
props1.setProperty("ebean.persistBatch", "ALL");
props1.setProperty("ebean.persistBatchOnCascade", "ALL");
@@ -175,6 +183,8 @@ class DatabaseConfigTest {
assertTrue(config.getPlatformConfig().isCaseSensitiveCollation());
assertTrue(config.isAutoLoadModuleInfo());
assertTrue(config.isLoadModuleInfo());
assertThat(config.getLazyLoadBatchSize()).isEqualTo(100);
assertThat(config.getQueryBatchSize()).isEqualTo(100);
assertFalse(config.isQueryPlanEnable());
assertEquals(Long.MAX_VALUE, config.getQueryPlanThresholdMicros());
@@ -182,6 +192,7 @@ class DatabaseConfigTest {
assertEquals(600, config.getQueryPlanCapturePeriodSecs());
assertEquals(10000L, config.getQueryPlanCaptureMaxTimeMillis());
assertEquals(10, config.getQueryPlanCaptureMaxCount());
assertThat(config.getQueryPlanExplain()).isNull();
assertThat(config.getLengthCheck()).isEqualTo(LengthCheck.OFF);
assertTrue(config.isIncludeLabelInSql());
@@ -192,6 +203,10 @@ class DatabaseConfigTest {
assertTrue(config.isAutoPersistUpdates());
config.setSkipDataSourceCheck(true);
assertTrue(config.skipDataSourceCheck());
config.lazyLoadBatchSize(20);
assertThat(config.getLazyLoadBatchSize()).isEqualTo(20);
config.queryBatchSize(30);
assertThat(config.getQueryBatchSize()).isEqualTo(30);
}
@Test
@@ -0,0 +1,43 @@
package io.ebean.meta;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class QueryPlanInitTest {
@Test
void initialQueryPlanInit() {
var init = new QueryPlanInit();
assertThat(init.isEmpty()).isTrue();
assertThat(init.isAll()).isFalse();
assertThat(init.thresholdMicros()).isEqualTo(0L);
}
@Test
void add_all() {
var init = new QueryPlanInit();
init.add("all", 57L);
assertThat(init.isEmpty()).isFalse();
assertThat(init.isAll()).isTrue();
assertThat(init.thresholdMicros()).isEqualTo(57L);
}
@Test
void addWithThresholds() {
var init = new QueryPlanInit();
init.thresholdMicros(1000);
init.add("xOne", 0);
init.add("xTwo", 2000L);
assertThat(init.isEmpty()).isFalse();
assertThat(init.isAll()).isFalse();
assertThat(init.includeHash("xJunk")).isFalse();
assertThat(init.includeHash("xOne")).isTrue();
assertThat(init.includeHash("xTwo")).isTrue();
assertThat(init.thresholdMicros("xJunk")).isEqualTo(1000L);
assertThat(init.thresholdMicros("xOne")).isEqualTo(1000L);
assertThat(init.thresholdMicros("xTwo")).isEqualTo(2000L);
}
}
+26 -26
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</parent>
<name>ebean bom</name>
@@ -89,25 +89,25 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -125,13 +125,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jackson-mapper</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-ddl-generator</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -155,37 +155,37 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>querybean-generator</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>kotlin-querybean-generator</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-redis</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-spring-txn</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<!-- platforms -->
@@ -193,79 +193,79 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-clickhouse</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-db2</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-h2</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-hana</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-mariadb</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-mysql</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-nuodb</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-oracle</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgres</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgis</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgis-types</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-sqlite</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-sqlserver</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
</dependencies>
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</parent>
<artifactId>ebean-core-type</artifactId>
@@ -16,7 +16,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
+6 -6
View File
@@ -3,7 +3,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</parent>
<artifactId>ebean-core</artifactId>
@@ -22,7 +22,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -46,7 +46,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -159,21 +159,21 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlserver</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>test</scope>
</dependency>
@@ -26,7 +26,7 @@ import java.util.stream.Stream;
/**
* Service Provider extension to EbeanServer.
*/
public interface SpiEbeanServer extends SpiServer, ExtendedServer, BeanCollectionLoader {
public interface SpiEbeanServer extends SpiServer, BeanCollectionLoader {
/**
* Return the NOW time from the Clock.
@@ -348,6 +348,8 @@ public interface SpiEbeanServer extends SpiServer, ExtendedServer, BeanCollectio
<T> FutureList<T> findFutureList(SpiQuery<T> query);
<K, T> FutureMap<K, T> findFutureMap(SpiQuery<T> query);
<T> PagedList<T> findPagedList(SpiQuery<T> query);
<T> Set<T> findSet(SpiQuery<T> query);
@@ -14,6 +14,7 @@ import io.ebeanservice.docstore.api.DocStoreTransaction;
import jakarta.persistence.PersistenceException;
import java.sql.Connection;
import java.sql.SQLException;
import java.time.Instant;
/**
* Extends Transaction with additional API required on server.
@@ -95,7 +96,7 @@ public interface SpiTransaction extends Transaction {
/**
* Return the start timestamp for the transaction (JVM side).
*/
long startNanoTime();
Instant startTime();
/**
* Return true if this transaction has updateAllLoadedProperties set.
@@ -14,6 +14,7 @@ import io.ebeanservice.docstore.api.DocStoreTransaction;
import jakarta.persistence.PersistenceException;
import java.sql.Connection;
import java.sql.SQLException;
import java.time.Instant;
/**
* Proxy for an underlying SpiTransaction (most of the API).
@@ -28,8 +29,8 @@ public abstract class SpiTransactionProxy implements SpiTransaction {
}
@Override
public long startNanoTime() {
return transaction.startNanoTime();
public Instant startTime() {
return transaction.startTime();
}
@Override
@@ -23,7 +23,7 @@ public class DefaultServerQueryCache extends DefaultServerCache {
@Override
protected Object unwrapEntry(CacheEntry entry) {
return ((QueryCacheEntry) entry.getValue()).getValue();
return ((QueryCacheEntry) entry.getValue()).value();
}
@Override
@@ -1,29 +0,0 @@
package io.ebeaninternal.server.core;
import java.time.Clock;
/**
* Wraps the Clock such that we can change the Clock for testing purposes.
*/
public class ClockService {
private Clock clock;
public ClockService(Clock clock) {
this.clock = clock;
}
/**
* Change the clock for testing purposes.
*/
public void setClock(Clock clock) {
this.clock = clock;
}
/**
* Return the Clock current timestamp in millis.
*/
public long nowMillis() {
return clock.millis();
}
}
@@ -77,7 +77,12 @@ public class DatabasePlatformFactory {
*/
private DatabasePlatform byDataSource(DataSource dataSource) {
try (Connection connection = dataSource.getConnection()) {
return byDatabaseMeta(connection.getMetaData(), connection);
DatabasePlatform platform = byDatabaseMeta(connection.getMetaData(), connection);
if (!connection.getAutoCommit()) {
// we must roll back before close.
connection.rollback();
}
return platform;
} catch (SQLException ex) {
throw new PersistenceException(ex);
}
@@ -262,6 +262,8 @@ public final class DefaultContainer implements SpiContainer {
try (Connection connection = config.getDataSource().getConnection()) {
if (connection.getAutoCommit()) {
log.log(WARNING, "DataSource [{0}] has autoCommit defaulting to true!", config.getName());
} else {
connection.rollback();
}
return true;
} catch (SQLException ex) {
@@ -82,7 +82,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
private final QueryPlanManager queryPlanManager;
private final ExtraMetrics extraMetrics;
private final DataTimeZone dataTimeZone;
private final ClockService clockService;
private final Clock clock;
private final CallOriginFactory callStackFactory;
private final Persister persister;
private final OrmQueryEngine queryEngine;
@@ -150,7 +150,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
this.beanLoader = new DefaultBeanLoader(this);
this.jsonContext = config.createJsonContext(this);
this.dataTimeZone = config.getDataTimeZone();
this.clockService = config.getClockService();
this.clock = config.clock();
DocStoreIntegration docStoreComponents = config.createDocStoreIntegration(this);
this.transactionManager = config.createTransactionManager(this, docStoreComponents.updateProcessor());
@@ -412,19 +412,9 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
return serverName;
}
@Override
public ExtendedServer extended() {
return this;
}
@Override
public long clockNow() {
return clockService.nowMillis();
}
@Override
public void setClock(Clock clock) {
this.clockService.setClock(clock);
return clock.millis();
}
@Override
@@ -1259,66 +1249,55 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
}
private <T> SpiQuery<T> configureForFuture(SpiQuery<T> query) {
query.usingFuture();
if (query.transaction() == null) {
// use a current transaction if active
query.usingTransaction(currentServerTransaction());
}
return query;
}
@Override
public <T> FutureRowCount<T> findFutureCount(SpiQuery<T> query) {
SpiQuery<T> copy = query.copy();
copy.usingFuture();
boolean createdTransaction = false;
SpiTransaction transaction = query.transaction();
if (transaction == null) {
transaction = currentServerTransaction();
if (transaction == null) {
transaction = (SpiTransaction) createTransaction();
createdTransaction = true;
}
copy.usingTransaction(transaction);
}
var queryFuture = new QueryFutureRowCount<>(new CallableQueryCount<>(this, copy, createdTransaction));
SpiQuery<T> copy = configureForFuture(query.copy());
var queryFuture = new QueryFutureRowCount<>(new CallableQueryCount<>(this, copy));
backgroundExecutor.execute(queryFuture.futureTask());
return queryFuture;
}
@Override
public <T> FutureIds<T> findFutureIds(SpiQuery<T> query) {
SpiQuery<T> copy = query.copy();
copy.usingFuture();
boolean createdTransaction = false;
SpiTransaction transaction = query.transaction();
if (transaction == null) {
transaction = currentServerTransaction();
if (transaction == null) {
transaction = (SpiTransaction) createTransaction();
createdTransaction = true;
}
copy.usingTransaction(transaction);
}
QueryFutureIds<T> queryFuture = new QueryFutureIds<>(new CallableQueryIds<>(this, copy, createdTransaction));
SpiQuery<T> copy = configureForFuture(query.copy());
final var queryFuture = new QueryFutureIds<T>(new CallableQueryIds<>(this, copy));
backgroundExecutor.execute(queryFuture.futureTask());
return queryFuture;
}
@Override
public <T> FutureList<T> findFutureList(SpiQuery<T> query) {
SpiQuery<T> spiQuery = query.copy();
spiQuery.usingFuture();
// FutureList query always run in it's own persistence content
SpiQuery<T> spiQuery = configureForFuture(query.copy());
// FutureList query always run in its own persistence content
spiQuery.setPersistenceContext(new DefaultPersistenceContext());
if (!spiQuery.isDisableReadAudit()) {
BeanDescriptor<T> desc = descriptorManager.descriptor(spiQuery.getBeanType());
desc.readAuditFutureList(spiQuery);
}
// Create a new transaction solely to execute the findList() at some future time
boolean createdTransaction = false;
SpiTransaction transaction = query.transaction();
if (transaction == null) {
transaction = currentServerTransaction();
if (transaction == null) {
transaction = (SpiTransaction) createTransaction();
createdTransaction = true;
}
spiQuery.usingTransaction(transaction);
final var queryFuture = new QueryFutureList<T>(new CallableQueryList<>(this, spiQuery));
backgroundExecutor.execute(queryFuture.futureTask());
return queryFuture;
}
@Override
public <K, T> FutureMap<K, T> findFutureMap(SpiQuery<T> query) {
SpiQuery<T> spiQuery = configureForFuture(query.copy());
// FutureMap query always run in it's own persistence content
spiQuery.setPersistenceContext(new DefaultPersistenceContext());
if (!spiQuery.isDisableReadAudit()) {
BeanDescriptor<T> desc = descriptorManager.descriptor(spiQuery.getBeanType());
desc.readAuditFutureList(spiQuery);
}
QueryFutureList<T> queryFuture = new QueryFutureList<>(new CallableQueryList<>(this, spiQuery, createdTransaction));
final var queryFuture = new QueryFutureMap<K, T>(new CallableQueryMap<>(this, spiQuery));
backgroundExecutor.execute(queryFuture.futureTask());
return queryFuture;
}
@@ -55,6 +55,7 @@ import io.ebeanservice.docstore.api.DocStoreIntegration;
import io.ebeanservice.docstore.api.DocStoreUpdateProcessor;
import io.ebeanservice.docstore.none.NoneDocStoreFactory;
import java.time.Clock;
import java.util.*;
import static java.lang.System.Logger.Level.*;
@@ -75,7 +76,7 @@ public final class InternalConfiguration {
private final DeployInherit deployInherit;
private final TypeManager typeManager;
private final DtoBeanManager dtoBeanManager;
private final ClockService clockService;
private final Clock clock;
private final DataTimeZone dataTimeZone;
private final Binder binder;
private final DeployCreateProperties deployCreateProperties;
@@ -103,7 +104,7 @@ public final class InternalConfiguration {
this.online = online;
this.config = config;
this.jacksonCorePresent = config.getClassLoadConfig().isJacksonCorePresent();
this.clockService = new ClockService(config.settings().getClock());
this.clock = config.settings().getClock();
this.tableModState = new TableModState();
this.logManager = initLogManager();
this.docStoreFactory = initDocStoreFactory(service(DocStoreFactory.class));
@@ -189,8 +190,8 @@ public final class InternalConfiguration {
return docStoreFactory;
}
ClockService getClockService() {
return clockService;
Clock clock() {
return clock;
}
public ExtraMetrics getExtraMetrics() {
@@ -391,7 +392,7 @@ public final class InternalConfiguration {
TransactionManagerOptions options =
new TransactionManagerOptions(server, notifyL2CacheInForeground, config, scopeManager, clusterManager, backgroundExecutor,
indexUpdateProcessor, beanDescriptorManager, dataSource(), profileHandler(), logManager,
tableModState, cacheNotify, clockService);
tableModState, cacheNotify);
if (config.isDocStoreOnly()) {
return new DocStoreTransactionManager(options);
@@ -584,27 +585,32 @@ public final class InternalConfiguration {
return QueryPlanManager.NOOP;
}
long threshold = config.getQueryPlanThresholdMicros();
return new CQueryPlanManager(transactionManager, threshold, queryPlanLogger(databasePlatform.platform()), extraMetrics);
return new CQueryPlanManager(transactionManager, threshold, queryPlanLogger(databasePlatform.platform(), config), extraMetrics);
}
/**
* Returns the logger to log query plans for the given platform.
*/
QueryPlanLogger queryPlanLogger(Platform platform) {
QueryPlanLogger queryPlanLogger(Platform platform, DatabaseBuilder.Settings config) {
switch (platform.base()) {
case SQLSERVER:
return new QueryPlanLoggerSqlServer();
case ORACLE:
return new QueryPlanLoggerOracle();
case POSTGRES:
return new QueryPlanLoggerExplain("explain (analyze, buffers) ");
return new QueryPlanLoggerExplain(explain(config, "explain (analyze, costs, verbose, buffers) "));
case YUGABYTE:
return new QueryPlanLoggerExplain("explain (analyze, buffers, dist) ");
return new QueryPlanLoggerExplain(explain(config,"explain (analyze, buffers, dist) "));
default:
return new QueryPlanLoggerExplain("explain ");
return new QueryPlanLoggerExplain(explain(config,"explain "));
}
}
private static String explain(DatabaseBuilder.Settings config, String defaultExplain) {
String explain = config.getQueryPlanExplain();
return explain == null ? defaultExplain : explain + ' ';
}
/**
* Return the DDL generator.
*/
@@ -665,7 +665,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
}
public void putToQueryCache(Object result) {
beanDescriptor.queryCachePut(cacheKey, new QueryCacheEntry(result, dependentTables, transaction.startNanoTime()));
beanDescriptor.queryCachePut(cacheKey, new QueryCacheEntry(result, dependentTables, transaction.startTime()));
}
/**
@@ -1471,7 +1471,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
void queryPlanInit(QueryPlanInit request, List<MetaQueryPlan> list) {
for (CQueryPlan queryPlan : queryPlanCache.values()) {
if (request.includeHash(queryPlan.hash())) {
queryPlan.queryPlanInit(request.thresholdMicros());
queryPlan.queryPlanInit(request.thresholdMicros(queryPlan.hash()));
list.add(queryPlan.createMeta(null, null));
}
}
@@ -58,7 +58,7 @@ final class BeanEmbeddedMetaFactory {
}
private static int dbLength(Column override, BeanProperty source) {
return (override != null && (override.length() != 255)) ? override.length() : source.dbLength();
return (override != null && (override.length() != 0)) ? override.length() : source.dbLength();
}
private static int dbScale(Column override, BeanProperty source) {
@@ -1,6 +1,5 @@
package io.ebeaninternal.server.deploy;
import io.ebean.Query;
import io.ebean.SqlUpdate;
import io.ebean.Transaction;
import io.ebean.ValuePair;
@@ -125,6 +124,10 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
// no imported or exported information
} else if (!oneToOneExported) {
importedId = createImportedId(this, targetDescriptor, tableJoin);
if (importedId == null) {
throw new PersistenceException("Cannot find imported id for " + fullName() + " from " + targetDescriptor
+ ". If using native-image, possibly missing reflect-config for the Id property.");
}
if (importedId.isScalar()) {
// limit JoinColumn mapping to the @Id / primary key
TableJoinColumn[] columns = tableJoin.columns();
@@ -20,6 +20,7 @@ public final class TableJoinColumn {
private final String foreignSqlFormula;
private final boolean insertable;
private final boolean updateable;
private final boolean nullable;
/**
* Hash for including in a query plan
*/
@@ -34,7 +35,8 @@ public final class TableJoinColumn {
this.localSqlFormula = InternString.intern(deploy.getLocalSqlFormula());
this.foreignSqlFormula = InternString.intern(deploy.getForeignSqlFormula());
this.insertable = deploy.isInsertable();
this.updateable = deploy.isUpdateable();
this.updateable = deploy.isUpdatable();
this.nullable = deploy.isNullable();
this.queryHash = hash();
}
@@ -45,6 +47,7 @@ public final class TableJoinColumn {
this.foreignSqlFormula = null;
this.insertable = source.isInsertable();
this.updateable = source.isUpdateable();
this.nullable = source.isNullable();
this.queryHash = hash();
}
@@ -115,6 +118,13 @@ public final class TableJoinColumn {
return updateable;
}
/**
* Return if this column is nullable.
*/
public boolean isNullable() {
return nullable;
}
public String getLocalSqlFormula() {
return localSqlFormula;
}
@@ -81,7 +81,7 @@ public final class DeployTableJoin {
// only add the join column details when name or referencedColumnName is specified
String ref = deploy.convertQuotes(jc.referencedColumnName());
String nam = deploy.convertQuotes(jc.name());
addJoinColumn(new DeployTableJoinColumn(order, ref, nam, jc.insertable(), jc.updatable(), beanTable));
addJoinColumn(new DeployTableJoinColumn(order, ref, nam, jc.insertable(), jc.updatable(), jc.nullable(), beanTable));
}
}
@@ -25,7 +25,8 @@ public final class DeployTableJoinColumn {
*/
private String foreignSqlFormula;
private boolean insertable;
private boolean updateable;
private boolean updatable;
private boolean nullable;
/**
* Construct when automatically determining the join.
@@ -34,21 +35,24 @@ public final class DeployTableJoinColumn {
* </p>
*/
public DeployTableJoinColumn(String localDbColumn, String foreignDbColumn) {
this(localDbColumn, foreignDbColumn, true, true);
this(localDbColumn, foreignDbColumn, true, true, true);
}
/**
* Construct with explicit insertable and updateable flags.
*/
public DeployTableJoinColumn(String localDbColumn, String foreignDbColumn, boolean insertable, boolean updateable) {
public DeployTableJoinColumn(String localDbColumn, String foreignDbColumn,
boolean insertable, boolean updatable, boolean nullable) {
this.localDbColumn = nullEmptyString(localDbColumn);
this.foreignDbColumn = nullEmptyString(foreignDbColumn);
this.insertable = insertable;
this.updateable = updateable;
this.updatable = updatable;
this.nullable = nullable;
}
public DeployTableJoinColumn(boolean order, String ref, String name, boolean insertable, boolean updateable, BeanTable beanTable) {
this(ref, name, insertable, updateable);
public DeployTableJoinColumn(boolean order, String ref, String name,
boolean insertable, boolean updatable, boolean nullable, BeanTable beanTable) {
this(ref, name, insertable, updatable, nullable);
setReferencedColumn(beanTable);
if (!order) {
reverse();
@@ -60,7 +64,7 @@ public final class DeployTableJoinColumn {
this.localSqlFormula = localSqlFormula;
this.localDbColumn = null;
this.insertable = false;
this.updateable = false;
this.updatable = false;
}
}
@@ -73,7 +77,7 @@ public final class DeployTableJoinColumn {
this.foreignSqlFormula = foreignSqlFormula;
this.foreignDbColumn = null;
this.insertable = false;
this.updateable = false;
this.updatable = false;
}
}
@@ -121,12 +125,12 @@ public final class DeployTableJoinColumn {
// but will leave it like this for now
DeployTableJoinColumn ret;
if (reverse) {
ret = new DeployTableJoinColumn(foreignDbColumn, localDbColumn, insertable, updateable);
ret = new DeployTableJoinColumn(foreignDbColumn, localDbColumn, insertable, updatable, nullable);
ret.setLocalSqlFormula(foreignSqlFormula);
ret.setForeignSqlFormula(localSqlFormula);
} else {
ret = new DeployTableJoinColumn(localDbColumn, foreignDbColumn, insertable, updateable);
ret = new DeployTableJoinColumn(localDbColumn, foreignDbColumn, insertable, updatable, nullable);
ret.setLocalSqlFormula(localSqlFormula);
ret.setForeignSqlFormula(foreignSqlFormula);
}
@@ -148,8 +152,8 @@ public final class DeployTableJoinColumn {
/**
* Return true if this column should be updateable.
*/
public boolean isUpdateable() {
return updateable;
public boolean isUpdatable() {
return updatable;
}
/**
@@ -173,4 +177,7 @@ public final class DeployTableJoinColumn {
this.localDbColumn = localDbColumn;
}
public boolean isNullable() {
return nullable;
}
}
@@ -223,7 +223,7 @@ final class AnnotationAssocOnes extends AnnotationAssoc {
BeanTable baseBeanTable = factory.beanTable(info.getDescriptor().getBeanType());
String localPrimaryKey = baseBeanTable.getIdColumn();
String foreignColumn = getBeanTable(prop).getIdColumn();
prop.getTableJoin().addJoinColumn(new DeployTableJoinColumn(localPrimaryKey, foreignColumn, false, false));
prop.getTableJoin().addJoinColumn(new DeployTableJoinColumn(localPrimaryKey, foreignColumn, false, false, prop.isNullable()));
}
private void readEmbedded(DeployBeanPropertyAssocOne<?> prop, Embedded embedded) {
@@ -98,7 +98,7 @@ public abstract class AnnotationParser extends AnnotationBase {
prop.setUnique(columnAnn.unique());
if (columnAnn.precision() > 0) {
prop.setDbLength(columnAnn.precision());
} else if (columnAnn.length() != 255) {
} else if (columnAnn.length() != 0) {
// set default 255 on DbTypeMap
prop.setDbLength(columnAnn.length());
}
@@ -63,6 +63,13 @@ public final class CQueryPlanManager implements QueryPlanManager {
while (req.hasNext()) {
req.nextCapture();
}
if (!connection.getAutoCommit()) {
// CHECKME: commit or rollback here?
// arguments for rollback: the collecting should never modify data.
// if there are collectors that may copy the plan into tables, it's up to the collector to
// commit the transaction.
connection.rollback();
}
return req.plans();
} catch (SQLException e) {
CoreLog.log.log(ERROR, "Error during query plan collection", e);
@@ -1,6 +1,5 @@
package io.ebeaninternal.server.query;
import io.ebean.Transaction;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.SpiQuery;
@@ -11,11 +10,9 @@ abstract class CallableQuery<T> {
final SpiQuery<T> query;
final SpiEbeanServer server;
final Transaction transaction;
CallableQuery(SpiEbeanServer server, SpiQuery<T> query) {
this.server = server;
this.query = query;
this.transaction = query.transaction();
}
}
@@ -10,15 +10,8 @@ import java.util.concurrent.Callable;
*/
public final class CallableQueryCount<T> extends CallableQuery<T> implements Callable<Integer> {
private final boolean createdTransaction;
/**
* Note that the transaction passed in is always a new transaction solely to
* find the row count so it must be cleaned up by this CallableQueryRowCount.
*/
public CallableQueryCount(SpiEbeanServer server, SpiQuery<T> query, boolean createdTransaction) {
public CallableQueryCount(SpiEbeanServer server, SpiQuery<T> query) {
super(server, query);
this.createdTransaction = createdTransaction;
}
/**
@@ -26,13 +19,7 @@ public final class CallableQueryCount<T> extends CallableQuery<T> implements Cal
*/
@Override
public Integer call() {
try {
return server.findCountWithCopy(query);
} finally {
if (createdTransaction) {
transaction.end();
}
}
return server.findCountWithCopy(query);
}
}
@@ -11,28 +11,16 @@ import java.util.concurrent.Callable;
*/
public final class CallableQueryIds<T> extends CallableQuery<T> implements Callable<List<Object>> {
private final boolean createdTransaction;
public CallableQueryIds(SpiEbeanServer server, SpiQuery<T> query, boolean createdTransaction) {
public CallableQueryIds(SpiEbeanServer server, SpiQuery<T> query) {
super(server, query);
this.createdTransaction = createdTransaction;
}
/**
* Execute the find Id's query returning the list of Id's.
*/
@Override
public List<Object> call() {
// we have already made a copy of the query
// this way the same query instance is available to the
// QueryFutureIds (as so has access to the List before it is done)
try {
return server.findIdsWithCopy(query);
} finally {
if (createdTransaction) {
transaction.end();
}
}
return server.findIdsWithCopy(query);
}
}
@@ -11,25 +11,13 @@ import java.util.concurrent.Callable;
*/
public final class CallableQueryList<T> extends CallableQuery<T> implements Callable<List<T>> {
private final boolean createdTransaction;
public CallableQueryList(SpiEbeanServer server, SpiQuery<T> query, boolean createdTransaction) {
public CallableQueryList(SpiEbeanServer server, SpiQuery<T> query) {
super(server, query);
this.createdTransaction = createdTransaction;
}
/**
* Execute the query returning the resulting List.
*/
@Override
public List<T> call() {
try {
return server.findList(query);
} finally {
if (createdTransaction) {
transaction.end();
}
}
return server.findList(query);
}
}
@@ -0,0 +1,23 @@
package io.ebeaninternal.server.query;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.SpiQuery;
import java.util.Map;
import java.util.concurrent.Callable;
/**
* Represent the findMap query as a Callable.
*/
public final class CallableQueryMap<K, T> extends CallableQuery<T> implements Callable<Map<K, T>> {
public CallableQueryMap(SpiEbeanServer server, SpiQuery<T> query) {
super(server, query);
}
@Override
public Map<K, T> call() {
return server.findMap(query);
}
}
@@ -365,6 +365,11 @@ final class DefaultFetchGroupQuery<T> implements SpiFetchGroupQuery<T>, SpiQuery
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
}
@Override
public <K> FutureMap<K,T> findFutureMap() {
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
}
@Override
public PagedList<T> findPagedList() {
throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup");
@@ -23,10 +23,6 @@ public final class QueryFutureIds<T> extends BaseFuture<List<Object>> implements
return futureTask;
}
public Transaction transaction() {
return call.transaction;
}
@Override
public Query<T> getQuery() {
return call.query;
@@ -27,10 +27,6 @@ public final class QueryFutureList<T> extends BaseFuture<List<T>> implements Fut
return futureTask;
}
public Transaction transaction() {
return call.transaction;
}
@Override
public Query<T> getQuery() {
return call.query;
@@ -0,0 +1,71 @@
package io.ebeaninternal.server.query;
import io.ebean.FutureMap;
import io.ebean.Query;
import io.ebean.Transaction;
import jakarta.persistence.PersistenceException;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Default implementation for FutureMap.
*/
public final class QueryFutureMap<K, T> extends BaseFuture<Map<K, T>> implements FutureMap<K, T> {
private final CallableQueryMap<K, T> call;
public QueryFutureMap(CallableQueryMap<K, T> call) {
super(new FutureTask<>(call));
this.call = call;
}
public FutureTask<Map<K, T>> futureTask() {
return futureTask;
}
@Override
public Query<T> getQuery() {
return call.query;
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
call.query.cancel();
return super.cancel(mayInterruptIfRunning);
}
@Override
public Map<K, T> getUnchecked() {
try {
return get();
} catch (InterruptedException e) {
// restore the interrupted status (so client can check for that)
Thread.currentThread().interrupt();
throw new PersistenceException(e);
} catch (ExecutionException e) {
throw new PersistenceException(e);
}
}
@Override
public Map<K, T> getUnchecked(long timeout, TimeUnit unit) throws TimeoutException {
try {
return get(timeout, unit);
} catch (InterruptedException e) {
// restore the interrupted status (so client can check for that)
Thread.currentThread().interrupt();
throw new PersistenceException(e);
} catch (ExecutionException e) {
throw new PersistenceException(e);
}
}
}
@@ -21,10 +21,6 @@ public final class QueryFutureRowCount<T> extends BaseFuture<Integer> implements
return futureTask;
}
public Transaction transaction() {
return call.transaction;
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
call.query.cancel();
@@ -76,6 +76,7 @@ final class SqlTreeNodeRoot extends SqlTreeNodeBean {
@Override
public void dependentTables(Set<String> tables) {
tables.add(baseTable);
for (SqlTreeNode child : children) {
child.dependentTables(tables);
}
@@ -1614,6 +1614,11 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
return server.findFutureList(this);
}
@Override
public final <K> FutureMap<K, T> findFutureMap() {
return server.findFutureMap(this);
}
@Override
public final FutureRowCount<T> findFutureCount() {
return server.findFutureCount(this);
@@ -14,6 +14,7 @@ import io.ebeanservice.docstore.api.DocStoreTransaction;
import jakarta.persistence.PersistenceException;
import java.sql.Connection;
import java.sql.SQLException;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
@@ -58,6 +59,7 @@ final class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEve
private SpiPersistenceContext persistenceContext;
private Object tenantId;
private Map<String, Object> userObjects;
private final Instant startTime = Instant.now();
private final long startNanos;
private ProfileLocation profileLocation;
@@ -89,9 +91,8 @@ final class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEve
}
@Override
public long startNanoTime() {
// not used on read only transaction
return startNanos;
public Instant startTime() {
return startTime;
}
@Override
@@ -17,6 +17,7 @@ import jakarta.persistence.PersistenceException;
import jakarta.persistence.RollbackException;
import java.sql.Connection;
import java.sql.SQLException;
import java.time.Instant;
import java.util.*;
import java.util.function.Consumer;
@@ -91,6 +92,7 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
DocStoreTransaction docStoreTxn;
private ProfileStream profileStream;
private ProfileLocation profileLocation;
private final Instant startTime = Instant.now();
private final long startNanos;
private boolean autoPersistUpdates;
@@ -141,8 +143,8 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
}
@Override
public final long startNanoTime() {
return startNanos;
public final Instant startTime() {
return startTime;
}
@Override
@@ -17,6 +17,7 @@ import io.ebeanservice.docstore.api.DocStoreTransaction;
import jakarta.persistence.PersistenceException;
import java.sql.Connection;
import java.sql.SQLException;
import java.time.Instant;
/**
* Placeholder for use with SUPPORTS and NEVER transactional when there really isn't a transaction.
@@ -56,9 +57,9 @@ final class NoTransaction implements SpiTransaction {
}
@Override
public long startNanoTime() {
public Instant startTime() {
// not used
return System.nanoTime();
return Instant.now();
}
@Override
@@ -6,6 +6,7 @@ import io.ebean.cache.QueryCacheEntryValidate;
import io.ebean.cache.ServerCacheNotification;
import io.ebean.cache.ServerCacheNotify;
import java.time.Instant;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -23,7 +24,7 @@ public final class TableModState implements QueryCacheEntryValidate, ServerCache
private static final System.Logger log = AppLog.getLogger("io.ebean.cache.TABLEMOD");
private final Map<String, Long> tableModStamp = new ConcurrentHashMap<>();
private final Map<String, Instant> tableModStamp = new ConcurrentHashMap<>();
public TableModState() {
}
@@ -32,22 +33,22 @@ public final class TableModState implements QueryCacheEntryValidate, ServerCache
* Set the modified timestamp on the tables that have been touched.
*/
void touch(Set<String> touchedTables) {
long modNanoTime = System.nanoTime();
final var modTime = Instant.now();
for (String tableName : touchedTables) {
tableModStamp.put(tableName, modNanoTime);
tableModStamp.put(tableName, modTime);
}
if (log.isLoggable(DEBUG)) {
log.log(DEBUG, "TableModState updated - touched:{0} modNanoTime:{1}", touchedTables, modNanoTime);
log.log(DEBUG, "TableModState updated - touched:{0} modTime:{1}", touchedTables, modTime);
}
}
/**
* Return true if all the tables are valid based on timestamp comparison.
*/
boolean isValid(Set<String> tables, long sinceNanoTime) {
boolean isValid(Set<String> tables, Instant sinceTime) {
for (String tableName : tables) {
Long modTime = tableModStamp.get(tableName);
if (modTime != null && modTime >= sinceNanoTime) {
final var modTime = tableModStamp.get(tableName);
if (modTime != null && !modTime.isBefore(sinceTime)) {
if (log.isLoggable(TRACE)) {
log.log(TRACE, "Invalidate on table:{0}", tableName);
}
@@ -59,9 +60,9 @@ public final class TableModState implements QueryCacheEntryValidate, ServerCache
@Override
public boolean isValid(QueryCacheEntry entry) {
Set<String> dependentTables = entry.getDependentTables();
Set<String> dependentTables = entry.dependentTables();
if (dependentTables != null && !dependentTables.isEmpty()) {
return isValid(dependentTables, entry.getTimestamp());
return isValid(dependentTables, entry.timestamp());
}
return true;
}
@@ -7,7 +7,6 @@ import io.ebean.plugin.SpiServer;
import io.ebeaninternal.api.SpiLogManager;
import io.ebeaninternal.api.SpiProfileHandler;
import io.ebeaninternal.server.cluster.ClusterManager;
import io.ebeaninternal.server.core.ClockService;
import io.ebeaninternal.server.deploy.BeanDescriptorManager;
import io.ebeanservice.docstore.api.DocStoreUpdateProcessor;
@@ -30,13 +29,11 @@ public final class TransactionManagerOptions {
final SpiLogManager logManager;
final TableModState tableModState;
final ServerCacheNotify cacheNotify;
final ClockService clockService;
public TransactionManagerOptions(SpiServer server, boolean notifyL2CacheInForeground, DatabaseBuilder.Settings config, TransactionScopeManager scopeManager,
ClusterManager clusterManager, BackgroundExecutor backgroundExecutor, DocStoreUpdateProcessor docStoreUpdateProcessor,
BeanDescriptorManager descMgr, DataSourceSupplier dataSourceSupplier, SpiProfileHandler profileHandler,
SpiLogManager logManager, TableModState tableModState, ServerCacheNotify cacheNotify, ClockService clockService) {
SpiLogManager logManager, TableModState tableModState, ServerCacheNotify cacheNotify) {
this.server = server;
this.notifyL2CacheInForeground = notifyL2CacheInForeground;
this.config = config;
@@ -50,7 +47,6 @@ public final class TransactionManagerOptions {
this.logManager = logManager;
this.tableModState = tableModState;
this.cacheNotify = cacheNotify;
this.clockService = clockService;
}
}
@@ -8,7 +8,7 @@ import static org.assertj.core.api.Assertions.assertThat;
public class TableJoinColumnTest {
TableJoinColumn col(String localDbColumn, String foreignDbColumn, boolean insertable, boolean updateable) {
DeployTableJoinColumn column = new DeployTableJoinColumn(localDbColumn, foreignDbColumn, insertable, updateable);
DeployTableJoinColumn column = new DeployTableJoinColumn(localDbColumn, foreignDbColumn, insertable, updateable, true);
return new TableJoinColumn(column);
}
@@ -9,22 +9,22 @@ import static org.assertj.core.api.Assertions.assertThat;
public class TableJoinTest {
DeployTableJoinColumn col(String localDbColumn, String foreignDbColumn, boolean insertable, boolean updateable) {
return new DeployTableJoinColumn(localDbColumn, foreignDbColumn, insertable, updateable);
DeployTableJoinColumn col(String localDbColumn, String foreignDbColumn, boolean insertable, boolean updateable, boolean nullable) {
return new DeployTableJoinColumn(localDbColumn, foreignDbColumn, insertable, updateable, nullable);
}
TableJoin table(String tableName, String col1, String col2) {
DeployTableJoin deploy = new DeployTableJoin();
deploy.setTable(tableName);
deploy.addJoinColumn(col(col1, col2, true, true));
deploy.addJoinColumn(col(col1, col2, true, true, true));
return new TableJoin(deploy);
}
TableJoin table(String tableName, String col1, String col2, String col3, String col4) {
DeployTableJoin deploy = new DeployTableJoin();
deploy.setTable(tableName);
deploy.addJoinColumn(col(col1, col2, true, true));
deploy.addJoinColumn(col(col3, col4, true, true));
deploy.addJoinColumn(col(col1, col2, true, true, true));
deploy.addJoinColumn(col(col3, col4, true, true, true));
return new TableJoin(deploy);
}
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.transaction;
import org.junit.jupiter.api.Test;
import java.time.Instant;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@@ -9,24 +10,23 @@ import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class TableModStateTest {
class TableModStateTest {
private TableModState tableModState = new TableModState();
private final TableModState tableModState = new TableModState();
@Test
public void isValid() {
long before = System.nanoTime();
void isValid() {
Instant before = Instant.now();
tableModState.touch(setOf("one", "two", "three"));
long after = System.nanoTime();
Instant after = Instant.now();
// empty
assertTrue(tableModState.isValid(Collections.emptySet(), 12L));
assertTrue(tableModState.isValid(Collections.emptySet(), before));
// no entry
assertTrue(tableModState.isValid(setOf("noEntry"), 12L));
assertTrue(tableModState.isValid(setOf("noEntry"), before));
// later timestamp
assertTrue(tableModState.isValid(setOf("one"), after));
+4 -4
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</parent>
<name>ebean ddl generation</name>
@@ -28,14 +28,14 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>provided</scope>
</dependency>
@@ -65,7 +65,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-all</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>test</scope>
</dependency>
@@ -155,8 +155,8 @@ EXECUTE stmt;
END LOOP;
CLOSE curs;
END
-- play-ebean-end
END
$$
DROP PROCEDURE IF EXISTS usp_ebean_drop_column;
@@ -173,8 +173,8 @@ CALL usp_ebean_drop_foreign_keys(p_table_name, p_column_name);
SET @sql = CONCAT('ALTER TABLE `', p_table_name, '` DROP COLUMN `', p_column_name, '`');
PREPARE stmt FROM @sql;
EXECUTE stmt;
END
-- play-ebean-end
END
$$
</ddl-script>
+2 -2
View File
@@ -3,7 +3,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -14,7 +14,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>provided</scope>
</dependency>
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</parent>
<name>ebean net postgis types</name>
@@ -19,14 +19,14 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<!-- provided scope -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>provided</scope>
</dependency>
@@ -54,7 +54,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>test</scope>
</dependency>
@@ -78,7 +78,7 @@
<extensions>true</extensions>
<configuration>
<tiles>
<tile>io.ebean.tile:enhancement:14.9.0</tile>
<tile>io.ebean.tile:enhancement:14.10.0</tile>
</tiles>
</configuration>
</plugin>
@@ -12,7 +12,7 @@ ebean:
postgis:
containerName: ebeanbuild_postgis2
port: 9433
image: ghcr.io/baosystems/postgis:15
image: ghcr.io/baosystems/postgis:16
# extensions: postgis
# url: jdbc:postgresql_lwgis://localhost:6432/mygisapp
# driver: org.postgis.DriverWrapperLW
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</parent>
<name>ebean postgis types</name>
@@ -19,14 +19,14 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<!-- provided scope -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>provided</scope>
</dependency>
@@ -62,7 +62,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>test</scope>
</dependency>
@@ -86,7 +86,7 @@
<extensions>true</extensions>
<configuration>
<tiles>
<tile>io.ebean.tile:enhancement:14.9.0</tile>
<tile>io.ebean.tile:enhancement:14.10.0</tile>
</tiles>
</configuration>
</plugin>
@@ -12,7 +12,7 @@ ebean:
postgis:
containerName: ebeanbuild_postgis
port: 9432
image: ghcr.io/baosystems/postgis:15
image: ghcr.io/baosystems/postgis:16
# extensions: postgis
# url: jdbc:postgresql_lwgis://localhost:6432/mygisapp
# driver: org.postgis.DriverWrapperLW
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</parent>
<name>ebean querybean</name>
@@ -17,7 +17,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>provided</scope>
</dependency>
@@ -59,14 +59,14 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-ddl-generator</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>test</scope>
</dependency>
@@ -80,7 +80,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>querybean-generator</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>provided</scope>
</dependency>
@@ -96,7 +96,7 @@
<extensions>true</extensions>
<configuration>
<tiles>
<tile>io.ebean.tile:enhancement:14.9.0</tile>
<tile>io.ebean.tile:enhancement:14.10.0</tile>
</tiles>
</configuration>
</plugin>
@@ -856,6 +856,11 @@ public abstract class QueryBean<T, R extends QueryBean<T, R>> implements IQueryB
return query.findFutureList();
}
@Override
public final <K> FutureMap<K,T> findFutureMap() {
return query.findFutureMap();
}
@Override
public final PagedList<T> findPagedList() {
return query.findPagedList();
@@ -442,6 +442,7 @@ public class QCustomerTest {
.usingConnection(connection)
.findList();
connection.rollback();
assertThat(foo).hasSize(1);
}
@@ -11,6 +11,7 @@ datasource.default=h2
datasource.h2.username=sa
datasource.h2.password=
datasource.h2.url=jdbc:h2:mem:tests;NON_KEYWORDS=KEY,VALUE
datasource.h2.closeWithinTxn=fail
datasource.pg.username=sa
datasource.pg.password=
+7 -7
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</parent>
<artifactId>ebean-redis</artifactId>
@@ -29,35 +29,35 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>querybean-generator</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>provided</scope>
</dependency>
@@ -72,7 +72,7 @@
<extensions>true</extensions>
<configuration>
<tiles>
<tile>io.ebean.tile:enhancement:14.9.0</tile>
<tile>io.ebean.tile:enhancement:14.10.0</tile>
</tiles>
</configuration>
</plugin>
@@ -1,7 +1,6 @@
package io.ebean.redis;
import io.ebean.cache.ServerCache;
import io.ebean.cache.ServerCacheStatistics;
import io.ebean.meta.MetricVisitor;
import io.ebeaninternal.server.cache.DefaultServerCache;
@@ -281,7 +281,7 @@ final class RedisCacheFactory implements ServerCacheFactory {
public void invalidateKeys(String cacheKey, Set<Object> keySet) {
try {
sendMessage(messageInvalidateKeys(cacheKey, keySet));
} catch (IOException e) {
} catch (Exception e) {
logger.log(ERROR, "failed to transmit invalidateKeys() message", e);
}
}
@@ -290,7 +290,7 @@ final class RedisCacheFactory implements ServerCacheFactory {
public void invalidateKey(String cacheKey, Object id) {
try {
sendMessage(messageInvalidateKey(cacheKey, id));
} catch (IOException e) {
} catch (Exception e) {
logger.log(ERROR, "failed to transmit invalidateKeys() message", e);
}
}
@@ -299,7 +299,7 @@ final class RedisCacheFactory implements ServerCacheFactory {
public void invalidateClear(String cacheKey) {
try {
sendMessage(messageInvalidateClear(cacheKey));
} catch (IOException e) {
} catch (Exception e) {
logger.log(ERROR, "failed to transmit invalidateKeys() message", e);
}
}
@@ -422,7 +422,7 @@ final class RedisCacheFactory implements ServerCacheFactory {
throw new IllegalStateException("Unexpected message type ? " + msgType);
}
} catch (IOException | ClassNotFoundException e) {
} catch (Exception e) {
logger.log(ERROR, "failed to decode near cache message [" + SafeEncoder.encode(message) + "] for cache:" + cacheKey, e);
if (cacheKey != null) {
nearCacheInvalidateClear(cacheKey);
+4 -4
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</parent>
<artifactId>ebean-spring-txn</artifactId>
@@ -28,7 +28,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>provided</scope>
</dependency>
@@ -77,7 +77,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>test</scope>
</dependency>
@@ -99,7 +99,7 @@
<extensions>true</extensions>
<configuration>
<tiles>
<tile>io.ebean.tile:enhancement:14.9.0</tile>
<tile>io.ebean.tile:enhancement:14.10.0</tile>
</tiles>
</configuration>
</plugin>
+7 -7
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</parent>
<name>ebean test</name>
@@ -33,20 +33,20 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-ddl-generator</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
</dependency>
<dependency>
@@ -149,14 +149,14 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jackson-mapper</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-all</artifactId>
<version>14.9.0</version>
<version>16.0.0-rc1</version>
<scope>test</scope>
</dependency>
@@ -309,7 +309,7 @@
<extensions>true</extensions>
<configuration>
<tiles>
<tile>io.ebean.tile:enhancement:14.9.0</tile>
<tile>io.ebean.tile:enhancement:14.10.0</tile>
</tiles>
</configuration>
</plugin>
@@ -49,7 +49,7 @@ class PostgisSetup implements PlatformSetup {
}
config.setExtensions("hstore,pgcrypto,postgis");
config.setDockerContainerName("ut_postgis");
config.setDockerVersion("14-3.2");
config.setDockerVersion("16-3.5");
return config.getDockerProperties();
}
@@ -25,7 +25,7 @@ class PostgresSetup implements PlatformSetup {
if (!config.isUseDocker()) {
return new Properties();
}
config.setDockerVersion("14");
config.setDockerVersion("16");
config.setExtensions("hstore,pgcrypto");
return config.getDockerProperties();
}
@@ -1,5 +1,6 @@
package io.ebean.xtest;
import io.avaje.config.Config;
import io.ebean.CacheMode;
import io.ebean.DB;
import io.ebean.Database;
@@ -71,6 +72,12 @@ public abstract class BaseTestCase {
String propsFile = System.getProperty("props.file");
System.out.println("BaseTestCase: -Dprops.file=" + propsFile); // help debug CI
// First try, if we get the default server. If this fails, all tests will fail.
String dsName = Config.getNullable("datasource.default");
System.out.println("config: datasource.default " + dsName);
System.out.println("config: username " + Config.getNullable("datasource." + dsName + ".username"));
System.out.println("config: password " + Config.getNullable("datasource." + dsName + ".password"));
System.out.println("config: url " + Config.getNullable("datasource." + dsName + ".url"));
DB.getDefault();
} catch (Throwable e) {
logger.error("Fatal error while getting ebean-server. Exiting...", e);
@@ -1,10 +1,12 @@
package io.ebean.xtest.base;
import io.ebean.*;
import io.ebean.annotation.Platform;
import io.ebean.xtest.BaseTestCase;
import org.junit.jupiter.api.AfterEach;
import io.ebean.xtest.ForPlatform;
import org.junit.jupiter.api.Test;
import org.tests.model.basic.Customer;
import org.tests.model.basic.EBasicVer;
import org.tests.model.basic.ResetBasicData;
import java.time.Clock;
@@ -14,18 +16,10 @@ import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
public class ExtendedServerTest extends BaseTestCase {
@AfterEach
public void cleanup() {
DB.getDefault()
.extended()
.setClock(Clock.systemUTC());
}
class ExtendedServerTest extends BaseTestCase {
@Test
public void findList() {
void findList() {
ResetBasicData.reset();
Database server = DB.getDefault();
@@ -51,47 +45,57 @@ public class ExtendedServerTest extends BaseTestCase {
}
}
@ForPlatform(Platform.H2)
@Test
public void mockClock() {
Database database = DB.getDefault();
final Instant snapshot = Instant.now();
Instant backedSnapshot = snapshot.minus(1, ChronoUnit.DAYS);
void fixedClock() {
final Instant now = Instant.now();
Instant backedSnapshot = now.minus(1, ChronoUnit.DAYS);
Clock snapshotClock = Clock.fixed(backedSnapshot, Clock.systemUTC().getZone());
database.extended().setClock(snapshotClock);
Database db = Database.builder()
.name("db")
.loadFromProperties()
.clock(snapshotClock)
.addClass(EBasicVer.class)
.ddlExtra(false)
.name("fixed-clock-db")
.register(false)
.defaultDatabase(false)
.build();
ResetBasicData.reset();
EBasicVer e0 = new EBasicVer("CheckClock");
db.save(e0);
int count = database
.find(Customer.class)
EBasicVer found = db.find(EBasicVer.class, e0.getId());
assertThat(found).isNotNull();
int count = db
.find(EBasicVer.class)
.where()
.gt("cretime", snapshot)
.gt("lastUpdate", now)
.findCount();
assertThat(count).isEqualTo(0);
int count2 = database
.find(Customer.class)
int count2 = db
.find(EBasicVer.class)
.where()
.ge("cretime", backedSnapshot)
.ge("lastUpdate", snapshotClock.instant().minusSeconds(60))
.findCount();
assertThat(count2).isGreaterThan(0);
assertThat(count2).isEqualTo(1);
int count3 = database
.find(Customer.class)
int count3 = db
.find(EBasicVer.class)
.where()
.gt("updtime", snapshot)
.gt("lastUpdate", now)
.findCount();
assertThat(count3).isEqualTo(0);
int count4 = database
.find(Customer.class)
int count4 = db
.find(EBasicVer.class)
.where()
.ge("updtime", backedSnapshot)
.ge("lastUpdate", backedSnapshot.minus(2, ChronoUnit.DAYS))
.findCount();
assertThat(count4).isGreaterThan(0);
assertThat(count4).isEqualTo(1);
}
}
@@ -220,7 +220,7 @@ public class DbMigrationTest extends BaseTestCase {
config.setName(server().name());
config.loadFromProperties(server().pluginApi().config().getProperties());
config.setDataSource(server().dataSource());
config.setReadOnlyDataSource(server().dataSource());
config.setReadOnlyDataSource(server().readOnlyDataSource());
config.setDdlGenerate(false);
config.setDdlRun(false);
config.setRegister(false);
@@ -292,7 +292,7 @@ public class DbMigrationTest extends BaseTestCase {
config.setName(server().name());
config.loadFromProperties(server().pluginApi().config().getProperties());
config.setDataSource(server().dataSource());
config.setReadOnlyDataSource(server().dataSource());
config.setReadOnlyDataSource(server().readOnlyDataSource());
config.setDdlGenerate(false);
config.setDdlRun(false);
config.setRegister(false);
@@ -50,20 +50,11 @@ public class TDSpiEbeanServer extends TDSpiServer implements SpiEbeanServer {
this.name = name;
}
@Override
public ExtendedServer extended() {
return this;
}
@Override
public long clockNow() {
return System.currentTimeMillis();
}
@Override
public void setClock(Clock clock) {
}
@Override
public boolean isDisableL2Cache() {
return false;
@@ -662,6 +653,11 @@ public class TDSpiEbeanServer extends TDSpiServer implements SpiEbeanServer {
return null;
}
@Override
public <K, T> FutureMap<K, T> findFutureMap(SpiQuery<T> query) {
return null;
}
@Override
public <T> PagedList<T> findPagedList(SpiQuery<T> query) {
return null;
@@ -253,11 +253,6 @@ public class TDSpiServer implements SpiServer {
return null;
}
@Override
public ExtendedServer extended() {
return null;
}
@Override
public void save(Object bean) throws OptimisticLockException {
@@ -2,99 +2,50 @@ package io.ebean.xtest.internal.server.query;
import io.ebean.*;
import io.ebean.xtest.BaseTestCase;
import io.ebeaninternal.server.query.QueryFutureIds;
import io.ebeaninternal.server.query.QueryFutureList;
import io.ebeaninternal.server.query.QueryFutureRowCount;
import org.junit.jupiter.api.Test;
import org.tests.model.basic.Customer;
import org.tests.model.basic.ResetBasicData;
import java.util.concurrent.ExecutionException;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.jupiter.api.Assertions.*;
public class TestFutureRowCountErrorHandling extends BaseTestCase {
class TestFutureRowCountErrorHandling extends BaseTestCase {
@Test
public void testFutureRowCount() throws InterruptedException {
void testFutureRowCount() {
ResetBasicData.reset();
Database server = DB.getDefault();
Query<Customer> query = server.createQuery(Customer.class)
Query<Customer> query = DB.find(Customer.class)
.where().eq("doesNotExist", "this will fail")
.query();
FutureRowCount<Customer> futureRowCount = query.findFutureCount();
QueryFutureRowCount<Customer> internalRowCount = (QueryFutureRowCount<Customer>) futureRowCount;
Transaction t = internalRowCount.transaction();
try {
futureRowCount.get();
fail("never get here as the SQL is invalid");
} catch (ExecutionException e) {
// Confirm the Transaction has been rolled back
assertFalse(t.isActive());
}
assertThrows(ExecutionException.class, futureRowCount::get);
}
@Test
public void testFutureIds() throws InterruptedException {
void testFutureIds() {
ResetBasicData.reset();
Database server = DB.getDefault();
Query<Customer> query = server.createQuery(Customer.class)
Query<Customer> query = DB.find(Customer.class)
.where().eq("doesNotExist", "this will fail")
.query();
FutureIds<Customer> futureIds = query.findFutureIds();
QueryFutureIds<Customer> internalFuture = (QueryFutureIds<Customer>) futureIds;
Transaction t = internalFuture.transaction();
try {
internalFuture.get();
fail("never get here as the SQL is invalid");
} catch (ExecutionException e) {
// Confirm the Transaction has been rolled back
assertFalse(t.isActive());
}
assertThrows(ExecutionException.class, futureIds::get);
}
@Test
public void testFutureList() throws InterruptedException {
void testFutureList() {
ResetBasicData.reset();
Database server = DB.getDefault();
Query<Customer> query = server.createQuery(Customer.class)
Query<Customer> query = DB.createQuery(Customer.class)
.where().eq("doesNotExist", "this will fail")
.query();
FutureList<Customer> futureList = query.findFutureList();
QueryFutureList<Customer> internalFuture = (QueryFutureList<Customer>) futureList;
Transaction t = internalFuture.transaction();
try {
internalFuture.get();
fail("never get here as the SQL is invalid");
} catch (ExecutionException e) {
// Confirm the Transaction has been rolled back
assertFalse(t.isActive());
}
assertThrows(ExecutionException.class, futureList::get);
}
}

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