Compare commits

...
392 Commits
Author SHA1 Message Date
Rob Bygrave 0171c1afef Version 13.23.1 2023-10-18 15:47:04 +13:00
Rob Bygrave 31c106f604 Bump ebean-agent to 13.23.1 2023-10-18 15:16:20 +13:00
Rob BygraveandGitHub 20d2838be4 Merge pull request #3250 from ebean-orm/feature/bump-parent
Make Jackson a transitive dependency of ebean-jackson-mapper
2023-10-17 23:25:43 +13:00
Rob Bygrave 4238a951ca Make Jackson a transitive dependency of ebean-jackson-mapper
So jackson-core and jackson-databind are both transitive dependencies
of ebean-jackson-mapper.
2023-10-17 23:25:09 +13:00
Rob BygraveandGitHub b5d4bed615 Merge pull request #3249 from ebean-orm/feature/bump-parent
Support native-image via querybean-generator
2023-10-17 23:18:17 +13:00
Rob Bygrave 3ef715ef64 Support native-image via querybean-generator 2023-10-17 23:09:18 +13:00
Rob BygraveandGitHub aea39528ab Merge pull request #3248 from ebean-orm/feature/bump-parent
Bump dependency for avaje-config to 3.9
2023-10-17 22:39:04 +13:00
Rob Bygrave dd498409e0 Bump dependency for avaje-config to 3.9 2023-10-17 22:38:33 +13:00
Rob BygraveandGitHub bae33101df Merge pull request #3247 from ebean-orm/feature/bump-parent
Bump parent pom
2023-10-17 22:37:53 +13:00
Rob Bygrave e1972ac544 Bump parent pom 2023-10-17 22:37:20 +13:00
Rob Bygrave c7241ba3dc Fix test for java 16+ annotation processor version 2023-10-16 23:30:45 +13:00
Rob Bygrave 73416ed65a For testing java 16+ include JDK 17 and 21 only 2023-10-16 23:19:48 +13:00
Rob Bygrave cd70c178f1 For testing java 16+ include JDK 17 and 21 only 2023-10-16 23:17:25 +13:00
Rob Bygrave aa298235f3 For testing java 16+ include JDK 21 and 22 2023-10-16 23:15:32 +13:00
Rob BygraveandGitHub 8733fed14b Merge pull request #3246 from ebean-orm/feature/annotation-processing-jdk-22
Explicit annotation processors required with JDK 22
2023-10-16 22:06:20 +13:00
Rob Bygrave 169d170247 Explicit annotation processors required with JDK 22
JDK 22 changes such that annotation processors are not found by default on
the classpath. As such they either need to be explicitly registered with
the compiler (e.g. maven-compiler-plugin) or use -proc:full
2023-10-16 21:54:32 +13:00
Rob Bygrave d0ee42e0de Include <compilerArgument>-proc:full</compilerArgument> for JDK 22 EA build 2023-10-16 20:32:41 +13:00
Rob BygraveandGitHub 91ecc074a7 Merge pull request #3243 from ebean-orm/feature/postgis-dependency
Fix ebean-bom dependencies for ebean-test
2023-10-11 20:04:12 +13:00
Rob Bygrave c2b381af1e Fix ebean-bom dependencies for ebean-test
Fix by removing the scopes test and provided in the ebean-bom
2023-10-11 20:03:12 +13:00
Rob BygraveandGitHub eeb0a15617 Merge pull request #3242 from ebean-orm/feature/postgis-dependency
Add missing dependency for ebean-postgis-types to ebean-postgis
2023-10-11 19:59:48 +13:00
Rob Bygrave 6abed0dd73 Add missing dependency for ebean-postgis-types to ebean-postgis 2023-10-11 19:58:12 +13:00
Rob BygraveandGitHub 1318cd706f Merge pull request #3241 from ebean-orm/feature/StdOperators-dep
Remove the Deprecated(experimental) from StdOperators
2023-10-10 23:43:29 +13:00
Rob Bygrave 1e8c609dec Remove the Deprecated(experimental) from StdOperators 2023-10-10 23:42:47 +13:00
Rob Bygrave 4506596379 Tidy remove old stylesheet.css from source 2023-10-10 23:41:42 +13:00
Rob Bygrave 0b2c016af2 Version 13.23.0 2023-10-10 22:46:30 +13:00
Rob Bygrave 29d946ec59 Bump ebean-agent 2023-10-10 22:33:35 +13:00
Rob Bygrave da76b422c8 Fix test with sql logging including executeBatch() for sqlserver 2023-10-10 22:26:25 +13:00
Rob Bygrave a1a3b33fc6 Fix test with sql logging including executeBatch() for sqlserver 2023-10-10 21:47:14 +13:00
Rob BygraveandGitHub 7ecd7877d5 Merge pull request #3240 from ebean-orm/feature/OneToOne-softDelete-join
OneToOne with SoftDelete join missing deleted predicate
2023-10-10 21:38:50 +13:00
Rob Bygrave e5f64f4211 Fix test with sql logging including executeBatch() 2023-10-10 21:38:17 +13:00
Rob Bygrave 90a6b71b7e #3240 followup no functional change, tidy use of ctx.joinAdded() 2023-10-10 21:33:23 +13:00
Rob Bygrave 131d531922 #3240 followup no functional change, tidy use of ctx.joinAdded() 2023-10-10 21:32:28 +13:00
Rob Bygrave 5684919a9f Fix for OneToOne with SoftDelete join missing deleted predicate 2023-10-10 21:27:26 +13:00
Rob Bygrave 80fc0723c8 Failing test for OneToOne with SoftDelete join missing deleted predicate 2023-10-10 21:24:35 +13:00
Rob BygraveandGitHub 3ae4c8981e Merge pull request #3238 from ebean-orm/feature/sql-log-executeBatch
Change SQL log to include executeBatch() via BatchedPstmt
2023-10-10 09:15:06 +13:00
Rob Bygrave b80c67286b Change SQL log to include executeBatch() via BatchedPstmt
Adjustments to tests to support this
2023-10-10 01:02:11 +13:00
Rob Bygrave 0bead4135e Change SQL log to include executeBatch() via BatchedPstmt
Adjustments to tests to support this
2023-10-10 00:59:25 +13:00
Rob Bygrave ac6473e039 Change SQL log to include executeBatch() via BatchedPstmt 2023-10-10 00:59:06 +13:00
Rob BygraveandGitHub 32188bdd54 Merge pull request #3237 from ebean-orm/feature/3233
#3234 - Query Bean Generator Generates Non-Compilable Code When Entit…
2023-10-09 22:04:05 +13:00
Rob Bygrave b3a577e3f9 #3234 - Query Bean Generator Generates Non-Compilable Code When Entity Uses @Embeddable Inner Class For Primary Key Type 2023-10-09 22:03:02 +13:00
Rob BygraveandGitHub 7d1774e2ed Merge pull request #3236 from ebean-orm/feature/3233
In version 13.22 if the entity definition is in a different package, …
2023-10-09 22:01:38 +13:00
Rob Bygrave 395edb62bf In version 13.22 if the entity definition is in a different package, the generated query bean cannot resolve the symbol erro 2023-10-09 21:10:56 +13:00
Rob BygraveandGitHub 716b7e7b93 Merge pull request #3232 from ebean-orm/feature/postgis-rename-types-add-composite
Add ebean-postgres-types to ebean-bom
2023-10-06 23:16:27 +13:00
Rob Bygrave 9aadc347d7 Add ebean-postgres-types to ebean-bom 2023-10-06 23:15:43 +13:00
Rob BygraveandGitHub d2d1423c88 Merge pull request #3231 from ebean-orm/feature/postgis-rename-types-add-composite
Rename ebean-postgis -> ebean-postgis-types + add new composite ebean…
2023-10-06 23:07:03 +13:00
Rob Bygrave 73cfea6053 For postgres dependency exclude checker framework dependency 2023-10-06 23:06:41 +13:00
Rob Bygrave 1614166d75 Rename ebean-postgis -> ebean-postgis-types + add new composite ebean-postgis
With this, people can depend on ebean-postgis (the composite) and get all the
dependencies they need (which is ebean-platform-postgres + ebean-postgis-types
+ others).

This should just make it easier for people in that currently we need both
ebean-postgis + ebean-postgres which isn't obvious enough.
2023-10-06 22:59:00 +13:00
Rob BygraveandGitHub 3d9b122a9f Merge pull request #3230 from ebean-orm/feature/deprecate-servletContextListener
Deprecate ServletContextListener (for shutdown in servlet container)
2023-10-06 22:40:07 +13:00
Rob Bygrave 1cc1d29c2f Deprecate ServletContextListener (for shutdown in servlet container)
Deprecated for removal - no intention to replace. Create your own
ServletContextListener if needed for your application.
2023-10-06 22:38:26 +13:00
Rob Bygrave 45467a3358 Bump ebean-agent 2023-10-06 22:07:01 +13:00
Rob Bygrave bdc236159b Bump avaje-config to 3.8 2023-10-06 22:03:45 +13:00
Rob BygraveandGitHub f0047ffd75 Merge pull request #3228 from ebean-orm/feature/3209
#3209 MetricsAsJson escape the SQL string content
2023-10-04 23:43:07 +13:00
Rob Bygrave 429843c358 #3209 MetricsAsJson escape the SQL string content 2023-10-04 23:15:14 +13:00
Rob Bygrave eab4f9c739 Add Java 21 to Multi-JDK Build 2023-09-20 23:12:04 +12:00
Rob BygraveandGitHub b445857227 Merge pull request #3224 from FOCONIS/use-glassfish-jaxb
use glassfish jaxb instead of old com.sun jaxb
2023-09-19 23:14:42 +12:00
Rob Bygrave dc7b73fc25 Follow up #3223 - modify test, could use @Column(insertable = false, updatable = false) instead of @Formula 2023-09-19 23:03:30 +12:00
Rob Bygrave d5048db2c6 Follow up #3223 - Add @IdClass example test 2023-09-19 23:02:31 +12:00
Rob Bygrave 0b0b7cbc67 Follow up #3223 - tidy test only
Make Embedded Id bean more immutable via final fields and constructor
2023-09-19 22:47:23 +12:00
Rob BygraveandGitHub 008f132453 Merge pull request #3223 from FOCONIS/fix-find-props-for-id-class
Regression of #3133 with formula properties
2023-09-19 22:39:29 +12:00
Roland Praml 6d2038355f use glassfish jaxb instead of old com.sun jaxb 2023-09-19 08:37:20 +02:00
Roland Praml 004f4deae3 Regression of #3133 with formula properties 2023-09-18 14:59:17 +02:00
Rob BygraveandGitHub 9223796f02 Merge pull request #3221 from ebean-orm/feature/jakarta-master
Move source to Jakarta (use ./jakarta-to-javax.sh)
2023-09-11 23:34:15 +12:00
Rob Bygrave ff43672f4e Move source to Jakarta (use ./jakarta-to-javax.sh)
Moving the master branch to use jakarta based code and
dependencies. Change to use ./jakarta-to-javax.sh to convert
back to javax when releasing that.
2023-09-11 23:31:01 +12:00
Rob Bygrave 811255200e Update jakarta-to-javax.sh for jakarta.transaction module name 2023-09-11 23:21:55 +12:00
Rob BygraveandGitHub 6db1b86e12 Merge pull request #3220 from ebean-orm/feature/3216
#3216 - Fix querybean generation for @Embedded beans (fix for 13.22.0…
2023-09-11 23:06:31 +12:00
Rob Bygrave 400e840c22 Fix test for MariaDB which does not support delete with subquery with limit
like:

delete from bbookmark_user where id in (select t0.id from bbookmark_user t0 where t0.name = ? limit 10)
2023-09-11 23:05:55 +12:00
Rob Bygrave f03892a4bd #3216 - Fix querybean generation for @Embedded beans (fix for 13.22.0 change)
Version 13.22.0 added a change to query bean generation that has an issue for
embedded beans. This fixes that issue.
2023-09-11 23:01:44 +12:00
Rob Bygrave 0842a3f3e2 Version 13.22.0 2023-08-30 22:17:31 +12:00
Rob Bygrave bd0cad723d Add test for Map @OneToMany without orphanRemoval
Without orphanRemoval then map.clear() does not invoke any lazy loading.
2023-08-29 22:16:37 +12:00
Rob BygraveandGitHub c83c85efc3 Merge pull request #3206 from ebean-orm/feature/3173-beanMap-clear
Map.clear() on a @OneToMany orphanRemoval=true invokes 1+N queries du…
2023-08-29 22:10:36 +12:00
Rob Bygrave b6b8f77213 Map.clear() on a @OneToMany orphanRemoval=true invokes 1+N queries due to MapKey
The fix is for LoadManyRequest to detect when a MapKey is on the collection
and include that in the lazy loading query (to avoid the N queries invoked)
2023-08-29 22:08:56 +12:00
Rob Bygrave 770eb06cab Add test for lazy loading @OneToMany using Map 2023-08-29 22:03:58 +12:00
Rob BygraveandGitHub 180b4d6e46 Merge pull request #3205 from ebean-orm/feature/3173-beanSet-clear
Follow up #3173 - Change BeanSet clear() to lazy load ALL properties
2023-08-29 22:02:07 +12:00
Rob Bygrave 5377454476 Follow up #3173 - Change BeanSet clear() to lazy load ALL properties
To avoid the 1+N lazy loading queries that are invoked due to the clear()
when the entity bean in the Set has a hashCode/equals implementation
2023-08-29 21:20:19 +12:00
Rob BygraveandGitHub dbbf6dd566 Merge pull request #3204 from ebean-orm/feature/3173-beanSet-clear
Follow up #3173 - Add test for BeanSet clear() when hashCode/equals used
2023-08-29 21:16:44 +12:00
Rob Bygrave 4b9d4d0a90 Follow up #3173 - Add test for BeanSet clear() when hashCode/equals used
This shows the extra lazy loading that is occurring when clear() is
called on the [Bean]Set DUE to the hashcode/equals implementation that
is present on the entity bean that is in the Set.
2023-08-29 21:13:19 +12:00
Rob Bygrave 90fc4466bf Follow up #3173 - Add test for BeanSet lazy loading OneToMany with hashCode/equals 2023-08-29 18:43:16 +12:00
Rob BygraveandGitHub 0d69377f8b Merge pull request #3203 from ebean-orm/feature/3173-BeanSet
#3173 - BeanSet lazy loading / Too many DataSource connections used
2023-08-29 18:32:04 +12:00
Rob Bygrave 359a55d7a5 #3173 - BeanSet lazy loading / Too many DataSource connections used
- The error reported was that a DataSource connection pool maxed out
- The symptom was that there was an additional lazy loading queries invoked via the hashCode/equals implementation of ManyToMany Set.
- The fix is for BeanSet init() to lazy load with onlyIds = false, that avoids the extra lazy loading query from being executed
2023-08-29 18:28:09 +12:00
Rob BygraveandGitHub b7804e7486 Merge pull request #3197 from ebean-orm/feature/parent-poms
Update ebean-agent to 13.22.0, required to support change in query bean generation
2023-08-27 22:48:17 +12:00
Rob Bygrave febb018036 Update ebean-agent to 13.22.0 2023-08-27 21:59:34 +12:00
Rob BygraveandGitHub dc0585246f Merge pull request #3196 from ebean-orm/feature/parent-poms
Use ebean-parent as parent pom for composites and platforms
2023-08-27 21:55:34 +12:00
Rob Bygrave 22c1848f58 Use ebean-parent as parent pom for composites and platforms 2023-08-27 21:53:11 +12:00
Rob BygraveandGitHub 054ea26893 Merge pull request #3195 from ebean-orm/feature/deprecate-database-commitTransaction
Deprecate for removal Database.commitTransaction() and Database.rollb…
2023-08-27 20:32:07 +12:00
Rob Bygrave 8c30b66d39 Add forRemoval = true on existing @Deprecated 2023-08-27 20:31:03 +12:00
Rob Bygrave 14f9fe68f7 Deprecate for removal Database.commitTransaction() and Database.rollbackTransaction() 2023-08-27 20:30:33 +12:00
Rob Bygrave d56ca5b841 Deprecate for removal Database.commitTransaction() and Database.rollbackTransaction()
Migrate to using try-with-resources and transaction.commit() and transaction.rollback()
2023-08-27 20:29:05 +12:00
Rob BygraveandGitHub 3f97f0f212 Merge pull request #3192 from ebean-orm/feature/spiEbeanServer
Refactor internal SpiEbeanServer API - transaction from SpiQuery
2023-08-26 00:19:16 +12:00
Rob Bygrave 60e0c552ab Fix test for MySql, which does not support delete statement with limit clause 2023-08-26 00:17:57 +12:00
Rob Bygrave f889628677 No functional change, tidy in persist.dml and dmlbind packages only 2023-08-26 00:15:37 +12:00
Rob Bygrave 128bd171f5 Refactor SpiEbeanServer for SpiSqlQuery with transaction (vs passing transaction) 2023-08-25 23:51:09 +12:00
Rob Bygrave 6402a346a1 Reuse via adding SpiOrmQueryRequest.isGetAllFromBeanCache() 2023-08-25 23:28:07 +12:00
Rob Bygrave 0ab0f9c569 Refactor internal SpiEbeanServer API - transaction from SpiQuery
Originally the API took explicit transactions but then the API changed
toward query.usingTransaction(), which means the SpiQuery holds the
explicit transaction.

This change is to update the SpiEbeanServer API to reflect that it can get
explicit transaction from SpiQuery.transaction() rather than pass transaction
around.

Doing this also identified a small bug where L2 cache could be hit when it should
not after there is some update on the transaction (hence the adjustment to the
test TestBeanCache missCount)
2023-08-25 23:15:51 +12:00
Rob BygraveandGitHub 19e21e17cc Merge pull request #3191 from ebean-orm/feature/spiEbeanServer
#3188 Fix findFutureCount() when there is a current transaction in scope
2023-08-25 21:15:15 +12:00
Rob Bygrave 7e60c66759 Follow up for #3188 Add tests for futures when creating new transaction 2023-08-25 21:05:14 +12:00
Rob Bygrave 4f18dc339f Follow up for #3188 Fix findFutureList() and findFutureIds() when txn in scope
Apply the same fix to findFutureList() and findFutureIds()
2023-08-25 20:56:55 +12:00
Rob Bygrave 60a2626f61 #3188 Fix findFutureCount() when there is a current transaction in scope 2023-08-25 20:32:48 +12:00
Rob BygraveandGitHub e3a6f12478 Merge pull request #3190 from ebean-orm/feature/spiEbeanServer
Refactor SpiEbeanServer to use SpiQuery
2023-08-25 20:31:29 +12:00
Rob Bygrave 2e980b06f6 Refactor SpiEbeanServer to use SpiQuery 2023-08-25 17:53:23 +12:00
Rob BygraveandGitHub b27b5512e3 Merge pull request #3189 from ebean-orm/feature/bump-datasource-dependency
Bump to ebean-datasource 8.7
2023-08-25 15:40:39 +12:00
Rob Bygrave 3a013d50d6 Bump to ebean-datasource 8.7 2023-08-25 15:40:09 +12:00
Rob Bygrave 3ebfd2e9e6 Update test only - TestDeleteCascadingOneToMany 2023-08-24 21:01:11 +12:00
Rob BygraveandGitHub f51b69445a Merge pull request #3187 from ebean-orm/feature/3183-deleteQueryIn
Update test only - TestDeleteCascadeById
2023-08-24 20:55:14 +12:00
Rob Bygrave 96904d525f Update test only - TestDeleteCascadeById 2023-08-24 20:54:43 +12:00
Rob BygraveandGitHub 26fa885adb Merge pull request #3186 from ebean-orm/feature/3183-deleteQueryIn
#3183 - Fix for: Wrong limit using setMaxRows on delete between calls
2023-08-24 20:38:32 +12:00
Rob Bygrave f4ca4ec476 #3183 - Fix for: Wrong limit using setMaxRows on delete between calls
Reproduces when the delete needs to perform a select due to caching or
cascading of the delete
2023-08-24 20:35:11 +12:00
Rob Bygrave 327995526e Fix tests for Postgres 2023-08-24 20:17:41 +12:00
Rob BygraveandGitHub dfbbdc7d58 Merge pull request #3182 from ebean-orm/feature/delete-batch-v2
When delete batching, use number of id properties
2023-08-23 10:54:21 +12:00
Rob Bygrave 35894b3d8f When delete batching, ALSO in deleteManyDetails use number of properties
Use int batch = maxDeleteBatch / targetDesc.idBinder().size()
2023-08-22 23:55:55 +12:00
Rob Bygrave 0f219b4cd0 When delete batching, use number of id properties 2023-08-22 23:49:38 +12:00
Rob Bygrave bfe94786de Merge branch 'FOCONIS-experimental-elliminate-not-in-with-too-many-params' 2023-08-22 23:43:41 +12:00
Rob Bygrave 6cab2498dc Merge branch 'experimental-elliminate-not-in-with-too-many-params' of github.com:FOCONIS/ebean into FOCONIS-experimental-elliminate-not-in-with-too-many-params 2023-08-22 23:22:11 +12:00
Rob BygraveandGitHub dbe81bdb6e Merge pull request #3180 from FOCONIS/bugfix/setId-or-idEq-in-subquery
BUG: Using a subquery with idEq or setId is missing the bind value
2023-08-22 22:35:31 +12:00
Jonas Pöhler 2e2b3844fe Tidy test 2023-08-22 11:36:44 +02:00
Jonas Pöhler 78b77dcd82 Potential Fix for using idEq or setId in subquery 2023-08-22 11:04:48 +02:00
Jonas Pöhler 90614adb2b ADD: Testcase to show missing bind values when using idEq or setId in subquery 2023-08-22 11:04:24 +02:00
Rob BygraveandGitHub 019ef43fe7 Merge pull request #3177 from ebean-orm/feature/remove-InTuples-literal-mode
#3166 Remove InTuples literal mode
2023-08-22 08:23:54 +12:00
Rob Bygrave cfb6f0a908 #3166 Remove InTuples literal mode, remove related plan useCache() 2023-08-22 08:18:19 +12:00
Roland Praml 77aeda1753 draft: elliminate the "not in" query that may 'explode' on SqlServer 2023-08-21 17:10:23 +02:00
Roland Praml 2a24ec3d49 Added some tests 2023-08-21 16:51:19 +02:00
Roland Praml d9d09b31b4 Refactored delete-by-id 2023-08-21 15:36:05 +02:00
Rob Bygrave 56550a9534 #3166 Remove InTuples literal mode 2023-08-21 23:16:55 +12:00
Rob BygraveandGitHub f40beb8234 Merge pull request #3175 from ebean-orm/feature/ListsPartition
For Lists.partition() fix for empty list input
2023-08-21 20:37:32 +12:00
Rob Bygrave cb06052c86 For Lists.partition() fix for empty list input
Fix such that empty list input produces an empty list
2023-08-21 20:19:59 +12:00
Rob BygraveandGitHub e09265fbc5 Merge pull request #3174 from FOCONIS/more-char-append
Use char-append instead of String-append
2023-08-21 19:58:42 +12:00
Roland Praml dede93ca62 Use char-append instead of String-append 2023-08-21 08:22:18 +02:00
Rob BygraveandGitHub caf8bd0c0f Merge pull request #3172 from ebean-orm/feature/filterManyRaw
Add filterManyRaw() and Deprecate filterMany( <string expressions> )
2023-08-21 11:30:43 +12:00
Rob Bygrave 01d89a01a5 Fix new test in QCustomerTest 2023-08-21 11:22:02 +12:00
Rob Bygrave b0da647b0e Fix javadoc for filterManyRaw() 2023-08-21 11:17:29 +12:00
Rob Bygrave fbcd4c3133 Add filterManyRaw() and Deprecate filterMany( <string expressions> )
The filterMany( <string expressions> ) uses the language parser which
ultimately will we probably remove in ebean 15.x

Code can migrate to filterManyRaw() instead or better yet change to
use the improved query beans filterMany( <closure> ) option that will
be included in this same ebean release.
2023-08-21 11:15:39 +12:00
Rob BygraveandGitHub 3e41c5973b Merge pull request #3171 from ebean-orm/feature/filterMany-raw-expression
FIX for filterMany with raw expression with single SQL query
2023-08-21 09:39:40 +12:00
Rob Bygrave 1933beed9b Tidy unused import in CQueryPredicates 2023-08-20 23:52:10 +12:00
Rob Bygrave defb35b258 FIX for filterMany with raw expression with single SQL query
Fix for the case where the filterMany is not executed on a separate
query but instead part of the origin query.

The fix is to use the appropriate DeployParser and also fix the path
alias like ${} -> ${contacts}
2023-08-20 23:32:55 +12:00
Rob Bygrave 8a4024ecfc FIX for filterMany with raw expression with single SQL query
Fix for the case where the filterMany is not executed on a separate
query but instead part of the origin query.

The fix is to use the appropriate DeployParser and also fix the path
alias like ${} -> ${contacts}
2023-08-19 13:54:38 +12:00
Rob Bygrave 9756c9133e Improve existing test for filterMany using raw with separate SQL query for filterMany 2023-08-19 13:46:45 +12:00
Rob BygraveandGitHub c07d5e2c97 Merge pull request #3170 from ebean-orm/feature/prefer-char-append
Refactor prefer char append
2023-08-19 11:11:35 +12:00
Rob Bygrave 00e594d4fa Refactor prefer char append 2023-08-19 11:01:15 +12:00
Rob Bygrave 3bf316af2b Update Test QCustomerTest removing extra space character in the SQL 2023-08-19 10:17:00 +12:00
Rob BygraveandGitHub b116d3da28 Merge pull request #3169 from ebean-orm/feature/filterMany-TQAssoc
Add Query bean filterMany() taking a closure
2023-08-19 10:11:46 +12:00
Rob BygraveandGitHub 804618d699 Merge pull request #3168 from ebean-orm/feature/like-extra-space
Remove extra space added to the generated SQL via the LIKE expression
2023-08-19 10:05:17 +12:00
Rob Bygrave 0e9fe6a096 Remove extra space added to the generated SQL via the LIKE expression 2023-08-19 09:29:19 +12:00
Rob Bygrave ded4b94e54 Add Query bean filterMany() taking a closure
Query beans also generate a "Assoc" query bean that is used
for the relationships. Previously these were generated into a
.query.assoc package and with this they are generated as an
inner class of the query bean.

This then allows the change where an additional filterMany()
is generated on the "Assoc" bean that takes a closure. This
simplifies the use of query beans for filterMany.

This change to the generated query beans needs a change to the
ebean-agent enhancement.
2023-08-18 22:12:30 +12:00
Rob Bygrave eb0812df16 Bump to next snapshot 2023-08-17 23:26:26 +12:00
Rob Bygrave 9ccaa824e0 Version 13.21.0 2023-08-17 22:51:00 +12:00
Rob BygraveandGitHub d6e46b15a3 Merge pull request #3167 from ebean-orm/feature/InTuples-Literal-skipCache
Change Lists.partition() argument order to match Guava's
2023-08-17 15:36:35 +12:00
robin.bygrave bab9be0228 Change Lists.partition() argument order to match Guava's
- May as well match what they have in terms of arg order
- Change from interface to class might be better
2023-08-17 15:36:03 +12:00
Rob BygraveandGitHub 9331050a43 Merge pull request #3166 from ebean-orm/feature/InTuples-Literal-skipCache
InTuples literal mode - don't cache ebean compiled query plan
2023-08-17 15:34:17 +12:00
robin.bygrave 9bcd189730 Test TestInTuplesWithLocalDate does not support SQLServer and DB2 yet 2023-08-17 15:24:28 +12:00
Rob BygraveandGitHub 428365ceb9 Merge pull request #3164 from FOCONIS/bugfix/drop_foreign_key_without_index
BUG: Include drop for foreign keys without index when dropping table
2023-08-17 15:12:19 +12:00
robin.bygrave 76c889c6d9 InTuples literal mode - don't cache ebean compiled query plan
- Don't cache ebean compiled query plan when InTuples goes into literal mode
- Postgres maxInBinding = 32_000;
- SQLite maxInBinding = 800;
- Note that not caching the compiled query plan means that metrics visitor isn't
  going to see it, we lose collection of that query execution metric. We might
  need a plan to fix this later.
2023-08-17 15:08:16 +12:00
Rob BygraveandGitHub 9e4007d25a Merge pull request #3165 from ebean-orm/feature/Lists-partitions
Add support for literal mode for InTuples with lots of entries
2023-08-17 10:31:03 +12:00
Rob Bygrave 9d7754b92d Add support for literal mode for InTuples with lots of entries
So as to not exceed the limit on bind values, the InTuples expression can
go into literal mode where it uses literal values for supported types -
Numbers, Strings, UUID, and LocalDate.
2023-08-17 00:33:56 +12:00
Rob BygraveandGitHub 3c80032063 Merge pull request #3163 from ebean-orm/feature/Lists-partitions
Add Lists.partition() helper method and use in DefaultPersister batch deletion
2023-08-17 00:32:04 +12:00
Jonas Pöhler 7dae937491 Generate working migration 2023-08-16 12:00:23 +02:00
Jonas Pöhler 6ce5e865ca FIX: also include foreign keys without index in drop statement 2023-08-16 11:59:50 +02:00
Jonas Pöhler b0d8fa0286 Generate failing migration 2023-08-16 11:58:57 +02:00
Jonas Pöhler 83c85adbde ADD: testcase 2023-08-16 11:57:34 +02:00
Rob Bygrave a1b51fd8ef For DefaultPersister batch deletion, use more explicit maxDeleteBatch 2023-08-16 17:55:41 +12:00
Rob Bygrave bcc4034371 Add Lists.partition() helper method and use in DefaultPersister batch deletion 2023-08-16 17:39:10 +12:00
Rob BygraveandGitHub 3dde07fc9f Merge pull request #3162 from ebean-orm/feature/3133-postgres
Tidy IdBinderEmbedded - merge use of getIdProperty() and idSelect()
2023-08-16 00:17:23 +12:00
Rob Bygrave 87ada9e999 IdBinder - refactor rename methods 2023-08-16 00:11:46 +12:00
Rob Bygrave ea55f25d44 Tidy IdBinderEmbedded - merge use of getIdProperty() and idSelect() to use idSelect()
Means we can remove getIdProperty()
2023-08-15 23:36:59 +12:00
Rob BygraveandGitHub 2231f723f8 Merge pull request #3161 from ebean-orm/feature/3133-postgres
Fix to #3133 changes for Postgres adding back support for MultiValue binding
2023-08-15 23:18:53 +12:00
Rob Bygrave 7c16694d4b Fix to #3133 changes for Postgres adding back support for MultiValue binding
The MultiValue binding that we use for Postgres, Yugabyte etc was lost with
the changes in #3133 and this puts that back.

We desire to use Postgres ANY Array binding for these cases.
2023-08-15 23:17:31 +12:00
Rob BygraveandGitHub ea60ff47cf Merge pull request #3160 from ebean-orm/feature/alsoIf
Add Query alsoIf() to conditionally apply changes to a query
2023-08-15 22:25:28 +12:00
Rob BygraveandGitHub 1f7912dab6 Merge pull request #3159 from ebean-orm/feature/idClass
Change IdClass property name to _$IdClass$
2023-08-15 21:59:56 +12:00
Rob Bygrave ec0c00eb72 Add Query alsoIf() to conditionally apply changes to a query 2023-08-15 21:56:50 +12:00
Rob Bygrave dd99e32cc6 Change IdClass property name to _$IdClass$ 2023-08-15 21:55:09 +12:00
Rob BygraveandGitHub 1decbe0152 Merge pull request #3147 from FOCONIS/rethrow-error-in-commit
FIX: Rethrow error in commit path of callbacks
2023-08-14 23:25:04 +12:00
Rob BygraveandGitHub d58e3d023f Merge pull request #3158 from ebean-orm/feature/tidy-idBinderEmbedded
Followup for #3133 - "Embedded id expansion on parentIds" for SQLServer and DB2
2023-08-14 23:06:28 +12:00
Rob Bygrave 1598b40c36 Followup for #3133 - "Embedded id expansion on parentIds" for SQLServer and DB2 2023-08-14 23:00:41 +12:00
Rob BygraveandGitHub 66ef667a0a Merge pull request #3157 from ebean-orm/feature/tidy-idBinderEmbedded
Tidy IdBinderEmbedded final fields, StringBuilder sizes and reuse code
2023-08-14 22:59:15 +12:00
Rob Bygrave e821d66268 Tidy IdBinderEmbedded final fields, StringBuilder sizes and reuse code 2023-08-14 15:10:00 +12:00
Rob BygraveandGitHub b8e164e04c Merge pull request #3148 from FOCONIS/fix-recursive-batch-flush
FIX: Recursive batch flush can save beans in wrong order
2023-08-14 13:55:50 +12:00
Rob BygraveandGitHub 9097466a7b Merge pull request #3145 from FOCONIS/m2m-where-formula
FIX: Query on formula m2o-property uses wrong alias:
2023-08-14 13:55:21 +12:00
Rob BygraveandGitHub 99604d8ec3 Merge pull request #3155 from ebean-orm/feature/3133-IdClass-match-on-name
#3133 - For IdClass match on property name
2023-08-14 13:53:58 +12:00
Rob Bygrave 95d37fc3dc Temporary ignore test TestCompositeForeignKey for DB2 and SQLServer 2023-08-14 13:41:34 +12:00
Rob Bygrave 76d85adc98 Fix tests for #3133 MySql and SQLServer which require column ordering of PK and FK to match 2023-08-14 11:14:43 +12:00
Rob Bygrave 2f233db465 #3133 - For IdClass match on property name 2023-08-10 23:22:57 +12:00
Rob Bygrave 1ca73ca6aa Test only - Update test IdClass CEPProductCategoryId to match expectations 2023-08-10 23:17:47 +12:00
Rob BygraveandGitHub d5e4c13fa8 Merge pull request #3154 from ebean-orm/feature/3134-idClass-delete
#3134 - String cannot be cast to class io.ebean.bean.EntityBean" when deleting entities that use cascade = [CascadeType.ALL] with composite keys
2023-08-10 21:15:09 +12:00
Rob Bygrave b5ac31838c #3134 Fix for - String cannot be cast to class io.ebean.bean.EntityBean" when deleting entities that use cascade = [CascadeType.ALL] with composite keys 2023-08-10 21:11:58 +12:00
Rob Bygrave e3e9412eea #3134 Failing test - String cannot be cast to class io.ebean.bean.EntityBean" when deleting entities that use cascade = [CascadeType.ALL] with composite keys 2023-08-10 20:50:40 +12:00
Roland PramlandRoland Praml d3427876b7 FIX: Recursive batch flush can save dependant beans in wrong order 2023-08-08 16:59:46 +02:00
Roland Praml 4b2976e31b Rethrow error in commit path of callbacks 2023-08-08 16:35:25 +02:00
Roland Praml 5720ee65b3 Ignored Postgres Platform 2023-08-08 14:02:49 +02:00
Roland Praml 7f441ce72e FIX: M2M Where Formula joins 2023-08-08 14:02:34 +02:00
Rob BygraveandGitHub 83e87b0c67 Merge pull request #3140 from ebean-orm/feature/bump-datasource
Bump ebean-datasource to 8.6, increases validation timeout default to 30 secs
2023-07-23 14:35:57 +12:00
Rob Bygrave 578feac87f Bump ebean-datasource to 8.6, increases validation timeout default to 30 secs 2023-07-21 17:02:08 +12:00
Rob BygraveandGitHub 42a64e715d Merge pull request #3138 from ebean-orm/feature/postgres-queryplan-capture-buffers
[Postgres] Include buffers in Postgres explain - explain (analyze, buffers)
2023-07-18 14:35:24 +12:00
robin.bygrave 12a3a180f4 [Postgres] Include buffers in Postgres explain - explain (analyze, buffers) 2023-07-18 13:52:21 +12:00
Rob BygraveandGitHub 8acd5bcb39 Merge pull request #3131 from ebean-orm/feature/h2-nonKeyWords
Modify ebean-test H2Database setup to default KEY,VALUE as non-keywords
2023-07-11 12:49:15 +12:00
Rob BygraveandGitHub eb71756c65 Merge pull request #3136 from ebean-orm/dependabot/maven/com.h2database-h2-2.2.220
Bump h2 from 2.1.214 to 2.2.220
2023-07-11 12:48:04 +12:00
dependabot[bot]andGitHub 8c8cadd471 Bump h2 from 2.1.214 to 2.2.220
Bumps [h2](https://github.com/h2database/h2database) from 2.1.214 to 2.2.220.
- [Release notes](https://github.com/h2database/h2database/releases)
- [Commits](https://github.com/h2database/h2database/compare/version-2.1.214...version-2.2.220)

---
updated-dependencies:
- dependency-name: com.h2database:h2
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-07 21:57:51 +00:00
Rob BygraveandGitHub 222c49c59b Merge pull request #3130 from ebean-orm/feature/3123-root-error-suppressed
#3123 Root cause error can be suppressed on initialisation
2023-07-05 23:47:11 +12:00
Rob Bygrave 1e860112e6 Modify ebean-test H2Database setup to default KEY,VALUE as non-keywords
H2Database 2.x changed KEY and VALUE to be deemed keywords for SQL compliance. This is actually a bit of a pain as all the other databases we test allow KEY and VALUE as column names.

This changes the setup for H2Database to treat KEY and VALUE as non keywords as before and be more consistent with the other databases.
2023-07-05 23:46:06 +12:00
Rob Bygrave ffc21daaba Bump to next snapshot 2023-07-05 23:28:49 +12:00
Rob Bygrave f9adcb2c5a #3123 Root cause error can be suppressed on initialisation 2023-07-05 23:16:00 +12:00
Rob Bygrave d051bba71f Version 13.20.1 2023-07-04 12:05:30 +12:00
Rob Bygrave f414f04033 Add note on lack of support for InTuples with SQLServer and DB2 2023-07-04 12:05:10 +12:00
Rob Bygrave ac466ecd79 #3125 Add query.usingMaster() for query beans 2023-07-03 23:30:02 +12:00
Rob Bygrave 262a7f9bab Bump ebean-agent version 2023-07-03 22:57:55 +12:00
Rob BygraveandGitHub bb02d74005 Merge pull request #3125 from ebean-orm/feature/query-usingMaster
Add query.usingMaster() to explicitly choose master data source
2023-07-03 22:48:47 +12:00
Rob BygraveandGitHub e9b2b8d266 Merge pull request #3017 from ebean-orm/feature/db2luw9
Initial DB2Luw9Platform using row_number() for row limiting sql
2023-07-03 22:43:55 +12:00
Rob Bygrave fc16bde227 Modify ImplicitReadOnlyTransaction, call deactivate in finally 2023-07-03 22:43:13 +12:00
Rob Bygrave d1775dfcc4 #3017 Change DB2LegacyPlatform to also use the row_number limiters 2023-07-03 22:35:46 +12:00
3d5937f6da Update platforms/db2/src/main/java/io/ebean/platform/db2/DB2RowNumberBasicLimiter.java
Bump StringBuilder to use 120

Co-authored-by: Roland Praml <roland.praml@foconis.de>
2023-07-03 22:31:01 +12:00
Rob BygraveandGitHub adca8cd8fa Merge branch 'master' into feature/db2luw9 2023-07-03 22:28:43 +12:00
Rob BygraveandGitHub 6d30e6310b Merge pull request #3127 from ebean-orm/feature/3126
#3126 - Incorrect complex indexes generation
2023-07-03 22:22:32 +12:00
Rob Bygrave 79ed0a5f8e #3126 - Incorrect complex indexes generation 2023-07-03 22:19:38 +12:00
Rob Bygrave 94b3a020d5 Modify ImplicitReadOnlyTransaction useCommit to check connection.getAutoCommit() 2023-07-03 21:40:21 +12:00
Rob Bygrave 3e241907e6 Modify internal ImplicitReadOnlyTransaction to also support calling commit()
Originally, ImplicitReadOnlyTransaction was built to support read-only DataSource where the connections are using autoCommit true. This change modified ImplicitReadOnlyTransaction to also support use with the main DataSource where the connection are not using autoCommit true.

This is also now needed for the query.usingMaster() case where we have an implicit read only transaction but use the main DataSource with underlying connection requiring explicit commit() at the end of the transaction.
2023-07-03 21:27:58 +12:00
Rob Bygrave c4af1d9b23 Add query.usingMaster() to explicitly choose master data source
When we have a read replica with potential for replication lag, and config a read only DataSource to use that read replica, by default a query executed without a current transaction will use the read replica.

We specify usingMaster() when we explicitly want to execute a query and use the master data source.
2023-07-03 16:41:22 +12:00
Rob BygraveandGitHub 7702169762 Merge pull request #3124 from ebean-orm/feature/InTuples
Add InTuples expression for multi-column IN expression
2023-07-03 12:48:21 +12:00
Rob Bygrave 8209d9e229 Add SpiInTuples to hide more details from InTuples 2023-07-03 12:41:31 +12:00
Rob Bygrave 664120f369 Add InTuples expression for multi-column IN expression 2023-07-03 11:54:38 +12:00
Rob Bygrave e952b555e0 Add InTuples expression for multi-column IN expression 2023-07-03 11:49:53 +12:00
Rob BygraveandGitHub d99c50da75 Merge pull request #3122 from ebean-orm/feature/3109-jta-txn-fix
#3109 Fix for JtaTransactionManager when no active transaction
2023-06-26 21:30:55 +12:00
Rob Bygrave d4bec166f7 #3109 Fix for JtaTransactionManager when no active transaction
The call to registry() can throw an exception so
pulling that inside the try catch block and handle
that as no active transaction returning null.
2023-06-26 21:30:01 +12:00
Rob Bygrave 9a4b9d4bec Bump to next snapshot version 2023-06-21 07:08:13 +12:00
Rob Bygrave 68a6e98292 Version 13.20.0 2023-06-20 20:35:04 +12:00
Rob Bygrave d61bdb028b Bump ebean-agent to 13.20.0 2023-06-20 20:32:29 +12:00
Rob BygraveandGitHub 9ddadb1338 Merge pull request #3118 from ebean-orm/feature/3109-JtaTransaction-currentTransaction
#3109 JtaTransactionManager - fix getCurrentTransaction()
2023-06-20 19:46:45 +12:00
Rob Bygrave fa1f225e67 #3109 follow up - refactor rename internal methods 2023-06-20 19:41:00 +12:00
Rob Bygrave 7a72adedfa #3109 JtaTransactionManager - fix getCurrentTransaction()
Fix for JtaTransactionManager to allow Wildfly (or other) to throw an Exception when TransactionSynchronizationRegistry.getResource() is called.
2023-06-20 19:39:08 +12:00
Rob BygraveandGitHub 3d3e5c2c34 Merge pull request #3117 from ebean-orm/feature/bump-test-containers
Bump ebean-test-containers to 7.1
2023-06-20 18:45:06 +12:00
Rob Bygrave 708f429c21 Bump ebean-test-containers to 7.1 2023-06-20 18:40:48 +12:00
Rob BygraveandGitHub bca49ed2e2 Merge pull request #3116 from ebean-orm/feature/bump-test-containers
Bump ebean-test-containers to 7.0
2023-06-20 17:47:15 +12:00
Rob Bygrave e103ec7706 Bump ebean-test-containers to 7.0 2023-06-20 17:46:36 +12:00
Rob BygraveandGitHub 9fc1bec6a9 Merge pull request #3046 from FOCONIS/bugfix/lazy_loading_findEach_garbage_collection
Bugfix for NPE when lazyLoading in findEach due to Garbage Collection
2023-06-17 11:56:25 +12:00
Rob BygraveandGitHub f712635860 Merge pull request #3107 from FOCONIS/json-tests
DB specific length support in JSONs/Varchars/binary data
2023-06-17 11:38:46 +12:00
Rob BygraveandGitHub 47a0e38eac Merge pull request #3114 from ebean-orm/feature/3113-followup
Followup to #3113, remove unused first BatchControl queue
2023-06-17 11:36:53 +12:00
Rob Bygrave 870d90d055 Followup to #3113, remove unused first BatchControl queue 2023-06-17 11:35:51 +12:00
Rob BygraveandGitHub ac1b30782a Merge pull request #3113 from FOCONIS/bugfix/batch_ordering_many2many_intersection
Bugfix for wrong batch statement ordering with many2many relations
2023-06-17 11:28:01 +12:00
Jonas Pöhler b63445e9c9 FIX: Put the delete statements into the correct flush-queue, so they do not conflict with the following inserts 2023-06-16 16:26:14 +02:00
Jonas Pöhler 09f616aae8 ADD: testcase for showing an issue with deleting and re-adding many-to-many elements (size > 20)
(cherry picked from commit e6a4bc4e0c31bb35ab5a13c958c7c4b1f68ca037)
2023-06-16 16:16:53 +02:00
Roland Praml 994fb267ad Merge branch 'master-upstream' into json-tests 2023-06-16 07:40:01 +02:00
Rob BygraveandGitHub 53b1e4d682 Merge pull request #3111 from ebean-orm/feature/3101-jpa-indexes
#3101 - Support JPA Indexes
2023-06-16 13:53:48 +12:00
robin.bygrave c7f6c508a6 #3101 - Support JPA Indexes 2023-06-16 13:44:03 +12:00
Rob BygraveandGitHub 9109fd356f Merge pull request #3108 from FOCONIS/regenerated-scripts
No code change: Regenerated scripts
2023-06-15 23:37:51 +12:00
Roland Praml 55477d4fab No code change: Regenerated scripts 2023-06-15 08:07:51 +02:00
Rob BygraveandGitHub 340281113f Merge pull request #3106 from focbenz/patch-1
Update CONFIGURATION.md with small corrections and comment for includeGeneratedFileComment
2023-06-15 08:05:26 +12:00
Roland Praml 77610672a9 Regenerated migration scripts again 2023-06-14 18:24:23 +02:00
Roland Praml d8238735c1 Fix also DbTypeMapTest, which uses the new varbinary type 2023-06-14 18:19:17 +02:00
Roland Praml f63b013ef9 Added and fixed tests 2023-06-14 18:14:12 +02:00
Roland Praml 6fe3ec9355 Migration scripts 2023-06-14 17:50:26 +02:00
Roland Praml d1c21bf50a Hana, NuoDb, SqlAnywhere: add limits (untested!) 2023-06-14 17:50:08 +02:00
Roland Praml 578560c2e2 Oracle: max varchar length = 4000, raw = 2000 2023-06-14 17:49:10 +02:00
Roland Praml 0f9462b7b5 Postgres: max varchar limit = 10MB 2023-06-14 17:32:00 +02:00
Roland Praml e89891038b Mysql: max varchar length = 4000, varbinary = 8000. Also refactored MySql(C|B)lob 2023-06-14 17:30:28 +02:00
Roland Praml 2a7a2d4dd4 DB2: max varchar length = 4000, varbinary = 8000 2023-06-14 17:27:58 +02:00
Roland Praml f499cc8c2c SQLSERVER: max nvarchar length = 4000, varbinary = 8000 (no longer using deprecated image type by default) 2023-06-14 17:19:48 +02:00
Roland Praml 0dc4c6b11b NEW: DbPlatformType supports fallback, when length exceeded (removed SqlServer workaround) 2023-06-14 17:18:06 +02:00
Roland Praml f5d0777b86 Added new test models with lengths 2023-06-14 17:17:31 +02:00
Roland Praml 81443b77bc Fixes for Clickhouse platform 2023-06-14 17:16:14 +02:00
Roland Praml 2867c50090 Do not convert explicit defined column definitions 2023-06-14 17:16:14 +02:00
Michael BenzandGitHub c04171c1a5 Update CONFIGURATION.md with small corrections
Updated configuration markdown with small corrections and removed TODO for includeGeneratedFileComment

See https://github.com/ebean-orm/ebean/issues/550
2023-06-14 14:34:09 +02:00
Rob BygraveandGitHub e19cbdc2f6 Merge pull request #3104 from FOCONIS/dbmigration-fixes
Fixed DbMigration classes (put them in the right place)
2023-06-14 07:58:50 +12:00
Roland Praml 3e2e84e8bf Fixed DbMigration classes (put them in the right place) 2023-06-13 17:20:02 +02:00
Rob Bygrave 462d30bbb7 Version 13.19.0 2023-06-07 17:56:19 +12:00
Rob BygraveandGitHub 5466b889a7 Merge pull request #3098 from ebean-orm/deprecated/BeanFinder-server
Refactor ebean-core internal API - getters -> accessors
2023-06-02 09:06:54 +12:00
Rob Bygrave d27d20dd1c Refactor ebean-core internal API - getters -> accessors 2023-06-02 09:03:29 +12:00
Rob BygraveandGitHub b6edc54cd9 Merge pull request #3097 from ebean-orm/deprecated/BeanFinder-server
Refactor ebean-core internal API - getters -> accessors and  tidy
2023-06-01 22:15:52 +12:00
Rob Bygrave 2929483b0d Refactor ebean-core internal API - getters -> accessors 2023-06-01 22:05:53 +12:00
Rob Bygrave 2ab7c3529a Tidy ebean-core internal API
- Remove unused BeanIdList
2023-06-01 21:27:55 +12:00
Rob BygraveandGitHub f409ea2431 Merge pull request #3096 from ebean-orm/deprecated/BeanFinder-server
Deprecate order() methods on Query, ExpressionList - migrate to orderBy()
2023-06-01 21:22:54 +12:00
Rob Bygrave e71be4e1b1 Deprecate order() methods on Query, ExpressionList - migrate to orderBy()
Unfortunately we have order() and orderBy() methods which do the
same thing. I have decided to deprecate the order() ones in
favour of the orderBy() methods so that ultimately we will end
up with less methods and I think orderBy() is the correct choice.

Apologies for the migration pain here.
2023-06-01 21:21:39 +12:00
Rob BygraveandGitHub 507aec20d9 Merge pull request #3095 from ebean-orm/deprecated/BeanFinder-server
No functional change, Expr internal reuse of factory() method
2023-06-01 20:57:55 +12:00
Rob Bygrave 6a2d0c233a No functional change, Expr internal reuse of factory() method 2023-06-01 20:56:13 +12:00
Rob BygraveandGitHub a1db8794bb Merge pull request #3094 from ebean-orm/deprecated/BeanFinder-server
Remove deprecated Query Bean fetchAll() - migrate to fetch()
2023-06-01 20:48:50 +12:00
Rob Bygrave bac7cd1ee7 Remove deprecated Query Bean fetchAll() - migrate to fetch()
```java

  /**
   * Deprecated in favor of fetch().
   */
  @Deprecated
  public final R fetchAll() {
    return fetch();
  }

```
2023-06-01 20:48:13 +12:00
Rob BygraveandGitHub 7ec0c72522 Merge pull request #3093 from ebean-orm/deprecated/BeanFinder-server
Remove deprecated Query setLoadBeanCache() - migrate to setBeanCacheM…
2023-06-01 20:45:34 +12:00
Rob Bygrave 430926c5a9 Remove deprecated Query setLoadBeanCache() - migrate to setBeanCacheMode()
Typically migrate to `.setBeanCacheMode(CacheMode.PUT)` or `.setBeanCacheMode(CacheMode.OFF)`

```java

  /**
   * Deprecated - migrate to use setBeanCacheMode(CacheMode.PUT) or other CacheMode.
   * <p>
   * When set to true all the beans from this query are loaded into the bean cache.
   */
  @Deprecated
  Query<T> setLoadBeanCache(boolean loadBeanCache);

```
2023-06-01 20:44:31 +12:00
Rob BygraveandGitHub a2389be4aa Merge pull request #3092 from ebean-orm/deprecated/BeanFinder-server
Remove deprecated ExpressionList.setOrderBy() - migrate to orderBy()
2023-06-01 20:34:44 +12:00
Rob Bygrave f21caa0755 Remove deprecated ExpressionList.setOrderBy() - migrate to orderBy()
Migrate to `.orderBy(String orderBy)`

```java

  /**
   * Deprecated migrate to {@link #orderBy(String)}
   */
  @Deprecated
  Query<T> setOrderBy(String orderBy);

```
2023-06-01 20:34:04 +12:00
Rob BygraveandGitHub e42d3dac18 Merge pull request #3091 from ebean-orm/deprecated/BeanFinder-server
Remove deprecated DatabaseConfig.defaultOrderById
2023-06-01 20:11:51 +12:00
Rob Bygrave 4c47a84daf Remove deprecated DatabaseConfig.defaultOrderById
Should no longer be used / set to true.

```java

  /**
   * Deprecated - look to have explicit order by. Sets the default orderById setting for queries.
   */
  @Deprecated
  public void setDefaultOrderById(boolean defaultOrderById) {
    this.defaultOrderById = defaultOrderById;
  }

```
2023-06-01 20:09:14 +12:00
Rob BygraveandGitHub 42aaceaafa Merge pull request #3090 from ebean-orm/deprecated/BeanFinder-server
Remove deprecated methods from ProfileLocation
2023-06-01 20:07:01 +12:00
Rob Bygrave e5f7a28d80 Remove deprecated methods from ProfileLocation
These methods are no longer used.
2023-06-01 20:00:50 +12:00
Rob BygraveandGitHub 074a3bacc7 Merge pull request #3089 from ebean-orm/deprecated/BeanFinder-server
Remove deprecated BeanFinder.server, migrate to BeanFinder.database
2023-06-01 19:56:34 +12:00
Rob Bygrave f52a18989c Remove deprecated BeanFinder.server, migrate to BeanFinder.database 2023-06-01 19:54:39 +12:00
Rob Bygrave f415ee22b8 Update javadoc for ExtendedServer 2023-06-01 19:51:31 +12:00
Rob Bygrave 4878ca47b5 Remove deprecated ExtendedServer query methods - use query.usingTransaction() instead
Removing all the deprecated query methods from ExtendedServer. Migrate to passing
the explicit transaction to the query using query.usingTransaction() instead.
2023-06-01 19:45:17 +12:00
Rob BygraveandGitHub 59a3766a53 Merge pull request #3087 from ebean-orm/deprecated/collectMetricsAsJson
Remove deprecated MetaInfoManager.collectMetricsAsJson() - move to co…
2023-06-01 19:36:04 +12:00
Rob Bygrave 15de44eef8 Remove deprecated MetaInfoManager.collectMetricsAsJson() - move to collectMetrics().asJson()
Removing these deprecated methods:
- collectMetricsAsJson() -> collectMetrics().asJson();
- collectMetricsAsData() -> collectMetrics().asData()

```java
  /**
   * Deprecated migrate to collectMetrics().asJson().
   */
  @Deprecated
  default ServerMetricsAsJson collectMetricsAsJson() {
    return collectMetrics().asJson();
  }

  /**
   * Deprecated migrate to collectMetrics().asData().
   */
  @Deprecated
  default List<MetricData> collectMetricsAsData() {
    return collectMetrics().asData();
  }
```
2023-06-01 19:35:03 +12:00
Rob Bygrave 5ae9942dd5 Remove unused and empty ebean-kotlin module
It never got used, may as well clean up and remove it.
2023-06-01 19:26:17 +12:00
Rob BygraveandGitHub bf375f1065 Merge pull request #3086 from ebean-orm/feature/move-components
Remove unused and empty ebean-kotlin module
2023-06-01 19:22:45 +12:00
Rob Bygrave 510e129ff6 Remove unused and empty ebean-kotlin module
It never got used, may as well clean up and remove it.
2023-06-01 19:22:16 +12:00
Rob BygraveandGitHub 1c32b9b0bc Merge pull request #3085 from ebean-orm/feature/move-components
Moved - ebean-autotune, ebean-csv-reader, ebean-joda-time, ebean-jack…
2023-06-01 19:19:39 +12:00
Rob Bygrave f25a20ff90 Moved - ebean-autotune, ebean-csv-reader, ebean-joda-time, ebean-jackson-jsonnode, ebean-externalmapping-xml
These modules have all been moved to ebean-component git repo.
These are all optional modules and will be released at a
slower cadence.
2023-06-01 19:17:14 +12:00
Rob BygraveandGitHub 0ba6753c8c Merge pull request #3084 from ebean-orm/fix/jakarta-transaction
Fix javax-to-jakarta support for jakarta.transaction
2023-06-01 08:26:54 +12:00
Rob Bygrave 7efef027c0 Fix javax-to-jakarta support for jakarta.transaction 2023-06-01 08:24:14 +12:00
Rob Bygrave 3a84695130 Version 13.18.0 2023-05-31 22:06:30 +12:00
Rob BygraveandGitHub 3f6d6908e2 Merge pull request #3081 from ebean-orm/feature/bump-migration-2
Bump ebean-migration to 13.9.0 - changes API for checkState()
2023-05-31 20:53:24 +12:00
Rob Bygrave 9f4bf6103f Bump ebean-migration to 13.9.0 - changes API for checkState()
Code using ebean-migration checkState() methods needs to change
as those methods now return a new MigrationResource interface type
2023-05-31 20:51:28 +12:00
Rob BygraveandGitHub ad7bb7063d Merge pull request #3079 from ebean-orm/feature/bump-migration
Bump ebean-migration to 13.8.0 and ebean-ddl-runner to 2.3
2023-05-29 16:28:44 +12:00
Rob Bygrave 04b4fea559 Bump ebean-migration to 13.8.0 and ebean-ddl-runner to 2.3 2023-05-29 16:27:54 +12:00
Rob BygraveandGitHub eb824949fe Merge pull request #3078 from ebean-orm/feature/refactor-renameDtoMethodUsingAccessors
Refactor internal dto methods to use accessors
2023-05-26 15:24:40 +12:00
robin.bygrave 34db4d0c1f Refactor internal dto methods to use accessors 2023-05-26 15:09:11 +12:00
Rob BygraveandGitHub 54a3113dbc Merge pull request #3077 from ebean-orm/feature/3062-dtoQuery
Use Statement for truncate table and postgres version query
2023-05-26 15:03:52 +12:00
robin.bygrave 7635630808 Use Statement for truncate table and postgres version query 2023-05-26 15:03:13 +12:00
Rob BygraveandGitHub e4018864ac Merge pull request #3075 from ebean-orm/feature/3062-dtoQuery
#3062 - DtoQuery may match the wrong constructor
2023-05-25 21:58:52 +12:00
robin.bygrave 75e69a0a23 #3062 - DtoQuery may match the wrong constructor
When 2 or more Dto constructors clash by argument count
then we need to ignore those constructors.
2023-05-25 21:57:54 +12:00
Rob BygraveandGitHub 6061f80dcc Merge pull request #3074 from ebean-orm/feature/toString_roundBrackets
Change toString to use (trimmed) with round brackets
2023-05-25 21:15:31 +12:00
robin.bygrave c60525a685 Change toString to use (trimmed) with round brackets
Change from use <> angle brackets as with json logger these are escaped which is a little ugly
2023-05-25 21:14:51 +12:00
Rob BygraveandGitHub eef628531a Merge pull request #3073 from ebean-orm/feature/bump-yugabyte
Bump yugabyte version to 2.18.0.0
2023-05-25 21:04:07 +12:00
robin.bygrave 33d9257a61 Bump yugabyte version to 2.18.0.0 2023-05-25 20:56:10 +12:00
robin.bygrave 7b032351b1 Bump yugabyte version to 2.18.0.0 2023-05-25 20:48:50 +12:00
robin.bygrave 265f865a7d Postgres DDL - Use IF NOT EXISTS with ADD COLUMN
Update generated hashes
2023-05-25 20:30:47 +12:00
Rob BygraveandGitHub 73d30310fd Merge pull request #3072 from ebean-orm/feature/postgres-dll-addColumn-ifNotExists
Postgres DDL - Use IF NOT EXISTS with ADD COLUMN
2023-05-25 20:28:41 +12:00
Rob BygraveandGitHub e26fbbb11f Merge branch 'master' into feature/postgres-dll-addColumn-ifNotExists 2023-05-25 20:25:54 +12:00
Rob BygraveandGitHub a548c16789 Merge pull request #3071 from ebean-orm/feature/postres-ddl-varchar-changeSize
Postgres DDL - Don't use cast when just changing varchar column size
2023-05-25 20:23:04 +12:00
robin.bygrave ecf650c9bc Postgres DDL - Use IF NOT EXISTS with ADD COLUMN 2023-05-25 20:22:18 +12:00
robin.bygrave b27b4e7038 Postgres DDL - Don't use cast when just changing varchar column size 2023-05-25 20:00:36 +12:00
Rob BygraveandGitHub 58d190ef12 Merge pull request #3070 from ebean-orm/dependabot/maven/ebean-test/org.xerial-sqlite-jdbc-3.41.2.2
Bump sqlite-jdbc from 3.36.0.3 to 3.41.2.2 in /ebean-test
2023-05-24 09:28:05 +12:00
dependabot[bot]andGitHub bffc9108f9 Bump sqlite-jdbc from 3.36.0.3 to 3.41.2.2 in /ebean-test
Bumps [sqlite-jdbc](https://github.com/xerial/sqlite-jdbc) from 3.36.0.3 to 3.41.2.2.
- [Release notes](https://github.com/xerial/sqlite-jdbc/releases)
- [Changelog](https://github.com/xerial/sqlite-jdbc/blob/master/CHANGELOG)
- [Commits](https://github.com/xerial/sqlite-jdbc/compare/3.36.0.3...3.41.2.2)

---
updated-dependencies:
- dependency-name: org.xerial:sqlite-jdbc
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-23 20:15:29 +00:00
Rob BygraveandGitHub 114a715432 Merge pull request #3068 from FOCONIS/throw-exceptions
DB.refrence throws EntityNotFoundException instead returning null
2023-05-23 19:29:51 +12:00
Rob BygraveandGitHub 67d98954b2 Merge pull request #3069 from ebean-orm/feature/bump-avaje-config
Bump avaje-config to 3.4
2023-05-23 19:28:47 +12:00
Rob Bygrave 53e7aafb06 Bump avaje-config to 3.4 2023-05-23 19:26:29 +12:00
Roland Praml e207b4720b DB.refrence throws EntityNotFoundException instead returning null 2023-05-23 08:37:52 +02:00
Rob BygraveandGitHub af6da23411 Merge pull request #3067 from ebean-orm/feature/2064-jakarta-transaction
#3064 - JtaTransaction does not use jarkarta prefix for javax.transaction classes
2023-05-23 17:11:38 +12:00
robin.bygrave 21f274fd34 #3064 - JtaTransaction does not use jarkarta prefix for javax.transaction classes 2023-05-23 17:09:53 +12:00
Rob BygraveandGitHub 1b8df12a01 Merge pull request #3066 from ebean-orm/feature/3060-part2
From #3060 - Add missing @Nullable to ExpressionList.findSingleAttribute()
2023-05-23 17:00:14 +12:00
robin.bygrave b210d1a6a7 From #3060 - Add missing @Nullable to ExpressionList.findSingleAttribute() 2023-05-23 16:12:13 +12:00
Rob BygraveandGitHub d53ca87d43 Merge pull request #3057 from FOCONIS/property-value-intercept
Property.value use intercept to trigger lazy load
2023-05-23 13:36:09 +12:00
Rob BygraveandGitHub 635820cab5 Merge pull request #3058 from ebean-orm/feature/BeanProperty-value-to-getValue
No functional change, change use of BeanProperty.value() to BeanProperty.getValue()
2023-05-19 16:09:37 +12:00
Rob BygraveandGitHub aedb0fdcac Merge pull request #3063 from ebean-orm/feature/improve-error-message-no-join-columns
Use DeployBeanProperty toString() removing getFullBeanName()
2023-05-19 16:08:54 +12:00
robin.bygrave 4db1925328 No functional change, change use of BeanProperty.value() to BeanProperty.getValue()
Noting that value() currently calls through to getValue() hence
this is no real change. This is done because value() is also
a public method Property.value() [and this should probably
change to use getValueIntercept() rather than getValue()]
2023-05-17 15:31:52 +12:00
Roland Praml 6f2a444954 Property.value use intercept 2023-05-16 15:28:30 +02:00
Rob BygraveandGitHub 59b6621077 Merge pull request #3055 from ebean-orm/feature/queryPlanCaptureMicros
ENH: Add captureMicros and whenCaptured to MetaQueryPlan
2023-05-16 15:38:05 +12:00
Rob BygraveandGitHub 15a39f62e6 Merge pull request #3056 from ebean-orm/bump/yugabyte
Testing - Bump YugabyteDB version for testing to 2.17.3.0-b152
2023-05-16 15:37:29 +12:00
robin.bygrave 40489706ce Testing - Bump YugabyteDB version for testing to 2.17.3.0-b152 2023-05-16 14:39:46 +12:00
robin.bygrave 742f3b6dc4 ENH: Add captureMicros and whenCaptured to MetaQueryPlan
- captureMicros is the time taken to capture the specific query plan
- whenCaptured is the time when the bind values were taken

The DefaultQueryPlanListener logging will include these in the
output it logs
2023-05-16 13:47:27 +12:00
Rob BygraveandGitHub 753617a616 Merge pull request #3039 from FOCONIS/detailed-error-message
Throw excepction when trying to create unregistered bean
2023-05-10 16:37:18 +12:00
Rob BygraveandGitHub 114da00d98 Merge pull request #3040 from FOCONIS/correct-quotes
FIX: Use correct quotes when logging
2023-05-10 16:36:27 +12:00
Rob BygraveandGitHub 283ab7a1ac Merge pull request #3038 from FOCONIS/fix-javadoc-plugin
FIX build on system without JAVA_HOME set
2023-05-10 16:35:39 +12:00
Rob BygraveandGitHub 096988c19f Merge pull request #3052 from ebean-orm/feature/dep-config
Bump jackson dependency to 2.15.0
2023-05-10 16:34:06 +12:00
Rob Bygrave baf727e8ea Bump jackson dependency to 2.15.0 2023-05-10 16:33:38 +12:00
Rob BygraveandGitHub 2eb6558145 Merge pull request #3051 from ebean-orm/feature/dep-config
Bump avaje-config dependency to 3.2
2023-05-10 16:30:39 +12:00
Rob Bygrave d946504503 Bump avaje-config dependency to 3.2 2023-05-10 16:30:03 +12:00
Rob Bygrave ed94edd96b Bump to next snapshot version 2023-05-10 16:26:03 +12:00
Rob BygraveandGitHub 6441030161 Merge pull request #3030 from ebean-orm/feature/bump-avaje-config
Included ebean-migration as a dependency of ebean, ebean-postgres etc
2023-05-10 16:24:54 +12:00
Rob Bygrave 588527a5b9 Version 13.17.4 2023-05-10 00:34:53 +12:00
Rob Bygrave 06cad500c1 #3031 Improve error message 2023-05-10 00:34:27 +12:00
Rob Bygrave e29b57811b Update README add end 2023-05-10 00:30:07 +12:00
Rob Bygrave e6bf46e8c4 Improve error message for #3031 2023-05-09 23:37:05 +12:00
Rob BygraveandGitHub 646f8cc66b Merge pull request #3050 from ebean-orm/feature/LoadBeanRequest
Fix SqlTreeLoadBean to only register new beans into load context
2023-05-09 23:23:31 +12:00
Rob Bygrave 4c9f0f23f0 Fix SqlTreeLoadBean to only register new beans into load context
Additionally, refactor LoadBeanRequest moving the MarkedAsDeleted logging
2023-05-09 22:49:17 +12:00
Rob Bygrave ecfd831603 #3049 - Support for ebean.test.containers.mirror 2023-05-08 17:22:41 +12:00
Rob BygraveandGitHub b8324905ae Merge pull request #3036 from Ryszard-Trojnacki/postgis
Implemented missing cache functions for Postgis module.
2023-05-08 17:15:14 +12:00
Rob BygraveandGitHub 8cbcd1afad Merge pull request #3049 from ebean-orm/feature/ebean.test.containers.mirror
[ebean-test] Add support for ebean.test.containers.mirror
2023-05-08 17:12:22 +12:00
Rob Bygrave 7970ea39f3 Bump to next snapshot version 2023-05-08 17:11:24 +12:00
robin.bygrave a399d4f2cd [ebean-test] Add support for ebean.test.containers.mirror
Can use this property to specify a mirror to use for test images when running in CI

Currently, we assume that for local builds we actually prefer to not use the mirror (for Arm64 support etc)
2023-05-08 14:35:14 +12:00
Jonas Pöhler edb3759b3d Potential fix for NPE in lazyLoad under HeapPressure
(cherry picked from commit 5aa163bb75)
2023-05-05 09:58:01 +02:00
Jonas Pöhler 7ee0610db1 ADD: Test for reproducing NPE with lazyloaing in findEach under HeapPressure
(cherry picked from commit 96f071e08b)
2023-05-05 09:57:43 +02:00
Rob Bygrave 5b91e671dd Version 13.17.3 2023-05-01 14:51:33 +12:00
Rob Bygrave 547843fd52 Bump ebean-agent to 13.17.3 (no effective change) 2023-05-01 13:30:39 +12:00
Rob BygraveandGitHub 21e9c5c3d4 Merge pull request #3044 from ebean-orm/feature/markedAsDeleted-v3
Modify MarkedAsDeleted to ignore beans added during load
2023-05-01 13:21:36 +12:00
Rob Bygrave 05ab1ba25e Modify MarkedAsDeleted to ignore beans added during load
Adds the additional queryIds.contains(id) check
2023-05-01 13:11:03 +12:00
Roland Praml 82a6ec6957 Fix also other places 2023-04-26 11:11:12 +02:00
Roland Praml cf1c08c4ac FIX: Use correct quotes when logging 2023-04-26 10:59:41 +02:00
Roland Praml d32df16137 Throw excepction when trying to create unregistered bean 2023-04-26 10:56:14 +02:00
Roland Praml 2bcbc6fa07 FIX also other plugin versions 2023-04-26 10:39:18 +02:00
Roland Praml ba9158ec9c Javadoc POM fixes 2023-04-26 10:22:27 +02:00
Ryszard Trojnacki 40a6693a4c Implemented missing cache functions for Postgis module. 2023-04-21 08:58:44 +02:00
Rob Bygrave e04f33aaf0 Bump to next snapshot version 2023-04-21 16:53:12 +12:00
Rob Bygrave e4162a5b03 Version 13.17.2 2023-04-21 16:14:48 +12:00
Rob BygraveandGitHub 23e6b18262 Merge pull request #3035 from ebean-orm/feature/markedAsDeleted-mutateAfterLoadingFlag
Update MarkedAsDeleted logging to included check for loadingStarted
2023-04-21 02:44:39 +12:00
Rob Bygrave c8852c521e Update MarkedAsDeleted logging to included check for loadingStarted 2023-04-21 02:43:34 +12:00
Rob Bygrave 7351258d99 Bump ebean-agent to 13.17.2 (no functional change) 2023-04-21 00:51:57 +12:00
Rob BygraveandGitHub af9f9585fb Merge pull request #3034 from ebean-orm/feature/3033
#3033 - Fix for ConcurrentModificationException introduced in 13.17.1
2023-04-21 00:50:23 +12:00
Rob Bygrave d7f9dd40a0 #3033 - Fix for ConcurrentModificationException introduced in 13.17.1
java.util.ConcurrentModificationException
	at java.base/java.util.HashMap$HashIterator.nextNode(HashMap.java:1493)
	at java.base/java.util.HashMap$KeyIterator.next(HashMap.java:1516)
	at java.base/java.util.AbstractCollection.toString(AbstractCollection.java:472)
	at java.base/java.lang.String.valueOf(String.java:2951)
	at io.ebeaninternal.server.core.DefaultBeanLoader.loadBean(DefaultBeanLoader.java:134)
	at io.ebeaninternal.server.core.DefaultServer.loadBean(DefaultServer.java:475)
	at io.ebeaninternal.server.loadcontext.DLoadBeanContext$LoadBuffer.loadBean(DLoadBeanContext.java:217)
	at io.ebean.bean.InterceptReadWrite.loadBeanInternal(InterceptReadWrite.java:742)
	at io.ebean.bean.InterceptReadWrite.loadBean(InterceptReadWrite.java:724)
	at io.ebean.bean.InterceptReadWrite.preGetter(InterceptReadWrite.java:837)
	at ...
2023-04-21 00:49:41 +12:00
Rob Bygrave 1ec389864d Included ebean-migration as a dependency of ebean, ebean-postgres etc
Include ebean-migration as a dependency of all the composites. The thinking here is that we now expect to prefer ebean-migration over flyway or liquibase as the migration runner of choice. Including it means one less thing for folks to worry about in terms of syncing the versions to use etc.
2023-04-18 00:12:44 +12:00
Rob BygraveandGitHub d353b98307 Merge pull request #3029 from ebean-orm/feature/bump-avaje-config
Bump avaje-config to version 3.1
2023-04-18 00:04:14 +12:00
Rob Bygrave 3ddd7b4b2b Bump avaje-config to version 3.1 2023-04-18 00:03:35 +12:00
Rob Bygrave 3960e1deb5 Bump test tile use to 13.17.1 2023-04-17 23:56:20 +12:00
Rob Bygrave 84af78e43c Bump parent pom to 3.10 2023-04-17 23:52:36 +12:00
Rob Bygrave cbdbf6d2e0 Bump to next snapshot version 2023-04-17 23:51:58 +12:00
Rob Bygrave 548bf871a9 Version 13.17.1 2023-04-17 23:31:00 +12:00
Rob BygraveandGitHub b5245544d2 Merge pull request #3028 from ebean-orm/feature/markedAsDeleted-beforeState
Change MarkedAsDeleted to log batch before state
2023-04-17 22:40:29 +12:00
Rob Bygrave a986d0c8cd Change MarkedAsDeleted to log batch before state 2023-04-17 22:18:33 +12:00
Rob BygraveandGitHub 0e02449f67 Merge pull request #3027 from rvowles/docs/update-ebean-test
Update the documentation for test tenants
2023-04-17 17:52:48 +12:00
Richard Vowles 19389fb9d4 Update the documentation for test tenants
The existing docs for test tenants is no
longer correct and additional class level
docs point users in the right direction.
2023-04-17 16:22:06 +12:00
Rob Bygrave 63a23904ac Update for DB2Luw9 with rn column as last column 2023-04-13 21:52:09 +12:00
Rob BygraveandGitHub ab1a79281b Merge pull request #3023 from ebean-orm/feature/profileLabel-withQueryType
Add the [+query,+cache,+lazy] query type to the profile label
2023-04-13 19:46:27 +12:00
Rob BygraveandGitHub 073669d312 Merge pull request #3025 from ebean-orm/fix/3024
Fix for #3024 NPE when lazy loading after deserialising an entity bean
2023-04-13 19:46:08 +12:00
Rob Bygrave f66662fdfa Fix for #3024 NPE when lazy loading after deserialising an entity bean 2023-04-13 19:42:14 +12:00
Rob Bygrave 04b0d23932 Update tiles-maven-plugin to version 2.34 2023-04-11 10:34:52 +12:00
Rob Bygrave af613d3096 Add the [+query,+cache,+lazy] query type to the profile label 2023-04-06 21:59:51 +12:00
Rob Bygrave ecd27e145e bump to next snapshot version 2023-04-06 17:07:52 +12:00
Rob Bygrave 1807fc201e Initial DB2Luw9Platform using row_number() for row limiting sql 2023-03-30 22:56:55 +13:00
Rob Bygrave 2d03421de4 Use DeployBeanProperty toString() removing getFullBeanName() 2023-03-28 18:44:00 +13:00
1896 changed files with 14951 additions and 15693 deletions
+3 -1
View File
@@ -16,7 +16,7 @@ jobs:
strategy:
fail-fast: false
matrix:
java_version: [11, 17]
java_version: [11, 17, 21]
os: [ubuntu-latest]
steps:
@@ -34,6 +34,8 @@ jobs:
path:
~/.m2
key: build-${{ env.cache-name }}
- name: Maven version
run: mvn --version
- name: Build with Maven
run: mvn package
+1
View File
@@ -11,6 +11,7 @@ ebean-profiling*.xml
/db
/mydb.db
profiling/
.DS_Store
# Intellij project files
*.iml
+11 -12
View File
@@ -4,13 +4,13 @@ Overview of ebean.properties file
### DbMigration options
You can set individual values for different platforms when generating migrations
You can set individual values for different platforms when generating migrations.
`dbmigration.platform.<PLATFORM>.databaseSequenceBatchSize`
For DB's using sequences this is the number of sequence values prefetched.
`dbmigration.platform.<PLATFORM>.dbuuid`
Control, how UUID generation should work - it affects DDL which column type is generated. Possible values:
Control, how UUID generation should work - it affects which column type is generated in DDL. Possible values:
- BINARY enforces binary UUID
- VARCHAR enforces varchar UUID
- BINARY_OPTIMIZED enforces binary-optimized UUID (makes sense only with Type1 ID)
@@ -19,7 +19,7 @@ Control, how UUID generation should work - it affects DDL which column type is g
- AUTO_VARCHAR (default) use varchar when platform does not support UUID
`dbmigration.platform.<PLATFORM>.uuidStoreAsBinary`
Same as setting dbuuid to BINARY
Same as setting dbuuid to BINARY.
`dbmigration.platform.<PLATFORM>.geometrySRID`
The Geometry SRID value (default 4326).
@@ -30,7 +30,6 @@ The ID type (IDENTITY, SEQUENCE, GENERATOR, EXTERNAL)
`dbmigration.platform.<PLATFORM>.mapping`
Adjust the mapping. For example `BOOLEAN=integer(32);BIT=tinyint(3)`
`ebean.migration.applyPrefix`
Set this to "V" to be compatible with FlywayDB.
@@ -50,7 +49,7 @@ Set to true if the DB migration should be generated on server start.
The version of a pending drop that should be generated as the next migration.
`ebean.migration.includeGeneratedFileComment`
TODO
Adds the header about the migration files being generated when true. Reading 'THIS IS A GENERATED FILE - DO NOT MODIFY'
`ebean.migration.metaTable`
For running migration the DB table that holds migration execution status. Default 'db_migration'
@@ -65,17 +64,17 @@ Subdirectory the model xml files go into. Default 'model'
Suffix. Default '.model.xml'
`ebean.migration.name`
Description text that can be appended to the version to become the ddl script file name
Description text that can be appended to the version to become the ddl script file name.
`ebean.migration.patchInsertOn`
migration versions that should be added to history without running.
Migration versions that should be added to history without running.
`ebean.migration.patchResetChecksumOn`
migration versions that should have their checksum reset and not run.
Use this if you get a 'Checksum mismatch' error.
`ebean.migration.placeholders`
A comma and equals delimited placeholders that are substituted in SQL scripts when running migration (used by DB Migration runner only).
A comma and equals delimited map of placeholders that are substituted in SQL scripts when running migration (used by DB Migration runner only).
`ebean.migration.platform`
The database platform to generate migration DDL for.
@@ -90,7 +89,7 @@ The migration version name (typically FlywayDb compatible). Example: 1.1.1_2
### Ebean UUID options
`ebean.uuidVersion`
Controls, how the UUIDs are generated. Possible values
Controls how the UUIDs are generated. Possible values:
- VERSION4 (default) generate random V4 UUIDs,
- VERSION1 generate rfc4122 compliant Type 1 UUIDs (requires a state file)
- VERSION1RND generate fake Type 1 UUIDs
@@ -98,7 +97,7 @@ Controls, how the UUIDs are generated. Possible values
Note, that V1 UUIDs in conjunction with AUTO_BINARY_OPTIMIZED will give you the best index performance, but you MUST understand how this works to avoid collisions.
`ebean.uuidStateFile`
The state file that is Required to generate V1 UUIDs
The state file that is required to generate V1 UUIDs.
### DocStoreConfig
@@ -107,7 +106,7 @@ The state file that is Required to generate V1 UUIDs
True when the Document store integration is active/on.
`ebean.docstore.allowAllCertificates`
Set to true such that the client allows connections to invalid/self signed SSL certificates.
Set to true such that the client allows connections to invalid/self-signed SSL certificates.
`ebean.docstore.bulkBatchSize`
The default batch size to use for the Bulk API calls.
@@ -192,7 +191,7 @@ Suffix appended to the base table to derive the view that contains the union of
Set to true if the DataSource uses autoCommit. Indicates that Ebean should use autoCommit friendly Transactions and TransactionManager.
`ebean.autoReadOnlyDataSource`
When true create a read only DataSource using readOnlyDataSourceConfig defaulting values from dataSourceConfig
When true create a read only DataSource using readOnlyDataSourceConfig defaulting values from dataSourceConfig.
`ebean.autostart`
Should the server start all
+1
View File
@@ -120,3 +120,4 @@ To set this option as the global default for IntelliJ use:
`Run - Edit Configurations -> Edit configuration templates -> JUnit -> modify options - Do not use module-path option`
end
+13 -6
View File
@@ -2,9 +2,10 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>composites</artifactId>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
<relativePath>../..</relativePath>
</parent>
<name>ebean-clickhouse</name>
@@ -16,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
@@ -31,17 +32,23 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-clickhouse</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
</dependencies>
+13 -6
View File
@@ -2,9 +2,10 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>composites</artifactId>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
<relativePath>../..</relativePath>
</parent>
<name>ebean-cockroach</name>
@@ -16,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
@@ -31,17 +32,23 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
</dependencies>
+13 -6
View File
@@ -2,9 +2,10 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>composites</artifactId>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
<relativePath>../..</relativePath>
</parent>
<name>ebean-db2</name>
@@ -16,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
@@ -31,17 +32,23 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-db2</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
</dependencies>
+13 -6
View File
@@ -2,9 +2,10 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>composites</artifactId>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
<relativePath>../..</relativePath>
</parent>
<name>ebean-h2</name>
@@ -16,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
@@ -31,17 +32,23 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
</dependencies>
+13 -6
View File
@@ -2,9 +2,10 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>composites</artifactId>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
<relativePath>../..</relativePath>
</parent>
<name>ebean-hana</name>
@@ -16,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
@@ -31,17 +32,23 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-hana</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
</dependencies>
+13 -6
View File
@@ -2,9 +2,10 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>composites</artifactId>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
<relativePath>../..</relativePath>
</parent>
<name>ebean-mariadb</name>
@@ -16,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
@@ -31,17 +32,23 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mariadb</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
</dependencies>
+13 -6
View File
@@ -2,9 +2,10 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>composites</artifactId>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
<relativePath>../..</relativePath>
</parent>
<name>ebean-mysql</name>
@@ -16,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
@@ -31,17 +32,23 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mysql</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
</dependencies>
+13 -6
View File
@@ -2,9 +2,10 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>composites</artifactId>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
<relativePath>../..</relativePath>
</parent>
<name>ebean-nuodb</name>
@@ -16,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
@@ -31,17 +32,23 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-nuodb</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
</dependencies>
+13 -6
View File
@@ -2,9 +2,10 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>composites</artifactId>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
<relativePath>../..</relativePath>
</parent>
<name>ebean-oracle</name>
@@ -16,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
@@ -31,17 +32,23 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-oracle</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
</dependencies>
+85
View File
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.23.1-jakarta</version>
<relativePath>../..</relativePath>
</parent>
<name>ebean-postgis</name>
<description>ebean-postgis composite</description>
<artifactId>ebean-postgis</artifactId>
<properties>
<postgis.jdbc.version>2.5.1</postgis.jdbc.version>
<postgres.jdbc.version>42.6.0</postgres.jdbc.version>
</properties>
<dependencies>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-datasource</artifactId>
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgis-types</artifactId>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>${postgres.jdbc.version}</version>
<exclusions>
<!-- exclude unnecessary checker framework -->
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>net.postgis</groupId>
<artifactId>postgis-jdbc</artifactId>
<version>${postgis.jdbc.version}</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,7 @@
package io.ebean.postgis.assembly;
/**
* Nothing interesting here - required placeholder for javadoc.
*/
public class Assembly {
}
@@ -0,0 +1,10 @@
module io.ebean.postgis {
requires transitive io.ebean.api;
requires transitive io.ebean.core;
requires transitive io.ebean.datasource;
requires transitive io.ebean.querybean;
requires transitive io.ebean.platform.postgres;
// requires transitive io.ebean.postgis.types;
}
+13 -6
View File
@@ -2,9 +2,10 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>composites</artifactId>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
<relativePath>../..</relativePath>
</parent>
<name>ebean-postgres</name>
@@ -16,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
@@ -31,17 +32,23 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
</dependencies>
+13 -6
View File
@@ -2,9 +2,10 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>composites</artifactId>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
<relativePath>../..</relativePath>
</parent>
<name>ebean-sqlite</name>
@@ -16,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
@@ -31,17 +32,23 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlite</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
</dependencies>
+13 -6
View File
@@ -2,9 +2,10 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>composites</artifactId>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
<relativePath>../..</relativePath>
</parent>
<name>ebean-sqlserver</name>
@@ -16,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
@@ -31,17 +32,23 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlserver</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
</dependencies>
+13 -6
View File
@@ -2,9 +2,10 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>composites</artifactId>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
<relativePath>../..</relativePath>
</parent>
<name>ebean-yugabyte</name>
@@ -16,13 +17,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
@@ -31,17 +32,23 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
</dependencies>
+16 -9
View File
@@ -2,9 +2,10 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>composites</artifactId>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
<relativePath>../..</relativePath>
</parent>
<name>ebean (all platforms)</name>
@@ -16,31 +17,31 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-joda-time</artifactId>
<version>13.17.0</version>
<version>13.18.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jackson-jsonnode</artifactId>
<version>13.17.0</version>
<version>13.18.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jackson-mapper</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
@@ -49,17 +50,23 @@
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<!-- Technically optional but most expected to use query beans -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-all</artifactId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</dependency>
</dependencies>
+2 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</parent>
<artifactId>composites</artifactId>
@@ -23,6 +23,7 @@
<module>ebean-nuodb</module>
<module>ebean-oracle</module>
<module>ebean-postgres</module>
<module>ebean-postgis</module>
<!-- <module>sqlanywhere</module>-->
<module>ebean-sqlite</module>
<module>ebean-sqlserver</module>
+12 -12
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.17.0</version>
<version>13.23.1-jakarta</version>
</parent>
<name>ebean api</name>
@@ -26,12 +26,6 @@
<version>1.0</version>
</dependency>
<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-config</artifactId>
<version>2.4</version>
</dependency>
<!--
Class retention Nonnull and Nullable annotations
to assist with IDE auto-completion with Ebean API
@@ -42,9 +36,15 @@
<version>1.1</version>
</dependency>
<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-config</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>persistence-api</artifactId>
<artifactId>jakarta-persistence-api</artifactId>
<version>${ebean-persistence-api.version}</version>
</dependency>
@@ -90,22 +90,22 @@
<optional>true</optional>
</dependency>
<!-- JAVAX-DEPENDENCY-START -->
<!-- JAVAX-DEPENDENCY-START ___
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<optional>true</optional>
</dependency>
<!-- JAVAX-DEPENDENCY-END -->
<!-- JAKARTA-DEPENDENCY-START ___
____ JAVAX-DEPENDENCY-END -->
<!-- JAKARTA-DEPENDENCY-START -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<optional>true</optional>
</dependency>
____ JAKARTA-DEPENDENCY-END -->
<!-- JAKARTA-DEPENDENCY-END -->
<dependency>
<groupId>io.avaje</groupId>
@@ -1,6 +1,6 @@
package io.ebean;
import javax.persistence.PessimisticLockException;
import jakarta.persistence.PessimisticLockException;
/**
* Thrown when failing to acquire a pessimistic lock.
@@ -33,11 +33,6 @@ import java.util.Optional;
@NonNullApi
public abstract class BeanFinder<I,T> {
/**
* Migrate to using database rather than server.
*/
@Deprecated
protected final Database server;
protected final Database database;
protected final Class<T> type;
@@ -50,7 +45,6 @@ public abstract class BeanFinder<I,T> {
protected BeanFinder(Class<T> type, Database database) {
this.type = type;
this.database = database;
this.server = database;
}
/**
+8 -2
View File
@@ -7,8 +7,8 @@ import io.ebean.cache.ServerCacheManager;
import io.ebean.plugin.Property;
import io.ebean.text.json.JsonContext;
import javax.persistence.OptimisticLockException;
import javax.persistence.PersistenceException;
import jakarta.persistence.OptimisticLockException;
import jakarta.persistence.PersistenceException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -267,15 +267,21 @@ public final class DB {
}
/**
* Deprecated for removal migrate using try-with-resources and commit on the transaction itself.
* <p>
* Commit the current transaction.
*/
@Deprecated(forRemoval = true)
public static void commitTransaction() {
getDefault().commitTransaction();
}
/**
* Deprecated for removal migrate to using try-with-resources and rollback on the transaction itself.
* <p>
* Rollback the current transaction.
*/
@Deprecated(forRemoval = true)
public static void rollbackTransaction() {
getDefault().rollbackTransaction();
}
@@ -0,0 +1,49 @@
package io.ebean;
import io.ebean.service.SpiInTuples;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Default implementation of SpiInTuples.
*/
final class DInTuples implements SpiInTuples {
private final String[] properties;
private final int propertyCount;
private final List<Object[]> entries = new ArrayList<>();
DInTuples(String[] properties) {
this.properties = properties;
this.propertyCount = properties.length;
}
@Override
public InTuples add(Object... values) {
if (values.length != propertyCount) {
throw new IllegalArgumentException("Require " + propertyCount + " values but got " + values.length);
}
entries.add(values);
return this;
}
/**
* Return the first property name.
*/
@Override
public String[] properties() {
return properties;
}
/**
* Return all the value pairs.
*/
@Override
public List<Object[]> entries() {
return Collections.unmodifiableList(entries);
}
}
@@ -1,6 +1,6 @@
package io.ebean;
import javax.persistence.PersistenceException;
import jakarta.persistence.PersistenceException;
/**
* Thrown when a foreign key constraint is enforced.
+10 -4
View File
@@ -11,8 +11,8 @@ import io.ebean.plugin.Property;
import io.ebean.plugin.SpiServer;
import io.ebean.text.json.JsonContext;
import javax.persistence.OptimisticLockException;
import javax.persistence.PersistenceException;
import jakarta.persistence.OptimisticLockException;
import jakarta.persistence.PersistenceException;
import javax.sql.DataSource;
import java.util.Collection;
import java.util.List;
@@ -35,7 +35,7 @@ import java.util.concurrent.Callable;
* <h5>The 'default' Database</h5>
* <p>
* One Database can be designated as the 'default' or 'primary' Database
* (see {@link DatabaseConfig#setDefaultServer(boolean)}. Many methods on DB
* (see {@link DatabaseConfig#setDefaultServer(boolean)}). Many methods on DB
* such as {@link DB#find(Class)} etc are actually just a convenient way to
* call methods on the 'default/primary' Database.
*
@@ -166,7 +166,7 @@ public interface Database {
/**
* Return the BeanState for a given entity bean.
* <p>
* This will return null if the bean is not an enhanced entity bean.
* This will throw an IllegalArgumentException if the bean is not an enhanced entity bean.
*/
BeanState beanState(Object bean);
@@ -650,13 +650,19 @@ public interface Database {
void flush();
/**
* Deprecated for removal migrate using try-with-resources and commit on the transaction itself.
* <p>
* Commit the current transaction.
*/
@Deprecated(forRemoval = true)
void commitTransaction();
/**
* Deprecated for removal migrate to using try-with-resources and rollback on the transaction itself.
* <p>
* Rollback the current transaction.
*/
@Deprecated(forRemoval = true)
void rollbackTransaction();
/**
@@ -5,7 +5,7 @@ import io.ebean.config.DatabaseConfig;
import io.ebean.service.SpiContainer;
import io.ebean.service.SpiContainerFactory;
import javax.persistence.PersistenceException;
import jakarta.persistence.PersistenceException;
import java.util.Iterator;
import java.util.Properties;
import java.util.ServiceLoader;
@@ -3,7 +3,7 @@ package io.ebean;
import io.ebean.config.BeanNotEnhancedException;
import io.ebean.datasource.DataSourceConfigurationException;
import javax.persistence.PersistenceException;
import jakarta.persistence.PersistenceException;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
@@ -38,12 +38,15 @@ final class DbContext {
}
}
} catch (BeanNotEnhancedException e) {
String msg = "Bean is not enhanced? See https://ebean.io/docs/trouble-shooting#not-enhanced";
log.log(ERROR, msg, e);
throw e;
} catch (DataSourceConfigurationException e) {
String msg = "Configuration error creating DataSource for the default Database." +
" This typically means a missing application-test.yaml or missing ebean-test dependency." +
" See https://ebean.io/docs/trouble-shooting#datasource";
log.log(ERROR, msg, e);
throw new DataSourceConfigurationException(msg, e);
} catch (Throwable e) {
@@ -205,4 +205,16 @@ public interface DtoQuery<T> extends CancelableQuery {
* Use the explicit transaction to execute the query.
*/
DtoQuery<T> usingTransaction(Transaction transaction);
/**
* Ensure that the master DataSource is used if there is a read only data source
* being used (that is using a read replica database potentially with replication lag).
* <p>
* When the database is configured with a read-only DataSource via
* say {@link io.ebean.config.DatabaseConfig#setReadOnlyDataSource(DataSource)} then
* by default when a query is run without an active transaction, it uses the read-only data
* source. We we use {@code usingMaster()} to instead ensure that the query is executed
* against the master data source.
*/
DtoQuery<T> usingMaster();
}
+39 -39
View File
@@ -41,14 +41,14 @@ public final class Expr {
* Equal To - property equal to the given value.
*/
public static Expression eq(String propertyName, Object value) {
return DB.expressionFactory().eq(propertyName, value);
return factory().eq(propertyName, value);
}
/**
* Not Equal To - property not equal to the given value.
*/
public static Expression ne(String propertyName, Object value) {
return DB.expressionFactory().ne(propertyName, value);
return factory().ne(propertyName, value);
}
/**
@@ -56,7 +56,7 @@ public final class Expr {
* using a lower() function to make it case insensitive).
*/
public static Expression ieq(String propertyName, String value) {
return DB.expressionFactory().ieq(propertyName, value);
return factory().ieq(propertyName, value);
}
/**
@@ -66,28 +66,28 @@ public final class Expr {
* </p>
*/
public static Expression inRange(String propertyName, Object value1, Object value2) {
return DB.expressionFactory().inRange(propertyName, value1, value2);
return factory().inRange(propertyName, value1, value2);
}
/**
* Between - property between the two given values.
*/
public static Expression between(String propertyName, Object value1, Object value2) {
return DB.expressionFactory().between(propertyName, value1, value2);
return factory().between(propertyName, value1, value2);
}
/**
* Between - value between two given properties.
*/
public static Expression between(String lowProperty, String highProperty, Object value) {
return DB.expressionFactory().betweenProperties(lowProperty, highProperty, value);
return factory().betweenProperties(lowProperty, highProperty, value);
}
/**
* Greater Than - property greater than the given value.
*/
public static Expression gt(String propertyName, Object value) {
return DB.expressionFactory().gt(propertyName, value);
return factory().gt(propertyName, value);
}
/**
@@ -95,42 +95,42 @@ public final class Expr {
* value.
*/
public static Expression ge(String propertyName, Object value) {
return DB.expressionFactory().ge(propertyName, value);
return factory().ge(propertyName, value);
}
/**
* Less Than - property less than the given value.
*/
public static Expression lt(String propertyName, Object value) {
return DB.expressionFactory().lt(propertyName, value);
return factory().lt(propertyName, value);
}
/**
* Less Than or Equal to - property less than or equal to the given value.
*/
public static Expression le(String propertyName, Object value) {
return DB.expressionFactory().le(propertyName, value);
return factory().le(propertyName, value);
}
/**
* Is Null - property is null.
*/
public static Expression isNull(String propertyName) {
return DB.expressionFactory().isNull(propertyName);
return factory().isNull(propertyName);
}
/**
* Is Not Null - property is not null.
*/
public static Expression isNotNull(String propertyName) {
return DB.expressionFactory().isNotNull(propertyName);
return factory().isNotNull(propertyName);
}
/**
* Case insensitive {@link #exampleLike(Object)}
*/
public static ExampleExpression iexampleLike(Object example) {
return DB.expressionFactory().iexampleLike(example);
return factory().iexampleLike(example);
}
/**
@@ -138,14 +138,14 @@ public final class Expr {
* LikeType.RAW (you need to add you own wildcards % and _).
*/
public static ExampleExpression exampleLike(Object example) {
return DB.expressionFactory().exampleLike(example);
return factory().exampleLike(example);
}
/**
* Create the query by Example expression specifying more options.
*/
public static ExampleExpression exampleLike(Object example, boolean caseInsensitive, LikeType likeType) {
return DB.expressionFactory().exampleLike(example, caseInsensitive, likeType);
return factory().exampleLike(example, caseInsensitive, likeType);
}
/**
@@ -153,7 +153,7 @@ public final class Expr {
* characters % (percentage) and _ (underscore).
*/
public static Expression like(String propertyName, String value) {
return DB.expressionFactory().like(propertyName, value);
return factory().like(propertyName, value);
}
/**
@@ -162,14 +162,14 @@ public final class Expr {
* a lower() function to make the expression case insensitive.
*/
public static Expression ilike(String propertyName, String value) {
return DB.expressionFactory().ilike(propertyName, value);
return factory().ilike(propertyName, value);
}
/**
* Starts With - property like value%.
*/
public static Expression startsWith(String propertyName, String value) {
return DB.expressionFactory().startsWith(propertyName, value);
return factory().startsWith(propertyName, value);
}
/**
@@ -177,14 +177,14 @@ public final class Expr {
* lower() function to make the expression case insensitive.
*/
public static Expression istartsWith(String propertyName, String value) {
return DB.expressionFactory().istartsWith(propertyName, value);
return factory().istartsWith(propertyName, value);
}
/**
* Ends With - property like %value.
*/
public static Expression endsWith(String propertyName, String value) {
return DB.expressionFactory().endsWith(propertyName, value);
return factory().endsWith(propertyName, value);
}
/**
@@ -192,14 +192,14 @@ public final class Expr {
* function to make the expression case insensitive.
*/
public static Expression iendsWith(String propertyName, String value) {
return DB.expressionFactory().iendsWith(propertyName, value);
return factory().iendsWith(propertyName, value);
}
/**
* Contains - property like %value%.
*/
public static Expression contains(String propertyName, String value) {
return DB.expressionFactory().contains(propertyName, value);
return factory().contains(propertyName, value);
}
/**
@@ -207,42 +207,42 @@ public final class Expr {
* function to make the expression case insensitive.
*/
public static Expression icontains(String propertyName, String value) {
return DB.expressionFactory().icontains(propertyName, value);
return factory().icontains(propertyName, value);
}
/**
* For collection properties that are empty (have not existing elements).
*/
public static Expression isEmpty(String propertyName) {
return DB.expressionFactory().isEmpty(propertyName);
return factory().isEmpty(propertyName);
}
/**
* For collection properties that are not empty (have existing elements).
*/
public static Expression isNotEmpty(String propertyName) {
return DB.expressionFactory().isNotEmpty(propertyName);
return factory().isNotEmpty(propertyName);
}
/**
* In - property has a value in the array of values.
*/
public static Expression in(String propertyName, Object[] values) {
return DB.expressionFactory().in(propertyName, values);
return factory().in(propertyName, values);
}
/**
* In - using a subQuery.
*/
public static Expression in(String propertyName, Query<?> subQuery) {
return DB.expressionFactory().in(propertyName, subQuery);
return factory().in(propertyName, subQuery);
}
/**
* In - property has a value in the collection of values.
*/
public static Expression in(String propertyName, Collection<?> values) {
return DB.expressionFactory().in(propertyName, values);
return factory().in(propertyName, values);
}
/**
@@ -279,14 +279,14 @@ public final class Expr {
* }</pre>
*/
public static Expression inOrEmpty(String propertyName, Collection<?> values) {
return DB.expressionFactory().inOrEmpty(propertyName, values);
return factory().inOrEmpty(propertyName, values);
}
/**
* Id Equal to - ID property is equal to the value.
*/
public static Expression idEq(Object value) {
return DB.expressionFactory().idEq(value);
return factory().idEq(value);
}
/**
@@ -299,7 +299,7 @@ public final class Expr {
* @param propertyMap a map keyed by property names.
*/
public static Expression allEq(Map<String, Object> propertyMap) {
return DB.expressionFactory().allEq(propertyMap);
return factory().allEq(propertyMap);
}
/**
@@ -310,7 +310,7 @@ public final class Expr {
* </p>
*/
public static Expression raw(String raw, Object value) {
return DB.expressionFactory().raw(raw, value);
return factory().raw(raw, value);
}
/**
@@ -321,48 +321,48 @@ public final class Expr {
* </p>
*/
public static Expression raw(String raw, Object[] values) {
return DB.expressionFactory().raw(raw, values);
return factory().raw(raw, values);
}
/**
* Add raw expression with no parameters.
*/
public static Expression raw(String raw) {
return DB.expressionFactory().raw(raw);
return factory().raw(raw);
}
/**
* And - join two expressions with a logical and.
*/
public static Expression and(Expression expOne, Expression expTwo) {
return DB.expressionFactory().and(expOne, expTwo);
return factory().and(expOne, expTwo);
}
/**
* Or - join two expressions with a logical or.
*/
public static Expression or(Expression expOne, Expression expTwo) {
return DB.expressionFactory().or(expOne, expTwo);
return factory().or(expOne, expTwo);
}
/**
* Negate the expression (prefix it with NOT).
*/
public static Expression not(Expression exp) {
return DB.expressionFactory().not(exp);
return factory().not(exp);
}
/**
* Return a list of expressions that will be joined by AND's.
*/
public static <T> Junction<T> conjunction(Query<T> query) {
return DB.expressionFactory().conjunction(query);
return factory().conjunction(query);
}
/**
* Return a list of expressions that will be joined by OR's.
*/
public static <T> Junction<T> disjunction(Query<T> query) {
return DB.expressionFactory().disjunction(query);
return factory().disjunction(query);
}
}
@@ -36,6 +36,11 @@ import java.util.Map;
*/
public interface ExpressionFactory {
/**
* Return a new ExpressionList.
*/
<T> ExpressionList<T> expressionList();
/**
* Path exists - for the given path in a JSON document.
*/
@@ -369,6 +374,11 @@ public interface ExpressionFactory {
*/
Expression inPairs(Pairs pairs);
/**
* In expression using multiple columns.
*/
Expression inTuples(InTuples pairs);
/**
* In - property has a value in the array of values.
*/
@@ -4,7 +4,7 @@ import io.avaje.lang.NonNullApi;
import io.avaje.lang.Nullable;
import io.ebean.search.*;
import javax.persistence.NonUniqueResultException;
import jakarta.persistence.NonUniqueResultException;
import java.sql.Connection;
import java.sql.Timestamp;
import java.util.*;
@@ -54,14 +54,12 @@ public interface ExpressionList<T> {
Query<T> orderById(boolean orderById);
/**
* Set the order by clause replacing the existing order by clause if there is
* one.
* <p>
* This follows SQL syntax using commas between each property with the
* optional asc and desc keywords representing ascending and descending order
* respectively.
* Deprecated migrate to {@link #orderBy(String)}
*/
ExpressionList<T> order(String orderByClause);
@Deprecated(since = "13.19", forRemoval = true)
default ExpressionList<T> order(String orderByClause) {
return orderBy(orderByClause);
}
/**
* Set the order by clause replacing the existing order by clause if there is
@@ -74,15 +72,12 @@ public interface ExpressionList<T> {
ExpressionList<T> orderBy(String orderBy);
/**
* Return the OrderBy so that you can append an ascending or descending
* property to the order by clause.
* <p>
* This will never return a null. If no order by clause exists then an 'empty'
* OrderBy object is returned.
* <p>
* This is the same as <code>orderBy()</code>
* Deprecated migrate to orderBy().
*/
OrderBy<T> order();
@Deprecated(forRemoval = true)
default OrderBy<T> order() {
return orderBy();
}
/**
* Return the OrderBy so that you can append an ascending or descending
@@ -95,12 +90,6 @@ public interface ExpressionList<T> {
*/
OrderBy<T> orderBy();
/**
* Deprecated migrate to {@link #orderBy(String)}
*/
@Deprecated
Query<T> setOrderBy(String orderBy);
/**
* Apply the path properties to the query replacing the select and fetch clauses.
*/
@@ -404,6 +393,7 @@ public interface ExpressionList<T> {
*
* }</pre>
*/
@Nullable
default <A> A findSingleAttribute() {
List<A> list = findSingleAttributeList();
return !list.isEmpty() ? list.get(0) : null;
@@ -518,6 +508,8 @@ public interface ExpressionList<T> {
ExpressionList<T> filterMany(String manyProperty);
/**
* Deprecated for removal - migrate to filterManyRaw()
* <p>
* Add filter expressions to the many property.
*
* <pre>{@code
@@ -534,8 +526,29 @@ public interface ExpressionList<T> {
* @param expressions Filter expressions with and, or and ? or ?1 type bind parameters
* @param params Bind parameters used in the expressions
*/
@Deprecated(forRemoval = true)
ExpressionList<T> filterMany(String manyProperty, String expressions, Object... params);
/**
* Add filter expressions for the many path. The expressions can include SQL functions if
* desired and the property names are translated to column names.
* <p>
* The expressions can contain placeholders for bind values using <code>?</code> or <code>?1</code> style.
*
* <pre>{@code
*
* new QCustomer()
* .name.startsWith("Postgres")
* .contacts.filterManyRaw("status = ? and firstName like ?", Contact.Status.NEW, "Rob%")
* .findList();
*
* }</pre>
*
* @param rawExpressions The raw expressions which can include ? and ?1 style bind parameter placeholders
* @param params The parameter values to bind
*/
ExpressionList<T> filterManyRaw(String manyProperty, String rawExpressions, Object... params);
/**
* Specify specific properties to fetch on the main/root bean (aka partial
* object).
@@ -1141,6 +1154,11 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> inPairs(Pairs pairs);
/**
* In expression using multiple columns.
*/
ExpressionList<T> inTuples(InTuples pairs);
/**
* EXISTS a raw SQL SubQuery.
*
@@ -1,26 +1,9 @@
package io.ebean;
import io.avaje.lang.Nullable;
import java.time.Clock;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
/**
* The extended API for Database.
* <p>
* Deprecated in favour of using {@link Query#usingTransaction(Transaction)} instead.
* <p>
* This provides the finder methods that take an explicit transaction rather than obtaining
* the transaction from the usual mechanism (which is ThreadLocal based).
* <p>
* Note that in all cases the transaction supplied can be null and in this case the Database
* will use the normal mechanism to obtain the transaction to use.
*/
public interface ExtendedServer {
@@ -35,162 +18,4 @@ public interface ExtendedServer {
@Deprecated
void setClock(Clock clock);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> boolean exists(Query<T> ormQuery, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> int findCount(Query<T> query, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<A, T> List<A> findIds(Query<T> query, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> QueryIterator<T> findIterate(Query<T> query, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> Stream<T> findStream(Query<T> query, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> void findEach(Query<T> query, Consumer<T> consumer, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> void findEach(Query<T> query, int batch, Consumer<List<T>> consumer, Transaction t);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> void findEachWhile(Query<T> query, Predicate<T> consumer, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> List<Version<T>> findVersions(Query<T> query, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> List<T> findList(Query<T> query, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> FutureRowCount<T> findFutureCount(Query<T> query, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> FutureIds<T> findFutureIds(Query<T> query, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> FutureList<T> findFutureList(Query<T> query, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> PagedList<T> findPagedList(Query<T> query, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> Set<T> findSet(Query<T> query, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<K, T> Map<K, T> findMap(Query<T> query, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<A, T> List<A> findSingleAttributeList(Query<T> query, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<A, T> Set<A> findSingleAttributeSet(Query<T> query, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
@Nullable
<T> T findOne(Query<T> query, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> Optional<T> findOneOrEmpty(Query<T> query, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> int delete(Query<T> query, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> int update(Query<T> query, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
List<SqlRow> findList(SqlQuery query, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
void findEach(SqlQuery query, Consumer<SqlRow> consumer, Transaction transaction);
/**
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
void findEachWhile(SqlQuery query, Predicate<SqlRow> consumer, Transaction transaction);
/**
* Deprecated migrate to using {@link SqlQuery#usingTransaction(Transaction)}.
*/
@Deprecated
@Nullable
SqlRow findOne(SqlQuery query, Transaction transaction);
}
@@ -1,6 +1,6 @@
package io.ebean;
import javax.persistence.PersistenceException;
import jakarta.persistence.PersistenceException;
import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
@@ -0,0 +1,36 @@
package io.ebean;
/**
* IN expression using multiple columns.
* <p>
* Currently this is not supported with SQLServer or DB2.
* <p>
* Produces SQL expression in the form of (A,B,C) IN ((a0,b0,c0), (a1,b1,c1), ... )
* where A,B,C are the properties in the tuples.
*/
public interface InTuples {
/**
* Create given the properties in the tuples.
*/
static InTuples of(String... properties) {
return new DInTuples(properties);
}
/**
* Create given the properties in the tuples.
*/
static InTuples of(Query.Property<?>... properties) {
String[] props = new String[properties.length];
for (int i = 0; i < properties.length; i++) {
props[i] = properties[i].toString();
}
return new DInTuples(props);
}
/**
* Add a tuple entry. All values must be non-null.
*/
InTuples add(Object... values);
}
@@ -0,0 +1,42 @@
package io.ebean;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Helper methods for Lists.
*/
public final class Lists {
private Lists() {
}
/**
* Partition the source List into sub-lists with a maximum size.
* <p>
* The sub-lists will all be the max size except for the last sub-list
* which can potentially be smaller.
*
* @param source The source list
* @param max The max size of each partition
* @param <T> The list element type
* @return List of sub-list partitions
*/
public static <T> List<List<T>> partition(List<T> source, int max) {
final int totalCount = source.size();
if (totalCount == 0) {
return Collections.emptyList();
} else if (totalCount <= max) {
return List.of(source);
}
final int numOfPartitions = (totalCount + max - 1) / max; // round up
final var dest = new ArrayList<List<T>>(numOfPartitions);
for (int i = 0; i < numOfPartitions; i++) {
final int from = i * max;
final int to = Math.min(from + max, totalCount);
dest.add(source.subList(from, to));
}
return dest;
}
}
@@ -333,10 +333,10 @@ public class OrderBy<T> implements Serializable {
sb.append(property);
}
if (!ascending) {
sb.append(" ").append("desc");
sb.append(' ').append("desc");
}
if (nulls != null) {
sb.append(" ").append(nulls).append(" ").append(highLow);
sb.append(' ').append(nulls).append(' ').append(highLow);
}
return sb.toString();
}
@@ -1,6 +1,6 @@
package io.ebean;
import javax.persistence.PersistenceException;
import jakarta.persistence.PersistenceException;
/**
* Captures and wraps IOException's occurring during ElasticSearch processing etc.
@@ -30,23 +30,6 @@ public interface ProfileLocation {
return XServiceProvider.profileLocationFactory().create(label);
}
/**
* Deprecated in favor of {@link #create(String)}.
*/
@Deprecated
static ProfileLocation create(int lineNumber, String label) {
return create(label);
}
/**
* Deprecated for removal - not used.
* Create and return a new ProfileLocation with a given location.
*/
@Deprecated
static ProfileLocation createAt(String location) {
return XServiceProvider.profileLocationFactory().createAt(location);
}
/**
* Obtain the description returning true if this is the initial call.
*/
+31 -23
View File
@@ -3,13 +3,15 @@ package io.ebean;
import io.avaje.lang.NonNullApi;
import io.avaje.lang.Nullable;
import javax.persistence.NonUniqueResultException;
import jakarta.persistence.NonUniqueResultException;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.Timestamp;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
@@ -670,6 +672,16 @@ public interface Query<T> extends CancelableQuery {
*/
Query<T> apply(FetchPath fetchPath);
/**
* Apply changes to the query conditional on the supplied predicate.
* <p>
* Typically, the changes are extra predicates etc.
*
* @param predicate The predicate which when true the changes are applied
* @param apply The changes to apply to the query
*/
Query<T> alsoIf(BooleanSupplier predicate, Consumer<Query<T>> apply);
/**
* Execute the query using the given transaction.
*/
@@ -685,6 +697,18 @@ public interface Query<T> extends CancelableQuery {
*/
Query<T> usingDatabase(Database database);
/**
* Ensure that the master DataSource is used if there is a read only data source
* being used (that is using a read replica database potentially with replication lag).
* <p>
* When the database is configured with a read-only DataSource via
* say {@link io.ebean.config.DatabaseConfig#setReadOnlyDataSource(DataSource)} then
* by default when a query is run without an active transaction, it uses the read-only data
* source. We we use {@code usingMaster()} to instead ensure that the query is executed
* against the master data source.
*/
Query<T> usingMaster();
/**
* Execute the query returning the list of Id's.
* <p>
@@ -1372,13 +1396,9 @@ public interface Query<T> extends CancelableQuery {
Query<T> orderBy(String orderByClause);
/**
* Set the order by clause replacing the existing order by clause if there is
* one.
* <p>
* This follows SQL syntax using commas between each property with the
* optional asc and desc keywords representing ascending and descending order
* respectively.
* Deprecated migrate to orderBy().
*/
@Deprecated(since = "13.19", forRemoval = true)
default Query<T> order(String orderByClause) {
return orderBy(orderByClause);
}
@@ -1395,14 +1415,9 @@ public interface Query<T> extends CancelableQuery {
OrderBy<T> orderBy();
/**
* Return the OrderBy so that you can append an ascending or descending
* property to the order by clause.
* <p>
* This will never return a null. If no order by clause exists then an 'empty'
* OrderBy object is returned.
* <p>
* This is the same as <code>orderBy()</code>
* Deprecated migrate to orderBy().
*/
@Deprecated(since = "13.19", forRemoval = true)
default OrderBy<T> order() {
return orderBy();
}
@@ -1413,8 +1428,9 @@ public interface Query<T> extends CancelableQuery {
Query<T> setOrderBy(OrderBy<T> orderBy);
/**
* Set an OrderBy object to replace any existing OrderBy clause.
* Deprecated migrate to setOrderBy().
*/
@Deprecated(since = "13.19", forRemoval = true)
default Query<T> setOrder(OrderBy<T> orderBy) {
return setOrderBy(orderBy);
}
@@ -1579,14 +1595,6 @@ public interface Query<T> extends CancelableQuery {
*/
Query<T> setReadOnly(boolean readOnly);
/**
* Deprecated - migrate to use setBeanCacheMode(CacheMode.PUT) or other CacheMode.
* <p>
* When set to true all the beans from this query are loaded into the bean cache.
*/
@Deprecated
Query<T> setLoadBeanCache(boolean loadBeanCache);
/**
* Set a timeout on this query.
* <p>
@@ -1,6 +1,6 @@
package io.ebean;
import javax.persistence.OptimisticLockException;
import jakarta.persistence.OptimisticLockException;
/**
* Thrown at SERIALIZABLE isolation level for non-recoverable concurrent conflict.
@@ -45,6 +45,18 @@ public interface SqlQuery extends Serializable, CancelableQuery {
*/
SqlQuery usingTransaction(Transaction transaction);
/**
* Ensure that the master DataSource is used if there is a read only data source
* being used (that is using a read replica database potentially with replication lag).
* <p>
* When the database is configured with a read-only DataSource via
* say {@link io.ebean.config.DatabaseConfig#setReadOnlyDataSource(DataSource)} then
* by default when a query is run without an active transaction, it uses the read-only data
* source. We we use {@code usingMaster()} to instead ensure that the query is executed
* against the master data source.
*/
SqlQuery usingMaster();
/**
* Execute the query returning a list.
*/
@@ -9,7 +9,6 @@ import java.util.Collection;
* <p>
* This is currently deemed to be experimental and subject to change.
*/
@Deprecated(since = "experimental")
public final class StdOperators {
// ---- Functions ---- //
@@ -77,9 +76,9 @@ public final class StdOperators {
StringBuilder expression = new StringBuilder(50);
expression.append("concat(").append(property.toString());
for (Object value : values) {
expression.append(",").append(sqlConcatString(value));
expression.append(',').append(sqlConcatString(value));
}
expression.append(")");
expression.append(')');
return Property.of(expression.toString());
}
@@ -5,7 +5,7 @@ import io.ebean.annotation.PersistBatch;
import io.ebean.config.DatabaseConfig;
import io.ebean.config.DocStoreConfig;
import javax.persistence.PersistenceException;
import jakarta.persistence.PersistenceException;
import java.sql.Connection;
/**
@@ -4,8 +4,8 @@ import io.ebean.DB;
import io.ebean.Database;
import io.ebean.ValuePair;
import javax.persistence.EntityNotFoundException;
import javax.persistence.PersistenceException;
import jakarta.persistence.EntityNotFoundException;
import jakarta.persistence.PersistenceException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@@ -47,7 +47,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
*/
private static final byte FLAG_MUTABLE_HASH_SET = 16;
private transient final ReentrantLock lock = new ReentrantLock();
private final ReentrantLock lock = new ReentrantLock();
private transient NodeUsageCollector nodeUsageCollector;
private transient PersistenceContext persistenceContext;
private transient BeanLoader beanLoader;
@@ -115,7 +115,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
@Override
public String toString() {
return "InterceptReadWrite{state=" + state +
return "InterceptReadWrite@" + hashCode() + "{state=" + state +
(dirty ? " dirty;" : "") +
(forceUpdate ? " forceUpdate;" : "") +
(readOnly ? " readOnly;" : "") +
@@ -128,7 +128,6 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
(lazyLoadProperty > -1 ? (", lazyLoadProperty=" + lazyLoadProperty) : "") +
", loader=" + beanLoader +
(ownerId != null ? (", ownerId=" + ownerId) : "") +
", owner=" + owner +
'}';
}
@@ -45,7 +45,7 @@ public final class ToStringBuilder {
id.putIfAbsent(bean, 0);
}
if (counter <= MAX) {
sb.append(bean.getClass().getSimpleName()).append("@").append(counter).append("(");
sb.append(bean.getClass().getSimpleName()).append('@').append(counter).append('(');
}
}
@@ -77,7 +77,7 @@ public final class ToStringBuilder {
*/
public void end() {
if (counter <= MAX) {
sb.append(")");
sb.append(')');
}
}
@@ -90,7 +90,7 @@ public final class ToStringBuilder {
} else {
sb.append(", ");
}
sb.append(name).append(":");
sb.append(name).append(':');
}
private void value(Object value) {
@@ -110,7 +110,7 @@ public final class ToStringBuilder {
} else {
String content = String.valueOf(value);
if (content.length() > TRIM_LENGTH) {
content = content.substring(0, TRIM_LENGTH) + " <trimmed>";
content = content.substring(0, TRIM_LENGTH) + " (trimmed)";
}
sb.append(content);
if (sb.length() >= MAX_TOTAL_CONTENT) {
@@ -125,20 +125,20 @@ public final class ToStringBuilder {
sb.append("{}");
} else {
boolean firstElement = true;
sb.append("{");
sb.append('{');
for (Map.Entry<?, ?> entry : map.entrySet()) {
if (firstElement) {
firstElement = false;
} else {
sb.append(", ");
}
sb.append(entry.getKey()).append(":");
sb.append(entry.getKey()).append(':');
value(entry.getValue());
if (counter > MAX) {
return;
}
}
sb.append("}");
sb.append('}');
}
}
@@ -151,7 +151,7 @@ public final class ToStringBuilder {
return;
}
boolean firstElement = true;
sb.append("[");
sb.append('[');
for (Object o : c) {
if (firstElement) {
firstElement = false;
@@ -163,7 +163,7 @@ public final class ToStringBuilder {
return;
}
}
sb.append("]");
sb.append(']');
}
private boolean push(Object bean) {
@@ -178,7 +178,7 @@ public final class ToStringBuilder {
Integer idx = id.putIfAbsent(bean, counter++);
if (idx != null) {
--counter;
sb.append(bean.getClass().getSimpleName()).append("@").append(idx);
sb.append(bean.getClass().getSimpleName()).append('@').append(idx);
return false;
}
first = true;
+1 -1
View File
@@ -69,7 +69,7 @@ public class TenantAwareKey {
public String toString() {
StringBuilder sb = new StringBuilder(key.toString());
if (tenantId != null) {
sb.append(":").append(tenantId);
sb.append(':').append(tenantId);
}
return sb.toString();
}
@@ -119,7 +119,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
try {
if (set == null) {
if (!disableLazyLoad && modifyListening) {
lazyLoadCollection(true);
lazyLoadCollection(false);
} else {
set = new LinkedHashSet<>();
}
@@ -136,7 +136,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
if (disableLazyLoad) {
set = new LinkedHashSet<>();
} else {
lazyLoadCollection(true);
lazyLoadCollection(false);
}
}
} finally {
@@ -3,9 +3,9 @@ package io.ebean.config;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.util.AnnotationUtil;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Inheritance;
import javax.persistence.Table;
import jakarta.persistence.DiscriminatorValue;
import jakarta.persistence.Inheritance;
import jakarta.persistence.Table;
import static io.ebean.util.StringHelper.isNull;
@@ -228,7 +228,7 @@ public abstract class AbstractNamingConvention implements NamingConvention {
public TableName getM2MJoinTableName(TableName lhsTable, TableName rhsTable) {
StringBuilder buffer = new StringBuilder();
buffer.append(unQuote(lhsTable.getName()));
buffer.append("_");
buffer.append('_');
String rhsTableName = unQuote(rhsTable.getName());
if (rhsTableName.indexOf('_') < rhsPrefixLength) {
@@ -271,10 +271,10 @@ public abstract class AbstractNamingConvention implements NamingConvention {
public String getTableName(String catalog, String schema, String name) {
StringBuilder sb = new StringBuilder();
if (!isNull(catalog)) {
sb.append(quoteIdentifiers(catalog)).append(".");
sb.append(quoteIdentifiers(catalog)).append('.');
}
if (!isNull(schema)) {
sb.append(quoteIdentifiers(schema)).append(".");
sb.append(quoteIdentifiers(schema)).append('.');
}
return sb.append(quoteIdentifiers(name)).toString();
}
@@ -19,7 +19,7 @@ import io.ebean.event.readaudit.ReadAuditPrepare;
import io.ebean.meta.MetricNamingMatch;
import io.ebean.util.StringHelper;
import javax.persistence.EnumType;
import jakarta.persistence.EnumType;
import javax.sql.DataSource;
import java.time.Clock;
import java.time.ZonedDateTime;
@@ -526,11 +526,6 @@ public class DatabaseConfig {
private ProfilingConfig profilingConfig = new ProfilingConfig();
/**
* Controls the default order by id setting of queries. See {@link Query#orderById(boolean)}
*/
private boolean defaultOrderById;
/**
* The mappingLocations for searching xml mapping.
*/
@@ -595,22 +590,6 @@ public class DatabaseConfig {
this.slowQueryListener = slowQueryListener;
}
/**
* Deprecated - look to have explicit order by. Sets the default orderById setting for queries.
*/
@Deprecated
public void setDefaultOrderById(boolean defaultOrderById) {
this.defaultOrderById = defaultOrderById;
}
/**
* Returns the default orderById setting for queries.
*/
public boolean isDefaultOrderById() {
return defaultOrderById;
}
/**
* Put a service object into configuration such that it can be used by ebean or a plugin.
* <p>
@@ -2327,8 +2306,6 @@ public class DatabaseConfig {
* <p>
* If no classes are specified then the classes are found automatically via
* searching the class path.
* <p>
* Alternatively the classes can be added via {@link #setClasses(List)}.
*
* @param cls the entity type (or other type) that should be registered by this database.
*/
@@ -2399,7 +2376,7 @@ public class DatabaseConfig {
* Sorry if returning Set rather than List breaks code but it feels safer to
* do that than a subtle change to return a shallow copy which you will not detect.
*/
@Deprecated
@Deprecated(forRemoval = true)
public Set<Class<?>> getClasses() {
return classes;
}
@@ -2942,7 +2919,6 @@ public class DatabaseConfig {
jdbcFetchSizeFindEach = p.getInt("jdbcFetchSizeFindEach", jdbcFetchSizeFindEach);
jdbcFetchSizeFindList = p.getInt("jdbcFetchSizeFindList", jdbcFetchSizeFindList);
databasePlatformName = p.get("databasePlatformName", databasePlatformName);
defaultOrderById = p.getBoolean("defaultOrderById", defaultOrderById);
uuidVersion = p.getEnum(UuidVersion.class, "uuidVersion", uuidVersion);
uuidStateFile = p.get("uuidStateFile", uuidStateFile);
@@ -3413,7 +3389,7 @@ public class DatabaseConfig {
/**
* Deprecated - migrate to isLoadModuleInfo().
*/
@Deprecated
@Deprecated(forRemoval = true)
public boolean isAutoLoadModuleInfo() {
return loadModuleInfo;
}
@@ -135,16 +135,16 @@ public class DbConstraintNaming {
*/
protected String joinColumnNames(String[] columns) {
if (columns.length == 1) {
return normaliseColumn(columns[0]);
return normaliseColumn(columns[0]).replace(" ", "_");
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < columns.length; i++) {
if (i > 0) {
sb.append("_");
sb.append('_');
}
sb.append(normaliseColumn(columns[i]));
}
return sb.toString();
return sb.toString().replace(" ", "_");
}
/**
@@ -27,7 +27,6 @@ public class DbConstraintNormalise {
* quoted identifier characters (",',[,] etc).
*/
public String normaliseTable(String tableName) {
tableName = trimQuotes(tableName);
int lastPeriod = tableName.lastIndexOf('.');
if (lastPeriod > -1) {
@@ -59,7 +58,6 @@ public class DbConstraintNormalise {
* Trim off the platform quoted identifier quotes like [ ' and ".
*/
public String trimQuotes(String identifier) {
if (identifier == null) {
return "";
}
@@ -1,7 +1,7 @@
package io.ebean.config;
/**
* Matches the functionality of javax.persistence.AttributeConverter
* Matches the functionality of jakarta.persistence.AttributeConverter
* <p>
* In general AttributeConverter should be used in preference to this
* ScalarTypeConverter as it is JPA standard and offers the same functionality.
@@ -117,12 +117,12 @@ public final class TableName {
// Add schema
if (schema != null) {
if (buffer.length() > 0) {
buffer.append(".");
buffer.append('.');
}
buffer.append(schema);
}
if (buffer.length() > 0) {
buffer.append(".");
buffer.append('.');
}
return buffer.append(name).toString();
}
@@ -23,11 +23,11 @@ public class BasicSqlLimitOffset implements BasicSqlLimiter {
sb.append(dbSql);
if (maxRows > 0) {
sb.append(" ").append(LIMIT);
sb.append(" ").append(maxRows);
sb.append(' ').append(LIMIT);
sb.append(' ').append(maxRows);
}
if (firstRow > 0) {
sb.append(" ").append(OFFSET).append(" ");
sb.append(' ').append(OFFSET).append(' ');
sb.append(firstRow);
}
return sb.toString();
@@ -9,7 +9,7 @@ import io.ebean.config.CustomDbTypeMapping;
import io.ebean.config.PlatformConfig;
import io.ebean.util.JdbcClose;
import javax.persistence.PersistenceException;
import jakarta.persistence.PersistenceException;
import javax.sql.DataSource;
import java.sql.*;
@@ -673,7 +673,7 @@ public class DatabasePlatform {
protected String withForUpdate(String sql, Query.LockWait lockWait, Query.LockType lockType) {
// silently assume the database does not support the "for update" clause.
log.log(INFO, "it seems your database does not support the 'for update' clause");
log.log(INFO, "it seems your database does not support the ''for update'' clause");
return sql;
}
@@ -28,6 +28,16 @@ public class DbPlatformType implements ExtraDbTypes {
*/
private final boolean canHaveLength;
/**
* The maximum length supported by this platform type. If length is too big, fallback is used.
*/
private final int maxLength;
/**
* Use this platform type if length exceedes
*/
private final DbPlatformType fallback;
/**
* Parse a type definition into a DbPlatformType.
* <p>
@@ -53,6 +63,41 @@ public class DbPlatformType implements ExtraDbTypes {
this(name, defaultLength, 0);
}
/**
* Construct without length, but with a max length limit and a fallback type, that is used if maxLength is exceeded.
* This can be used to use <ul>
* <li>"longtext" for unspecified length</li>
* <li>"text" for length up to 2^16-1</li>
* <li>"mediumtext" for length up to 2^24-1</li>
* <li>"longtext" else</li>
* </ul>
*/
public DbPlatformType(String name, int maxLength, DbPlatformType fallback) {
this.name = name;
this.defaultLength = 0;
this.defaultScale = 0;
this.canHaveLength = false;
this.maxLength = maxLength;
this.fallback = fallback;
}
/**
* Construct with a given default length, a max length limit and a fallback type, that is used if maxLength is exceeded.
* This can be used to use <ul>
* <li>"varchar(255)" for unspecified length</li>
* <li>"varchar(N)" for N <= maxLength</li>
* <li>"varchar(max)" else</li>
* </ul>
*/
public DbPlatformType(String name, int defaultPrecision, int maxLength, DbPlatformType fallback) {
this.name = name;
this.defaultLength = defaultPrecision;
this.defaultScale = 0;
this.canHaveLength = true;
this.maxLength = maxLength;
this.fallback = fallback;
}
/**
* Construct for Decimal with precision and scale.
*/
@@ -61,6 +106,8 @@ public class DbPlatformType implements ExtraDbTypes {
this.defaultLength = defaultPrecision;
this.defaultScale = defaultScale;
this.canHaveLength = true;
this.maxLength = Integer.MAX_VALUE;
this.fallback = null;
}
/**
@@ -74,6 +121,8 @@ public class DbPlatformType implements ExtraDbTypes {
this.defaultLength = 0;
this.defaultScale = 0;
this.canHaveLength = canHaveLength;
this.maxLength = Integer.MAX_VALUE;
this.fallback = null;
}
/**
@@ -124,33 +173,33 @@ public class DbPlatformType implements ExtraDbTypes {
*/
public String renderType(int deployLength, int deployScale, boolean strict) {
StringBuilder sb = new StringBuilder();
sb.append(name);
if (canHaveLength || !strict) {
renderLengthScale(deployLength, deployScale, sb);
}
int len = deployLength != 0 ? deployLength : defaultLength;
if (len > maxLength) {
return fallback.renderType(deployLength, deployScale, strict);
} else {
StringBuilder sb = new StringBuilder();
sb.append(name);
if ((canHaveLength || !strict) && len > 0) {
renderLengthScale(len, deployScale, sb);
}
return sb.toString();
return sb.toString();
}
}
/**
* Render the length and scale part of the column definition.
*/
protected void renderLengthScale(int deployLength, int deployScale, StringBuilder sb) {
protected void renderLengthScale(int len, int deployScale, StringBuilder sb) {
// see if there is a precision/scale to add (or not)
int len = deployLength != 0 ? deployLength : defaultLength;
if (len == Integer.MAX_VALUE) {
sb.append("(max)"); // TODO: this is sqlserver specific
} else if (len > 0) {
sb.append("(");
sb.append(len);
int scale = deployScale != 0 ? deployScale : defaultScale;
if (scale > 0) {
sb.append(",");
sb.append(scale);
}
sb.append(")");
sb.append('(');
sb.append(len);
int scale = deployScale != 0 ? deployScale : defaultScale;
if (scale > 0) {
sb.append(',');
sb.append(scale);
}
sb.append(')');
}
/**
@@ -5,7 +5,7 @@ import io.ebean.BackgroundExecutor;
import io.ebean.Transaction;
import io.ebean.util.JdbcClose;
import javax.persistence.PersistenceException;
import jakarta.persistence.PersistenceException;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -3,7 +3,7 @@ package io.ebean.config.dbplatform;
import io.ebean.Transaction;
import io.ebean.util.JdbcClose;
import javax.persistence.PersistenceException;
import jakarta.persistence.PersistenceException;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -5,7 +5,7 @@ import io.ebean.DataIntegrityException;
import io.ebean.DuplicateKeyException;
import io.ebean.SerializableConflictException;
import javax.persistence.PersistenceException;
import jakarta.persistence.PersistenceException;
import java.sql.SQLException;
import java.util.Collections;
import java.util.Map;
@@ -1,6 +1,6 @@
package io.ebean.config.dbplatform;
import javax.persistence.PersistenceException;
import jakarta.persistence.PersistenceException;
import java.sql.SQLException;
/**
@@ -1,8 +1,11 @@
package io.ebean.event;
import javax.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextEvent;
/**
* Deprecated for removal - no intention to replace. Create your own copy of this
* ServletContextListener if needed for your application.
* <p>
* Listens for webserver server starting and stopping events.
* <p>
* This should be used when the deployment is into a servlet container where the webapp
@@ -15,7 +18,8 @@ import javax.servlet.ServletContextEvent;
* hook that Ebean registers.
* </p>
*/
public class ServletContextListener implements javax.servlet.ServletContextListener {
@Deprecated(forRemoval = true)
public class ServletContextListener implements jakarta.servlet.ServletContextListener {
/**
* The servlet container is stopping.
@@ -16,22 +16,6 @@ public interface MetaInfoManager {
*/
ServerMetrics collectMetrics();
/**
* Deprecated migrate to collectMetrics().asJson().
*/
@Deprecated
default ServerMetricsAsJson collectMetricsAsJson() {
return collectMetrics().asJson();
}
/**
* Deprecated migrate to collectMetrics().asData().
*/
@Deprecated
default List<MetricData> collectMetricsAsData() {
return collectMetrics().asData();
}
/**
* Visit the metrics resetting and collecting/reporting as desired.
*/
@@ -2,6 +2,8 @@ package io.ebean.meta;
import io.ebean.ProfileLocation;
import java.time.Instant;
/**
* Meta data for captured query plan.
*/
@@ -51,4 +53,14 @@ public interface MetaQueryPlan {
* Return the total count of times bind capture has occurred.
*/
long captureCount();
/**
* Return the time taken to capture this plan in microseconds.
*/
long captureMicros();
/**
* Return the instant when the bind values were captured.
*/
Instant whenCaptured();
}
@@ -118,28 +118,28 @@ final class MetricsAsJson implements ServerMetricsAsJson {
private void objStart() throws IOException {
objKeyCounter = 0;
writer.append("{");
writer.append('{');
}
private void objEnd() throws IOException {
writer.append("}");
writer.append('}');
}
private void listStart() throws IOException {
listCounter = 0;
writer.append("[");
writer.append('[');
writer.append(newLine);
}
private void listEnd() throws IOException {
writer.append("]");
writer.append(']');
}
private void key(String key) throws IOException {
if (objKeyCounter++ > 0) {
writer.append(", ");
}
writer.append("\"").append(key).append("\":");
writer.append('"').append(key).append("\":");
}
private void val(long count) throws IOException {
@@ -147,12 +147,12 @@ final class MetricsAsJson implements ServerMetricsAsJson {
}
private void val(String val) throws IOException {
writer.append("\"").append(val).append("\"");
writer.append('"').append(val).append('"');
}
private void metricStart(MetaMetric metric) throws IOException {
if (listCounter++ > 0) {
writer.append(",").append(newLine);
writer.append(',').append(newLine);
}
objStart();
key("name");
@@ -187,11 +187,22 @@ final class MetricsAsJson implements ServerMetricsAsJson {
}
if (isIncludeDetail(metric)) {
append("loc", metric.location());
append("sql", metric.sql());
append("sql", escape(metric.sql()));
}
metricEnd();
}
static String escape(String sql) {
return sql == null ? null : sql
.replace("\\", "\\\\")
.replace("\"", "\\\"")
.replace("\b", "\\b")
.replace("\f", "\\f")
.replace("\n", "\\n")
.replace("\r", "\\r")
.replace("\t", "\\t");
}
private boolean isIncludeDetail(MetaTimedMetric metric) {
return includeExtraAttributes == 2 || includeExtraAttributes == 1 && metric.initialCollection();
}
@@ -0,0 +1,22 @@
package io.ebean.service;
import io.ebean.InTuples;
import java.util.List;
/**
* Internal extension to InTuples.
*/
public interface SpiInTuples extends InTuples {
/**
* Return the properties of the tuples.
*/
String[] properties();
/**
* Return all the tuple entries.
*/
List<Object[]> entries();
}
@@ -1,91 +0,0 @@
/* Javadoc style sheet */
/* Define colors, fonts and other style attributes here to override the defaults */
/* Page background color */
body {
background-color: #FFFFFF;
font-family: Arial, Helvetica, sans-serif;
font-size: 10pt;
}
pre.code {
padding: 1em;
margin-left: 2em;
border: 1px solid #ccc;
background-color: #eee;
}
/* Headings */
h1 {
font-size: 14pt
}
#overviewexamples h3 {
font-size: 10pt
}
/* Table colors */
.TableHeadingColor {
background: #CCCCFF
}
/* Dark mauve */
.TableSubHeadingColor {
background: #EEEEFF
}
/* Light mauve */
.TableRowColor {
background: #FFFFFF
}
/* White */
/* Font used in left-hand frame lists */
.FrameTitleFont {
font-size: 12pt;
font-family: Helvetica, Arial, sans-serif
}
.FrameHeadingFont {
font-size: 10pt;
font-family: Helvetica, Arial, sans-serif
}
.FrameItemFont {
font-size: 10pt;
font-family: Helvetica, Arial, sans-serif
}
/* Navigation bar fonts and colors */
.NavBarCell1 {
background-color: #EEEEFF;
}
/* Light mauve */
.NavBarCell1Rev {
background-color: #00008B;
}
/* Dark Blue */
.NavBarFont1 {
font-family: Arial, Helvetica, sans-serif;
color: #000000;
}
.NavBarFont1Rev {
font-family: Arial, Helvetica, sans-serif;
color: #FFFFFF;
}
.NavBarCell2 {
font-family: Arial, Helvetica, sans-serif;
background-color: #FFFFFF;
}
.NavBarCell3 {
font-family: Arial, Helvetica, sans-serif;
background-color: #FFFFFF;
}
@@ -205,7 +205,7 @@ public class PathProperties implements FetchPath {
sb.append(it.next());
hasNext = it.hasNext();
if (hasNext) {
sb.append(",");
sb.append(',');
}
}
return sb.toString();
@@ -25,14 +25,14 @@ public final class CamelCaseHelper {
lastUpper = i;
} else if (Character.isDigit(c)) {
if (i > lastUpper + 1 && !digitsCompressed) {
sb.append("_");
sb.append('_');
lastUpper = i;
}
sb.append(c);
} else if (Character.isUpperCase(c)) {
if (i > lastUpper + 1) {
sb.append("_");
sb.append('_');
}
sb.append(Character.toLowerCase(c));
lastUpper = i;
+2 -2
View File
@@ -12,7 +12,7 @@ module io.ebean.api {
requires transitive java.sql;
requires transitive io.avaje.config;
requires transitive io.avaje.lang;
requires transitive persistence.api;
requires transitive jakarta.persistence.api;
requires transitive io.ebean.annotation;
requires transitive io.ebean.datasource.api;
requires transitive io.avaje.applog;
@@ -21,7 +21,7 @@ module io.ebean.api {
requires static io.ebean.types;
requires static com.fasterxml.jackson.core;
requires static com.fasterxml.jackson.databind;
requires static javax.servlet.api;
requires static jakarta.servlet;
exports io.ebean;
exports io.ebean.bean;
@@ -0,0 +1,82 @@
package io.ebean;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
class ListsTest {
@Test
void partition_empty() {
List<List<Integer>> partitions = Lists.partition(List.of(), 5);
assertThat(partitions).isEmpty();
}
@Test
void partition_lt() {
List<List<Integer>> partitions = Lists.partition(List.of(1, 2, 3, 4), 5);
assertThat(partitions).hasSize(1);
assertThat(partitions.get(0)).hasSize(4);
}
@Test
void partition_eq() {
List<List<Integer>> partitions = Lists.partition(List.of(1, 2, 3, 4, 5), 5);
assertThat(partitions).hasSize(1);
assertThat(partitions.get(0)).hasSize(5);
}
@Test
void partition_gt() {
List<List<Integer>> partitions = Lists.partition(List.of(1, 2, 3, 4, 5, 6), 5);
assertThat(partitions).hasSize(2);
assertThat(partitions.get(0)).hasSize(5);
assertThat(partitions.get(1)).hasSize(1);
assertThat(partitions.get(0)).containsExactly(1, 2, 3, 4, 5);
assertThat(partitions.get(1)).containsExactly(6);
}
@Test
void partition_gt1_letters() {
var partitions = Lists.partition(List.of("a", "b", "c", "d"), 3);
assertThat(partitions).hasSize(2);
assertThat(partitions.get(0)).hasSize(3);
assertThat(partitions.get(1)).hasSize(1);
assertThat(partitions.get(0)).containsExactly("a", "b", "c");
assertThat(partitions.get(1)).containsExactly("d");
}
@Test
void partition_gt1a_letters() {
var partitions = Lists.partition(List.of("a", "b", "c", "d", "e"), 3);
assertThat(partitions).hasSize(2);
assertThat(partitions.get(0)).hasSize(3);
assertThat(partitions.get(1)).hasSize(2);
assertThat(partitions.get(0)).containsExactly("a", "b", "c");
assertThat(partitions.get(1)).containsExactly("d", "e");
}
@Test
void partition_eq2_letters() {
var partitions = Lists.partition(List.of("a", "b", "c", "d", "e", "f"), 3);
assertThat(partitions).hasSize(2);
assertThat(partitions.get(0)).hasSize(3);
assertThat(partitions.get(1)).hasSize(3);
assertThat(partitions.get(0)).containsExactly("a", "b", "c");
assertThat(partitions.get(1)).containsExactly("d", "e", "f");
}
@Test
void partition_gt2_letters() {
var partitions = Lists.partition(List.of("a", "b", "c", "d", "e", "f", "g"), 3);
assertThat(partitions).hasSize(3);
assertThat(partitions.get(0)).hasSize(3);
assertThat(partitions.get(1)).hasSize(3);
assertThat(partitions.get(2)).hasSize(1);
assertThat(partitions.get(0)).containsExactly("a", "b", "c");
assertThat(partitions.get(1)).containsExactly("d", "e", "f");
assertThat(partitions.get(2)).containsExactly("g");
}
}
@@ -0,0 +1,25 @@
package io.ebean.meta;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class MetricsAsJsonTest {
@Test
void trimIt() {
assertThat(MetricsAsJson.escape(null)).isNull();
assertThat(MetricsAsJson.escape("abc")).isEqualTo("abc");
}
@Test
void escape() {
assertThat(MetricsAsJson.escape("a\"bc")).isEqualTo("a\\\"bc");
assertThat(MetricsAsJson.escape("a\tbc")).isEqualTo("a\\tbc");
assertThat(MetricsAsJson.escape("a\bbc")).isEqualTo("a\\bbc");
assertThat(MetricsAsJson.escape("a\bc")).isEqualTo("a\\bc");
assertThat(MetricsAsJson.escape("a\rbc")).isEqualTo("a\\rbc");
assertThat(MetricsAsJson.escape("a\nbc")).isEqualTo("a\\nbc");
assertThat(MetricsAsJson.escape("a\\bc")).isEqualTo("a\\\\bc");
}
}
-101
View File
@@ -1,101 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.17.0</version>
</parent>
<!-- <parent>-->
<!-- <groupId>org.avaje</groupId>-->
<!-- <artifactId>java8-oss</artifactId>-->
<!-- <version>2.2</version>-->
<!-- </parent>-->
<scm>
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
<tag>HEAD</tag>
</scm>
<name>ebean autotune</name>
<description>ebean automatic query tuning module</description>
<artifactId>ebean-autotune</artifactId>
<dependencies>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.17.0</version>
<scope>provided</scope>
</dependency>
<!-- JAVAX-DEPENDENCY-START -->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.6</version>
<scope>provided</scope>
</dependency>
<!-- JAVAX-DEPENDENCY-END -->
<!-- JAKARTA-DEPENDENCY-START ___
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>4.0.0</version>
<scope>runtime</scope>
</dependency>
____ JAKARTA-DEPENDENCY-END -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-datasource</artifactId>
<version>${ebean-datasource.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-ddl-generator</artifactId>
<version>13.17.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.avaje</groupId>
<artifactId>junit</artifactId>
<version>1.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>13.17.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.repaint.maven</groupId>
<artifactId>tiles-maven-plugin</artifactId>
<version>2.24</version>
<extensions>true</extensions>
<configuration>
<tiles>
<tile>io.ebean.tile:enhancement:13.12.0</tile>
</tiles>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -1,133 +0,0 @@
package io.ebeaninternal.server.autotune.model;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import java.util.ArrayList;
import java.util.List;
/**
* Java class for anonymous complex type.
* <p>
* The following schema fragment specifies the expected content contained within this class.
* <p>
* <pre>
* &lt;complexType>
* &lt;complexContent>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* &lt;sequence>
* &lt;element ref="{http://ebean-orm.github.io/xml/ns/autotune}origin" maxOccurs="unbounded" minOccurs="0"/>
* &lt;element ref="{http://ebean-orm.github.io/xml/ns/autotune}profileDiff" minOccurs="0"/>
* &lt;element ref="{http://ebean-orm.github.io/xml/ns/autotune}profileNew" minOccurs="0"/>
* &lt;element ref="{http://ebean-orm.github.io/xml/ns/autotune}profileEmpty" minOccurs="0"/>
* &lt;/sequence>
* &lt;/restriction>
* &lt;/complexContent>
* &lt;/complexType>
* </pre>
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"origin",
"profileDiff",
"profileNew",
"profileEmpty"
})
@XmlRootElement(name = "autotune")
public class Autotune {
protected List<Origin> origin;
protected ProfileDiff profileDiff;
protected ProfileNew profileNew;
protected ProfileEmpty profileEmpty;
/**
* Gets the value of the origin property.
* <p>
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the origin property.
* <p>
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getOrigin().add(newItem);
* </pre>
* <p>
* <p>
* <p>
* Objects of the following type(s) are allowed in the list
* {@link Origin }
*/
public List<Origin> getOrigin() {
if (origin == null) {
origin = new ArrayList<>();
}
return this.origin;
}
/**
* Gets the value of the profileDiff property.
*
* @return possible object is
* {@link ProfileDiff }
*/
public ProfileDiff getProfileDiff() {
return profileDiff;
}
/**
* Sets the value of the profileDiff property.
*
* @param value allowed object is
* {@link ProfileDiff }
*/
public void setProfileDiff(ProfileDiff value) {
this.profileDiff = value;
}
/**
* Gets the value of the profileNew property.
*
* @return possible object is
* {@link ProfileNew }
*/
public ProfileNew getProfileNew() {
return profileNew;
}
/**
* Sets the value of the profileNew property.
*
* @param value allowed object is
* {@link ProfileNew }
*/
public void setProfileNew(ProfileNew value) {
this.profileNew = value;
}
/**
* Gets the value of the profileEmpty property.
*
* @return possible object is
* {@link ProfileEmpty }
*/
public ProfileEmpty getProfileEmpty() {
return profileEmpty;
}
/**
* Sets the value of the profileEmpty property.
*
* @param value allowed object is
* {@link ProfileEmpty }
*/
public void setProfileEmpty(ProfileEmpty value) {
this.profileEmpty = value;
}
}
@@ -1,64 +0,0 @@
package io.ebeaninternal.server.autotune.model;
import javax.xml.bind.annotation.XmlRegistry;
/**
* This object contains factory methods for each
* Java content interface and Java element interface
* generated in the io.ebeaninternal.server.autotune.model package.
* <p>An ObjectFactory allows you to programatically
* construct new instances of the Java representation
* for XML content. The Java representation of XML
* content can consist of schema derived interfaces
* and classes representing the binding of schema
* type definitions, element declarations and model
* groups. Factory methods for each of these are
* provided in this class.
*/
@XmlRegistry
public class ObjectFactory {
/**
* Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: io.ebeaninternal.server.autotune.model
*/
public ObjectFactory() {
}
/**
* Create an instance of {@link ProfileNew }
*/
public ProfileNew createProfileNew() {
return new ProfileNew();
}
/**
* Create an instance of {@link Origin }
*/
public Origin createOrigin() {
return new Origin();
}
/**
* Create an instance of {@link ProfileEmpty }
*/
public ProfileEmpty createProfileEmpty() {
return new ProfileEmpty();
}
/**
* Create an instance of {@link Autotune }
*/
public Autotune createAutotune() {
return new Autotune();
}
/**
* Create an instance of {@link ProfileDiff }
*/
public ProfileDiff createProfileDiff() {
return new ProfileDiff();
}
}
@@ -1,148 +0,0 @@
package io.ebeaninternal.server.autotune.model;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
/**
* <p>Java class for anonymous complex type.
* <p>
* <p>The following schema fragment specifies the expected content contained within this class.
* <p>
* <pre>
* &lt;complexType>
* &lt;complexContent>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* &lt;sequence>
* &lt;element name="callStack" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
* &lt;/sequence>
* &lt;attribute name="key" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;attribute name="beanType" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;attribute name="detail" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;attribute name="original" type="{http://www.w3.org/2001/XMLSchema}string" />
* &lt;/restriction>
* &lt;/complexContent>
* &lt;/complexType>
* </pre>
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"callStack"
})
@XmlRootElement(name = "origin")
public class Origin {
protected String callStack;
@XmlAttribute(name = "key", required = true)
protected String key;
@XmlAttribute(name = "beanType")
protected String beanType;
@XmlAttribute(name = "detail")
protected String detail;
@XmlAttribute(name = "original")
protected String original;
/**
* Gets the value of the callStack property.
*
* @return possible object is
* {@link String }
*/
public String getCallStack() {
return callStack;
}
/**
* Sets the value of the callStack property.
*
* @param value allowed object is
* {@link String }
*/
public void setCallStack(String value) {
this.callStack = value;
}
/**
* Gets the value of the key property.
*
* @return possible object is
* {@link String }
*/
public String getKey() {
return key;
}
/**
* Sets the value of the key property.
*
* @param value allowed object is
* {@link String }
*/
public void setKey(String value) {
this.key = value;
}
/**
* Gets the value of the beanType property.
*
* @return possible object is
* {@link String }
*/
public String getBeanType() {
return beanType;
}
/**
* Sets the value of the beanType property.
*
* @param value allowed object is
* {@link String }
*/
public void setBeanType(String value) {
this.beanType = value;
}
/**
* Gets the value of the detail property.
*
* @return possible object is
* {@link String }
*/
public String getDetail() {
return detail;
}
/**
* Sets the value of the detail property.
*
* @param value allowed object is
* {@link String }
*/
public void setDetail(String value) {
this.detail = value;
}
/**
* Gets the value of the original property.
*
* @return possible object is
* {@link String }
*/
public String getOriginal() {
return original;
}
/**
* Sets the value of the original property.
*
* @param value allowed object is
* {@link String }
*/
public void setOriginal(String value) {
this.original = value;
}
}
@@ -1,64 +0,0 @@
package io.ebeaninternal.server.autotune.model;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import java.util.ArrayList;
import java.util.List;
/**
* <p>Java class for anonymous complex type.
* <p>
* <p>The following schema fragment specifies the expected content contained within this class.
* <p>
* <pre>
* &lt;complexType>
* &lt;complexContent>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* &lt;sequence>
* &lt;element ref="{http://ebean-orm.github.io/xml/ns/autotune}origin" maxOccurs="unbounded" minOccurs="0"/>
* &lt;/sequence>
* &lt;/restriction>
* &lt;/complexContent>
* &lt;/complexType>
* </pre>
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"origin"
})
@XmlRootElement(name = "profileDiff")
public class ProfileDiff {
protected List<Origin> origin;
/**
* Gets the value of the origin property.
* <p>
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the origin property.
* <p>
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getOrigin().add(newItem);
* </pre>
* <p>
* <p>
* <p>
* Objects of the following type(s) are allowed in the list
* {@link Origin }
*/
public List<Origin> getOrigin() {
if (origin == null) {
origin = new ArrayList<>();
}
return this.origin;
}
}
@@ -1,64 +0,0 @@
package io.ebeaninternal.server.autotune.model;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import java.util.ArrayList;
import java.util.List;
/**
* <p>Java class for anonymous complex type.
* <p>
* <p>The following schema fragment specifies the expected content contained within this class.
* <p>
* <pre>
* &lt;complexType>
* &lt;complexContent>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* &lt;sequence>
* &lt;element ref="{http://ebean-orm.github.io/xml/ns/autotune}origin" maxOccurs="unbounded" minOccurs="0"/>
* &lt;/sequence>
* &lt;/restriction>
* &lt;/complexContent>
* &lt;/complexType>
* </pre>
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"origin"
})
@XmlRootElement(name = "profileEmpty")
public class ProfileEmpty {
protected List<Origin> origin;
/**
* Gets the value of the origin property.
* <p>
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the origin property.
* <p>
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getOrigin().add(newItem);
* </pre>
* <p>
* <p>
* <p>
* Objects of the following type(s) are allowed in the list
* {@link Origin }
*/
public List<Origin> getOrigin() {
if (origin == null) {
origin = new ArrayList<>();
}
return this.origin;
}
}
@@ -1,64 +0,0 @@
package io.ebeaninternal.server.autotune.model;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import java.util.ArrayList;
import java.util.List;
/**
* <p>Java class for anonymous complex type.
* <p>
* <p>The following schema fragment specifies the expected content contained within this class.
* <p>
* <pre>
* &lt;complexType>
* &lt;complexContent>
* &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* &lt;sequence>
* &lt;element ref="{http://ebean-orm.github.io/xml/ns/autotune}origin" maxOccurs="unbounded" minOccurs="0"/>
* &lt;/sequence>
* &lt;/restriction>
* &lt;/complexContent>
* &lt;/complexType>
* </pre>
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"origin"
})
@XmlRootElement(name = "profileNew")
public class ProfileNew {
protected List<Origin> origin;
/**
* Gets the value of the origin property.
* <p>
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the origin property.
* <p>
* <p>
* For example, to add a new item, do as follows:
* <pre>
* getOrigin().add(newItem);
* </pre>
* <p>
* <p>
* <p>
* Objects of the following type(s) are allowed in the list
* {@link Origin }
*/
public List<Origin> getOrigin() {
if (origin == null) {
origin = new ArrayList<>();
}
return this.origin;
}
}
@@ -1,2 +0,0 @@
@javax.xml.bind.annotation.XmlSchema(namespace = "http://ebean-orm.github.io/xml/ns/autotune", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package io.ebeaninternal.server.autotune.model;
@@ -1,61 +0,0 @@
package io.ebeaninternal.server.autotune.service;
import io.ebeaninternal.server.autotune.model.Autotune;
import java.util.Collection;
/**
* Event where all tuned query information is collected.
* <p>
* This is for writing the "all" file on shutdown when using runtime tuning.
* </p>
*/
public class AutoTuneAllCollection {
final Autotune document = new Autotune();
final BaseQueryTuner queryTuner;
/**
* Construct to collect/report all tuned queries.
*/
public AutoTuneAllCollection(BaseQueryTuner queryTuner) {
this.queryTuner = queryTuner;
loadAllTuned();
}
/**
* Return the number of origin elements in the document.
*/
public int size() {
return document.getOrigin().size();
}
/**
* Return the Autotune document object.
*/
public Autotune getDocument() {
return document;
}
/**
* Write the document as an xml file.
*/
public void writeFile(String filePrefix, boolean withNow) {
AutoTuneXmlWriter writer = new AutoTuneXmlWriter();
writer.write(document, filePrefix, withNow);
}
/**
* Loads all the existing query tuning into the document.
*/
private void loadAllTuned() {
Collection<TunedQueryInfo> all = queryTuner.getAll();
for (TunedQueryInfo tuned : all) {
document.getOrigin().add(tuned.getOrigin());
}
}
}
@@ -1,115 +0,0 @@
package io.ebeaninternal.server.autotune.service;
import io.ebean.bean.ObjectGraphOrigin;
import io.ebeaninternal.server.querydefn.OrmQueryDetail;
import java.util.ArrayList;
import java.util.List;
/**
* Profiling information collected.
*/
public class AutoTuneCollection {
final List<Entry> entries = new ArrayList<>();
public Entry add(ObjectGraphOrigin origin, OrmQueryDetail detail, String sourceQuery) {
Entry entry = new Entry(origin, detail, sourceQuery);
entries.add(entry);
return entry;
}
public List<Entry> getEntries() {
return entries;
}
/**
* Profiling entry at a given origin point.
*/
public static class Entry {
/**
* Profiling origin point.
*/
private final ObjectGraphOrigin origin;
/**
* The tuned query detail.
*/
private final OrmQueryDetail detail;
/**
* The original/existing query detail.
*/
private final String originalQuery;
/**
* Summary execution statistics for queries related to this origin point.
*/
private final List<EntryQuery> queries = new ArrayList<>();
public Entry(ObjectGraphOrigin origin, OrmQueryDetail detail, String originalQuery) {
this.origin = origin;
this.detail = detail;
this.originalQuery = originalQuery;
}
public void addQuery(EntryQuery entryQuery) {
queries.add(entryQuery);
}
public ObjectGraphOrigin getOrigin() {
return origin;
}
public OrmQueryDetail getDetail() {
return detail;
}
public String getOriginalQuery() {
return originalQuery;
}
public List<EntryQuery> getQueries() {
return queries;
}
}
/**
* Summary query execution statistics for the origin point.
*/
public static class EntryQuery {
final String path;
final long exeCount;
final long totalBeanLoaded;
final long totalMicros;
public EntryQuery(String path, long exeCount, long totalBeanLoaded, long totalMicros) {
this.path = path;
this.exeCount = exeCount;
this.totalBeanLoaded = totalBeanLoaded;
this.totalMicros = totalMicros;
}
/**
* Return the relative path with empty string for the origin query.
*/
public String getPath() {
return path;
}
public long getExeCount() {
return exeCount;
}
public long getTotalBeanLoaded() {
return totalBeanLoaded;
}
public long getTotalMicros() {
return totalMicros;
}
}
}
@@ -1,161 +0,0 @@
package io.ebeaninternal.server.autotune.service;
import io.ebean.bean.ObjectGraphOrigin;
import io.ebeaninternal.server.autotune.model.Autotune;
import io.ebeaninternal.server.autotune.model.Origin;
import io.ebeaninternal.server.autotune.model.ProfileDiff;
import io.ebeaninternal.server.autotune.model.ProfileNew;
import io.ebeaninternal.server.querydefn.OrmQueryDetail;
/**
* Event where profiling information is collected and processed for differences
* relative to the current query tuning.
*/
public class AutoTuneDiffCollection {
final Autotune document = new Autotune();
final AutoTuneCollection profiling;
final BaseQueryTuner queryTuner;
final boolean updateTuning;
int newCount;
int diffCount;
/**
* Construct to collect/report the new/diff query tuning entries.
*/
public AutoTuneDiffCollection(AutoTuneCollection profiling, BaseQueryTuner queryTuner, boolean updateTuning) {
this.profiling = profiling;
this.queryTuner = queryTuner;
this.updateTuning = updateTuning;
}
/**
* Return true if there are no new or diff entries.
*/
public boolean isEmpty() {
return newCount == 0 && diffCount == 0;
}
/**
* Return the underlying Autotune document object.
*/
public Autotune getDocument() {
return document;
}
/**
* Return the number of diff entries.
*/
public int getDiffCount() {
return diffCount;
}
/**
* Return the number of new entries.
*/
public int getNewCount() {
return newCount;
}
/**
* Return the total new and diff entries.
*/
public int getChangeCount() {
return newCount + diffCount;
}
/**
* Write the underlying document as an xml file.
*/
public void writeFile(String filePrefix) {
AutoTuneXmlWriter writer = new AutoTuneXmlWriter();
writer.write(document, filePrefix, true);
}
/**
* Process checking profiling entries against existing query tuning.
*/
public void process() {
for (AutoTuneCollection.Entry entry : profiling.getEntries()) {
addToDocument(entry);
}
}
/**
* Check if the entry is new or diff and add as necessary.
*/
private void addToDocument(AutoTuneCollection.Entry entry) {
ObjectGraphOrigin point = entry.getOrigin();
OrmQueryDetail profileDetail = entry.getDetail();
// compare with the existing query tuning entry
OrmQueryDetail tuneDetail = queryTuner.get(point.key());
if (tuneDetail == null) {
addToDocumentNewEntry(entry, point);
} else if (!tuneDetail.isAutoTuneEqual(profileDetail)) {
addToDocumentDiffEntry(entry, point, tuneDetail);
}
}
/**
* Add as a diff entry.
*/
private void addToDocumentDiffEntry(AutoTuneCollection.Entry entry, ObjectGraphOrigin point, OrmQueryDetail tuneDetail) {
diffCount++;
Origin origin = createOrigin(entry, point, tuneDetail.asString());
ProfileDiff diff = document.getProfileDiff();
if (diff == null) {
diff = new ProfileDiff();
document.setProfileDiff(diff);
}
diff.getOrigin().add(origin);
}
/**
* Add as a "new" entry.
*/
private void addToDocumentNewEntry(AutoTuneCollection.Entry entry, ObjectGraphOrigin point) {
newCount++;
ProfileNew profileNew = document.getProfileNew();
if (profileNew == null) {
profileNew = new ProfileNew();
document.setProfileNew(profileNew);
}
Origin origin = createOrigin(entry, point, entry.getOriginalQuery());
profileNew.getOrigin().add(origin);
}
/**
* Create the XML Origin bean for the given entry and ObjectGraphOrigin.
*/
private Origin createOrigin(AutoTuneCollection.Entry entry, ObjectGraphOrigin point, String query) {
Origin origin = new Origin();
origin.setKey(point.key());
origin.setBeanType(point.beanType());
origin.setDetail(entry.getDetail().asString());
origin.setCallStack(point.callOrigin().description());
origin.setOriginal(query);
if (updateTuning) {
queryTuner.put(origin);
}
return origin;
}
}
@@ -1,15 +0,0 @@
package io.ebeaninternal.server.autotune.service;
import io.ebean.config.DatabaseConfig;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.server.autotune.AutoTuneService;
import io.ebeaninternal.server.autotune.AutoTuneServiceProvider;
public class AutoTuneServiceFactory implements AutoTuneServiceProvider {
@Override
public AutoTuneService create(SpiEbeanServer server, DatabaseConfig config) {
return new DefaultAutoTuneService(server, config);
}
}
@@ -1,52 +0,0 @@
package io.ebeaninternal.server.autotune.service;
import io.ebeaninternal.server.autotune.model.Autotune;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* Reads a profiling xml document.
*/
public class AutoTuneXmlReader {
/**
* Read and return a Profiling from an xml file.
*/
public static Autotune read(File file) {
try {
return readFile(file);
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
protected static Autotune readFile(File file) throws IOException {
if (!file.exists()) {
return new Autotune();
}
try (FileInputStream is = new FileInputStream(file)) {
return read(is);
}
}
/**
* Read and return a Profiling from an xml document.
*/
public static Autotune read(InputStream is) {
try {
JAXBContext jaxbContext = JAXBContext.newInstance(Autotune.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
return (Autotune) unmarshaller.unmarshal(is);
} catch (JAXBException e) {
throw new IllegalStateException(e);
}
}
}
@@ -1,57 +0,0 @@
package io.ebeaninternal.server.autotune.service;
import io.ebeaninternal.server.autotune.model.Autotune;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Simple writer for output of the AutoTune Profiling as an XML document.
*/
public class AutoTuneXmlWriter {
/**
* Return 'now' as a string to second precision.
*/
public static String now() {
SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd-HHmmss");
return df.format(new Date());
}
/**
* Write the document as xml file with the given prefix.
*/
public void write(Autotune document, String fileName, boolean withNow) {
SortAutoTuneDocument.sort(document);
if (withNow) {
fileName += "-" + now() + ".xml";
}
// write the file with serverName and now suffix as we can output the profiling many times
write(document, new File(fileName));
}
/**
* Write Profiling to a file as xml.
*/
public void write(Autotune profiling, File file) {
try {
JAXBContext jaxbContext = JAXBContext.newInstance(Autotune.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.marshal(profiling, file);
} catch (JAXBException e) {
throw new RuntimeException(e);
}
}
}
@@ -1,204 +0,0 @@
package io.ebeaninternal.server.autotune.service;
import io.ebean.bean.CallOrigin;
import io.ebean.bean.ObjectGraphNode;
import io.ebean.config.AutoTuneConfig;
import io.ebean.config.AutoTuneMode;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.server.autotune.ProfilingListener;
import io.ebeaninternal.server.autotune.model.Origin;
import io.ebeaninternal.server.querydefn.OrmQueryDetail;
import javax.persistence.PersistenceException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
*
*/
public class BaseQueryTuner {
private final boolean queryTuning;
private final boolean profiling;
private final AutoTuneMode mode;
/**
* Map of the tuned query details per profile query point.
*/
private final Map<String, TunedQueryInfo> tunedQueryInfoMap = new ConcurrentHashMap<>();
private final SpiEbeanServer server;
private final ProfilingListener profilingListener;
/**
* Flag set true when there is no profiling or query tuning.
*/
private final boolean skipAll;
BaseQueryTuner(AutoTuneConfig config, SpiEbeanServer server, ProfilingListener profilingListener) {
this.server = server;
this.profilingListener = profilingListener;
this.mode = config.getMode();
this.queryTuning = config.isQueryTuning();
this.profiling = config.isProfiling();
this.skipAll = !queryTuning && !profiling;
}
/**
* Return all the current tuned query entries.
*/
public Collection<TunedQueryInfo> getAll() {
return tunedQueryInfoMap.values();
}
/**
* Put a query tuning entry.
*/
public void put(Origin origin) {
tunedQueryInfoMap.put(origin.getKey(), new TunedQueryInfo(origin));
}
/**
* Load the tuned query information.
*/
public void load(String key, TunedQueryInfo queryInfo) {
tunedQueryInfoMap.put(key, queryInfo);
}
/**
* Return the detail currently used for tuning.
* This returns null if there is currently no matching tuning.
*/
public OrmQueryDetail get(String key) {
TunedQueryInfo info = tunedQueryInfoMap.get(key);
return (info == null) ? null : info.getTunedDetail();
}
/**
* Auto tune the query and enable profiling.
*/
boolean tuneQuery(SpiQuery<?> query) {
if (skipAll || !tunableQuery(query)) {
return false;
}
if (query.getProfilingListener() != null) {
// profiling secondary query
return false;
}
if (!useTuning(query)) {
if (profiling) {
profiling(query, server.createCallOrigin());
}
return false;
}
if (query.getParentNode() != null) {
// This is a +lazy/+query query with profiling on.
// We continue to collect the profiling information.
query.setProfilingListener(profilingListener);
return true;
}
// create a query point to identify the query
CallOrigin callOrigin = server.createCallOrigin();
ObjectGraphNode origin = query.setOrigin(callOrigin);
if (profiling) {
if (profilingListener.isProfileRequest(origin, query)) {
// collect more profiling based on profiling rate etc
query.setProfilingListener(profilingListener);
}
}
if (queryTuning) {
// get current "tuned fetch" for this query point
TunedQueryInfo tuneInfo = tunedQueryInfoMap.get(origin.origin().key());
return tuneInfo != null && tuneInfo.tuneQuery(query);
}
return false;
}
/**
* Return false for row count, find ids, subQuery, delete and Versions queries.
* <p>
* These queries are not applicable for autoTune in that they don't have a select/fetch (fetch group).
* </p>
* <p>
* We also exclude queries that are explicitly set to load the L2 bean cache as we want full beans
* in that case.
* </p>
*/
private boolean tunableQuery(SpiQuery<?> query) {
SpiQuery.Type type = query.getType();
switch (type) {
case COUNT:
case ATTRIBUTE:
case ATTRIBUTE_SET:
case ID_LIST:
case UPDATE:
case DELETE:
case SQ_EXISTS:
case SQ_EX:
return false;
default:
// not using autoTune when explicitly loading the l2 bean cache
// or when using Versions query
return !query.isForceHitDatabase() && SpiQuery.TemporalMode.VERSIONS != query.getTemporalMode();
}
}
private void profiling(SpiQuery<?> query, CallOrigin call) {
// create a query point to identify the query
ObjectGraphNode origin = query.setOrigin(call);
if (profilingListener.isProfileRequest(origin, query)) {
// collect more profiling based on profiling rate etc
query.setProfilingListener(profilingListener);
}
}
/**
* Return true if we should try to tune this query.
*/
private boolean useTuning(SpiQuery<?> query) {
Boolean autoTune = query.isAutoTune();
if (autoTune != null) {
// explicitly set...
return autoTune;
} else {
// determine using implicit mode...
switch (mode) {
case DEFAULT_ON:
return true;
case DEFAULT_OFF:
return false;
case DEFAULT_ONIFEMPTY:
return query.isDetailEmpty();
default:
throw new PersistenceException("Invalid AutoTuneMode " + mode);
}
}
}
/**
* Return the keys as a set.
*/
public Set<String> keySet() {
return tunedQueryInfoMap.keySet();
}
}
@@ -1,295 +0,0 @@
package io.ebeaninternal.server.autotune.service;
import io.avaje.applog.AppLog;
import io.ebean.config.AutoTuneConfig;
import io.ebean.config.DatabaseConfig;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.server.autotune.AutoTuneService;
import io.ebeaninternal.server.autotune.model.Autotune;
import io.ebeaninternal.server.autotune.model.Origin;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import static java.lang.System.Logger.Level.*;
/**
* Implementation of the AutoTuneService which is comprised of profiling and query tuning.
*/
public class DefaultAutoTuneService implements AutoTuneService {
private static final System.Logger logger = AppLog.getLogger(DefaultAutoTuneService.class);
private final ReentrantLock lock = new ReentrantLock();
private final SpiEbeanServer server;
private final long defaultGarbageCollectionWait;
private final boolean skipGarbageCollectionOnShutdown;
private final boolean skipProfileReportingOnShutdown;
private final BaseQueryTuner queryTuner;
private final ProfileManager profileManager;
private final boolean profiling;
private final boolean queryTuning;
private final String tuningFile;
private final String profilingFile;
private final String serverName;
private final int profilingUpdateFrequency;
private long runtimeChangeCount;
public DefaultAutoTuneService(SpiEbeanServer server, DatabaseConfig databaseConfig) {
AutoTuneConfig config = databaseConfig.getAutoTuneConfig();
this.server = server;
this.queryTuning = config.isQueryTuning();
this.profiling = config.isProfiling();
this.tuningFile = config.getQueryTuningFile();
this.profilingFile = config.getProfilingFile();
this.profilingUpdateFrequency = config.getProfilingUpdateFrequency();
this.serverName = server.name();
this.profileManager = new ProfileManager(config, server);
this.queryTuner = new BaseQueryTuner(config, server, profileManager);
this.skipGarbageCollectionOnShutdown = config.isSkipGarbageCollectionOnShutdown();
this.skipProfileReportingOnShutdown = config.isSkipProfileReportingOnShutdown();
this.defaultGarbageCollectionWait = config.getGarbageCollectionWait();
}
/**
* Load the query tuning information from it's data store.
*/
@Override
public void startup() {
if (queryTuning) {
loadTuningFile();
if (isRuntimeTuningUpdates()) {
// periodically gather and update query tuning
server.backgroundExecutor().scheduleWithFixedDelay(new ProfilingUpdate(), profilingUpdateFrequency, profilingUpdateFrequency, TimeUnit.SECONDS);
}
}
}
/**
* Return true if the tuning should update periodically at runtime.
*/
private boolean isRuntimeTuningUpdates() {
return profilingUpdateFrequency > 0;
}
private class ProfilingUpdate implements Runnable {
@Override
public void run() {
runtimeTuningUpdate();
}
}
/**
* Load tuning information from an existing tuning file.
*/
private void loadTuningFile() {
File file = new File(tuningFile);
if (file.exists()) {
loadAutoTuneProfiling(AutoTuneXmlReader.read(file));
} else {
// look for autotune as a resource
try (InputStream stream = getClass().getResourceAsStream("/" + tuningFile)) {
if (stream != null) {
loadAutoTuneProfiling(AutoTuneXmlReader.read(stream));
} else {
logger.log(WARNING, "AutoTune file {0} not found - no initial automatic query tuning", tuningFile);
}
} catch (IOException e) {
throw new IllegalStateException("Error on auto close of " + tuningFile, e);
}
}
}
private void loadAutoTuneProfiling(Autotune profiling) {
logger.log(INFO, "AutoTune loading {0} tuning entries", profiling.getOrigin().size());
for (Origin origin : profiling.getOrigin()) {
queryTuner.put(origin);
}
}
/**
* Collect profiling, check for new/diff to existing tuning and apply changes.
*/
private void runtimeTuningUpdate() {
lock.lock();
try {
try {
long start = System.currentTimeMillis();
AutoTuneCollection profiling = profileManager.profilingCollection(false);
AutoTuneDiffCollection event = new AutoTuneDiffCollection(profiling, queryTuner, true);
event.process();
if (event.isEmpty()) {
long exeMillis = System.currentTimeMillis() - start;
logger.log(DEBUG, "No query tuning updates for server:{0} executionMillis:{1}", serverName, exeMillis);
} else {
// report the query tuning changes that have been made
runtimeChangeCount += event.getChangeCount();
event.writeFile(profilingFile + "-" + serverName + "-update");
long exeMillis = System.currentTimeMillis() - start;
logger.log(INFO, "query tuning updates - new:{0} diff:{1} for server:{2} executionMillis:{3}", event.getNewCount(), event.getDiffCount(), serverName, exeMillis);
}
} catch (Throwable e) {
logger.log(ERROR, "Error collecting or applying automatic query tuning", e);
}
} finally {
lock.unlock();
}
}
private void saveProfilingOnShutdown(boolean reset) {
lock.lock();
try {
if (isRuntimeTuningUpdates()) {
runtimeTuningUpdate();
outputAllTuning();
} else {
AutoTuneCollection profiling = profileManager.profilingCollection(reset);
AutoTuneDiffCollection event = new AutoTuneDiffCollection(profiling, queryTuner, false);
event.process();
if (event.isEmpty()) {
logger.log(INFO, "No new or diff entries for profiling server:{0}", serverName);
} else {
event.writeFile(profilingFile + "-" + serverName);
logger.log(INFO, "writing new:{0} diff:{1} profiling entries for server:{2}", event.getNewCount(), event.getDiffCount(), serverName);
}
}
} finally {
lock.unlock();
}
}
/**
* Output all the query tuning (the "all" file).
* <p>
* This is the originally loaded tuning plus any tuning changes picked up and applied at runtime.
* </p>
* <p>
* This "all" file can be used as the next "ebean-autotune.xml" file.
* </p>
*/
private void outputAllTuning() {
if (runtimeChangeCount == 0) {
logger.log(INFO, "no runtime query tuning changes for server:{0}", serverName);
} else {
AutoTuneAllCollection event = new AutoTuneAllCollection(queryTuner);
int size = event.size();
File existingTuning = new File(tuningFile);
if (existingTuning.exists()) {
// rename the existing autotune.xml file (appending 'now')
if (!existingTuning.renameTo(new File(tuningFile + "." + AutoTuneXmlWriter.now()))) {
logger.log(WARNING, "Failed to rename autotune file [{0}]", tuningFile);
}
}
event.writeFile(tuningFile, false);
logger.log(INFO, "query tuning detected [{0}] changes, writing all [{1}] tuning entries for server:{2}", runtimeChangeCount, size, serverName);
}
}
/**
* Shutdown the listener.
* <p>
* We should try to collect the usage statistics by calling a System.gc().
* This is necessary for use with short lived applications where garbage
* collection may not otherwise occur at all.
* </p>
*/
@Override
public void shutdown() {
if (profiling) {
if (!skipGarbageCollectionOnShutdown && !skipProfileReportingOnShutdown) {
// trigger GC to update profiling information on recently executed queries
collectProfiling(-1);
}
if (!skipProfileReportingOnShutdown) {
saveProfilingOnShutdown(false);
}
}
}
/**
* Output the profiling.
* <p>
* When profiling updates are applied to tuning at runtime this reports all tuning and profiling combined.
* When profiling is not applied at runtime then this reports the diff report with new and diff entries relative
* to the existing tuning.
* </p>
*/
@Override
public void reportProfiling() {
saveProfilingOnShutdown(false);
}
/**
* Ask for a System.gc() so that we gather node usage information.
* <p>
* Really only want to do this sparingly but useful just prior to shutdown
* for short run application where garbage collection may otherwise not
* occur at all.
* </p>
* <p>
* waitMillis will do a thread sleep to give the garbage collection a little
* time to do its thing assuming we are shutting down the VM.
* </p>
* <p>
* If waitMillis is -1 then the defaultGarbageCollectionWait is used which
* defaults to 100 milliseconds.
* </p>
*/
@Override
public void collectProfiling() {
collectProfiling(-1);
}
public void collectProfiling(long waitMillis) {
System.gc();
try {
if (waitMillis < 0) {
waitMillis = defaultGarbageCollectionWait;
}
Thread.sleep(waitMillis);
} catch (InterruptedException e) {
// restore the interrupted status
Thread.currentThread().interrupt();
logger.log(WARNING, "Error while sleeping after System.gc() request.", e);
}
}
/**
* Auto tune the query and enable profiling.
*/
@Override
public boolean tuneQuery(SpiQuery<?> query) {
return queryTuner.tuneQuery(query);
}
}
@@ -1,122 +0,0 @@
package io.ebeaninternal.server.autotune.service;
import io.ebean.bean.NodeUsageCollector;
import io.ebean.bean.ObjectGraphNode;
import io.ebean.bean.ObjectGraphOrigin;
import io.ebean.config.AutoTuneConfig;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.server.autotune.ProfilingListener;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
/**
* Manages the collection of object graph usage profiling.
*/
public class ProfileManager implements ProfilingListener {
private final ReentrantLock lock = new ReentrantLock();
private final boolean queryTuningAddVersion;
/**
* Converted from a 0-100 int to a double. Effectively a percentage rate at
* which to collect profiling information.
*/
private final double profilingRate;
private final int profilingBase;
/**
* Map of the usage and query statistics gathered.
*/
private final Map<String, ProfileOrigin> profileMap = new ConcurrentHashMap<>();
private final SpiEbeanServer server;
public ProfileManager(AutoTuneConfig config, SpiEbeanServer server) {
this.server = server;
this.profilingRate = config.getProfilingRate();
this.profilingBase = config.getProfilingBase();
this.queryTuningAddVersion = config.isQueryTuningAddVersion();
}
@Override
public boolean isProfileRequest(ObjectGraphNode origin, SpiQuery<?> query) {
ProfileOrigin profileOrigin = profileMap.get(origin.origin().key());
if (profileOrigin == null) {
profileMap.put(origin.origin().key(), createProfileOrigin(origin, query));
return true;
} else {
return profileOrigin.isProfile();
}
}
/**
* Create the profile origin noting the query detail currently being used.
* <p>
* For new profiling entries it is useful to compare the profiling against the current
* query detail that is specified in the code (as the query might already be manually optimised).
*/
private ProfileOrigin createProfileOrigin(ObjectGraphNode origin, SpiQuery<?> query) {
ProfileOrigin profileOrigin = new ProfileOrigin(origin.origin(), queryTuningAddVersion, profilingBase, profilingRate);
// set the current query detail (fetch group) so that we can compare against profiling for new entries
profileOrigin.setOriginalQuery(query.getDetail().asString());
return profileOrigin;
}
/**
* Gather query execution statistics. This could either be the originating
* query in which case the parentNode will be null, or a lazy loading query
* resulting from traversal of the object graph.
*/
@Override
public void collectQueryInfo(ObjectGraphNode node, long beans, long micros) {
if (node != null) {
ObjectGraphOrigin origin = node.origin();
if (origin != null) {
ProfileOrigin stats = getProfileOrigin(origin);
stats.collectQueryInfo(node, beans, micros);
}
}
}
/**
* Collect usage statistics from a node in the object graph.
* <p>
* This is sent to use from a EntityBeanIntercept when the finalise method
* is called on the bean.
*/
@Override
public void collectNodeUsage(NodeUsageCollector.State usageCollector) {
ProfileOrigin profileOrigin = getProfileOrigin(usageCollector.node().origin());
profileOrigin.collectUsageInfo(usageCollector);
}
private ProfileOrigin getProfileOrigin(ObjectGraphOrigin originQueryPoint) {
lock.lock();
try {
return profileMap.computeIfAbsent(originQueryPoint.key(), k -> new ProfileOrigin(originQueryPoint, queryTuningAddVersion, profilingBase, profilingRate));
} finally {
lock.unlock();
}
}
/**
* Collect all the profiling information.
*/
public AutoTuneCollection profilingCollection(boolean reset) {
AutoTuneCollection req = new AutoTuneCollection();
for (ProfileOrigin origin : profileMap.values()) {
BeanDescriptor<?> desc = server.descriptorById(origin.getOrigin().beanType());
if (desc != null) {
origin.profilingCollection(desc, req, reset);
}
}
return req;
}
}
@@ -1,176 +0,0 @@
package io.ebeaninternal.server.autotune.service;
import io.ebean.bean.NodeUsageCollector;
import io.ebean.bean.ObjectGraphNode;
import io.ebean.bean.ObjectGraphOrigin;
import io.ebean.text.PathProperties;
import io.ebean.text.PathProperties.Props;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.querydefn.OrmQueryDetail;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
public class ProfileOrigin {
private final ReentrantLock lock = new ReentrantLock();
private static final long RESET_COUNT = -1000000000L;
private final ObjectGraphOrigin origin;
private final boolean queryTuningAddVersion;
private final int profilingBase;
private final double profilingRate;
private final Map<String, ProfileOriginQuery> queryStatsMap = new ConcurrentHashMap<>();
private final Map<String, ProfileOriginNodeUsage> nodeUsageMap = new ConcurrentHashMap<>();
private final AtomicLong requestCount = new AtomicLong();
private final AtomicLong profileCount = new AtomicLong();
private String originalQuery;
public ProfileOrigin(ObjectGraphOrigin origin, boolean queryTuningAddVersion, int profilingBase, double profilingRate) {
this.origin = origin;
this.queryTuningAddVersion = queryTuningAddVersion;
this.profilingBase = profilingBase;
this.profilingRate = profilingRate;
}
public String getOriginalQuery() {
return originalQuery;
}
public void setOriginalQuery(String originalQuery) {
this.originalQuery = originalQuery;
}
/**
* Return true if this query should be profiled based on a percentage rate.
*/
public boolean isProfile() {
long count = requestCount.incrementAndGet();
if (count < profilingBase) {
return true;
}
long hits = profileCount.get();
if (profilingRate > (double) hits / count) {
profileCount.incrementAndGet();
return true;
} else {
return false;
}
}
/**
* Collect profiling information with the option to reset the underlying profiling detail.
*/
public void profilingCollection(BeanDescriptor<?> rootDesc, AutoTuneCollection req, boolean reset) {
lock.lock();
try {
if (nodeUsageMap.isEmpty()) {
return;
}
OrmQueryDetail detail = buildDetail(rootDesc);
AutoTuneCollection.Entry entry = req.add(origin, detail, originalQuery);
Collection<ProfileOriginQuery> values = queryStatsMap.values();
for (ProfileOriginQuery queryEntry : values) {
entry.addQuery(queryEntry.createEntryQuery(reset));
}
if (reset) {
nodeUsageMap.clear();
if (requestCount.get() > RESET_COUNT) {
requestCount.set(profilingBase);
profileCount.set(0);
}
}
} finally {
lock.unlock();
}
}
OrmQueryDetail buildDetail(BeanDescriptor<?> rootDesc) {
PathProperties pathProps = new PathProperties();
for (ProfileOriginNodeUsage statsNode : nodeUsageMap.values()) {
statsNode.buildTunedFetch(pathProps, rootDesc, queryTuningAddVersion);
}
OrmQueryDetail detail = new OrmQueryDetail();
for (Props props : pathProps.getPathProps()) {
if (!props.isEmpty()) {
detail.fetch(props.getPath(), props.getPropertiesAsString(), null);
}
}
detail.sortFetchPaths(rootDesc);
return detail;
}
/**
* Return the origin.
*/
public ObjectGraphOrigin getOrigin() {
return origin;
}
/**
* Collect query execution summary statistics.
* <p>
* This can give us a quick overview into bad lazy loading areas etc.
* </p>
*/
public void collectQueryInfo(ObjectGraphNode node, long beansLoaded, long micros) {
String key = node.path();
if (key == null) {
key = "";
}
ProfileOriginQuery stats = queryStatsMap.get(key);
if (stats == null) {
// a race condition but we don't care
stats = new ProfileOriginQuery(key);
queryStatsMap.put(key, stats);
}
stats.add(beansLoaded, micros);
}
/**
* Collect the usage information for from a instance for this node.
*/
public void collectUsageInfo(NodeUsageCollector.State profile) {
if (!profile.isEmpty()) {
getNodeStats(profile.node().path()).collectUsageInfo(profile);
}
}
private ProfileOriginNodeUsage getNodeStats(String path) {
lock.lock();
try {
// handle null paths as using ConcurrentHashMap
path = (path == null) ? "" : path;
ProfileOriginNodeUsage nodeStats = nodeUsageMap.get(path);
if (nodeStats == null) {
nodeStats = new ProfileOriginNodeUsage(path);
nodeUsageMap.put(path, nodeStats);
}
return nodeStats;
} finally {
lock.unlock();
}
}
}
@@ -1,128 +0,0 @@
package io.ebeaninternal.server.autotune.service;
import io.avaje.applog.AppLog;
import io.ebean.bean.NodeUsageCollector;
import io.ebean.text.PathProperties;
import io.ebean.util.SplitName;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.BeanProperty;
import io.ebeaninternal.server.deploy.BeanPropertyAssoc;
import io.ebeaninternal.server.el.ElPropertyValue;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
import static java.lang.System.Logger.Level.WARNING;
/**
* Collects usages statistics for a given node in the object graph.
*/
public class ProfileOriginNodeUsage {
private static final System.Logger logger = AppLog.getLogger(ProfileOriginNodeUsage.class);
private final ReentrantLock lock = new ReentrantLock();
private final String path;
private int profileCount;
private int profileUsedCount;
private boolean modified;
private final Set<String> aggregateUsed = new LinkedHashSet<>();
public ProfileOriginNodeUsage(String path) {
// handle null paths as using ConcurrentHashMap
this.path = "".equals(path) ? null : path;
}
protected void buildTunedFetch(PathProperties pathProps, BeanDescriptor<?> rootDesc, boolean addVersionProperty) {
lock.lock();
try {
BeanDescriptor<?> desc = rootDesc;
if (path != null) {
ElPropertyValue elGetValue = rootDesc.elGetValue(path);
if (elGetValue == null) {
logger.log(WARNING, "AutoTune: Can't find join for path[" + path + "] for " + rootDesc.name());
return;
} else {
BeanProperty beanProperty = elGetValue.beanProperty();
if (beanProperty instanceof BeanPropertyAssoc<?>) {
desc = ((BeanPropertyAssoc<?>) beanProperty).targetDescriptor();
}
}
}
BeanProperty toOneIdProperty = null;
boolean addedToPath = false;
for (String propName : aggregateUsed) {
BeanProperty beanProp = desc.findPropertyFromPath(propName);
if (beanProp == null) {
logger.log(WARNING, "AutoTune: Can't find property[" + propName + "] for " + desc.name());
} else {
if (beanProp.isId()) {
// remember and maybe add ToOne property to parent path
toOneIdProperty = beanProp;
} else if (beanProp instanceof BeanPropertyAssoc<?>) {
// intentionally skip
} else {
//noinspection StatementWithEmptyBody
if (beanProp.isLob() && !beanProp.isFetchEager()) {
// AutoTune will not include Lob's marked FetchLazy
// (which is the default for Lob's so typical).
} else {
addedToPath = true;
pathProps.addToPath(path, beanProp.name());
}
}
}
}
if ((modified || addVersionProperty) && desc != null) {
BeanProperty versionProp = desc.versionProperty();
if (versionProp != null) {
addedToPath = true;
pathProps.addToPath(path, versionProp.name());
}
}
if (toOneIdProperty != null && !addedToPath) {
// add ToOne property to parent path
ElPropertyValue assocOne = rootDesc.elGetValue(path);
pathProps.addToPath(SplitName.parent(path), assocOne.name());
}
} finally {
lock.unlock();
}
}
/**
* Collect usage from a node.
*/
protected void collectUsageInfo(NodeUsageCollector.State profile) {
lock.lock();
try {
Set<String> used = profile.used();
profileCount++;
if (!used.isEmpty()) {
profileUsedCount++;
aggregateUsed.addAll(used);
}
if (profile.isModified()) {
modified = true;
}
} finally {
lock.unlock();
}
}
@Override
public String toString() {
return "path[" + path + "] profileCount[" + profileCount + "] used[" + profileUsedCount + "] props" + aggregateUsed;
}
}
@@ -1,41 +0,0 @@
package io.ebeaninternal.server.autotune.service;
import java.io.Serializable;
import java.util.concurrent.atomic.LongAdder;
/**
* Used to accumulate query execution statistics for paths relative to the origin query.
*/
public class ProfileOriginQuery implements Serializable {
private static final long serialVersionUID = -1133958958072778811L;
private final String path;
private final LongAdder exeCount = new LongAdder();
private final LongAdder totalBeanLoaded = new LongAdder();
private final LongAdder totalMicros = new LongAdder();
public ProfileOriginQuery(String path) {
this.path = path;
}
public void add(long beansLoaded, long micros) {
exeCount.increment();
totalBeanLoaded.add(beansLoaded);
totalMicros.add(micros);
}
public AutoTuneCollection.EntryQuery createEntryQuery(boolean reset) {
if (reset) {
return new AutoTuneCollection.EntryQuery(path, exeCount.sumThenReset(), totalBeanLoaded.sumThenReset(), totalMicros.sumThenReset());
} else {
return new AutoTuneCollection.EntryQuery(path, exeCount.sum(), totalBeanLoaded.sum(), totalMicros.sum());
}
}
}
@@ -1,70 +0,0 @@
package io.ebeaninternal.server.autotune.service;
import io.ebeaninternal.server.autotune.model.Autotune;
import io.ebeaninternal.server.autotune.model.Origin;
import io.ebeaninternal.server.autotune.model.ProfileDiff;
import io.ebeaninternal.server.autotune.model.ProfileEmpty;
import io.ebeaninternal.server.autotune.model.ProfileNew;
import java.util.Comparator;
import java.util.List;
/**
* Sorts Autotune document by
*/
public class SortAutoTuneDocument {
/**
* Set the diff and new entries by bean type followed by key.
*/
public static void sort(Autotune document) {
ProfileDiff profileDiff = document.getProfileDiff();
if (profileDiff != null) {
profileDiff.getOrigin().sort(NAME_KEY_SORT);
}
ProfileNew profileNew = document.getProfileNew();
if (profileNew != null) {
profileNew.getOrigin().sort(NAME_KEY_SORT);
}
ProfileEmpty profileEmpty = document.getProfileEmpty();
if (profileEmpty != null) {
profileEmpty.getOrigin().sort(KEY_SORT);
}
List<Origin> origins = document.getOrigin();
if (!origins.isEmpty()) {
origins.sort(NAME_KEY_SORT);
}
}
private static final OriginNameKeySort NAME_KEY_SORT = new OriginNameKeySort();
private static final OriginKeySort KEY_SORT = new OriginKeySort();
/**
* Comparator sort by bean type then key.
*/
private static class OriginNameKeySort implements Comparator<Origin> {
@Override
public int compare(Origin o1, Origin o2) {
int comp = o1.getBeanType().compareTo(o2.getBeanType());
if (comp == 0) {
comp = o1.getKey().compareTo(o2.getKey());
}
return comp;
}
}
/**
* Comparator sort by bean type then key.
*/
private static class OriginKeySort implements Comparator<Origin> {
@Override
public int compare(Origin o1, Origin o2) {
return o1.getKey().compareTo(o2.getKey());
}
}
}
@@ -1,71 +0,0 @@
package io.ebeaninternal.server.autotune.service;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.server.autotune.model.Origin;
import io.ebeaninternal.server.querydefn.OrmQueryDetail;
import io.ebeaninternal.server.querydefn.OrmQueryDetailParser;
import java.io.Serializable;
/**
* Holds tuned query information. Is immutable so this represents the tuning at
* a given point in time.
*/
public class TunedQueryInfo implements Serializable {
private static final long serialVersionUID = 8661702592481810396L;
private final Origin origin;
private final OrmQueryDetail tunedDetail;
public TunedQueryInfo(Origin origin) {
this.origin = origin;
this.tunedDetail = new OrmQueryDetailParser(origin.getDetail()).parse();
}
/**
* Return the origin entry (includes call stack and bean type).
*/
public Origin getOrigin() {
return origin;
}
/**
* Return the tuned detail (for comparison with profiling information).
*/
public OrmQueryDetail getTunedDetail() {
return tunedDetail;
}
/**
* Tune the query by replacing its OrmQueryDetail with a tuned one.
*
* @return true if the query was tuned, otherwise false.
*/
public boolean tuneQuery(SpiQuery<?> query) {
if (tunedDetail == null) {
return false;
}
boolean tuned;
if (query.isDetailEmpty()) {
tuned = true;
// tune by 'replacement'
query.setDetail(tunedDetail.copy());
} else {
// tune by 'addition'
tuned = query.tuneFetchProperties(tunedDetail);
}
if (tuned) {
query.setAutoTuned(true);
}
return tuned;
}
@Override
public String toString() {
return tunedDetail.asString();
}
}
@@ -1,15 +0,0 @@
import io.ebeaninternal.server.autotune.AutoTuneServiceProvider;
import io.ebeaninternal.server.autotune.service.AutoTuneServiceFactory;
/**
* Provider of AutoTuneServiceProvider
*/
module io.ebean.autotune {
provides AutoTuneServiceProvider with AutoTuneServiceFactory;
requires io.ebean.api;
requires io.ebean.core;
requires java.xml;
requires java.xml.bind;
}
@@ -1 +0,0 @@
io.ebeaninternal.server.autotune.service.AutoTuneServiceFactory
@@ -1,55 +0,0 @@
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://ebean-orm.github.io/xml/ns/autotune"
targetNamespace="http://ebean-orm.github.io/xml/ns/autotune" elementFormDefault="qualified">
<!-- Root level type : profiling -->
<xsd:element name="autotune">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="origin" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="profileDiff" minOccurs="0" maxOccurs="1"/>
<xsd:element ref="profileNew" minOccurs="0" maxOccurs="1"/>
<xsd:element ref="profileEmpty" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="origin">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="callStack" type="xsd:string" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
<xsd:attribute name="key" type="xsd:string" use="required"/>
<xsd:attribute name="beanType" type="xsd:string"/>
<xsd:attribute name="detail" type="xsd:string"/>
<xsd:attribute name="original" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="profileDiff">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="origin" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="profileNew">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="origin" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="profileEmpty">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="origin" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>

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