Compare commits

...
Author SHA1 Message Date
Rob Bygrave 25d0675532 [maven-release-plugin] prepare release ebean-parent-13.9.0 2022-09-01 12:33:01 +12:00
Rob Bygrave c8ffad2831 Fix TestSubQuery for postgres compatible syntax with ANY(?) 2022-09-01 12:25:50 +12:00
Rob Bygrave 8233058d2e Bump ebean-agent to 13.9.0 (no effective change) 2022-09-01 12:23:00 +12:00
Rob Bygrave f7e00aab78 #2457 #2810 - Add ebean-joda-time as a dependency to ebean composite
- Add ebean-joda-time as a dependency to ebean composite
- Add ebean-joda-time to BOM
2022-09-01 11:37:28 +12:00
Rob BygraveandGitHub a111f3ff10 Merge pull request #2816 from ebean-orm/feature/2813-subQueryCompile-raceCondition
#2813 - Sometimes subquery use wrong alias in SQL
2022-09-01 11:18:23 +12:00
Rob Bygrave 29e2b81092 #2813 - Sometimes subquery use wrong alias in SQL
The reason for this is that as part of DefaultOrmQuery.copy() it uses
DefaultExpressionList.copy() and that assumed that expressions were
safe to share which is NOT the case for IN and EXISTS sub-query expressions
so InQueryExpression and ExistsQueryExpression

The effective fix for this is that DefaultExpressionList.copy() changes
to call SpiExpression.copy() and for InQueryExpression and ExistsQueryExpression
to implement that copy() by creating a copy of the sub-query.

A "side-fix" is that in DefaultOrmQuery.createExtraJoinsToSupportManyWhereClause()
it was creating an instance of ManyWhereJoins, then mutating it ... and if we
change that to only doing the assignment at the end (object assignment is atomic)
then racy access reading ManyWhereJoins would always get a fully completed non-mutating
instance of ManyWhereJoins. Noting this because it kind of points to where I think
the race condition is (in createExtraJoinsToSupportManyWhereClause()) but noting that
with the change to DefaultExpressionList.copy() this "side-fix" isn't required per say.
2022-08-31 17:24:55 +12:00
Rob Bygrave f07c7411fa No effective change - tidy SqlTreeAlias only 2022-08-30 12:37:27 +12:00
Rob BygraveandGitHub b4d037fa18 Merge pull request #2812 from ebean-orm/feature/inspect-tidy
IntelliJ inspect various improvements
2022-08-30 11:58:54 +12:00
Rob Bygrave e46bbcf8cf NaturalKeyQueryData use the matchSingleProperty + IntelliJ Inspect various improvements
The non-use of the matchSingleProperty meant it fell back to the multi-property match
2022-08-27 23:10:13 +12:00
Rob Bygrave 0c2ab729bc IntelliJ Inspect various improvements 2022-08-27 22:37:48 +12:00
Rob Bygrave 81ef967d9f IntelliJ Inspect various improvements 2022-08-27 22:02:32 +12:00
Rob BygraveandGitHub 2d733795c7 Merge pull request #2811 from ebean-orm/feature/refactor-json-docstore-methods
Refactor method names SpiJsonReader and DocStore types
2022-08-27 20:16:03 +12:00
Rob Bygrave 7ce85fe5f2 Refactor method names SpiJsonReader and DocStore types 2022-08-27 20:09:27 +12:00
Rob Bygrave e3e30cafdd Refactor tidy error and log messages - part 2 2022-08-27 17:15:08 +12:00
Rob Bygrave e51ac7de36 Refactor tidy error and log messages 2022-08-27 16:50:54 +12:00
Rob Bygrave ee71c79125 Tidy DefaultTypeManager, reduce unnecessary fields 2022-08-27 16:08:30 +12:00
Rob Bygrave bce2dec1cd Remove unused imports in DefaultTypeManager 2022-08-27 15:40:06 +12:00
Rob Bygrave 3f2d0ef520 Bump to 13.9.0-SNAPSHOT 2022-08-26 17:49:01 +12:00
Rob BygraveandGitHub bbb3ad9333 Merge pull request #2810 from ebean-orm/feature/extract-joda-time-module
Refactor extract ebean-joda-time module - move joda ScalarTypes
2022-08-26 17:34:28 +12:00
Rob Bygrave b7e62df371 Refactor extract ebean-joda-time module - move joda ScalarTypes
Moves the joda-time ScalarTypes into a new ebean-joda-time module. Include
the ebean-joda-time module in the classpath, and the extra types will be
service loaded (by DefaultTypeManager).
2022-08-26 17:32:31 +12:00
Rob BygraveandGitHub 7b3405ca25 Merge pull request #2809 from ebean-orm/feature/refactor-move-BasicTypeConverter
Refactor move BasicTypeConverter to ebean-core-type module
2022-08-26 15:30:16 +12:00
Rob Bygrave 9984b53070 Refactor move BasicTypeConverter to ebean-core-type module
Doing this in preparation for moving the joda-type ScalarTypes into their own module
2022-08-26 15:21:30 +12:00
Rob BygraveandGitHub 5e1aef1953 Merge pull request #2808 from ebean-orm/feature/refactor-move-internal-bindAndJson
Refactor move package - server.type.DataBind to server.bind, server.text.json -> server.json
2022-08-26 14:52:02 +12:00
Rob Bygrave 4c13a3a779 Refactor move package - server.type.DataBind to server.bind, server.text.json -> server.json
The DataBind classes don't need to be in with server.type anymore.
The server.text.json package can just reduce package nesting.
2022-08-26 14:51:19 +12:00
Rob BygraveandGitHub 100719ac1f Merge pull request #2807 from ebean-orm/feature/move-scalarTypeBaseVarchar
Refactor move ScalarTypeBaseDate, ScalarTypeBaseDateTime, ScalarTypeBaseVarchar in ebean-core-type
2022-08-26 13:22:23 +12:00
Rob Bygrave a13f581a65 Refactor ScalarTypeBaseDateTime, merge into ScalarTypeUtils both IsoJsonDateTimeParser and DecimalUtils
That is, merge the static util methods into ScalarTypeUtils
2022-08-26 13:15:55 +12:00
Rob Bygrave f319ee66ad Refactor move ScalarTypeBaseDateTime to ebean-core-type module 2022-08-26 13:02:42 +12:00
Rob Bygrave 6f249c7b72 No effective change, tidy ScalarTypeBaseDate only 2022-08-26 12:36:04 +12:00
Rob Bygrave 09e20934d7 Refactor move ScalarTypeBaseDate to ebean-core-type module 2022-08-26 12:30:50 +12:00
Rob Bygrave 5b22506b9b Refactor move ScalarTypeBaseVarchar to ebean-core-type module 2022-08-26 12:28:29 +12:00
Rob Bygrave 13a913428e DecimalUtils - remove unused methods converting between Instance and BigDecimal 2022-08-26 12:24:15 +12:00
Rob Bygrave 5667f1b118 ScalarTypeCharArray - remove unused method jsonWrite() with incorrect params 2022-08-26 12:20:36 +12:00
Rob BygraveandGitHub fcb8e4ca64 Merge pull request #2806 from ebean-orm/feature/refactor-scalarType-convertFromMillis
Refactor ScalarType, remove convertFromMillis() method (no longer needed)
2022-08-25 22:49:03 +12:00
Rob Bygrave c5e8b217e3 Refactor ScalarType, remove convertFromMillis() method (no longer needed)
Due to the move and change of CsvReader using StringParser ScalarType no longer
needs that general convertFromMillis() method. Note that date and dateTime ScalarTypes
still retain this conversion method.
2022-08-25 22:37:47 +12:00
Rob BygraveandGitHub f98b6b0e2a Merge pull request #2805 from ebean-orm/feature/extract-csv-reader-module
Extract csv reader module
2022-08-25 22:24:07 +12:00
Rob Bygrave f01d8174e8 Extract CsvReader - fix parent pom version 2022-08-25 22:17:20 +12:00
Rob Bygrave ccf790a630 Extract CsvReader - provider scope for ebean-core 2022-08-25 22:15:15 +12:00
Rob Bygrave efe80a534c Extract CsvReader - remove built in date, time, dateTime parsing - use StringParser instead
Just always use our own StringParser lambda function instead for parsing date, time and dateTime types.
2022-08-25 22:09:38 +12:00
Rob Bygrave 1aac01ead0 Extract CsvReader - move DefaultCsvCallback and add module-info 2022-08-25 17:49:11 +12:00
Rob Bygrave 216c43eea6 Extract CsvReader into separate ebean-csv-reader module 2022-08-25 17:25:49 +12:00
Rob BygraveandGitHub 5b2a8cdacb Merge pull request #2804 from ebean-orm/feature/refactor-move-ScalarTypeBase
Refactor move ScalarTypeBase + remove loadIgnore()
2022-08-25 13:47:14 +12:00
Rob Bygrave d2da4f7e52 Reorder methods on ScalarType only 2022-08-25 13:12:35 +12:00
Rob Bygrave 186019da7f Refactor ScalarType move format() default method from ScalarTypeBase to ScalarType 2022-08-25 13:00:30 +12:00
Rob Bygrave 7d1772cb54 Refactor ScalarType remove loadIgnore() method to implement in BeanProperty & DynamicPropertyBase 2022-08-25 12:53:44 +12:00
Rob Bygrave cd30c47951 Refactor move ScalarTypeBase to the ebean-core-type module (for external reuse)
Doing this in preparation for moving the joda-time scalar types into their own module
(so that they can become optional).
2022-08-25 12:42:12 +12:00
Rob BygraveandGitHub 4b11147b83 Merge pull request #2801 from ebean-orm/feature/drop-feature-OnQueryOnly
Remove the OnQueryOnly (rollback) feature
2022-08-25 12:30:16 +12:00
Rob BygraveandGitHub 6d7a5f07f0 Merge pull request #2803 from ebean-orm/feature/refactor-scalarType-methodNames
Refactor ScalarType methods from getters to accessors
2022-08-25 12:30:05 +12:00
Rob Bygrave 26f0605d72 Refactor ScalarType methods from getters to accessors 2022-08-25 12:25:38 +12:00
Rob BygraveandGitHub 4959053ce0 Merge pull request #2802 from ebean-orm/feature/remove-ScalarType-isDateTimeCapable
Remove ScalarType.isDateTimeCapable() ... (only used by CSV reader)
2022-08-25 12:17:26 +12:00
Rob Bygrave 10c9b2addd Remove ScalarType.isDateTimeCapable() ... (only used by CSV reader)
So the complexity cost doesn't justify itself against only being used
by CSV reader to validate when assigning a date/time format to a property
/ expression path.
2022-08-25 12:16:37 +12:00
Rob BygraveandGitHub 3092b59622 Merge pull request #2800 from ebean-orm/feature/refactor-databasePlatform
Refactor database platform - remove unused tableExists() method, rename getters to accessors
2022-08-25 12:01:49 +12:00
Rob Bygrave 8b086e0e49 Bump to 13.8.2-SNAPSHOT after release 2022-08-25 11:48:18 +12:00
Rob Bygrave 981c3595a8 [maven-release-plugin] prepare for next development iteration 2022-08-25 11:34:05 +12:00
Rob Bygrave 5414fa17cf [maven-release-plugin] prepare release ebean-parent-13.8.1 2022-08-25 11:33:58 +12:00
Rob Bygrave 807b017463 Bump to ebean-agent 13.8.1 2022-08-25 11:29:25 +12:00
Rob Bygrave 96b674114c Remove the OnQueryOnly (rollback) feature
The better approach these days is to use the read-only datasource with autoCommit
2022-08-25 11:26:55 +12:00
Rob Bygrave 456086fb3c Refactor DatabasePlatform - rename getters to accessors
Although this is public API these getters are not expected to be used
by application code so, I feel comfortable making this change.
2022-08-25 10:34:39 +12:00
Rob Bygrave 341b9a7449 Refactor DatabasePlatform - remove unused method tableExists() 2022-08-25 10:23:14 +12:00
Rob Bygrave 6c7cedc1f1 #2799 - Remove unused DatabasePlatform.treatEmptyStringsAsNull 2022-08-25 10:19:11 +12:00
Rob Bygrave 01155c3466 #2798 - SQL Anywhere: invalid escape character on like expression 2022-08-23 18:16:51 +12:00
Rob Bygrave c297ebda5a No effective change, fix typo in DatabasePlatform variable name 2022-08-23 16:09:45 +12:00
Rob BygraveandGitHub cec7492c10 Merge pull request #2797 from ebean-orm/feature/systemLogger-logging
Use AppLog and System.Logger for logging rather than slf4j-api
2022-08-23 15:36:49 +12:00
Rob Bygrave 4252445eb4 Use AppLog and System.Logger for logging - static imports 2022-08-23 15:18:46 +12:00
Rob Bygrave a23f241fff Use AppLog and System.Logger for logging rather than slf4j-api
The avaje-applog-slf4j dependency means this is still using
slf4j-api for implementation. Remove that dependency and
service load the desired implementation.
2022-08-18 22:44:31 +12:00
Rob BygraveandGitHub d145e6494d Merge pull request #2796 from ebean-orm/feature/final-mods-querybeans
Add missing final modifier on methods of query bean types
2022-08-18 16:55:43 +12:00
Rob Bygrave 2563d52ecf Fix versions after release 2022-08-18 16:52:10 +12:00
Rob Bygrave 8632aef268 Add missing final modifier on methods of query bean types 2022-08-18 16:49:39 +12:00
Rob Bygrave f827a292ff [maven-release-plugin] prepare for next development iteration 2022-08-18 16:04:31 +12:00
Rob Bygrave a027c630b1 [maven-release-plugin] prepare release ebean-parent-13.8.0 2022-08-18 16:04:25 +12:00
Rob Bygrave ab1a49abee Include ebean-types and persistence-api in BOM 2022-08-18 15:42:55 +12:00
Rob Bygrave bc5cf0e326 Bump to ebean-agent 13.8.0 (no effective change) 2022-08-18 15:36:48 +12:00
Rob Bygrave 348535ec6c Bump to 13.8.0-SNAPSHOT 2022-08-18 15:35:17 +12:00
Rob BygraveandGitHub 273f994cdf Merge pull request #2795 from ebean-orm/feature/refactor-methodNames-query
Refactor rename internal methods - io.ebeaninternal.server.query
2022-08-18 13:26:55 +12:00
Rob Bygrave c0a3f7e05d Refactor rename internal methods - io.ebeaninternal.server.query 2022-08-18 11:11:12 +12:00
Rob Bygrave 1bc9bab988 #2794 - ebean-test-containers - Handle SQLServer specific occasional fail on start 2022-08-18 10:19:02 +12:00
Rob Bygrave dc730fd97b #2788 - Support mapping @DbArray List<Float> to Postgres float4[] 2022-08-18 08:23:52 +12:00
Rob Bygrave 6c15115530 #2786 - Support logging Ebean version unknown
We don't really care if we can't determine the version so only log when we can read it.
2022-08-17 17:42:39 +12:00
Rob BygraveandGitHub 841b268fc7 Merge pull request #2791 from ebean-orm/feature/InternString
Just use String.intern() now that we are on min Java 11 runtime.
2022-08-17 17:38:41 +12:00
Rob BygraveandGitHub 6c8db9dec7 Merge pull request #2793 from ebean-orm/feature/2782-mariaDb-driver-update
#2782 - Support MariaDB jdbc driver update - Batched JDBC SQLException translation, SqlRow BLOB reading
2022-08-17 17:27:07 +12:00
Rob Bygrave 51d2f52d19 #2782 - Support MariaDB jdbc driver update - Batched JDBC SQLException translation, SqlRow BLOB reading
- Batched JDBC SQLException translation - Need to dig into nested exception to get cause error state
- SqlRow BLOB reading - BLOB can come as LONGVARBINARY (TestRawSqlBuilder)
- Fix test for history using system time (TestHistoryInsert)
- Fix SqlQueryCancelTest
- Fix TestSqlUpdateExceptions
2022-08-17 17:25:28 +12:00
Rob BygraveandGitHub ff45f9ab63 Merge pull request #2792 from ebean-orm/feature/2782-fwdOnlyFetchSize
#2782 #2783 - Forward only fetchSize() for MySql and MariaDB is Integer.MIN_VALUE and 1 respectively
2022-08-17 16:19:22 +12:00
Rob Bygrave 507027df0a #2782 #2783 - Forward only fetchSize() for MySql and MariaDB is Integer.MIN_VALUE and 1 respectively 2022-08-17 16:17:26 +12:00
Rob Bygrave 50d45c6da9 Just use String.intern() now that we are on min Java 11 runtime. 2022-08-17 15:21:16 +12:00
Rob BygraveandGitHub f5e9356451 Merge pull request #2783 from Wooza/patch-1
Bump mariadb-java-client to 3.0.7
2022-08-17 14:55:20 +12:00
Rob BygraveandGitHub dfe46cc011 Merge pull request #2779 from ebean-orm/feature/refactor-rename-queryplan-methods
Refactor rename internal methods for SpiQueryPlan and DbReadContext
2022-08-17 14:42:54 +12:00
Rob BygraveandGitHub 34cdbc5620 Merge pull request #2787 from ebean-orm/revert-2722-feature/jakarta-jaxb
Revert "Migrate to Jakarta JAXB (jakarta.xml.bind <- javax.xml.bind)"
2022-08-16 17:05:27 +12:00
Rob Bygrave 595c057964 #2784 - Fix @Return javadoc for TQRootBean.findSingleAttribute() 2022-08-16 17:03:07 +12:00
Rob BygraveandGitHub 73bc9e516e Revert "Migrate to Jakarta JAXB (jakarta.xml.bind <- javax.xml.bind)" 2022-08-15 15:14:57 +12:00
Rob BygraveandGitHub 6a4cfb231d Merge pull request #2785 from ebean-orm/feature/2784-findSingleAttribute-nullable
#2784 - Correct documentation for TQRootBean.findSingleAttribute with @Nullable
2022-08-12 15:54:28 +12:00
Rob Bygrave 4523db85c3 Fix for generated migration index files in test 2022-08-12 15:54:09 +12:00
Rob Bygrave d703709f14 #2784 - Correct documentation for TQRootBean.findSingleAttribute with @Nullable 2022-08-12 15:50:17 +12:00
FloandGitHub e8afba7ed2 Use fetch size 1 instead of Integer.MIN_VALUE 2022-08-10 19:26:40 +02:00
FloandGitHub dd5bb3edff Bump mariadb-java-client to 3.0.7 2022-08-10 12:48:02 +02:00
Rob Bygrave 475b05052e Refactor rename internal methods for SpiQueryPlan and DbReadContext
Change the getter methods to use accessor style
2022-08-09 15:43:16 +12:00
Rob Bygrave 4cc012b974 Bump to 13.7.1-SNAPSHOT 2022-08-09 14:26:04 +12:00
Rob Bygrave c214fe52f0 Bump to 13.7.0 2022-08-09 13:59:43 +12:00
Rob Bygrave 4f57bd3511 Prepare release, set kotlin-querybean-generator used version 2022-08-09 13:53:38 +12:00
Rob Bygrave 82dc2d031a Change EA build to just use EA,GA - remove loom,metropolis,panama 2022-08-09 12:38:04 +12:00
Rob Bygrave a831ee9ac9 Bump to 13.7.0-SNAPSHOT 2022-08-09 12:35:00 +12:00
Rob Bygrave e01b20aecb Bump to 13.7.0-SNAPSHOT 2022-08-09 12:33:44 +12:00
Rob Bygrave 58713c7083 #2770 - Improve test asserts with SqlQuery usingTransaction() 2022-08-09 12:31:36 +12:00
Rob BygraveandGitHub 2df6f2e5fb Merge pull request #2770 from ebean-orm/feature/sqlquery-useTransaction
Add SqlQuery usingTransaction() for consistency and deprecate ExtendedServer API
2022-08-09 11:59:10 +12:00
Rob Bygrave 19724e71db Merge branch 'master' of github.com:ebean-orm/ebean 2022-08-09 11:28:33 +12:00
Rob BygraveandGitHub 1a74c7ca85 Merge pull request #2778 from ebean-orm/feature/metric-naming-convention
Support a naming convention function that can be applied to metrics names for reporting
2022-08-09 11:10:51 +12:00
Rob BygraveandGitHub 0356f595c8 Merge pull request #2777 from ebean-orm/dependabot/maven/ebean-postgis/org.postgresql-postgresql-42.4.1
Bump postgresql from 42.3.3 to 42.4.1 in /ebean-postgis
2022-08-09 10:48:38 +12:00
Rob BygraveandGitHub b12a9adf46 Merge pull request #2776 from ebean-orm/dependabot/maven/ebean-test/org.postgresql-postgresql-42.4.1
Bump postgresql from 42.3.3 to 42.4.1 in /ebean-test
2022-08-09 10:48:24 +12:00
Rob BygraveandGitHub 2b874189a2 Merge pull request #2775 from ebean-orm/dependabot/maven/ebean-core/org.postgresql-postgresql-42.4.1
Bump postgresql from 42.3.3 to 42.4.1 in /ebean-core
2022-08-09 10:47:56 +12:00
Rob Bygrave f2d95cf012 Merge branch 'master' of github.com:ebean-orm/ebean 2022-08-09 10:47:09 +12:00
Rob Bygrave d4825cd72c Bump ebean-agent to 13.7.0 2022-08-09 10:46:55 +12:00
Rob Bygrave c7bd6c8bde Support a naming convention function that can be applied to metrics names for reporting
For example, can apply a lower case underscore naming convention to the metrics names. This
can be done such that it doesn't have to be applied every time the metrics are collected and
reported.
2022-08-08 21:34:00 +12:00
dependabot[bot]andGitHub c9b3a91539 Bump postgresql from 42.3.3 to 42.4.1 in /ebean-postgis
Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.3.3 to 42.4.1.
- [Release notes](https://github.com/pgjdbc/pgjdbc/releases)
- [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md)
- [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.3.3...REL42.4.1)

---
updated-dependencies:
- dependency-name: org.postgresql:postgresql
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-06 05:55:53 +00:00
dependabot[bot]andGitHub 565f6c5ac6 Bump postgresql from 42.3.3 to 42.4.1 in /ebean-test
Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.3.3 to 42.4.1.
- [Release notes](https://github.com/pgjdbc/pgjdbc/releases)
- [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md)
- [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.3.3...REL42.4.1)

---
updated-dependencies:
- dependency-name: org.postgresql:postgresql
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-06 05:55:53 +00:00
dependabot[bot]andGitHub 356b5e58d9 Bump postgresql from 42.3.3 to 42.4.1 in /ebean-core
Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.3.3 to 42.4.1.
- [Release notes](https://github.com/pgjdbc/pgjdbc/releases)
- [Changelog](https://github.com/pgjdbc/pgjdbc/blob/master/CHANGELOG.md)
- [Commits](https://github.com/pgjdbc/pgjdbc/compare/REL42.3.3...REL42.4.1)

---
updated-dependencies:
- dependency-name: org.postgresql:postgresql
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-06 05:55:52 +00:00
Rob BygraveandGitHub 094fc3f4b8 Merge pull request #2772 from FOCONIS/add-ebean-annotation-to-bom
Add ebean-annotation to BOM
2022-08-04 10:16:06 +12:00
Roland PramlandGitHub cfb9d860f9 Merge branch 'ebean-orm:master' into add-ebean-annotation-to-bom 2022-08-03 14:40:22 +02:00
Rob Bygrave 2f7b553d7c Bump kotlin-querybean-generator version 2022-08-03 22:18:09 +12:00
Roland Praml ec9481420c Add ebean-annotation to BOM 2022-08-03 11:34:31 +02:00
Rob BygraveandGitHub 797e1f4bd2 Merge pull request #2767 from ebean-orm/feature/2766-json-ref-bean
#2766 Explicitly specify disableLazyLoad on beans created from JSON by default
2022-08-03 20:36:19 +12:00
Rob BygraveandGitHub a14507e563 Merge pull request #2765 from ebean-orm/feature/2762-forUpdate-pagingList-count
#2762 - forUpdate is NOT included in query copy() method
2022-08-03 20:35:45 +12:00
Rob BygraveandGitHub 732f0e13e2 Merge pull request #2745 from ebean-orm/feature/2733-rename-moduleInfoLoader
#2733 - Rename ModuleInfoLoader to EntityClassRegister and _Ebean$ModuleInfo to EbeanEntityRegister
2022-08-03 20:35:21 +12:00
Rob BygraveandGitHub a6304ebe8b Merge pull request #2722 from ebean-orm/feature/jakarta-jaxb
Migrate to Jakarta JAXB (jakarta.xml.bind <- javax.xml.bind)
2022-08-03 20:34:55 +12:00
Rob Bygrave 4050d5e900 Add SqlQuery usingTransaction() for consistency and deprecate ExtendedServer API
- The ExtendedServer API is replaced by use of query usingTransaction()
- Add SqlQuery usingTransaction() for consistency with Query and DtoQuery
2022-08-02 15:35:00 +12:00
Rob Bygrave 87cc95f60d Bump to 13.6.7-SNAPSHOT after release 2022-08-02 09:12:00 +12:00
Rob Bygrave e8d663c94e [maven-release-plugin] prepare for next development iteration 2022-08-02 08:56:47 +12:00
Rob Bygrave effcb86174 [maven-release-plugin] prepare release ebean-parent-13.6.6 2022-08-02 08:56:41 +12:00
Rob Bygrave 7e50e6e427 Bump ebean-agent to 13.6.6 (no functional change) 2022-08-02 08:49:09 +12:00
Rob Bygrave 47b940f672 #2760 - Add ServerMetrics.asData() ... for consistency 2022-08-02 08:35:48 +12:00
Rob Bygrave 01d5aa8199 #2760 - Add ServerMetrics.asJson() ... to support conversion of collected metrics to json 2022-08-01 16:54:49 +12:00
Rob Bygrave 7474430a63 #2768 - ENH: Add eqIfPresent() - a helper expression for fluid style when some EQ are optional 2022-08-01 16:36:09 +12:00
Rob Bygrave ed830aeb0c #2766 - Explicitly specify disableLazyLoad on beans created from JSON (default)
- Beans created from JSON default to disableLazyLoad true
- Explicitly use new JsonReadOptions().setEnableLazyLoading(true) when lazy loading is needed
2022-08-01 15:43:08 +12:00
Rob Bygrave 54cbdae22d #2766 - Failing test for reference bean created from JSON allows lazy loading. 2022-08-01 15:38:11 +12:00
Rob Bygrave bb77d6588a #2762 - forUpdate is NOT included in query copy() method
The copy() method is used by findPagedList(), findIds(), findFutureList() etc.
2022-08-01 11:35:58 +12:00
Rob Bygrave f930471beb Update README to put build status badges at top 2022-08-01 10:19:32 +12:00
Rob Bygrave 3a84e4183d Fix platform specific asserts with TestQuerySingleAttribute using limit/offset 2022-08-01 09:45:33 +12:00
Rob Bygrave d12dc9bfed Fix platform specific asserts with TestQuerySingleAttribute using limit/offset 2022-08-01 09:37:34 +12:00
Rob Bygrave 5f689dee1b No effective change - tidy test only, TestQuerySingleAttribute 2022-08-01 09:20:38 +12:00
Rob Bygrave 08d3a3b2f5 Fix platform specific assert in test TestQuerySingleAttribute 2022-08-01 09:16:55 +12:00
Rob Bygrave 4ed5f91963 #2756 - Fix for Bug findSingleAttributeList o2m maxrows
Allow maxRows use in this case
2022-07-29 22:37:06 +12:00
Rob Bygrave f36e4543ee #2755 - Effectively fixed by #2753, format only change 2022-07-29 18:08:31 +12:00
Rob Bygrave 37f92bf967 Merge branch 'bug-singleattributelist-o2m-orderby' of github.com:FOCONIS/ebean into FOCONIS-bug-singleattributelist-o2m-orderby 2022-07-29 18:07:22 +12:00
Rob Bygrave eb14531b66 #2754 - Adjust test query for oneToMany_notNull() 2022-07-29 17:29:56 +12:00
Rob Bygrave 6c1a3647f9 Merge branch 'bug-findsingleattributelist-o2m-notnull' of github.com:FOCONIS/ebean into FOCONIS-bug-findsingleattributelist-o2m-notnull 2022-07-29 17:29:10 +12:00
Rob Bygrave fa9e9be003 #2753 - Fix for, Bug findSingleAttributeList o2m distinct 2022-07-29 17:12:51 +12:00
Rob Bygrave 02ead0bcdb Merge branch 'bug-findsingleattributelist-o2m-distinct' of github.com:FOCONIS/ebean into FOCONIS-bug-findsingleattributelist-o2m-distinct 2022-07-29 16:58:04 +12:00
Rob Bygrave 892e7bc84a Update test migration output due to remove of - NOTE: table has @History #2764
-- NOTE: table has @History - special migration may be necessary
2022-07-29 16:47:42 +12:00
Rob Bygrave 4bdcd49eab Javadoc tidy for Database and DB 2022-07-29 16:46:18 +12:00
Rob Bygrave 7a0de51721 Javadoc tidy for Database and DB 2022-07-29 16:39:13 +12:00
Rob BygraveandGitHub 0ea44b36dc Merge pull request #2764 from FOCONIS/fix-history-warning
Fix: DDL will get wrong hint for special migration
2022-07-29 08:40:24 +12:00
Rob BygraveandGitHub 35e1aa2737 Merge pull request #2763 from FOCONIS/fix-tojson-with-target
Fix: toJson must use setIntercept if target bean is passed
2022-07-29 08:38:42 +12:00
Roland Praml dab428ead5 Fix: DDL will get wrong hint for special migration 2022-07-28 15:10:37 +02:00
Roland Praml dbcc779731 Fix: toJson must use setIntercept if target bean is passed 2022-07-28 15:07:05 +02:00
Rob Bygrave 3c2b5f253f Tidy DLoadContext only 2022-07-27 22:28:15 +12:00
Rob Bygrave 31c20ca9a2 Format and imports on test code only 2022-07-27 22:26:26 +12:00
Rob Bygrave 0100d024d9 #2750 #2751 SoftDeleted entity included via lazy loading (Jackson serialisation)
The effective fix is in DLoadContext, only allow includeSoftDeletes to be set from
the query when the query is SpiQuery.Mode.NORMAL (not a lazy loading query).
2022-07-27 22:25:10 +12:00
Rob Bygrave 7a6d91c2f4 Merge branch 'update_ignores_soft_delete' of github.com:Ichtil/ebean into Ichtil-update_ignores_soft_delete 2022-07-27 21:22:16 +12:00
Rob Bygrave 31ac0f794f Add avaje-applog-slf4j dependency to ebean-api
This means by default AppLog logging goes to slf4j-api. Exclude this dependency to otherwise
control the AppLog System.Logger implementation.
2022-07-27 21:12:19 +12:00
Rob Bygrave 648bdf4553 Bump ebean-dll-runner to 2.2 2022-07-27 15:07:17 +12:00
Rob Bygrave bda0786924 #2760 - Add MetaInfoManager.metricsAsJson() ... to support conversion of collected metrics to json 2022-07-27 09:31:58 +12:00
Rob Bygrave 64311b2b9d Merge branch 'master' of github.com:ebean-orm/ebean 2022-07-26 21:25:54 +12:00
Rob Bygrave 743acf1f30 Bump avaje-config to 2.2 and ebean-datasource 8.2, these use AppLog.getLogger() to obtain System.Logger 2022-07-26 21:25:38 +12:00
Rob BygraveandGitHub 74fef50b67 Merge pull request #2758 from evolvedhat/master
Update README.md
2022-07-25 13:33:48 +12:00
evolvedhatandGitHub 185404a537 Merge pull request #1 from evolvedhat/evolvedhat-patch-1
Update README.md
2022-07-24 15:58:47 -07:00
Rob BygraveandGitHub ced5bb1089 Merge pull request #2757 from tobias-/patch-2
Add notIn(Query) to query beans
2022-07-21 08:18:24 +12:00
SnōwballandGitHub 52759e0510 Add notIn(Query) to query beans
Missing from query beans, but is available in the `ExpressionList` class.
2022-07-20 14:54:30 +02:00
Alexander Wagner 7db2210ba4 Bug findsingleattributelist o2m maxrows 2022-07-20 13:47:17 +02:00
Alexander Wagner 9b80dd97c9 Bug findsingleattributelist o2m orderby 2022-07-20 13:38:38 +02:00
Alexander Wagner 23ca0e716c Bug findsingleattributelist o2m notNull 2022-07-20 09:16:10 +02:00
Alexander Wagner eac03a0721 assert 2022-07-20 09:02:06 +02:00
Alexander Wagner cf8f099447 test for findSingleAttributeList o2m distinct 2022-07-20 09:02:06 +02:00
Rob Bygrave 6698dda8ae Improve Javadoc only for InterceptReadOnly and InterceptReadWrite 2022-07-20 10:45:27 +12:00
Rob Bygrave 1cb011df5b Improve Javadoc only for EntityBeanIntercept and InterceptReadOnly 2022-07-20 10:38:02 +12:00
Rob Bygrave ac1e1757e8 #2748 - Fix partially loaded bean scenario with .setDisableLazyLoading(true) .setBeanCacheMode(CacheMode.PUT) // force query to hit database 2022-07-20 08:16:43 +12:00
Rob Bygrave 48404fc85d #2748 - Fix setDisableLazyLoading(true) ... does not set fully loaded state [fully loaded bean scenario] 2022-07-20 07:55:42 +12:00
Rob Bygrave 9252e72581 #2748 - Fix such that .setLoadBeanCache(false) ... sets CacheMode.OFF 2022-07-20 07:45:20 +12:00
Jan Klička 64f99f5205 2750 failing test case 2022-07-15 17:49:10 +02:00
Rob Bygrave a5e3b9e68a #2749 - Bump ebean-datasource, ebean-annotation, ebean-types, persistence-api 2022-07-15 21:53:32 +12:00
evolvedhatandGitHub 4b43751512 Update README.md
Added descriptions from the website to give a better idea of what the project does.
2022-07-13 11:39:59 -07:00
Rob Bygrave 1d9db88050 #2733 - Rename ModuleInfoLoader to EntityClassRegister and _Ebean$ModuleInfo to EbeanEntityRegister 2022-07-11 15:35:46 +12:00
Rob Bygrave 5f6efd29ef #2743 - Postgres DDL - For create table, improve column ordering for tighter storage 2022-07-07 22:06:21 +12:00
Rob Bygrave 110bc614e4 #2743 - Postgres DDL - For create table, improve column ordering for tighter storage 2022-07-07 13:45:06 +12:00
Rob Bygrave ec89d31a32 Bump to 13.6.5-SNAPSHOT after release 2022-07-07 12:11:54 +12:00
Rob Bygrave fbae9cad8a #2742 - ModelContainer.applyChangeSet(ModelContainer.java:167) - IllegalArgumentException: No rule for io.ebeaninternal.dbmigration.migration.CreateSchema 2022-07-07 12:03:39 +12:00
Rob Bygrave fdfe2533c9 [maven-release-plugin] prepare for next development iteration 2022-07-06 20:59:11 +12:00
Rob Bygrave 2d65a3f1c9 Migrate to Jakarta JAXB (jakarta.xml.bind <- javax.xml.bind) 2022-06-17 18:10:14 +12:00
651 changed files with 5280 additions and 5195 deletions
+1 -3
View File
@@ -16,9 +16,7 @@ jobs:
strategy:
fail-fast: false
matrix:
## valhalla - failing on javadoc with:
## javadoc: error - The code being documented uses packages in the unnamed module, but the packages defined in https://ebean.io/platforms/ebean-platform-h2/apidocs/ are in named modules.
java_version: [GA,EA,loom,metropolis,panama]
java_version: [GA,EA]
os: [ubuntu-latest]
steps:
+34 -4
View File
@@ -1,9 +1,11 @@
[![Build](https://github.com/ebean-orm/ebean/actions/workflows/build.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/build.yml)
[![Maven Central : ebean](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/ebean-orm/ebean/blob/master/LICENSE)
[![Multi-JDK Build](https://github.com/ebean-orm/ebean/actions/workflows/multi-jdk-build.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/multi-jdk-build.yml)
[![JDK 18-ea](https://github.com/ebean-orm/ebean/actions/workflows/jdk-18-ea.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/jdk-18-ea.yml)
##### Build with database platforms
[![H2Database](https://github.com/ebean-orm/ebean/actions/workflows/h2database.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/h2database.yml)
[![Postgres](https://github.com/ebean-orm/ebean/actions/workflows/postgres.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/postgres.yml)
[![MySql](https://github.com/ebean-orm/ebean/actions/workflows/mysql.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/mysql.yml)
@@ -13,15 +15,42 @@
[![Yugabyte](https://github.com/ebean-orm/ebean/actions/workflows/yugabyte.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/yugabyte.yml)
#### Builds against EA (Early Access) versions of Java (19, Loom, panama etc)
##### Build with Java Early Access versions
[![ebean EA](https://github.com/ebean-orm/ebean/actions/workflows/jdk-ea.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/jdk-ea.yml)
[![datasource EA](https://github.com/ebean-orm/ebean-datasource/actions/workflows/jdk-ea.yml/badge.svg)](https://github.com/ebean-orm/ebean-datasource/actions/workflows/jdk-ea.yml)
[![migration EA](https://github.com/ebean-orm/ebean-migration/actions/workflows/jdk-ea.yml/badge.svg)](https://github.com/ebean-orm/ebean-migration/actions/workflows/jdk-ea.yml)
[![test-docker EA](https://github.com/ebean-orm/ebean-test-docker/actions/workflows/jdk-ea.yml/badge.svg)](https://github.com/ebean-orm/ebean-test-docker/actions/workflows/jdk-ea.yml)
[![ebean-agent EA](https://github.com/ebean-orm/ebean-agent/actions/workflows/jdk-ea.yml/badge.svg)](https://github.com/ebean-orm/ebean-agent/actions/workflows/jdk-ea.yml)
----------------------
# Ebean ORM for Java & Kotlin
**Multiple abstraction levels**: Ebean provides multiple levels of query abstraction [ORM Queries, mixed with SQL](https://ebean.io/docs/intro/queries/orm-query), [DTO Queries](https://ebean.io/docs/intro/queries/dto-query), [SqlQuery and JDBC](https://ebean.io/docs/intro/queries/sql-query).
Work at the highest level of abstraction and drop down levels as needed.
**Database migrations**: Built in [DB migration](https://ebean.io/docs/db-migrations/) generation and running. Support for "rebase" migrations as well as repeatable, init and 'normal' migrations.
**Awesome SQL**: Ebean produces SQL that you would hand craft yourself. Use great SQL, never generate SQL cartesian product, always honor relational limit/offset.
**Automated query tuning**: For ORM queries Ebean can profile the object graph being used and either [automatically tune the query](https://ebean.io/docs/query/background/autotune).
**Docker test containers**: [Docker test containers](https://ebean.io/docs/testing/) for all the supported databases. Get 100% test coverage on all the features of the database we use.
**Type safe queries**: We can build queries using type safe [query beans](https://ebean.io/docs/query/query-beans). IDE auto-complete when writing queries, compile time checking and it's FUN.
**Performance isn't optional**: Optimise queries to only fetch what we need (partial objects). Automatically avoid N+1 via a smart load context.
#### Benefits of ORM
* Automatically avoid N+1
* L2 caching to reduce database load
* Queries mixing database and L2 cache
* Automatically tune ORM queries
* Elasticsearch for search or L3 cache
----------------------
# Sponsors
<table>
<tbody>
@@ -51,13 +80,14 @@
</table>
## Need help?
Post questions or issues to the Ebean google group - https://groups.google.com/forum/#!forum/ebean
Post questions or issues to the [Ebean google group](https://groups.google.com/forum/#!forum/ebean)
or [github discussions](https://github.com/ebean-orm/ebean/discussions)
## Documentation
Goto [https://ebean.io/docs/](https://ebean.io/docs/)
## Maven central
[Maven central - io.ebean](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22io.ebean%22%20)
[Maven central - g:io.ebean](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22io.ebean%22%20)
## Building Ebean from source
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.6.5</version>
<version>13.9.0</version>
</parent>
<name>ebean-clickhouse</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-clickhouse</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.6.5</tag>
<tag>ebean-parent-13.9.0</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.6.5</version>
<version>13.9.0</version>
</parent>
<name>ebean-cockroach</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.6.5</tag>
<tag>ebean-parent-13.9.0</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.6.5</version>
<version>13.9.0</version>
</parent>
<name>ebean-db2</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-db2</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.6.5</tag>
<tag>ebean-parent-13.9.0</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.6.5</version>
<version>13.9.0</version>
</parent>
<name>ebean-h2</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.6.5</tag>
<tag>ebean-parent-13.9.0</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.6.5</version>
<version>13.9.0</version>
</parent>
<name>ebean-hana</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-hana</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.6.5</tag>
<tag>ebean-parent-13.9.0</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.6.5</version>
<version>13.9.0</version>
</parent>
<name>ebean-mariadb</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mariadb</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.6.5</tag>
<tag>ebean-parent-13.9.0</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.6.5</version>
<version>13.9.0</version>
</parent>
<name>ebean-mysql</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mysql</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.6.5</tag>
<tag>ebean-parent-13.9.0</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.6.5</version>
<version>13.9.0</version>
</parent>
<name>ebean-nuodb</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-nuodb</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.6.5</tag>
<tag>ebean-parent-13.9.0</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.6.5</version>
<version>13.9.0</version>
</parent>
<name>ebean-oracle</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-oracle</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.6.5</tag>
<tag>ebean-parent-13.9.0</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.6.5</version>
<version>13.9.0</version>
</parent>
<name>ebean-postgres</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.6.5</tag>
<tag>ebean-parent-13.9.0</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.6.5</version>
<version>13.9.0</version>
</parent>
<name>ebean-sqlite</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlite</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.6.5</tag>
<tag>ebean-parent-13.9.0</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.6.5</version>
<version>13.9.0</version>
</parent>
<name>ebean-sqlserver</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlserver</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.6.5</tag>
<tag>ebean-parent-13.9.0</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.6.5</version>
<version>13.9.0</version>
</parent>
<name>ebean-yugabyte</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.6.5</tag>
<tag>ebean-parent-13.9.0</tag>
</scm>
</project>
+12 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.6.5</version>
<version>13.9.0</version>
</parent>
<name>ebean (all platforms)</name>
@@ -16,13 +16,19 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-joda-time</artifactId>
<version>13.9.0</version>
</dependency>
<dependency>
@@ -35,18 +41,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-all</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.6.5</tag>
<tag>ebean-parent-13.9.0</tag>
</scm>
</project>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.6.5</version>
<version>13.9.0</version>
</parent>
<artifactId>composites</artifactId>
+23 -13
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.6.5</version>
<version>13.9.0</version>
</parent>
<name>ebean api</name>
@@ -13,21 +13,23 @@
<dependencies>
<!--
Projects are expected to explicit depend on version
of slf4j that they want to use
-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
<scope>provided</scope>
<groupId>io.avaje</groupId>
<artifactId>avaje-applog</artifactId>
<version>1.0</version>
</dependency>
<!-- exclude avaje-applog-slf4j to direct logging to something else -->
<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-applog-slf4j</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-config</artifactId>
<version>2.1</version>
<version>2.2</version>
</dependency>
<!--
@@ -43,19 +45,19 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>persistence-api</artifactId>
<version>2.2.5</version>
<version>${ebean-persistence-api.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-annotation</artifactId>
<version>8.0</version>
<version>${ebean-annotation.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-types</artifactId>
<version>2.2</version>
<version>${ebean-types.version}</version>
</dependency>
<dependency>
@@ -64,6 +66,14 @@
<version>${ebean-datasource.version}</version>
</dependency>
<!-- Support MdcBackgroundExecutorWrapper -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
<optional>true</optional>
</dependency>
<!-- Jackson core used internally by Ebean -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
+5 -12
View File
@@ -5,7 +5,6 @@ import io.avaje.lang.Nullable;
import io.ebean.annotation.TxIsolation;
import io.ebean.cache.ServerCacheManager;
import io.ebean.plugin.Property;
import io.ebean.text.csv.CsvReader;
import io.ebean.text.json.JsonContext;
import javax.persistence.OptimisticLockException;
@@ -238,7 +237,7 @@ public final class DB {
}
/**
* The batch will be flushing automatically but you can use this to explicitly
* The batch will be flushing automatically but, you can use this to explicitly
* flush the batch if you like.
* <p>
* Flushing occurs automatically when:
@@ -785,12 +784,6 @@ public final class DB {
return getDefault().createUpdate(beanType, ormUpdate);
}
/**
* Create a CsvReader for a given beanType.
*/
public static <T> CsvReader<T> createCsvReader(Class<T> beanType) {
return getDefault().createCsvReader(beanType);
}
/**
* Create a named query.
@@ -961,7 +954,7 @@ public final class DB {
*
* DB.execute(scope, new TxRunnable() {
* public void run() {
* User u1 = DB.find(User.class, 1);
* User u1 = DB.find(User.class, 1);
* ...
* }
* });
@@ -1010,9 +1003,9 @@ public final class DB {
*
* DB.executeCall(scope, new Callable<String>() {
* public String call() {
* User u1 = DB.find(User.class, 1);
* ...
* return u1.getEmail();
* User u1 = DB.find(User.class, 1);
* ...
* return u1.getEmail();
* }
* });
* }</pre>
+113 -217
View File
@@ -9,7 +9,6 @@ import io.ebean.config.DatabaseConfig;
import io.ebean.meta.MetaInfoManager;
import io.ebean.plugin.Property;
import io.ebean.plugin.SpiServer;
import io.ebean.text.csv.CsvReader;
import io.ebean.text.json.JsonContext;
import javax.persistence.OptimisticLockException;
@@ -30,10 +29,8 @@ import java.util.concurrent.Callable;
* singleton (see {@link DatabaseConfig#setRegister(boolean)}). The DB
* singleton is essentially a map of Database's that have been registered
* with it.
* </p>
* <p>
* The Database can then be retrieved later via {@link DB#byName(String)}.
* </p>
*
* <h5>The 'default' Database</h5>
* <p>
@@ -41,18 +38,15 @@ import java.util.concurrent.Callable;
* (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.
* </p>
*
* <h5>Constructing a Database</h5>
* <p>
* Database's are constructed by the DatabaseFactory. They can be created
* Databases are constructed by the DatabaseFactory. They can be created
* programmatically via {@link DatabaseFactory#create(DatabaseConfig)} or they
* can be automatically constructed on demand using configuration information in
* the application.properties file.
* </p>
*
* <h5>Example: Get a Database</h5>
* <p>
* <pre>{@code
*
* // Get access to the Human Resources Database
@@ -71,22 +65,19 @@ import java.util.concurrent.Callable;
*
* <h5>Database vs DB API</h5>
* <p>
* Database provides additional API compared with DB. For example it
* Database provides additional API compared with DB. For example, it
* provides more control over the use of Transactions that is not available in
* the DB API.
* </p>
*
* <p>
* <em>External Transactions:</em> If you wanted to use transactions created
* externally to Ebean then Database provides additional methods where you
* can explicitly pass a transaction (that can be created externally).
* </p>
*
* <p>
* <em>Bypass ThreadLocal Mechanism:</em> If you want to bypass the built in
* <em>Bypass ThreadLocal Mechanism:</em> If you want to bypass the built-in
* ThreadLocal transaction management you can use the createTransaction()
* method. Example: a single thread requires more than one transaction.
* </p>
*
* @see DB
* @see DatabaseFactory
@@ -104,12 +95,10 @@ public interface Database {
* Shutdown the Database instance programmatically.
* <p>
* This method is not normally required. Ebean registers a shutdown hook and shuts down cleanly.
* </p>
* <p>
* If the under underlying DataSource is the Ebean implementation then you
* also have the option of shutting down the DataSource and deregistering the
* also have the option of shutting down the DataSource and de-registering the
* JDBC driver.
* </p>
*
* @param shutdownDataSource if true then shutdown the underlying DataSource if it is the Ebean
* DataSource implementation.
@@ -155,10 +144,10 @@ public interface Database {
* <p>
* Note many platforms have multiple specific platform types so often we want to
* get the base platform via {@link Platform#base()}.
* </p>
*
* <pre>{@code
*
* Platform platform = database.getPlatform().base();
* Platform platform = database.platform().base();
* if (platform == Platform.MYSQL) {
* // do MySql specific function
* }
@@ -178,7 +167,6 @@ 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.
* </p>
*/
BeanState beanState(Object bean);
@@ -192,7 +180,6 @@ public interface Database {
* <p>
* For example, if the id value passed in is a String but ought to be a Long or UUID etc
* then it will automatically be converted.
* </p>
*
* @param bean The entity bean to set the id value on.
* @param id The id value to set.
@@ -204,7 +191,6 @@ public interface Database {
* <p>
* When null is passed in for b, then the 'OldValues' of a is used for the
* difference comparison.
* </p>
*/
Map<String, ValuePair> diff(Object newBean, Object oldBean);
@@ -214,14 +200,9 @@ public interface Database {
* Useful if you use BeanPostConstructListeners or &#64;PostConstruct Annotations.
* In this case you should not use "new Bean...()". Making all bean constructors protected
* could be a good idea here.
* </p>
*/
<T> T createEntityBean(Class<T> type);
/**
* Create a CsvReader for a given beanType.
*/
<T> CsvReader<T> createCsvReader(Class<T> beanType);
/**
* Create an Update query to perform a bulk update.
@@ -248,7 +229,6 @@ public interface Database {
* Create a named query.
* <p>
* For RawSql the named query is expected to be in ebean.xml.
* </p>
*
* @param beanType The type of entity bean
* @param namedQuery The name of the query
@@ -304,17 +284,14 @@ public interface Database {
* <p>
* You can use the methods on the Query object to specify fetch paths,
* predicates, order by, limits etc.
* </p>
* <p>
* You then use findList(), findSet(), findMap() and findOne() to execute
* the query and return the collection or bean.
* </p>
* <p>
* Note that a query executed by {@link Query#findList()}
* {@link Query#findSet()} etc will execute against the same Database from
* which is was created.
* </p>
* <p>
*
* <pre>{@code
*
* // Find order 2 specifying explicitly the parts of the object graph to
@@ -344,7 +321,7 @@ public interface Database {
* Create a query using native SQL.
* <p>
* The native SQL can contain named parameters or positioned parameters.
* </p>
*
* <pre>{@code
*
* String sql = "select c.id, c.name from customer c where c.name like ? order by c.name";
@@ -367,12 +344,10 @@ public interface Database {
* <p>
* This will only work when a IdGenerator is on the bean such as for beans
* that use a DB sequence or UUID.
* </p>
* <p>
* For DB's supporting getGeneratedKeys and sequences such as Oracle10 you do
* not need to use this method generally. It is made available for more
* complex cases where it is useful to get an ID prior to some processing.
* </p>
*/
Object nextId(Class<?> beanType);
@@ -381,10 +356,8 @@ public interface Database {
* going back to the database.
* <p>
* This produces and returns a new list with the sort and filters applied.
* </p>
* <p>
* Refer to {@link Filter} for an example of its use.
* </p>
*/
<T> Filter<T> filter(Class<T> beanType);
@@ -401,12 +374,10 @@ public interface Database {
* <p>
* If you leave off any keywords the defaults are ascending order and treating
* nulls as high values.
* </p>
* <p>
* Note that the sorting uses a Comparator and Collections.sort(); and does
* not invoke a DB query.
* </p>
* <p>
*
* <pre>{@code
*
* // find orders and their customers
@@ -431,17 +402,15 @@ public interface Database {
<T> void sort(List<T> list, String sortByClause);
/**
* Create a orm update where you will supply the insert/update or delete
* Create an orm update where you will supply the insert/update or delete
* statement (rather than using a named one that is already defined using the
* &#064;NamedUpdates annotation).
* <p>
* The orm update differs from the sql update in that it you can use the bean
* name and bean property names rather than table and column names.
* </p>
* <p>
* An example:
* </p>
* <p>
*
* <pre>{@code
*
* // The bean name and properties - "topic","postCount" and "id"
@@ -466,7 +435,6 @@ public interface Database {
* <p>
* DTO beans are just normal bean like classes with public constructor(s) and setters.
* They do not need to be registered with DB before use.
* </p>
*
* @param dtoType The type of the DTO bean the rows will be mapped into.
* @param sql The SQL query to execute.
@@ -479,7 +447,6 @@ public interface Database {
* <p>
* DTO beans are just normal bean like classes with public constructor(s) and setters.
* They do not need to be registered with DB before use.
* </p>
*
* @param dtoType The type of the DTO bean the rows will be mapped into.
* @param namedQuery The name of the query
@@ -493,10 +460,8 @@ public interface Database {
*
* <p>
* Refer to {@link DtoQuery} for native sql queries returning DTO beans.
* </p>
* <p>
* Refer to {@link #findNative(Class, String)} for native sql queries returning entity beans.
* </p>
*/
SqlQuery sqlQuery(String sql);
@@ -505,11 +470,9 @@ public interface Database {
* <p>
* Use this to execute a Insert Update or Delete statement. The statement will
* be native to the database and contain database table and column names.
* </p>
*
* <p>
* See {@link SqlUpdate} for example usage.
* </p>
*
* @return The SqlUpdate instance to set parameters and execute
*/
@@ -522,7 +485,7 @@ public interface Database {
/**
* Register a TransactionCallback on the currently active transaction.
* <p/>
* <p>
* If there is no currently active transaction then a PersistenceException is thrown.
*
* @param transactionCallback The transaction callback to be registered with the current transaction.
@@ -536,7 +499,6 @@ public interface Database {
* You will want to do this if you want multiple Transactions in a single
* thread or generally use transactions outside of the TransactionThreadLocal
* management.
* </p>
*/
Transaction createTransaction();
@@ -544,7 +506,6 @@ public interface Database {
* Create a new transaction additionally specifying the isolation level.
* <p>
* Note that this transaction is NOT stored in a thread local.
* </p>
*/
Transaction createTransaction(TxIsolation isolation);
@@ -552,86 +513,77 @@ public interface Database {
* Start a transaction with 'REQUIRED' semantics.
* <p>
* With REQUIRED semantics if an active transaction already exists that transaction will be used.
* </p>
* <p>
* The transaction is stored in a ThreadLocal variable and typically you only
* need to use the returned Transaction <em>IF</em> you wish to do things like
* use batch mode, change the transaction isolation level, use savepoints or
* log comments to the transaction log.
* </p>
* <p>
* Example of using a transaction to span multiple calls to find(), save()
* etc.
* </p>
* <p>
* Example of using a transaction to span multiple calls to find(), save() etc.
*
* <h3>Using try with resources</h3>
* <pre>{@code
*
* // start a transaction (stored in a ThreadLocal)
* // start a transaction (stored in a ThreadLocal)
* try (Transaction txn = database.beginTransaction()) {
*
* try (Transaction txn = database.beginTransaction()) {
* Order order = database.find(Order.class, 10);
* ...
* database.save(order);
*
* Order order = database.find(Order.class, 10);
* ...
* database.save(order);
*
* txn.commit();
* }
* txn.commit();
* }
*
* }</pre>
* <p>
*
* <h3>Using try finally block</h3>
* <pre>{@code
*
* // start a transaction (stored in a ThreadLocal)
* Transaction txn = database.beginTransaction();
* try {
* Order order = database.find(Order.class,10);
* // start a transaction (stored in a ThreadLocal)
* Transaction txn = database.beginTransaction();
* try {
* Order order = database.find(Order.class,10);
*
* database.save(order);
*
* txn.commit();
*
* } finally {
* txn.end();
* }
* database.save(order);
* txn.commit();
*
* } finally {
* txn.end();
* }
* }</pre>
* <p>
*
* <h3>Transaction options</h3>
* <pre>{@code
*
* try (Transaction txn = database.beginTransaction()) {
* try (Transaction txn = database.beginTransaction()) {
*
* // explicitly turn on/off JDBC batch use
* txn.setBatchMode(true);
* txn.setBatchSize(50);
* // explicitly turn on/off JDBC batch use
* txn.setBatchMode(true);
* txn.setBatchSize(50);
*
* // control flushing when mixing save and queries
* txn.setBatchFlushOnQuery(false);
* // control flushing when mixing save and queries
* txn.setBatchFlushOnQuery(false);
*
* // turn off persist cascade if needed
* txn.setPersistCascade(false);
* // turn off persist cascade if needed
* txn.setPersistCascade(false);
*
* // for large batch insert processing when we do not
* // ... need the generatedKeys, don't get them
* txn.setBatchGetGeneratedKeys(false);
* // for large batch insert processing when we do not
* // ... need the generatedKeys, don't get them
* txn.setBatchGetGeneratedKeys(false);
*
* // explicitly flush the JDBC batch buffer
* txn.flush();
* // explicitly flush the JDBC batch buffer
* txn.flush();
*
* ...
* ...
*
* txn.commit();
* }
* txn.commit();
* }
*
* }</pre>
* <p>
* <p>
* If you want to externalise the transaction management then you use
* createTransaction() and pass the transaction around to the various methods on
* Database yourself.
* </p>
*/
Transaction beginTransaction();
@@ -643,11 +595,9 @@ public interface Database {
/**
* Start a transaction typically specifying REQUIRES_NEW or REQUIRED semantics.
* <p>
* <p>
* Note that this provides an try finally alternative to using {@link #executeCall(TxScope, Callable)} or
* {@link #execute(TxScope, Runnable)}.
* </p>
* <p>
*
* <h3>REQUIRES_NEW example:</h3>
* <pre>{@code
* // Start a new transaction. If there is a current transaction
@@ -694,10 +644,8 @@ public interface Database {
* This only is useful when JDBC batch is used. Flush occurs automatically when the
* transaction commits or batch size is reached. This manually flushes the JDBC batch
* buffer.
* </p>
* <p>
* This is the same as <code>currentTransaction().flush()</code>.
* </p>
*/
void flush();
@@ -717,7 +665,6 @@ public interface Database {
* <p>
* Useful to put in a finally block to ensure the transaction is ended, rather
* than a rollbackTransaction() in each catch block.
* </p>
* <p>
* Code example:
* <p>
@@ -744,7 +691,6 @@ public interface Database {
* <p>
* Note that this resets OneToMany and ManyToMany properties so that if they
* are accessed a lazy load will refresh the many property.
* </p>
*/
void refresh(Object bean);
@@ -763,12 +709,11 @@ public interface Database {
* // Fetch order 1
* Order order = database.find(Order.class, 1);
* }</pre>
* <p>
*
* <p>
* If you want more control over the query then you can use createQuery() and
* Query.findOne();
* </p>
* <p>
*
* <pre>{@code
* // ... additionally fetching customer, customer shipping address,
* // order details, and the product associated with each order detail.
@@ -810,10 +755,9 @@ public interface Database {
* <p>
* This will not perform a query against the database unless some property other
* that the id property is accessed.
* </p>
* <p>
* It is most commonly used to set a 'foreign key' on another bean like:
* </p>
*
* <pre>{@code
*
* Product product = database.getReference(Product.class, 1);
@@ -853,12 +797,10 @@ public interface Database {
* <p>
* The extended API has the options for executing queries that take an explicit
* transaction as an argument.
* </p>
* <p>
* Typically we only need to use the extended API when we do NOT want to use the
* Typically, we only need to use the extended API when we do NOT want to use the
* usual ThreadLocal based mechanism to obtain the current transaction but instead
* supply the transaction explicitly.
* </p>
*/
ExtendedServer extended();
@@ -867,32 +809,27 @@ public interface Database {
* <p>
* If there is no current transaction one will be created and committed for
* you automatically.
* </p>
* <p>
* Save can cascade along relationships. For this to happen you need to
* specify a cascade of CascadeType.ALL or CascadeType.PERSIST on the
* OneToMany, OneToOne or ManyToMany annotation.
* </p>
* <p>
* In this example below the details property has a CascadeType.ALL set so
* saving an order will also save all its details.
* </p>
* <p>
*
* <pre>{@code
* public class Order { ...
*
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
* List<OrderDetail> details;
* ...
* List<OrderDetail> details;
* ...
* }
* }</pre>
* <p>
* <p>
* When a save cascades via a OneToMany or ManyToMany Ebean will automatically
* set the 'parent' object to the 'detail' object. In the example below in
* saving the order and cascade saving the order details the 'parent' order
* will be set against each order detail when it is saved.
* </p>
*/
void save(Object bean) throws OptimisticLockException;
@@ -910,16 +847,13 @@ public interface Database {
* Delete the bean.
* <p>
* This will return true if the bean was deleted successfully or JDBC batch is being used.
* </p>
* <p>
* If there is no current transaction one will be created and committed for
* you automatically.
* </p>
* <p>
* If the Bean does not have a version property (or loaded version property) and
* the bean does not exist then this returns false indicating that nothing was
* deleted. Note that, if JDBC batch mode is used then this always returns true.
* </p>
*/
boolean delete(Object bean) throws OptimisticLockException;
@@ -927,12 +861,10 @@ public interface Database {
* Delete the bean with an explicit transaction.
* <p>
* This will return true if the bean was deleted successfully or JDBC batch is being used.
* </p>
* <p>
* If the Bean does not have a version property (or loaded version property) and
* the bean does not exist then this returns false indicating that nothing was
* deleted. However, if JDBC batch mode is used then this always returns true.
* </p>
*/
boolean delete(Object bean, Transaction transaction) throws OptimisticLockException;
@@ -1014,16 +946,13 @@ public interface Database {
* <p>
* If you wish to execute a Sql Select natively then you should use the
* SqlQuery object or DtoQuery.
* </p>
* <p>
* Note that the table modification information is automatically deduced and
* you do not need to call the DB.externalModification() method when you
* use this method.
* </p>
* <p>
* Example:
* </p>
* <p>
*
* <pre>{@code
*
* // example that uses 'named' parameters
@@ -1051,7 +980,6 @@ public interface Database {
* transaction.
* <p>
* This returns the number of rows that where inserted, updated or deleted.
* </p>
*/
int execute(Update<?> update);
@@ -1065,8 +993,7 @@ public interface Database {
* For making calls to stored procedures.
* <p>
* Example:
* </p>
* <p>
*
* <pre>{@code
*
* String sql = "{call sp_order_modify(?,?,?)}";
@@ -1091,23 +1018,19 @@ public interface Database {
* <p>
* If you use database.execute(UpdateSql) then the table modification information
* is automatically deduced and you do not need to call this method yourself.
* </p>
* <p>
* This information is used to invalidate objects out of the cache and
* potentially text indexes. This information is also automatically broadcast
* across the cluster.
* </p>
* <p>
* If there is a transaction then this information is placed into the current
* transactions event information. When the transaction is committed this
* information is registered (with the transaction manager). If this
* transaction is rolled back then none of the transaction event information
* registers including the information you put in via this method.
* </p>
* <p>
* If there is NO current transaction when you call this method then this
* information is registered immediately (with the transaction manager).
* </p>
*
* @param tableName the name of the table that was modified
* @param inserted true if rows where inserted into the table
@@ -1147,7 +1070,6 @@ public interface Database {
* Note: This checks only the root bean!
* <p>
* <pre>{@code
*
* // there is a unique constraint on title
*
* Document doc = new Document();
@@ -1176,7 +1098,7 @@ public interface Database {
* // uniqueProperties > [title]
* // custom msg > property[title] value[One flew over the cuckoo's nest]
*
* }
* }
*
* }</pre>
*
@@ -1200,13 +1122,12 @@ public interface Database {
* dirty so that it is not skipped.
* <p>
* <pre>{@code
* Customer customer = database.find(Customer, id);
*
* Customer customer = database.find(Customer, id);
*
* // mark the bean as dirty so that a save() or update() will
* // increment the version property
* database.markAsDirty(customer);
* database.save(customer);
* // mark the bean as dirty so that a save() or update() will
* // increment the version property
* database.markAsDirty(customer);
* database.save(customer);
*
* }</pre>
*/
@@ -1219,18 +1140,17 @@ public interface Database {
* <b>Stateless updates:</b> Note that the bean does not have to be previously fetched to call
* update().You can create a new instance and set some of its properties programmatically for via
* JSON/XML marshalling etc. This is described as a 'stateless update'.
* </p>
* <p>
* <b>Optimistic Locking: </b> Note that if the version property is not set when update() is
* called then no optimistic locking is performed (internally ConcurrencyMode.NONE is used).
* </p>
*
* <pre>{@code
*
* // A 'stateless update' example
* Customer customer = new Customer();
* customer.setId(7);
* customer.setName("ModifiedNameNoOCC");
* database.update(customer);
* // A 'stateless update' example
* Customer customer = new Customer();
* customer.setId(7);
* customer.setName("ModifiedNameNoOCC");
* database.update(customer);
*
* }</pre>
*/
@@ -1281,7 +1201,6 @@ public interface Database {
* Compared to save() this forces bean to perform an insert rather than trying to decide
* based on the bean state. As such this is useful when you fetch beans from one database
* and want to insert them into another database (and you want to explicitly insert them).
* </p>
*/
void insert(Object bean);
@@ -1314,21 +1233,18 @@ public interface Database {
/**
* Execute a Runnable in a Transaction with an explicit scope.
* <p>
* The scope can control the transaction type, isolation and rollback
* semantics.
* </p>
* <p>
* The scope can control the transaction type, isolation and rollback semantics.
*
* <pre>{@code
* // set specific transactional scope settings
* TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE);
*
* // set specific transactional scope settings
* TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE);
*
* database.execute(scope, new Runnable() {
* public void run() {
* User u1 = database.find(User.class, 1);
* ...
* }
* });
* database.execute(scope, new Runnable() {
* public void run() {
* User u1 = database.find(User.class, 1);
* ...
* }
* });
*
* }</pre>
*/
@@ -1339,21 +1255,19 @@ public interface Database {
* <p>
* The default scope runs with REQUIRED and by default will rollback on any
* exception (checked or runtime).
* </p>
* <p>
*
* <pre>{@code
* database.execute(() -> {
*
* database.execute(() -> {
* User u1 = database.find(User.class, 1);
* User u2 = database.find(User.class, 2);
*
* User u1 = database.find(User.class, 1);
* User u2 = database.find(User.class, 2);
* u1.setName("u1 mod");
* u2.setName("u2 mod");
*
* u1.setName("u1 mod");
* u2.setName("u2 mod");
*
* u1.save();
* u2.save();
* });
* u1.save();
* u2.save();
* });
*
* }</pre>
*/
@@ -1364,18 +1278,16 @@ public interface Database {
* <p>
* The scope can control the transaction type, isolation and rollback
* semantics.
* </p>
* <p>
* <pre>{@code
*
* <pre>{@code
* // set specific transactional scope settings
* TxScope scope = TxScope.requiresNew().setIsolation(TxIsolation.SERIALIZABLE);
*
* database.executeCall(scope, new Callable<String>() {
* public String call() {
* User u1 = database.find(User.class, 1);
* ...
* return u1.getEmail();
* public String call() {
* User u1 = database.find(User.class, 1);
* ...
* return u1.getEmail();
* }
* });
*
@@ -1388,10 +1300,8 @@ public interface Database {
* <p>
* The default scope runs with REQUIRED and by default will rollback on any
* exception (checked or runtime).
* </p>
* <p>
* <pre>{@code
*
* <pre>{@code
* database.executeCall(new Callable<String>() {
* public String call() {
* User u1 = database.find(User.class, 1);
@@ -1406,7 +1316,6 @@ public interface Database {
* return u1.getEmail();
* }
* });
*
* }</pre>
*/
<T> T executeCall(Callable<T> callable);
@@ -1417,8 +1326,7 @@ public interface Database {
ServerCacheManager cacheManager();
/**
* Return the BackgroundExecutor service for asynchronous processing of
* queries.
* Return the BackgroundExecutor service for asynchronous processing of queries.
*/
BackgroundExecutor backgroundExecutor();
@@ -1427,33 +1335,30 @@ public interface Database {
* <p>
* This instance is safe to be used concurrently by multiple threads and this
* method is cheap to call.
* </p>
* <p>
*
* <h3>Simple example:</h3>
* <pre>{@code
*
* JsonContext json = database.json();
* String jsonOutput = json.toJson(list);
* System.out.println(jsonOutput);
*
* JsonContext json = database.json();
* String jsonOutput = json.toJson(list);
* System.out.println(jsonOutput);
* }</pre>
*
* <p>
* <h3>Using PathProperties:</h3>
* <pre>{@code
* // specify just the properties we want
* PathProperties paths = PathProperties.parse("name, status, anniversary");
*
* // specify just the properties we want
* PathProperties paths = PathProperties.parse("name, status, anniversary");
* List<Customer> customers =
* database.find(Customer.class)
* // apply those paths to the query (only fetch what we need)
* .apply(paths)
* .where().ilike("name", "rob%")
* .findList();
*
* List<Customer> customers =
* database.find(Customer.class)
* // apply those paths to the query (only fetch what we need)
* .apply(paths)
* .where().ilike("name", "rob%")
* .findList();
*
* // ... get the json
* JsonContext jsonContext = database.json();
* String json = jsonContext.toJson(customers, paths);
* // ... get the json
* JsonContext jsonContext = database.json();
* String json = jsonContext.toJson(customers, paths);
*
* }</pre>
*
@@ -1478,7 +1383,6 @@ public interface Database {
* Publish a single bean given its type and id returning the resulting live bean.
* <p>
* The values are published from the draft to the live bean.
* </p>
*
* @param <T> the type of the entity bean
* @param beanType the type of the entity bean
@@ -1493,7 +1397,6 @@ public interface Database {
* This will use the current transaction or create one if required.
* <p>
* The values are published from the draft to the live bean.
* </p>
*
* @param <T> the type of the entity bean
* @param beanType the type of the entity bean
@@ -1506,7 +1409,6 @@ public interface Database {
* Publish the beans that match the query returning the resulting published beans.
* <p>
* The values are published from the draft beans to the live beans.
* </p>
*
* @param <T> the type of the entity bean
* @param query the query used to select the draft beans to publish
@@ -1519,7 +1421,6 @@ public interface Database {
* This will use the current transaction or create one if required.
* <p>
* The values are published from the draft beans to the live beans.
* </p>
*
* @param <T> the type of the entity bean
* @param query the query used to select the draft beans to publish
@@ -1531,7 +1432,6 @@ public interface Database {
* <p>
* The values from the live beans are set back to the draft bean and the
* <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset.
* </p>
*
* @param <T> the type of the entity bean
* @param beanType the type of the entity bean
@@ -1546,7 +1446,6 @@ public interface Database {
* <p>
* The values from the live beans are set back to the draft bean and the
* <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset.
* </p>
*
* @param <T> the type of the entity bean
* @param beanType the type of the entity bean
@@ -1560,7 +1459,6 @@ public interface Database {
* <p>
* The values from the live beans are set back to the draft bean and the
* <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset.
* </p>
*
* @param <T> the type of the entity bean
* @param query the query used to select the draft beans to restore
@@ -1573,7 +1471,6 @@ public interface Database {
* <p>
* The values from the live beans are set back to the draft bean and the
* <code>@DraftDirty</code> and <code>@DraftReset</code> properties are reset.
* </p>
*
* @param <T> the type of the entity bean
* @param query the query used to select the draft beans to restore
@@ -1585,7 +1482,6 @@ public interface Database {
* <p>
* Validate the query checking the where and orderBy expression paths to confirm if
* they represent valid properties/path for the given bean type.
* </p>
*/
<T> Set<String> validateQuery(Query<T> query);
@@ -1611,6 +1507,6 @@ public interface Database {
/**
* Truncate the base tables for the given bean types.
*/
void truncate(Class<?>... tables);
void truncate(Class<?>... beanTypes);
}
@@ -2,20 +2,20 @@ package io.ebean;
import io.ebean.config.BeanNotEnhancedException;
import io.ebean.datasource.DataSourceConfigurationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.persistence.PersistenceException;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
import static java.lang.System.Logger.Level.ERROR;
/**
* Holds Database instances.
*/
final class DbContext {
private static final Logger log = LoggerFactory.getLogger("io.ebean");
private static final System.Logger log = EbeanVersion.log;
static {
EbeanVersion.getVersion();
}
@@ -23,14 +23,9 @@ final class DbContext {
private static final DbContext INSTANCE = new DbContext();
private final ConcurrentHashMap<String, Database> concMap = new ConcurrentHashMap<>();
private final HashMap<String, Database> syncMap = new HashMap<>();
private final ReentrantLock lock = new ReentrantLock();
/**
* The 'default' Database.
*/
private Database defaultDatabase;
private DbContext() {
@@ -52,7 +47,7 @@ final class DbContext {
throw new DataSourceConfigurationException(msg, e);
} catch (Throwable e) {
log.error("Error trying to create the default Database", e);
log.log(ERROR, "Error trying to create the default Database", e);
throw new RuntimeException(e);
}
}
@@ -69,9 +64,9 @@ final class DbContext {
*/
Database getDefault() {
if (defaultDatabase == null) {
String msg = "The default Database has not been defined?";
msg += " This is normally set via the ebean.datasource.default property.";
msg += " Otherwise it should be registered programmatically via registerServer()";
String msg = "The default Database has not been defined?"
+ " This is normally set via the ebean.datasource.default property."
+ " Otherwise it should be registered programmatically via registerServer()";
throw new PersistenceException(msg);
}
return defaultDatabase;
@@ -1,11 +1,15 @@
package io.ebean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.avaje.applog.AppLog;
import java.io.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.Properties;
import static java.lang.System.Logger.Level.*;
/**
* Class to determine the ebean version.
*
@@ -13,7 +17,7 @@ import java.util.Properties;
*/
public final class EbeanVersion {
private static final Logger log = LoggerFactory.getLogger("io.ebean");
public static final System.Logger log = AppLog.getLogger("io.ebean");
/**
* Maintain the minimum ebean-agent version manually based on required ebean-agent bug fixes.
@@ -21,6 +25,7 @@ public final class EbeanVersion {
private static final int MIN_AGENT_MAJOR_VERSION = 12;
private static final int MIN_AGENT_MINOR_VERSION = 12;
private static String version = "unknown";
static {
readVersion();
checkAgentVersion();
@@ -32,12 +37,12 @@ public final class EbeanVersion {
if (in != null) {
try (LineNumberReader reader = new LineNumberReader(new InputStreamReader(in))) {
version = reader.readLine();
log.log(INFO, "ebean version: {0}", version);
}
}
}
log.info("ebean version: {}", version);
} catch (IOException e) {
log.warn("Could not determine ebean version: {}", e.getMessage());
log.log(WARNING, "Could not determine ebean version: {0}", e.getMessage());
}
}
@@ -49,13 +54,13 @@ public final class EbeanVersion {
String agentVersion = readVersion(in);
if (agentVersion != null) {
if (checkMinAgentVersion(agentVersion)) {
log.error("Expected minimum ebean-agent version {}.{}.0 but we have {}, please update the ebean-agent", MIN_AGENT_MAJOR_VERSION, MIN_AGENT_MINOR_VERSION, agentVersion);
log.log(ERROR, "Expected minimum ebean-agent version {0}.{1}.0 but we have {2}, please update the ebean-agent", MIN_AGENT_MAJOR_VERSION, MIN_AGENT_MINOR_VERSION, agentVersion);
}
}
}
}
} catch (IOException e) {
log.warn("Could not check minimum ebean-agent version {}.{}.0 required due to - {}", MIN_AGENT_MAJOR_VERSION, MIN_AGENT_MINOR_VERSION, e.getMessage());
log.log(WARNING, "Could not check minimum ebean-agent version {0}.{1}.0 required due to - {2}", MIN_AGENT_MAJOR_VERSION, MIN_AGENT_MINOR_VERSION, e.getMessage());
}
}
@@ -385,7 +385,7 @@ public interface ExpressionList<T> {
/**
* Executes the query returning a set of values for a single property.
*
* <p>
* This can be used to cache sets.
*
* @return a HashSet of values for the selegted property
@@ -835,6 +835,20 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> eq(String propertyName, Object value);
/**
* Is EQUAL TO if value is non-null and otherwise no expression is added to the query.
* <p>
* This is the EQUAL TO equivalent to {@link #inOrEmpty(String, Collection)} where the expression/predicate
* is only added when the value is non-null.
* <p>
* This is effectively a helper method that allows a query to be built in fluid style where some predicates are
* effectively optional. We can use <code>eqIfPresent()</code> rather than having a separate if block.
* <p>
* Another option is to instead globally use {@link io.ebean.config.DatabaseConfig#setExpressionEqualsWithNullAsNoop(boolean)}
* but that is not always desirable.
*/
ExpressionList<T> eqIfPresent(String propertyName, @Nullable Object value);
/**
* Equal To or Null - property is equal to a given value or null.
*/
@@ -2,7 +2,6 @@ package io.ebean;
import io.avaje.lang.Nullable;
import javax.persistence.NonUniqueResultException;
import java.time.Clock;
import java.util.List;
import java.util.Map;
@@ -15,470 +14,182 @@ 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>
* <p>
* In general we only want to use this ExtendedServer API when we want to avoid / bypass
* the use of the mechanism to get the current transaction and instead explicitly supply
* the transaction to use.
* </p>
* <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.
* </p>
*/
public interface ExtendedServer {
/**
* Return the NOW time from the Clock.
*/
long clockNow();
/**
* Deprecated but no yet determined suitable replacement (to support testing only change of clock).
* <p>
* Set the Clock to use for <code>@WhenCreated</code> and <code>@WhenModified</code>.
* <p>
* Note that we only expect to change the Clock for testing purposes.
* </p>
*/
@Deprecated
void setClock(Clock clock);
/**
* Execute the query returning true if a row is found.
* <p>
* The query is executed using max rows of 1 and will only select the id property.
* This method is really just a convenient way to optimise a query to perform a
* 'does a row exist in the db' check.
* </p>
*
* <h2>Example:</h2>
* <pre>{@code
*
* boolean userExists = query().where().eq("email", "rob@foo.com").exists();
*
* }</pre>
*
* <h2>Example using a query bean:</h2>
* <pre>{@code
*
* boolean userExists = new QContact().email.equalTo("rob@foo.com").exists();
*
* }</pre>
*
* @return True if the query finds a matching row in the database
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> boolean exists(Query<T> ormQuery, Transaction transaction);
/**
* Return the number of 'top level' or 'root' entities this query should return.
*
* @see Query#findCount()
* @see Query#findFutureCount()
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> int findCount(Query<T> query, Transaction transaction);
/**
* Return the Id values of the query as a List.
*
* @see Query#findIds()
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<A, T> List<A> findIds(Query<T> query, Transaction transaction);
/**
* Return a QueryIterator for the query.
* <p>
* Generally using {@link #findEach(Query, Consumer, Transaction)} or
* {@link #findEachWhile(Query, Predicate, Transaction)} is preferred
* to findIterate(). The reason is that those methods automatically take care of
* closing the queryIterator (and the underlying jdbc statement and resultSet).
* <p>
* This is similar to findEach in that not all the result beans need to be held
* in memory at the same time and as such is good for processing large queries.
*
* @see Query#findIterate()
* @see Query#findEach(Consumer)
* @see Query#findEachWhile(Predicate)
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> QueryIterator<T> findIterate(Query<T> query, Transaction transaction);
/**
* Execute the query returning the result as a Stream.
* <p>
* Note that this can support very large queries iterating any number of results.
* To do so internally it can use multiple persistence contexts.
* <p>
* Note that the stream needs to be closed so use with try with resources.
* </p>
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> Stream<T> findStream(Query<T> query, Transaction transaction);
/**
* Execute the query visiting the each bean one at a time.
* <p>
* Unlike findList() this is suitable for processing a query that will return
* a very large resultSet. The reason is that not all the result beans need to be
* held in memory at the same time and instead processed one at a time.
* </p>
* <p>
* Internally this query using a PersistenceContext scoped to each bean (and the
* beans associated object graph).
* </p>
* <p>
* <pre>{@code
*
* DB.find(Order.class)
* .where().eq("status", Order.Status.NEW)
* .order().asc("id")
* .findEach((Order order) -> {
*
* // do something with the order bean
* System.out.println(" -- processing order ... " + order);
* });
*
* }</pre>
*
* @see Query#findEach(Consumer)
* @see Query#findEachWhile(Predicate)
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> void findEach(Query<T> query, Consumer<T> consumer, Transaction transaction);
/**
* Execute findEach with batch consumer.
*
* @see Query#findEach(int, Consumer)
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> void findEach(Query<T> query, int batch, Consumer<List<T>> consumer, Transaction t);
/**
* Execute the query visiting the each bean one at a time.
* <p>
* Compared to findEach() this provides the ability to stop processing the query
* results early by returning false for the Predicate.
* </p>
* <p>
* Unlike findList() this is suitable for processing a query that will return
* a very large resultSet. The reason is that not all the result beans need to be
* held in memory at the same time and instead processed one at a time.
* </p>
* <p>
* Internally this query using a PersistenceContext scoped to each bean (and the
* beans associated object graph).
* </p>
* <p>
* <pre>{@code
*
* DB.find(Order.class)
* .where().eq("status", Order.Status.NEW)
* .order().asc("id")
* .findEachWhile((Order order) -> {
*
* // do something with the order bean
* System.out.println(" -- processing order ... " + order);
*
* boolean carryOnProcessing = ...
* return carryOnProcessing;
* });
*
* }</pre>
*
* @see Query#findEach(Consumer)
* @see Query#findEachWhile(Predicate)
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> void findEachWhile(Query<T> query, Predicate<T> consumer, Transaction transaction);
/**
* Return versions of a @History entity bean.
* <p>
* Generally this query is expected to be a find by id or unique predicates query.
* It will execute the query against the history returning the versions of the bean.
* </p>
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> List<Version<T>> findVersions(Query<T> query, Transaction transaction);
/**
* Execute a query returning a list of beans.
* <p>
* Generally you are able to use {@link Query#findList()} rather than
* explicitly calling this method. You could use this method if you wish to
* explicitly control the transaction used for the query.
* </p>
* <p>
* <pre>{@code
*
* List<Customer> customers = DB.find(Customer.class)
* .where().ilike("name", "rob%")
* .findList();
*
* }</pre>
*
* @param <T> the type of entity bean to fetch.
* @param query the query to execute.
* @param transaction the transaction to use (can be null).
* @return the list of fetched beans.
* @see Query#findList()
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> List<T> findList(Query<T> query, Transaction transaction);
/**
* Execute find row count query in a background thread.
* <p>
* This returns a Future object which can be used to cancel, check the
* execution status (isDone etc) and get the value (with or without a
* timeout).
* </p>
*
* @param query the query to execute the row count on
* @param transaction the transaction (can be null).
* @return a Future object for the row count query
* @see Query#findFutureCount()
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> FutureRowCount<T> findFutureCount(Query<T> query, Transaction transaction);
/**
* Execute find Id's query in a background thread.
* <p>
* This returns a Future object which can be used to cancel, check the
* execution status (isDone etc) and get the value (with or without a
* timeout).
* </p>
*
* @param query the query to execute the fetch Id's on
* @param transaction the transaction (can be null).
* @return a Future object for the list of Id's
* @see Query#findFutureIds()
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> FutureIds<T> findFutureIds(Query<T> query, Transaction transaction);
/**
* Execute find list query in a background thread returning a FutureList object.
* <p>
* This returns a Future object which can be used to cancel, check the
* execution status (isDone etc) and get the value (with or without a timeout).
* <p>
* This query will execute in it's own PersistenceContext and using its own transaction.
* What that means is that it will not share any bean instances with other queries.
*
* @param query the query to execute in the background
* @param transaction the transaction (can be null).
* @return a Future object for the list result of the query
* @see Query#findFutureList()
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> FutureList<T> findFutureList(Query<T> query, Transaction transaction);
/**
* Return a PagedList for this query using firstRow and maxRows.
* <p>
* The benefit of using this over findList() is that it provides functionality to get the
* total row count etc.
* </p>
* <p>
* If maxRows is not set on the query prior to calling findPagedList() then a
* PersistenceException is thrown.
* </p>
* <p>
* <pre>{@code
*
* PagedList<Order> pagedList = DB.find(Order.class)
* .setFirstRow(50)
* .setMaxRows(20)
* .findPagedList();
*
* // fetch the total row count in the background
* pagedList.loadRowCount();
*
* List<Order> orders = pagedList.getList();
* int totalRowCount = pagedList.getTotalRowCount();
*
* }</pre>
*
* @return The PagedList
* @see Query#findPagedList()
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> PagedList<T> findPagedList(Query<T> query, Transaction transaction);
/**
* Execute the query returning a set of entity beans.
* <p>
* Generally you are able to use {@link Query#findSet()} rather than
* explicitly calling this method. You could use this method if you wish to
* explicitly control the transaction used for the query.
* </p>
* <p>
* <pre>{@code
*
* Set<Customer> customers = DB.find(Customer.class)
* .where().ilike("name", "rob%")
* .findSet();
*
* }</pre>
*
* @param <T> the type of entity bean to fetch.
* @param query the query to execute
* @param transaction the transaction to use (can be null).
* @return the set of fetched beans.
* @see Query#findSet()
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> Set<T> findSet(Query<T> query, Transaction transaction);
/**
* Execute the query returning the entity beans in a Map.
* <p>
* Generally you are able to use {@link Query#findMap()} rather than
* explicitly calling this method. You could use this method if you wish to
* explicitly control the transaction used for the query.
* </p>
*
* @param <T> the type of entity bean to fetch.
* @param query the query to execute.
* @param transaction the transaction to use (can be null).
* @return the map of fetched beans.
* @see Query#findMap()
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<K, T> Map<K, T> findMap(Query<T> query, Transaction transaction);
/**
* Execute the query returning a list of values for a single property.
* <p>
* <h3>Example 1:</h3>
* <pre>{@code
*
* List<String> names =
* DB.find(Customer.class)
* .select("name")
* .order().asc("name")
* .findSingleAttributeList();
*
* }</pre>
* <h3>Example 2:</h3>
* <pre>{@code
*
* List<String> names =
* DB.find(Customer.class)
* .setDistinct(true)
* .select("name")
* .where().eq("status", Customer.Status.NEW)
* .order().asc("name")
* .setMaxRows(100)
* .findSingleAttributeList();
*
* }</pre>
*
* @return the list of values for the selected property
* @see Query#findSingleAttributeList()
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<A, T> List<A> findSingleAttributeList(Query<T> query, Transaction transaction);
/**
* Execute the query returning a hashset of values for a single property.
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<A, T> Set<A> findSingleAttributeSet(Query<T> query, Transaction transaction);
/**
* Execute the query returning at most one entity bean or null (if no matching
* bean is found).
* <p>
* This will throw a NonUniqueResultException if the query finds more than one result.
* </p>
* <p>
* Generally you are able to use {@link Query#findOne()} rather than
* explicitly calling this method. You could use this method if you wish to
* explicitly control the transaction used for the query.
* </p>
*
* @param <T> the type of entity bean to fetch.
* @param query the query to execute.
* @param transaction the transaction to use (can be null).
* @return the list of fetched beans.
* @throws NonUniqueResultException if more than one result was found
* @see Query#findOne()
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
@Nullable
<T> T findOne(Query<T> query, Transaction transaction);
/**
* Similar to findOne() but returns an Optional (rather than nullable).
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> Optional<T> findOneOrEmpty(Query<T> query, Transaction transaction);
/**
* Execute as a delete query deleting the 'root level' beans that match the predicates
* in the query.
* <p>
* Note that if the query includes joins then the generated delete statement may not be
* optimal depending on the database platform.
* </p>
*
* @param query the query used for the delete
* @param transaction the transaction to use (can be null)
* @param <T> the type of entity bean to fetch.
* @return the number of beans/rows that were deleted
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> int delete(Query<T> query, Transaction transaction);
/**
* Execute the update query returning the number of rows updated.
* <p>
* The update query must be created using {@link Database#update(Class)}.
* </p>
*
* @param query the update query to execute
* @param transaction the optional transaction to use for the update (can be null)
* @param <T> the type of entity bean
* @return The number of rows updated
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
<T> int update(Query<T> query, Transaction transaction);
/**
* Execute the sql query returning a list of MapBean.
* <p>
* Generally you are able to use {@link SqlQuery#findList()} rather than
* explicitly calling this method. You could use this method if you wish to
* explicitly control the transaction used for the query.
* </p>
*
* @param query the query to execute.
* @param transaction the transaction to use (can be null).
* @return the list of fetched MapBean.
* @see SqlQuery#findList()
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
List<SqlRow> findList(SqlQuery query, Transaction transaction);
/**
* Execute the SqlQuery iterating a row at a time.
* <p>
* This streaming type query is useful for large query execution as only 1 row needs to be held in memory.
* </p>
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
void findEach(SqlQuery query, Consumer<SqlRow> consumer, Transaction transaction);
/**
* Execute the SqlQuery iterating a row at a time with the ability to stop consuming part way through.
* <p>
* Returning false after processing a row stops the iteration through the query results.
* </p>
* <p>
* This streaming type query is useful for large query execution as only 1 row needs to be held in memory.
* </p>
* Deprecated migrate to using {@link Query#usingTransaction(Transaction)}.
*/
@Deprecated
void findEachWhile(SqlQuery query, Predicate<SqlRow> consumer, Transaction transaction);
/**
* Execute the sql query returning a single MapBean or null.
* <p>
* This will throw a PersistenceException if the query found more than one
* result.
* </p>
* <p>
* Generally you are able to use {@link SqlQuery#findOne()} rather than
* explicitly calling this method. You could use this method if you wish to
* explicitly control the transaction used for the query.
* </p>
*
* @param query the query to execute.
* @param transaction the transaction to use (can be null).
* @return the fetched MapBean or null if none was found.
* @see SqlQuery#findOne()
* Deprecated migrate to using {@link SqlQuery#usingTransaction(Transaction)}.
*/
@Deprecated
@Nullable
SqlRow findOne(SqlQuery query, Transaction transaction);
+4 -2
View File
@@ -931,7 +931,7 @@ public interface Query<T> extends CancelableQuery {
<A> Set<A> findSingleAttributeSet();
/**
* Execute a query returning a single value of a single property/column.
* Execute a query returning a single value or null for a single property/column.
* <p>
* <pre>{@code
*
@@ -943,6 +943,7 @@ public interface Query<T> extends CancelableQuery {
*
* }</pre>
*/
@Nullable
<A> A findSingleAttribute();
/**
@@ -1579,10 +1580,11 @@ public interface Query<T> extends CancelableQuery {
Query<T> setReadOnly(boolean readOnly);
/**
* Will be deprecated - migrate to use setBeanCacheMode(CacheMode.RECACHE).
* 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);
/**
+11 -1
View File
@@ -2,8 +2,8 @@ package io.ebean;
import io.avaje.lang.NonNullApi;
import io.avaje.lang.Nullable;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
@@ -40,6 +40,11 @@ import java.util.function.Predicate;
@NonNullApi
public interface SqlQuery extends Serializable, CancelableQuery {
/**
* Execute the query using the given transaction.
*/
SqlQuery usingTransaction(Transaction transaction);
/**
* Execute the query returning a list.
*/
@@ -298,6 +303,11 @@ public interface SqlQuery extends Serializable, CancelableQuery {
*/
interface TypeQuery<T> {
/**
* Execute the query using the given transaction.
*/
TypeQuery<T> usingTransaction(Transaction transaction);
/**
* Return the single value.
*/
@@ -6,6 +6,12 @@ import java.io.Serializable;
import java.util.Map;
import java.util.Set;
/**
* This is the object associated to every entity bean using byte code enhancement.
* <p>
* This provides per property state such as loaded state, changed state, original values
* as well as bean level dirty state etc.
*/
public interface EntityBeanIntercept extends Serializable {
/**
@@ -282,8 +288,14 @@ public interface EntityBeanIntercept extends Serializable {
*/
void markPropertyAsChanged(int propertyIndex);
/**
* Set the changed state for the given property.
*/
void setChangedProperty(int propertyIndex);
/**
* Set the changed and loaded state for the given property.
*/
void setChangeLoaded(int propertyIndex);
/**
@@ -291,6 +303,9 @@ public interface EntityBeanIntercept extends Serializable {
*/
void setEmbeddedPropertyDirty(int propertyIndex);
/**
* Set the original value for the property.
*/
void setOriginalValue(int propertyIndex, Object value);
/**
@@ -358,6 +373,9 @@ public interface EntityBeanIntercept extends Serializable {
*/
StringBuilder getLoadedPropertyKey();
/**
* Return the loaded state for all the properties.
*/
boolean[] getLoaded();
/**
@@ -385,6 +403,9 @@ public interface EntityBeanIntercept extends Serializable {
*/
void initialisedMany(int propertyIndex);
/**
* Invoke the PreGetterCallback if it has been set due to getter for the given property.
*/
void preGetterCallback(int propertyIndex);
/**
@@ -402,8 +423,14 @@ public interface EntityBeanIntercept extends Serializable {
*/
void preSetterMany(boolean interceptField, int propertyIndex, Object oldValue, Object newValue);
/**
* Set the property changed state, bean dirtyState and property original value.
*/
void setChangedPropertyValue(int propertyIndex, boolean setDirtyState, Object origValue);
/**
* Set the dirty state on the bean.
*/
void setDirtyStatus();
/**
@@ -482,6 +509,9 @@ public interface EntityBeanIntercept extends Serializable {
*/
void setDeletedFromCollection(boolean deletedFromCollection);
/**
* Return true if the bean was orphan deleted from a collection.
*/
boolean isOrphanDelete();
/**
@@ -494,7 +524,10 @@ public interface EntityBeanIntercept extends Serializable {
*/
Map<String, Exception> getLoadErrors();
boolean isChangedProp(int i);
/**
* Return true if the property has its changed state set.
*/
boolean isChangedProp(int propertyIndex);
/**
* Return the MutableValueInfo for the given property or null.
@@ -6,10 +6,20 @@ import java.util.Collections;
import java.util.Map;
import java.util.Set;
/**
* EntityBeanIntercept optimised for read only use.
* <p>
* For the read only use this intercept doesn't need to hold any state that is normally
* required for updates such as per property changed, loaded, dirty state, original values
* bean state etc.
*/
public class InterceptReadOnly implements EntityBeanIntercept {
private final EntityBean owner;
/**
* Create with a given entity.
*/
public InterceptReadOnly(Object ownerBean) {
this.owner = (EntityBean) ownerBean;
}
@@ -21,7 +21,6 @@ import java.util.concurrent.locks.ReentrantLock;
* <p>
* This provides the mechanisms to support deferred fetching of reference beans
* and oldValues generation for concurrency checking.
* </p>
*/
public final class InterceptReadWrite implements EntityBeanIntercept {
@@ -32,24 +31,17 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
private static final int STATE_LOADED = 2;
/**
* Used when a bean is partially filled.
* Used when a bean is partially loaded.
*/
private static final byte FLAG_LOADED_PROP = 1;
private static final byte FLAG_CHANGED_PROP = 2;
private static final byte FLAG_CHANGEDLOADED_PROP = 3;
/**
* Flags indicating if a property is a dirty embedded bean. Used to distinguish
* between an embedded bean being completely overwritten and one of its
* embedded properties being made dirty.
* Flags indicating if a property is a dirty embedded bean. Used to distinguish between an
* embedded bean being completely overwritten vs one with embedded properties that are dirty.
*/
private static final byte FLAG_EMBEDDED_DIRTY = 4;
/**
* Flags indicating if a property is a dirty embedded bean. Used to distinguish
* between an embedded bean being completely overwritten and one of its
* embedded properties being made dirty.
*/
private static final byte FLAG_ORIG_VALUE_SET = 8;
/**
* Flags indicating if the mutable hash is set.
*/
@@ -78,10 +70,9 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
private boolean readOnly;
private boolean dirty;
/**
* Flag set to disable lazy loading - typically for SQL "report" type entity beans.
* Flag set to disable lazy loading.
*/
private boolean disableLazyLoad;
/**
* Flag set when lazy loading failed due to the underlying bean being deleted in the DB.
*/
@@ -107,7 +98,7 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
private MutableValueNext[] mutableNext;
/**
* Create a intercept with a given entity.
* Create with a given entity.
*/
public InterceptReadWrite(Object ownerBean) {
this.owner = (EntityBean) ownerBean;
@@ -237,7 +237,7 @@ public abstract class AbstractNamingConvention implements NamingConvention {
}
buffer.append(rhsTableName);
int maxTableNameLength = databasePlatform.getMaxTableNameLength();
int maxTableNameLength = databasePlatform.maxTableNameLength();
// maxConstraintNameLength is used as the max table name length.
if (buffer.length() > maxTableNameLength) {
@@ -16,6 +16,7 @@ import io.ebean.event.changelog.ChangeLogPrepare;
import io.ebean.event.changelog.ChangeLogRegister;
import io.ebean.event.readaudit.ReadAuditLogger;
import io.ebean.event.readaudit.ReadAuditPrepare;
import io.ebean.meta.MetricNamingMatch;
import io.ebean.util.StringHelper;
import javax.persistence.EnumType;
@@ -24,6 +25,7 @@ import java.time.Clock;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
/**
* The configuration used for creating a Database.
@@ -115,9 +117,9 @@ public class DatabaseConfig {
private TenantCatalogProvider tenantCatalogProvider;
/**
* When true will load entity classes via ModuleInfoLoader.
* When true will load entity classes via EntityClassRegister.
* <p>
* NB: ModuleInfoLoader implementations are generated by querybean generator.
* NB: EntityClassRegister implementations are generated by querybean generator.
* Having this on and registering entity classes means we don't need to manually
* write that code or use classpath scanning to find entity classes.
*/
@@ -546,6 +548,8 @@ public class DatabaseConfig {
private String dumpMetricsOptions;
private Function<String, String> metricNaming = MetricNamingMatch.INSTANCE;
/**
* Construct a Database Configuration for programmatically creating an Database.
*/
@@ -3020,7 +3024,7 @@ public class DatabaseConfig {
public PersistBatch appliedPersistBatchOnCascade() {
if (persistBatchOnCascade == PersistBatch.INHERIT) {
// use the platform default (ALL except SQL Server which has NONE)
return databasePlatform.getPersistBatchOnCascade();
return databasePlatform.persistBatchOnCascade();
}
return persistBatchOnCascade;
}
@@ -3376,7 +3380,7 @@ public class DatabaseConfig {
}
/**
* Return true if entity classes should be loaded and registered via ModuleInfoLoader.
* Return true if entity classes should be loaded and registered via EntityClassRegister.
* <p>
* When false we either register entity classes via application code or use classpath
* scanning to find and register entity classes.
@@ -3396,6 +3400,20 @@ public class DatabaseConfig {
this.loadModuleInfo = loadModuleInfo;
}
/**
* Return the naming convention to apply to metrics names.
*/
public Function<String, String> getMetricNaming() {
return metricNaming;
}
/**
* Set the naming convention to apply to metrics names.
*/
public void setMetricNaming(Function<String, String> metricNaming) {
this.metricNaming = metricNaming;
}
public enum UuidVersion {
VERSION4,
VERSION1,
@@ -5,7 +5,7 @@ import java.util.List;
/**
* Loads and returns entity classes to register with Ebean databases.
*/
public interface ModuleInfoLoader {
public interface EntityClassRegister {
/**
* Return entity classes to register for a named DB (not default DB).
@@ -1,49 +1,26 @@
package io.ebean.config.dbplatform;
import io.ebean.BackgroundExecutor;
import io.ebean.EbeanVersion;
import io.ebean.Query;
import io.ebean.annotation.PartitionMode;
import io.ebean.annotation.PersistBatch;
import io.ebean.annotation.Platform;
import io.ebean.config.CustomDbTypeMapping;
import io.ebean.config.PlatformConfig;
import io.ebean.util.JdbcClose;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.persistence.PersistenceException;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.sql.*;
import static java.lang.System.Logger.Level.*;
/**
* Database platform specific settings.
*/
public class DatabasePlatform {
private static final Logger log = LoggerFactory.getLogger("io.ebean");
/**
* Behavior used when ending a query only transaction (at read committed isolation level).
*/
public enum OnQueryOnly {
/**
* Rollback the transaction.
*/
ROLLBACK,
/**
* Commit the transaction
*/
COMMIT
}
private static final System.Logger log = EbeanVersion.log;
/**
* Set to true for MySql, no other jdbc drivers need this workaround.
@@ -60,16 +37,11 @@ public class DatabasePlatform {
* Can we use native java time API objects in
* {@link ResultSet#getObject(int, Class)} and
* {@link PreparedStatement#setObject(int, Object)}.
*
* <p>
* Not all drivers (DB2 e.g.) will support this.
*/
protected boolean supportsNativeJavaTime = true;
/**
* The behaviour used when ending a read only transaction at read committed isolation level.
*/
protected OnQueryOnly onQueryOnly = OnQueryOnly.COMMIT;
/**
* The open quote used by quoted identifiers.
*/
@@ -146,11 +118,6 @@ public class DatabasePlatform {
*/
protected int clobDbType = Types.CLOB;
/**
* For Oracle treat empty strings as null.
*/
protected boolean treatEmptyStringsAsNull;
/**
* The database platform name.
*/
@@ -165,7 +132,7 @@ public class DatabasePlatform {
* want to use quoted identifiers for. The backticks get converted to the
* appropriate characters in convertQuotedIdentifiers
*/
private static final char[] QUOTED_IDENTIFIERS = new char[] { '"', '\'', '[', ']', '`' };
private static final char[] QUOTED_IDENTIFIERS = new char[]{'"', '\'', '[', ']', '`'};
/**
* The non-escaped like clause (to stop slash being escaped on some platforms).
@@ -299,7 +266,7 @@ public class DatabasePlatform {
/**
* Return the platform key.
*/
public Platform getPlatform() {
public Platform platform() {
return platform;
}
@@ -309,14 +276,14 @@ public class DatabasePlatform {
* "generic" is returned when no specific database platform has been set or found.
* </p>
*/
public String getName() {
public String name() {
return platform.name().toLowerCase();
}
/**
* Return true if we are using Sequence batch mode rather than STEP.
*/
public boolean isSequenceBatchMode() {
public boolean sequenceBatchMode() {
return sequenceBatchMode;
}
@@ -330,52 +297,52 @@ public class DatabasePlatform {
/**
* Return true if this database platform supports native ILIKE expression.
*/
public boolean isSupportsNativeIlike() {
public boolean supportsNativeIlike() {
return supportsNativeIlike;
}
/**
* Return true if the platform supports delete statements with table alias.
*/
public boolean isSupportsDeleteTableAlias() {
public boolean supportsDeleteTableAlias() {
return supportsDeleteTableAlias;
}
/**
* Return true if the collation is case sensitive.
* Return true if the collation is case-sensitive.
* <p>
* This is expected to be used for testing only.
* </p>
*/
public boolean isCaseSensitiveCollation() {
public boolean caseSensitiveCollation() {
return caseSensitiveCollation;
}
/**
* Return true if the platform supports SavepointId values.
*/
public boolean isSupportsSavepointId() {
public boolean supportsSavepointId() {
return supportsSavepointId;
}
/**
* Return true if migrations should use stored procedures.
*/
public boolean isUseMigrationStoredProcedures() {
public boolean useMigrationStoredProcedures() {
return useMigrationStoredProcedures;
}
/**
* Return true if the platform supports LIMIT with sql update.
*/
public boolean isInlineSqlUpdateLimit() {
public boolean inlineSqlUpdateLimit() {
return inlineSqlUpdateLimit;
}
/**
* Return the maximum number of bind values this database platform allows or zero for no limit.
*/
public int getMaxInBinding() {
public int maxInBinding() {
return maxInBinding;
}
@@ -385,14 +352,14 @@ public class DatabasePlatform {
* This is used when deriving names of intersection tables.
* </p>
*/
public int getMaxTableNameLength() {
public int maxTableNameLength() {
return maxTableNameLength;
}
/**
* Return the maximum constraint name allowed for the platform.
*/
public int getMaxConstraintNameLength() {
public int maxConstraintNameLength() {
return maxConstraintNameLength;
}
@@ -420,24 +387,10 @@ public class DatabasePlatform {
return null;
}
/**
* Return the behaviour to use when ending a read only transaction.
*/
public OnQueryOnly getOnQueryOnly() {
return onQueryOnly;
}
/**
* Set the behaviour to use when ending a read only transaction.
*/
public void setOnQueryOnly(OnQueryOnly onQueryOnly) {
this.onQueryOnly = onQueryOnly;
}
/**
* Return the DbEncrypt handler for this DB platform.
*/
public DbEncrypt getDbEncrypt() {
public DbEncrypt dbEncrypt() {
return dbEncrypt;
}
@@ -451,7 +404,7 @@ public class DatabasePlatform {
/**
* Return the history support for this database platform.
*/
public DbHistorySupport getHistorySupport() {
public DbHistorySupport historySupport() {
return historySupport;
}
@@ -465,14 +418,14 @@ public class DatabasePlatform {
/**
* So no except for Postgres and CockroachDB.
*/
public boolean isNativeArrayType() {
public boolean nativeArrayType() {
return false;
}
/**
* Return true if the DB supports native UUID.
*/
public boolean isNativeUuidType() {
public boolean nativeUuidType() {
return nativeUuidType;
}
@@ -481,21 +434,21 @@ public class DatabasePlatform {
*
* @return the db type map
*/
public DbPlatformTypeMapping getDbTypeMap() {
public DbPlatformTypeMapping dbTypeMap() {
return dbTypeMap;
}
/**
* Return the mapping for DB column default values.
*/
public DbDefaultValue getDbDefaultValue() {
public DbDefaultValue dbDefaultValue() {
return dbDefaultValue;
}
/**
* Return the column alias prefix.
*/
public String getColumnAliasPrefix() {
public String columnAliasPrefix() {
return columnAliasPrefix;
}
@@ -509,21 +462,21 @@ public class DatabasePlatform {
/**
* Return the close quote for quoted identifiers.
*/
public String getCloseQuote() {
public String closeQuote() {
return closeQuote;
}
/**
* Return the open quote for quoted identifiers.
*/
public String getOpenQuote() {
public String openQuote() {
return openQuote;
}
/**
* Return the JDBC type used to store booleans.
*/
public int getBooleanDbType() {
public int booleanDbType() {
return booleanDbType;
}
@@ -534,7 +487,7 @@ public class DatabasePlatform {
* example.
* </p>
*/
public int getBlobDbType() {
public int blobDbType() {
return blobDbType;
}
@@ -544,25 +497,16 @@ public class DatabasePlatform {
* This is typically Types.CLOB but for Postgres is Types.VARCHAR.
* </p>
*/
public int getClobDbType() {
public int clobDbType() {
return clobDbType;
}
/**
* Return true if empty strings should be treated as null.
*
* @return true, if checks if is treat empty strings as null
*/
public boolean isTreatEmptyStringsAsNull() {
return treatEmptyStringsAsNull;
}
/**
* Return true if a compound ID in (...) type expression needs to be in
* expanded form of (a=? and b=?) or (a=? and b=?) or ... rather than (a,b) in
* ((?,?),(?,?),...);
*/
public boolean isIdInExpandedForm() {
public boolean idInExpandedForm() {
return idInExpandedForm;
}
@@ -573,7 +517,7 @@ public class DatabasePlatform {
* This specifically is required for MySql when processing large results.
* </p>
*/
public boolean isForwardOnlyHintOnFindIterate() {
public boolean forwardOnlyHintOnFindIterate() {
return forwardOnlyHintOnFindIterate;
}
@@ -591,7 +535,7 @@ public class DatabasePlatform {
* This specifically is required for Hana which doesn't support CONCUR_UPDATABLE
* </p>
*/
public boolean isSupportsResultSetConcurrencyModeUpdatable() {
public boolean supportsResultSetConcurrencyModeUpdatable() {
return supportsResultSetConcurrencyModeUpdatable;
}
@@ -611,7 +555,7 @@ public class DatabasePlatform {
*
* @return the db identity
*/
public DbIdentity getDbIdentity() {
public DbIdentity dbIdentity() {
return dbIdentity;
}
@@ -624,14 +568,14 @@ public class DatabasePlatform {
*
* @return the sql limiter
*/
public SqlLimiter getSqlLimiter() {
public SqlLimiter sqlLimiter() {
return sqlLimiter;
}
/**
* Return the BasicSqlLimiter for limit/offset of SqlQuery queries.
*/
public BasicSqlLimiter getBasicSqlLimiter() {
public BasicSqlLimiter basicSqlLimiter() {
return basicSqlLimiter;
}
@@ -666,7 +610,7 @@ public class DatabasePlatform {
if (isQuote(dbName.charAt(dbName.length() - 1))) {
return openQuote + dbName.substring(1, dbName.length() - 1) + closeQuote;
} else {
log.error("Missing backquote on [" + dbName + "]");
log.log(ERROR, "Missing backquote on [" + dbName + "]");
}
} else if (allQuotedIdentifiers) {
return openQuote + dbName + closeQuote;
@@ -676,8 +620,8 @@ public class DatabasePlatform {
}
private boolean isQuote(char ch) {
for (char identifer : QUOTED_IDENTIFIERS) {
if (identifer == ch) {
for (char identifier : QUOTED_IDENTIFIERS) {
if (identifier == ch) {
return true;
}
}
@@ -700,14 +644,14 @@ public class DatabasePlatform {
/**
* Set to true if select count against anonymous view requires an alias.
*/
public boolean isSelectCountWithAlias() {
public boolean selectCountWithAlias() {
return selectCountWithAlias;
}
/**
* Return true if select count with subquery needs column alias (SQL Server).
*/
public boolean isSelectCountWithColumnAlias() {
public boolean selectCountWithColumnAlias() {
return selectCountWithColumnAlias;
}
@@ -729,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.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;
}
@@ -738,14 +682,14 @@ public class DatabasePlatform {
* <p>
* This may include an escape clause to disable a default escape character.
*/
public String getLikeClause(boolean rawLikeExpression) {
public String likeClause(boolean rawLikeExpression) {
return rawLikeExpression ? likeClauseRaw : likeClauseEscaped;
}
/**
* Return the platform default JDBC batch mode for persist cascade.
*/
public PersistBatch getPersistBatchOnCascade() {
public PersistBatch persistBatchOnCascade() {
return persistBatchOnCascade;
}
@@ -763,7 +707,7 @@ public class DatabasePlatform {
if (!schemaExists(dbSchema, connection)) {
Statement query = connection.createStatement();
try {
log.debug("create schema:{}", dbSchema);
log.log(DEBUG, "create schema:{0}", dbSchema);
query.executeUpdate("create schema " + dbSchema);
} finally {
JdbcClose.close(query);
@@ -789,19 +733,6 @@ public class DatabasePlatform {
return false;
}
/**
* Return true if the table exists.
*/
public boolean tableExists(Connection connection, String catalog, String schema, String table) throws SQLException {
DatabaseMetaData metaData = connection.getMetaData();
ResultSet tables = metaData.getTables(catalog, schema, table, null);
try {
return tables.next();
} finally {
JdbcClose.close(tables);
}
}
/**
* Escapes the like string for this DB-Platform
*/
@@ -1,10 +1,9 @@
package io.ebean.config.dbplatform;
import io.avaje.applog.AppLog;
import io.ebean.BackgroundExecutor;
import io.ebean.Transaction;
import io.ebean.util.JdbcClose;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.persistence.PersistenceException;
import javax.sql.DataSource;
@@ -19,12 +18,15 @@ import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock;
import static java.lang.System.Logger.Level.DEBUG;
import static java.lang.System.Logger.Level.ERROR;
/**
* Database sequence based IdGenerator.
*/
public abstract class SequenceIdGenerator implements PlatformIdGenerator {
protected static final Logger log = LoggerFactory.getLogger("io.ebean.SEQ");
protected static final System.Logger log = AppLog.getLogger("io.ebean.SEQ");
private final ReentrantLock lock = new ReentrantLock();
protected final String seqName;
@@ -120,7 +122,7 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
protected void loadInBackground(final int requestSize) {
if (currentlyBackgroundLoading.get()) {
// skip as already background loading
log.debug("... skip background sequence load (another load in progress)");
log.log(DEBUG, "... skip background sequence load (another load in progress)");
return;
}
currentlyBackgroundLoading.set(true);
@@ -152,9 +154,6 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
resultSet = statement.executeQuery();
List<Long> newIds = readIds(resultSet, requestSize);
if (log.isTraceEnabled()) {
log.trace("seq:{} loaded:{} sql:{}", seqName, newIds.size(), sql);
}
if (newIds.isEmpty()) {
throw new PersistenceException("Always expecting more than 1 row from " + sql);
}
@@ -164,7 +163,7 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
} catch (SQLException e) {
if (e.getMessage().contains("Database is already closed")) {
String msg = "Error getting SEQ when DB shutting down " + e.getMessage();
log.error(msg);
log.log(ERROR, msg);
System.out.println(msg);
return Collections.emptyList();
} else {
@@ -32,7 +32,12 @@ public class SqlCodeTranslator implements SqlExceptionTranslator {
}
private DataErrorType getErrorType(SQLException e) {
DataErrorType errorType = map.get(e.getSQLState());
String sqlState = e.getSQLState();
while (sqlState == null && e.getCause() instanceof SQLException) {
e = (SQLException)e.getCause();
sqlState = e.getSQLState();
}
DataErrorType errorType = map.get(sqlState);
if (errorType == null) {
// fall back to error code
errorType = map.get(String.valueOf(e.getErrorCode()));
@@ -1,9 +1,8 @@
package io.ebean.event;
import io.ebean.Database;
import io.ebean.EbeanVersion;
import io.ebean.service.SpiContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.Driver;
import java.sql.DriverManager;
@@ -13,6 +12,8 @@ import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
import static java.lang.System.Logger.Level.*;
/**
* Manages the shutdown of Ebean.
* <p>
@@ -20,13 +21,14 @@ import java.util.concurrent.locks.ReentrantLock;
*/
public final class ShutdownManager {
private static final Logger log = LoggerFactory.getLogger("io.ebean");
private static final System.Logger log = EbeanVersion.log;
private static final ReentrantLock lock = new ReentrantLock();
private static final List<Database> databases = new ArrayList<>();
private static final ShutdownHook shutdownHook = new ShutdownHook();
private static boolean stopping;
private static SpiContainer container;
static {
// Register the Shutdown hook
registerShutdownHook();
@@ -120,9 +122,7 @@ public final class ShutdownManager {
// Already run shutdown...
return;
}
if (log.isDebugEnabled()) {
log.debug("Ebean shutting down");
}
log.log(DEBUG, "Ebean shutting down");
stopping = true;
deregisterShutdownHook();
@@ -133,7 +133,7 @@ public final class ShutdownManager {
Runnable r = (Runnable) ClassUtil.newInstance(shutdownRunner);
r.run();
} catch (Exception e) {
log.error("Error running custom shutdown runnable", e);
log.log(ERROR, "Error running custom shutdown runnable", e);
}
}
@@ -147,7 +147,7 @@ public final class ShutdownManager {
try {
server.shutdown();
} catch (Exception ex) {
log.error("Error executing shutdown runnable", ex);
log.log(ERROR, "Error executing shutdown runnable", ex);
ex.printStackTrace();
}
}
@@ -165,10 +165,10 @@ public final class ShutdownManager {
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
try {
log.info("De-registering jdbc driver: " + driver);
log.log(INFO, "De-registering jdbc driver: " + driver);
DriverManager.deregisterDriver(driver);
} catch (SQLException e) {
log.error("Error de-registering driver " + driver, e);
log.log(ERROR, "Error de-registering driver " + driver, e);
}
}
}
@@ -204,6 +204,7 @@ public final class ShutdownManager {
private ShutdownHook() {
super("EbeanHook");
}
@Override
public void run() {
ShutdownManager.shutdown();
@@ -2,28 +2,57 @@ package io.ebean.meta;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
/**
* A simple MetricVisitor that can collect the desired metrics into lists.
*/
public class BasicMetricVisitor extends AbstractMetricVisitor implements ServerMetrics {
private final String name;
private final Function<String,String> naming;
private final List<MetaTimedMetric> timed = new ArrayList<>();
private final List<MetaQueryMetric> query = new ArrayList<>();
private final List<MetaCountMetric> count = new ArrayList<>();
public BasicMetricVisitor() {
this("db", MetricNamingMatch.INSTANCE);
}
/**
* Construct to reset and collect everything.
*/
public BasicMetricVisitor() {
super(true, true, true, true);
public BasicMetricVisitor(String name, Function<String,String> naming) {
this(name, naming, true, true, true, true);
}
/**
* Construct specifying reset and what to collect.
*/
public BasicMetricVisitor(boolean reset, boolean collectTransactionMetrics, boolean collectQueryMetrics, boolean collectL2Metrics) {
public BasicMetricVisitor(String name, Function<String,String> naming, boolean reset, boolean collectTransactionMetrics, boolean collectQueryMetrics, boolean collectL2Metrics) {
super(reset, collectTransactionMetrics, collectQueryMetrics, collectL2Metrics);
this.name = name;
this.naming = naming;
}
@Override
public String name() {
return name;
}
@Override
public Function<String, String> namingConvention() {
return naming;
}
@Override
public ServerMetricsAsJson asJson() {
return new MetricsAsJson(this);
}
@Override
public List<MetricData> asData() {
return new MetricsAsData(this).data();
}
@Override
@@ -17,21 +17,20 @@ public interface MetaInfoManager {
ServerMetrics collectMetrics();
/**
* Collect the metrics in raw JSON form.
* <pre>{@code
*
* String metricsJson = database.getMetaInfoManager()
* .collectMetricsAsJson()
* .json();
*
* }</pre>
* Deprecated migrate to collectMetrics().asJson().
*/
ServerMetricsAsJson collectMetricsAsJson();
@Deprecated
default ServerMetricsAsJson collectMetricsAsJson() {
return collectMetrics().asJson();
}
/**
* Return the metrics as a list of MetricData.
* Deprecated migrate to collectMetrics().asData().
*/
List<MetricData> collectMetricsAsData();
@Deprecated
default List<MetricData> collectMetricsAsData() {
return collectMetrics().asData();
}
/**
* Visit the metrics resetting and collecting/reporting as desired.
@@ -0,0 +1,16 @@
package io.ebean.meta;
import java.util.function.Function;
/**
* Metric naming convention that is exact match.
*/
public final class MetricNamingMatch implements Function<String, String> {
public static final Function<String, String> INSTANCE = new MetricNamingMatch();
@Override
public String apply(String name) {
return name;
}
}
@@ -1,10 +1,17 @@
package io.ebean.meta;
import java.util.function.Function;
/**
* Defines visitor to read and report the transaction and query metrics.
*/
public interface MetricVisitor {
/**
* Return the naming convention that should be applied to the reported metric names.
*/
Function<String, String> namingConvention();
/**
* Return true if the metrics should be reset.
*/
@@ -1,12 +1,4 @@
package io.ebeaninternal.server.core;
import io.ebean.Database;
import io.ebean.meta.MetaCountMetric;
import io.ebean.meta.MetaMetric;
import io.ebean.meta.MetaQueryMetric;
import io.ebean.meta.MetaTimedMetric;
import io.ebean.meta.MetricData;
import io.ebean.meta.ServerMetrics;
package io.ebean.meta;
import java.util.ArrayList;
import java.util.List;
@@ -14,34 +6,26 @@ import java.util.List;
/**
* Dump the metrics into a list of MetricData.
*/
final class DumpMetricsData {
final class MetricsAsData {
private final Database database;
private final ServerMetrics metrics;
private final List<MetricData> list = new ArrayList<>();
DumpMetricsData(Database database) {
this.database = database;
MetricsAsData(ServerMetrics metrics) {
this.metrics = metrics;
}
List<MetricData> data() {
collect(database.metaInfo().collectMetrics());
return list;
}
private void collect(ServerMetrics serverMetrics) {
final List<MetaTimedMetric> timedMetrics = serverMetrics.timedMetrics();
final List<MetaCountMetric> countMetrics = serverMetrics.countMetrics();
final List<MetaQueryMetric> queryMetrics = serverMetrics.queryMetrics();
for (MetaTimedMetric metric : timedMetrics) {
for (MetaTimedMetric metric : metrics.timedMetrics()) {
add(metric);
}
for (MetaCountMetric metric : countMetrics) {
for (MetaCountMetric metric : metrics.countMetrics()) {
addCount(metric);
}
for (MetaQueryMetric metric : queryMetrics) {
for (MetaQueryMetric metric : metrics.queryMetrics()) {
addQuery(metric);
}
return list;
}
private MetricData create(MetaMetric metric) {
@@ -1,25 +1,16 @@
package io.ebeaninternal.server.core;
import io.ebean.Database;
import io.ebean.meta.MetaCountMetric;
import io.ebean.meta.MetaMetric;
import io.ebean.meta.MetaQueryMetric;
import io.ebean.meta.MetaTimedMetric;
import io.ebean.meta.ServerMetrics;
import io.ebean.meta.ServerMetricsAsJson;
import io.ebean.meta.SortMetric;
package io.ebean.meta;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Comparator;
import java.util.List;
final class DumpMetricsJson implements ServerMetricsAsJson {
final class MetricsAsJson implements ServerMetricsAsJson {
private final Database database;
private final ServerMetrics metrics;
private Appendable writer;
/**
* By default include sql and location attributes for the initial collection only.
* By default, include sql and location attributes for the initial collection only.
*/
private int includeExtraAttributes = 1;
private boolean withHeader = true;
@@ -29,8 +20,8 @@ final class DumpMetricsJson implements ServerMetricsAsJson {
private int listCounter;
private int objKeyCounter;
DumpMetricsJson(Database database) {
this.database = database;
MetricsAsJson(ServerMetrics metrics) {
this.metrics = metrics;
}
@Override
@@ -66,24 +57,24 @@ final class DumpMetricsJson implements ServerMetricsAsJson {
@Override
public String json() {
writer = new StringWriter();
collect(database.metaInfo().collectMetrics());
collect();
return writer.toString();
}
@Override
public void write(Appendable buffer) {
writer = buffer;
collect(database.metaInfo().collectMetrics());
collect();
}
private void collect(ServerMetrics serverMetrics) {
private void collect() {
try {
start();
for (MetaTimedMetric metric : serverMetrics.timedMetrics()) {
for (MetaTimedMetric metric : metrics.timedMetrics()) {
logTimed(metric);
}
List<MetaCountMetric> countMetrics = serverMetrics.countMetrics();
List<MetaCountMetric> countMetrics = metrics.countMetrics();
if (!countMetrics.isEmpty()) {
if (sortBy != null) {
countMetrics.sort(SortMetric.COUNT_NAME);
@@ -93,7 +84,7 @@ final class DumpMetricsJson implements ServerMetricsAsJson {
}
}
List<MetaQueryMetric> queryMetrics = serverMetrics.queryMetrics();
List<MetaQueryMetric> queryMetrics = metrics.queryMetrics();
if (!queryMetrics.isEmpty()) {
if (sortBy != null) {
queryMetrics.sort(sortBy);
@@ -112,7 +103,7 @@ final class DumpMetricsJson implements ServerMetricsAsJson {
if (withHeader) {
objStart();
key("db");
val(database.name());
val(metrics.name());
key("metrics");
listStart();
}
@@ -7,6 +7,21 @@ import java.util.List;
*/
public interface ServerMetrics {
/**
* Return the name of the database these metrics were obtained for.
*/
String name();
/**
* Return ServerMetricsAsJson to build the metrics as JSON content.
*/
ServerMetricsAsJson asJson();
/**
* Return the metrics as a list of MetricData.
*/
List<MetricData> asData();
/**
* Return timed metrics for Transactions, labelled SqlQuery, labelled SqlUpdate.
*/
@@ -39,18 +39,6 @@ public interface ExpressionPath {
*/
StringParser stringParser();
/**
* For DateTime capable scalar types convert the long systemTimeMillis into
* an appropriate java time (Date,Timestamp,Time,Calendar, JODA type etc).
*/
Object parseDateTime(long systemTimeMillis);
/**
* Return true if the last type is "DateTime capable" - can support
* {@link #parseDateTime(long)}.
*/
boolean isDateTimeCapable();
/**
* Return the underlying JDBC type or 0 if this is not a scalar type.
*/
@@ -6,6 +6,7 @@ package io.ebean.text;
* Basic interface to support CSV, JSON and XML processing.
* </p>
*/
@FunctionalInterface
public interface StringFormatter {
/**
@@ -5,6 +5,7 @@ package io.ebean.text;
* <p>
* Basic interface to support CSV, JSON and XML processing.
*/
@FunctionalInterface
public interface StringParser {
/**
@@ -1,171 +0,0 @@
package io.ebean.text.csv;
import io.ebean.text.StringParser;
import java.io.Reader;
import java.util.Locale;
/**
* Reads CSV data turning it into object graphs that you can be saved (inserted)
* or processed yourself.
* <p>
* This first example doesn't use a {@link CsvCallback} and this means it will
* automatically create a transaction, save the customers and commit the
* transaction when successful.
* </p>
*
* <pre>{@code
* try {
* File f = new File("src/test/resources/test1.csv");
*
* FileReader reader = new FileReader(f, encoding);
*
* CsvReader<Customer> csvReader = DB.createCsvReader(Customer.class);
*
* csvReader.setPersistBatchSize(20);
*
* csvReader.addProperty("status");
* // ignore the next property
* csvReader.addIgnore();
* csvReader.addProperty("name");
* csvReader.addDateTime("anniversary", "dd-MMM-yyyy");
* csvReader.addProperty("billingAddress.line1");
* csvReader.addProperty("billingAddress.city");
*
* csvReader.process(reader);
*
* } catch (Exception e) {
* throw new RuntimeException(e);
* }
* }</pre>
*
* @param <T> the entity bean type
*/
public interface CsvReader<T> {
/**
* Explicitly set the default Locale.
*/
void setDefaultLocale(Locale defaultLocale);
/**
* Set the default format to use for Time types.
*/
void setDefaultTimeFormat(String defaultTimeFormat);
/**
* Set the default format to use for Date types.
*/
void setDefaultDateFormat(String defaultDateFormat);
/**
* Set the default format to use for Timestamp types.
*/
void setDefaultTimestampFormat(String defaultTimestampFormat);
/**
* Set the batch size for using JDBC statement batching.
* <p>
* By default this is set to 20 and setting this to 1 will disable the use of
* JDBC statement batching.
* </p>
*/
void setPersistBatchSize(int persistBatchSize);
/**
* Set to true if there is a header row that should be ignored.
* <p>
* If addPropertiesFromHeader is true then all the properties are added using
* the default time,date and timestamp formats.
* <p>
* If you have a mix of dateTime formats you can not use this method and must
* add the properties yourself.
* </p>
*/
void setHasHeader(boolean hasHeader, boolean addPropertiesFromHeader);
/**
* Same as setHasHeader(true,true);
* <p>
* This will use a header to define all the properties to load using the
* default formats for time, date and datetime types.
* </p>
*/
void setAddPropertiesFromHeader();
/**
* Same as setHasHeader(true, false);
* <p>
* This indicates that there is a header but that it should be ignored.
* </p>
*/
void setIgnoreHeader();
/**
* Set the frequency with which a INFO message will be logged showing the
* progress of the processing. You might set this to 1000 or 10000 etc.
* <p>
* If this is not set then no INFO messages will be logged.
* </p>
*/
void setLogInfoFrequency(int logInfoFrequency);
/**
* Ignore the next column of data.
*/
void addIgnore();
/**
* Define the property which will be loaded from the next column of data.
* <p>
* This takes into account the data type of the property and handles the
* String to object conversion automatically.
* </p>
*/
void addProperty(String propertyName);
/**
* Define the next property and use a custom StringParser to convert the
* string content into the appropriate type for the property.
*/
void addProperty(String propertyName, StringParser parser);
/**
* Add a property with a custom Date/Time/Timestamp format using the default
* Locale. This will convert the string into the appropriate java type for the
* given property (Date, Calendar, SQL Date, Time, Timestamp, JODA etc).
*/
void addDateTime(String propertyName, String dateTimeFormat);
/**
* Add a property with a custom Date/Time/Timestamp format. This will convert
* the string into the appropriate java type for the given property (Date,
* Calendar, SQL Date, Time, Timestamp, JODA etc).
*/
void addDateTime(String propertyName, String dateTimeFormat, Locale locale);
/**
* Automatically create a transaction if required to process all the CSV
* content from the reader.
* <p>
* This will check for a current transaction. If there is no current
* transaction then one is started and will commit (or rollback) at the end of
* processing. This will also set the persistBatchSize on the transaction.
* </p>
*/
void process(Reader reader) throws Exception;
/**
* Process the CSV content passing the bean to the CsvCallback after each row.
* <p>
* This provides you with the ability to modify and process the bean.
* </p>
* <p>
* When using a CsvCallback the reader WILL NOT create a transaction or save
* the bean(s) for you. If you want to insert the processed beans you must
* create your own transaction and save the bean(s) yourself.
* </p>
*/
void process(Reader reader, CsvCallback<T> callback) throws Exception;
}
@@ -1,4 +0,0 @@
/**
* CSV processing objects.
*/
package io.ebean.text.csv;
@@ -1,19 +1,20 @@
package io.ebean.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.ebean.EbeanVersion;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import static java.lang.System.Logger.Level.WARNING;
/**
* Utility for closing raw Jdbc resources.
*/
public final class JdbcClose {
private static final Logger log = LoggerFactory.getLogger("io.ebean");
private static final System.Logger log = EbeanVersion.log;
/**
* Close the resultSet logging if an error occurs.
@@ -24,7 +25,7 @@ public final class JdbcClose {
statement.close();
}
} catch (SQLException e) {
log.warn("Error closing statement", e);
log.log(WARNING, "Error closing statement", e);
}
}
@@ -37,7 +38,7 @@ public final class JdbcClose {
resultSet.close();
}
} catch (SQLException e) {
log.warn("Error closing resultSet", e);
log.log(WARNING, "Error closing resultSet", e);
}
}
@@ -50,7 +51,7 @@ public final class JdbcClose {
connection.close();
}
} catch (SQLException e) {
log.warn("Error closing connection", e);
log.log(WARNING, "Error closing connection", e);
}
}
@@ -63,7 +64,7 @@ public final class JdbcClose {
connection.rollback();
}
} catch (SQLException e) {
log.warn("Error on connection rollback", e);
log.log(WARNING, "Error on connection rollback", e);
}
}
@@ -76,7 +77,7 @@ public final class JdbcClose {
stmt.cancel();
}
} catch (SQLException e) {
log.warn("Error on cancelling statement", e);
log.log(WARNING, "Error on cancelling statement", e);
}
}
}
+2 -2
View File
@@ -15,8 +15,9 @@ module io.ebean.api {
requires transitive persistence.api;
requires transitive io.ebean.annotation;
requires transitive io.ebean.datasource.api;
requires transitive org.slf4j;
requires transitive io.avaje.applog;
requires static org.slf4j;
requires static io.ebean.types;
requires static com.fasterxml.jackson.core;
requires static com.fasterxml.jackson.databind;
@@ -39,7 +40,6 @@ module io.ebean.api {
exports io.ebean.service;
exports io.ebean.text;
exports io.ebean.text.json;
exports io.ebean.text.csv;
exports io.ebean.util;
}
+4 -4
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.6.5</version>
<version>13.9.0</version>
</parent>
<!-- <parent>-->
<!-- <groupId>org.avaje</groupId>-->
@@ -14,7 +14,7 @@
<scm>
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
<tag>ebean-parent-13.6.5</tag>
<tag>ebean-parent-13.9.0</tag>
</scm>
<name>ebean autotune</name>
@@ -26,7 +26,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
<scope>provided</scope>
</dependency>
@@ -55,7 +55,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
<scope>test</scope>
</dependency>
@@ -1,5 +1,6 @@
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;
@@ -7,8 +8,6 @@ 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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
@@ -16,12 +15,14 @@ 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 Logger logger = LoggerFactory.getLogger(DefaultAutoTuneService.class);
private static final System.Logger logger = AppLog.getLogger(DefaultAutoTuneService.class);
private final ReentrantLock lock = new ReentrantLock();
@@ -111,7 +112,7 @@ public class DefaultAutoTuneService implements AutoTuneService {
if (stream != null) {
loadAutoTuneProfiling(AutoTuneXmlReader.read(stream));
} else {
logger.warn("AutoTune file {} not found - no initial automatic query tuning", tuningFile);
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);
@@ -120,7 +121,7 @@ public class DefaultAutoTuneService implements AutoTuneService {
}
private void loadAutoTuneProfiling(Autotune profiling) {
logger.info("AutoTune loading {} tuning entries", profiling.getOrigin().size());
logger.log(INFO, "AutoTune loading {0} tuning entries", profiling.getOrigin().size());
for (Origin origin : profiling.getOrigin()) {
queryTuner.put(origin);
}
@@ -141,17 +142,17 @@ public class DefaultAutoTuneService implements AutoTuneService {
event.process();
if (event.isEmpty()) {
long exeMillis = System.currentTimeMillis() - start;
logger.debug("No query tuning updates for server:{} executionMillis:{}", serverName, exeMillis);
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.info("query tuning updates - new:{} diff:{} for server:{} executionMillis:{}", event.getNewCount(), event.getDiffCount(), serverName, exeMillis);
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.error("Error collecting or applying automatic query tuning", e);
logger.log(ERROR, "Error collecting or applying automatic query tuning", e);
}
} finally {
lock.unlock();
@@ -172,11 +173,11 @@ public class DefaultAutoTuneService implements AutoTuneService {
AutoTuneDiffCollection event = new AutoTuneDiffCollection(profiling, queryTuner, false);
event.process();
if (event.isEmpty()) {
logger.info("No new or diff entries for profiling server:{}", serverName);
logger.log(INFO, "No new or diff entries for profiling server:{0}", serverName);
} else {
event.writeFile(profilingFile + "-" + serverName);
logger.info("writing new:{} diff:{} profiling entries for server:{}", event.getNewCount(), event.getDiffCount(), serverName);
logger.log(INFO, "writing new:{0} diff:{1} profiling entries for server:{2}", event.getNewCount(), event.getDiffCount(), serverName);
}
}
} finally {
@@ -196,7 +197,7 @@ public class DefaultAutoTuneService implements AutoTuneService {
private void outputAllTuning() {
if (runtimeChangeCount == 0) {
logger.info("no runtime query tuning changes for server:{}", serverName);
logger.log(INFO, "no runtime query tuning changes for server:{0}", serverName);
} else {
AutoTuneAllCollection event = new AutoTuneAllCollection(queryTuner);
@@ -205,12 +206,12 @@ public class DefaultAutoTuneService implements AutoTuneService {
if (existingTuning.exists()) {
// rename the existing autotune.xml file (appending 'now')
if (!existingTuning.renameTo(new File(tuningFile + "." + AutoTuneXmlWriter.now()))) {
logger.warn("Failed to rename autotune file [{}]", tuningFile);
logger.log(WARNING, "Failed to rename autotune file [{0}]", tuningFile);
}
}
event.writeFile(tuningFile, false);
logger.info("query tuning detected [{}] changes, writing all [{}] tuning entries for server:{}", runtimeChangeCount, size, serverName);
logger.log(INFO, "query tuning detected [{0}] changes, writing all [{1}] tuning entries for server:{2}", runtimeChangeCount, size, serverName);
}
}
@@ -279,7 +280,7 @@ public class DefaultAutoTuneService implements AutoTuneService {
} catch (InterruptedException e) {
// restore the interrupted status
Thread.currentThread().interrupt();
logger.warn("Error while sleeping after System.gc() request.", e);
logger.log(WARNING, "Error while sleeping after System.gc() request.", e);
}
}
@@ -1,5 +1,6 @@
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;
@@ -7,19 +8,19 @@ 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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 Logger logger = LoggerFactory.getLogger(ProfileOriginNodeUsage.class);
private static final System.Logger logger = AppLog.getLogger(ProfileOriginNodeUsage.class);
private final ReentrantLock lock = new ReentrantLock();
@@ -45,7 +46,7 @@ public class ProfileOriginNodeUsage {
if (path != null) {
ElPropertyValue elGetValue = rootDesc.elGetValue(path);
if (elGetValue == null) {
logger.warn("AutoTune: Can't find join for path[" + path + "] for " + rootDesc.name());
logger.log(WARNING, "AutoTune: Can't find join for path[" + path + "] for " + rootDesc.name());
return;
} else {
BeanProperty beanProperty = elGetValue.beanProperty();
@@ -61,7 +62,7 @@ public class ProfileOriginNodeUsage {
for (String propName : aggregateUsed) {
BeanProperty beanProp = desc.findPropertyFromPath(propName);
if (beanProp == null) {
logger.warn("AutoTune: Can't find property[" + propName + "] for " + desc.name());
logger.log(WARNING, "AutoTune: Can't find property[" + propName + "] for " + desc.name());
} else {
if (beanProp.isId()) {
+39 -15
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.6.5</version>
<version>13.9.0</version>
</parent>
<name>ebean bom</name>
@@ -18,6 +18,24 @@
<!-- dependencies external to this ebean.git build -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>persistence-api</artifactId>
<version>${ebean-persistence-api.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-annotation</artifactId>
<version>${ebean-annotation.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-types</artifactId>
<version>${ebean-types.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-ddl-runner</artifactId>
@@ -71,88 +89,94 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-joda-time</artifactId>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-ddl-generator</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-externalmapping-api</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-externalmapping-xml</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-autotune</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>querybean-generator</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>kotlin-querybean-generator</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgis</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-redis</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
</dependencies>
+9 -2
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.6.5</version>
<version>13.9.0</version>
</parent>
<artifactId>ebean-core-type</artifactId>
@@ -16,7 +16,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
@@ -26,6 +26,13 @@
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.avaje</groupId>
<artifactId>junit</artifactId>
<version>1.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -1,8 +1,5 @@
package io.ebeaninternal.server.core;
package io.ebean.core.type;
import io.ebeaninternal.server.type.ScalarTypeUUIDBinary;
import java.io.Serializable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
@@ -14,14 +11,9 @@ import java.util.Calendar;
import java.util.UUID;
/**
* Default implementation of TypeConverter.
* <p>
* Converts objects to the required type if required.
* </p>
* Helper to converts objects to the basic types if required.
*/
public final class BasicTypeConverter implements Serializable {
private static final long serialVersionUID = 7691463236204070311L;
public final class BasicTypeConverter {
/**
* Type code for java.util.Calendar.
@@ -43,7 +35,6 @@ public final class BasicTypeConverter implements Serializable {
* @param toDataType the dataType as per java.sql.Types.
*/
public static Object convert(Object value, int toDataType) {
try {
switch (toDataType) {
case UTIL_DATE: {
@@ -58,7 +49,8 @@ public final class BasicTypeConverter implements Serializable {
case Types.INTEGER: {
return toInteger(value);
}
case Types.BIT: {
case Types.BIT:
case Types.BOOLEAN: {
return toBoolean(value);
}
case Types.TINYINT: {
@@ -67,59 +59,42 @@ public final class BasicTypeConverter implements Serializable {
case Types.SMALLINT: {
return toShort(value);
}
case Types.NUMERIC: {
return toBigDecimal(value);
}
case Types.NUMERIC:
case Types.DECIMAL: {
return toBigDecimal(value);
}
case Types.REAL: {
return toFloat(value);
}
case Types.DOUBLE: {
return toDouble(value);
}
case Types.DOUBLE:
case Types.FLOAT: {
return toDouble(value);
}
case Types.BOOLEAN: {
return toBoolean(value);
}
case Types.TIMESTAMP: {
return toTimestamp(value);
}
case Types.DATE: {
return toDate(value);
}
case Types.VARCHAR: {
return toString(value);
}
case Types.VARCHAR:
case Types.CHAR: {
return toString(value);
}
case Types.OTHER: {
return value;
}
case Types.JAVA_OBJECT: {
return value;
}
case Types.OTHER:
case Types.BINARY:
case Types.LONGVARBINARY:
case Types.BLOB: {
return value;
}
case Types.BLOB:
case Types.JAVA_OBJECT:
case Types.LONGVARCHAR:
case Types.CLOB: {
return value;
}
default: {
String msg = "Unhandled data type [" + toDataType + "] converting [" + value + "]";
throw new RuntimeException(msg);
throw new RuntimeException("Unhandled data type - " + toDataType);
}
}
} catch (ClassCastException e) {
String m = "ClassCastException converting to data type [" + toDataType + "] value [" + value + "]";
throw new RuntimeException(m);
throw new RuntimeException("ClassCastException converting to data type: " + toDataType + " value: " + value);
}
}
@@ -127,7 +102,6 @@ public final class BasicTypeConverter implements Serializable {
* Convert the value to a String.
*/
public static String toString(Object value) {
if (value == null) {
return null;
}
@@ -137,7 +111,6 @@ public final class BasicTypeConverter implements Serializable {
if (value instanceof char[]) {
return String.valueOf((char[]) value);
}
return value.toString();
}
@@ -145,8 +118,7 @@ public final class BasicTypeConverter implements Serializable {
/**
* Convert the value to a Boolean with an explicit String true value.
*/
public static Boolean toBoolean(Object value, String dbTrueValue) {
public static Boolean toBoolean(Object value, String trueValue) {
if (value == null) {
return null;
}
@@ -156,8 +128,7 @@ public final class BasicTypeConverter implements Serializable {
if (value instanceof Number) {
return ((Number) value).intValue() == 1;
}
String s = value.toString();
return s.equalsIgnoreCase(dbTrueValue);
return value.toString().equalsIgnoreCase(trueValue);
}
/**
@@ -165,14 +136,12 @@ public final class BasicTypeConverter implements Serializable {
* "true" or "false".
*/
public static Boolean toBoolean(Object value) {
if (value == null) {
return null;
}
if (value instanceof Boolean) {
return (Boolean) value;
}
return Boolean.valueOf(value.toString());
}
@@ -180,7 +149,6 @@ public final class BasicTypeConverter implements Serializable {
* Convert the value to a UUID.
*/
public static UUID toUUID(Object value, boolean optimizedBinary) {
if (value == null) {
return null;
}
@@ -191,17 +159,15 @@ public final class BasicTypeConverter implements Serializable {
return UUID.fromString((String) value);
}
if (value instanceof byte[]) {
return ScalarTypeUUIDBinary.convertFromBytes((byte[]) value, optimizedBinary);
return ScalarTypeUtils.uuidFromBytes((byte[]) value, optimizedBinary);
}
return UUID.fromString(value.toString());
}
/**
* convert the passed in object to a BigDecimal. It should be another
* numeric type.
* convert the passed in object to a BigDecimal. It should be another numeric type.
*/
public static BigDecimal toBigDecimal(Object value) {
if (value == null) {
return null;
}
@@ -212,7 +178,6 @@ public final class BasicTypeConverter implements Serializable {
}
public static Float toFloat(Object value) {
if (value == null) {
return null;
}
@@ -226,7 +191,6 @@ public final class BasicTypeConverter implements Serializable {
}
public static Short toShort(Object value) {
if (value == null) {
return null;
}
@@ -240,7 +204,6 @@ public final class BasicTypeConverter implements Serializable {
}
public static Byte toByte(Object value) {
if (value == null) {
return null;
}
@@ -251,11 +214,9 @@ public final class BasicTypeConverter implements Serializable {
}
/**
* convert the passed in object to a Integer. It should be another numeric
* type.
* convert the passed in object to an Integer.
*/
public static Integer toInteger(Object value) {
if (value == null) {
return null;
}
@@ -269,10 +230,9 @@ public final class BasicTypeConverter implements Serializable {
}
/**
* Convert the object to a Long. It should be another numeric type.
* Convert the object to a Long.
*/
public static Long toLong(Object value) {
if (value == null) {
return null;
}
@@ -294,8 +254,7 @@ public final class BasicTypeConverter implements Serializable {
return Long.valueOf(value.toString());
}
public static BigInteger toMathBigInteger(Object value) {
public static BigInteger toBigInteger(Object value) {
if (value == null) {
return null;
}
@@ -306,10 +265,9 @@ public final class BasicTypeConverter implements Serializable {
}
/**
* Convert the object to a Double. It should be another numberic type.
* Convert the object to a Double.
*/
public static Double toDouble(Object value) {
if (value == null) {
return null;
}
@@ -323,56 +281,42 @@ public final class BasicTypeConverter implements Serializable {
}
/**
* convert the passed in object to a Timestamp. It is expected to be a
* java.sql.Date really.
* convert the passed in object to a Timestamp.
*/
public static Timestamp toTimestamp(Object value) {
if (value == null) {
return null;
}
if (value instanceof Timestamp) {
return (Timestamp) value;
} else if (value instanceof java.util.Date) {
// no nanos here... so hopefully ok
return new Timestamp(((java.util.Date) value).getTime());
} else if (value instanceof Calendar) {
return new Timestamp(((Calendar) value).getTime().getTime());
} else if (value instanceof String) {
return Timestamp.valueOf((String) value);
} else if (value instanceof LocalDateTime) {
return Timestamp.valueOf((LocalDateTime) value);
} else if (value instanceof Number) {
return new Timestamp(((Number) value).longValue());
} else {
String msg = "Unable to convert [" + value.getClass().getName() + "] into a Timestamp.";
throw new RuntimeException(msg);
throw new RuntimeException("Unable to convert " + value);
}
}
public static java.sql.Time toTime(Object value) {
if (value == null) {
return null;
}
if (value instanceof java.sql.Time) {
return (java.sql.Time) value;
} else if (value instanceof String) {
return java.sql.Time.valueOf((String) value);
} else if (value instanceof LocalTime) {
return java.sql.Time.valueOf((LocalTime) value);
} else {
String m = "Unable to convert [" + value.getClass().getName() + "] into a java.sql.Date.";
throw new RuntimeException(m);
throw new RuntimeException("Unable to convert " + value);
}
}
@@ -380,31 +324,23 @@ public final class BasicTypeConverter implements Serializable {
* convert the passed in object to a java sql Date.
*/
public static java.sql.Date toDate(Object value) {
if (value == null) {
return null;
}
if (value instanceof java.sql.Date) {
return (java.sql.Date) value;
} else if (value instanceof java.util.Date) {
return new java.sql.Date(((java.util.Date) value).getTime());
} else if (value instanceof Calendar) {
return new java.sql.Date(((Calendar) value).getTime().getTime());
} else if (value instanceof String) {
return java.sql.Date.valueOf((String) value);
} else if (value instanceof Number) {
return new java.sql.Date(((Number) value).longValue());
} else if (value instanceof LocalDate) {
return java.sql.Date.valueOf((LocalDate)value);
return java.sql.Date.valueOf((LocalDate) value);
} else {
String m = "Unable to convert [" + value.getClass().getName() + "] into a java.sql.Date.";
throw new RuntimeException(m);
throw new RuntimeException("Unable to convert " + value);
}
}
@@ -412,7 +348,6 @@ public final class BasicTypeConverter implements Serializable {
* convert the passed in object to a java sql Date.
*/
public static java.util.Date toUtilDate(Object value) {
if (value == null) {
return null;
}
@@ -420,26 +355,19 @@ public final class BasicTypeConverter implements Serializable {
// loss of nanos precision
return new java.util.Date(((java.sql.Timestamp) value).getTime());
}
// DEVNOTE: strictly speaking do I need to convert a java.sql.Date to
// java.util.Date? equals() is symmetrical so perhaps this is not
// really required?
if (value instanceof java.sql.Date) {
return new java.util.Date(((java.sql.Date) value).getTime());
}
if (value instanceof java.util.Date) {
return (java.util.Date) value;
} else if (value instanceof Calendar) {
return ((Calendar) value).getTime();
} else if (value instanceof String) {
return new java.util.Date(Timestamp.valueOf((String) value).getTime());
} else if (value instanceof Number) {
return new java.util.Date(((Number) value).longValue());
} else {
throw new RuntimeException("Unable to convert [" + value.getClass().getName() + "] into a java.util.Date");
throw new RuntimeException("Unable to convert " + value);
}
}
@@ -447,37 +375,29 @@ public final class BasicTypeConverter implements Serializable {
* convert the passed in object to a java sql Date.
*/
public static Calendar toCalendar(Object value) {
if (value == null) {
return null;
}
if (value instanceof Calendar) {
return (Calendar) value;
} else if (value instanceof java.util.Date) {
java.util.Date date = ((java.util.Date) value);
return toCalendarFromDate(date);
} else if (value instanceof String) {
java.util.Date date = toUtilDate(value);
return toCalendarFromDate(date);
} else if (value instanceof Number) {
long timeMillis = ((Number) value).longValue();
java.util.Date date = new java.util.Date(timeMillis);
return toCalendarFromDate(date);
} else {
String m = "Unable to convert [" + value.getClass().getName() + "] into a java.util.Date";
throw new RuntimeException(m);
throw new RuntimeException("Unable to convert " + value);
}
}
private static Calendar toCalendarFromDate(java.util.Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
return cal;
}
@@ -2,7 +2,6 @@ package io.ebean.core.type;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import io.ebean.text.StringFormatter;
import io.ebean.text.StringParser;
@@ -34,7 +33,7 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
/**
* Return true for types that do mutation detection based on json content.
*/
default boolean isJsonMapper() {
default boolean jsonMapper() {
return false;
}
@@ -42,14 +41,14 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
* Return true if this is a binary type and can not support parse() and format() from/to string.
* This allows Ebean to optimise marshalling types to string.
*/
default boolean isBinaryType() {
default boolean binary() {
return false;
}
/**
* Return true if this is a mutable scalar type (like hstore).
*/
default boolean isMutable() {
default boolean mutable() {
return false;
}
@@ -67,7 +66,7 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
* If a BeanProperty has no explicit length defined then this length should
* be assigned.
*/
default int getLength() {
default int length() {
return 0;
}
@@ -77,7 +76,7 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
* If it is native to JDBC then its values/instances do not need to be
* converted to and from an associated JDBC type.
*/
boolean isJdbcNative();
boolean jdbcNative();
/**
* Return the type as per java.sql.Types that this maps to.
@@ -85,14 +84,19 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
* This type should be consistent with the toJdbcType() method in converting
* the type to the appropriate type for binding to preparedStatements.
*/
int getJdbcType();
int jdbcType();
/**
* Return the type that matches the bean property type.
* <p>
* This represents the 'logical' type rather than the JDBC type this maps to.
*/
Class<T> getType();
Class<T> type();
/**
* Return the type this maps to for JSON document stores.
*/
DocPropertyType docType();
/**
* Read the value from the resultSet and convert if necessary to the logical
@@ -101,12 +105,6 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
@Override
T read(DataReader reader) throws SQLException;
/**
* Ignore the reading of this value. Typically, this means moving the index
* position in the ResultSet.
*/
void loadIgnore(DataReader reader);
/**
* Convert (if necessary) and bind the value to the preparedStatement.
* <p>
@@ -135,6 +133,14 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
*/
T toBeanType(Object value);
/**
* Convert the string value to the appropriate java object.
* <p>
* Mostly used to support CSV, JSON and XML parsing.
*/
@Override
T parse(String value);
/**
* Convert the type into a string representation.
*/
@@ -147,34 +153,10 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
* <p>
* This is so that ScalarType also implements the StringFormatter interface.
*/
@SuppressWarnings("unchecked")
@Override
String format(Object value);
/**
* Convert the string value to the appropriate java object.
* <p>
* Mostly used to support CSV, JSON and XML parsing.
*/
@Override
T parse(String value);
/**
* Return the type this maps to for JSON document stores.
*/
DocPropertyType getDocType();
/**
* Return true if the type can accept long systemTimeMillis input.
* <p>
* This is used to determine if it is sensible to use the
* {@link #convertFromMillis(long)} method.
* <p>
* This includes the Date, Calendar, sql Date, Time, Timestamp, JODA types
* as well as Long, BigDecimal and String (although it generally is not
* expected to parse systemTimeMillis to a String or BigDecimal).
*/
default boolean isDateTimeCapable() {
return false;
default String format(Object value) {
return formatValue((T) value);
}
/**
@@ -184,15 +166,6 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
throw new UnsupportedOperationException();
}
/**
* Convert the systemTimeMillis into the appropriate java object.
* <p>
* For non dateTime types this will throw an exception.
*/
default T convertFromMillis(long dateTime) {
throw new UnsupportedOperationException();
}
/**
* Read the value from binary input.
*/
@@ -0,0 +1,33 @@
package io.ebean.core.type;
/**
* Base ScalarType object.
*/
public abstract class ScalarTypeBase<T> implements ScalarType<T> {
protected final Class<T> type;
protected final boolean jdbcNative;
protected final int jdbcType;
public ScalarTypeBase(Class<T> type, boolean jdbcNative, int jdbcType) {
this.type = type;
this.jdbcNative = jdbcNative;
this.jdbcType = jdbcType;
}
@Override
public boolean jdbcNative() {
return jdbcNative;
}
@Override
public int jdbcType() {
return jdbcType;
}
@Override
public Class<T> type() {
return type;
}
}
@@ -1,4 +1,4 @@
package io.ebeaninternal.server.type;
package io.ebean.core.type;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
@@ -7,6 +7,7 @@ import io.ebean.config.JsonConfig;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
import io.ebean.core.type.ScalarTypeBase;
import java.io.DataInput;
import java.io.DataOutput;
@@ -18,15 +19,20 @@ import java.sql.Types;
/**
* Base class for Date types.
*/
abstract class ScalarTypeBaseDate<T> extends ScalarTypeBase<T> {
public abstract class ScalarTypeBaseDate<T> extends ScalarTypeBase<T> {
protected final JsonConfig.Date mode;
ScalarTypeBaseDate(JsonConfig.Date mode, Class<T> type, boolean jdbcNative, int jdbcType) {
public ScalarTypeBaseDate(JsonConfig.Date mode, Class<T> type, boolean jdbcNative, int jdbcType) {
super(type, jdbcNative, jdbcType);
this.mode = mode;
}
/**
* Convert the value to ISO8601 format.
*/
protected abstract String toIsoFormat(T value);
/**
* Convert the target value to millis.
*/
@@ -53,38 +59,27 @@ abstract class ScalarTypeBaseDate<T> extends ScalarTypeBase<T> {
@Override
public T read(DataReader reader) throws SQLException {
Date ts = reader.getDate();
return ts == null ? null : convertFromDate(ts);
final Date date = reader.getDate();
return date == null ? null : convertFromDate(date);
}
@Override
public String formatValue(T t) {
Date date = convertToDate(t);
// format all dates into epoch millis
long epochMillis = date.getTime();
return Long.toString(epochMillis);
public String formatValue(T value) {
final Date date = convertToDate(value);
return Long.toString(date.getTime());
}
@Override
public T parse(String value) {
try {
long epochMillis = Long.parseLong(value);
return convertFromDate(new Date(epochMillis));
return convertFromDate(new Date(Long.parseLong(value)));
} catch (NumberFormatException e) {
Date date = Date.valueOf(value);
return convertFromDate(date);
return convertFromDate(Date.valueOf(value));
}
}
@Override
public T convertFromMillis(long systemTimeMillis) {
Date ts = new Date(systemTimeMillis);
return convertFromDate(ts);
}
@Override
public boolean isDateTimeCapable() {
return true;
return convertFromDate(new Date(systemTimeMillis));
}
@Override
@@ -105,13 +100,8 @@ abstract class ScalarTypeBaseDate<T> extends ScalarTypeBase<T> {
}
}
/**
* Convert the value to ISO8601 format.
*/
protected abstract String toIsoFormat(T value);
@Override
public DocPropertyType getDocType() {
public DocPropertyType docType() {
return DocPropertyType.DATE;
}
@@ -120,9 +110,7 @@ abstract class ScalarTypeBaseDate<T> extends ScalarTypeBase<T> {
if (!dataInput.readBoolean()) {
return null;
} else {
long val = dataInput.readLong();
Date date = new Date(val);
return convertFromDate(date);
return convertFromDate(new Date(dataInput.readLong()));
}
}
@@ -132,8 +120,7 @@ abstract class ScalarTypeBaseDate<T> extends ScalarTypeBase<T> {
dataOutput.writeBoolean(false);
} else {
dataOutput.writeBoolean(true);
Date date = convertToDate(value);
dataOutput.writeLong(date.getTime());
dataOutput.writeLong(convertToDate(value).getTime());
}
}
@@ -1,11 +1,8 @@
package io.ebeaninternal.server.type;
package io.ebean.core.type;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import io.ebean.config.JsonConfig;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
import java.io.DataInput;
import java.io.DataOutput;
@@ -16,16 +13,14 @@ import java.sql.Timestamp;
import java.sql.Types;
import java.time.Instant;
import static io.ebeaninternal.server.type.IsoJsonDateTimeParser.parseIso;
/**
* Base type for DateTime types.
*/
abstract class ScalarTypeBaseDateTime<T> extends ScalarTypeBase<T> {
public abstract class ScalarTypeBaseDateTime<T> extends ScalarTypeBase<T> {
protected final JsonConfig.DateTime mode;
ScalarTypeBaseDateTime(JsonConfig.DateTime mode, Class<T> type, boolean jdbcNative, int jdbcType) {
public ScalarTypeBaseDateTime(JsonConfig.DateTime mode, Class<T> type, boolean jdbcNative, int jdbcType) {
super(type, jdbcNative, jdbcType);
this.mode = mode;
}
@@ -53,7 +48,6 @@ abstract class ScalarTypeBaseDateTime<T> extends ScalarTypeBase<T> {
/**
* Convert from epoch millis to the value.
*/
@Override
public abstract T convertFromMillis(long systemTimeMillis);
/**
@@ -75,7 +69,7 @@ abstract class ScalarTypeBaseDateTime<T> extends ScalarTypeBase<T> {
* Convert the value to ISO8601 format.
*/
protected T fromJsonISO8601(String value) {
return convertFromInstant(parseIso(value));
return convertFromInstant(ScalarTypeUtils.parseInstant(value));
}
@Override
@@ -101,7 +95,7 @@ abstract class ScalarTypeBaseDateTime<T> extends ScalarTypeBase<T> {
* Helper method that given epoch seconds and nanos return a JSON nanos formatted string.
*/
protected String toJsonNanos(long epochSecs, int nanos) {
return DecimalUtils.toDecimal(epochSecs, nanos);
return ScalarTypeUtils.toDecimal(epochSecs, nanos);
}
@Override
@@ -112,7 +106,7 @@ abstract class ScalarTypeBaseDateTime<T> extends ScalarTypeBase<T> {
}
case VALUE_NUMBER_FLOAT: {
BigDecimal value = parser.getDecimalValue();
Timestamp timestamp = DecimalUtils.toTimestamp(value);
Timestamp timestamp = ScalarTypeUtils.toTimestamp(value);
return convertFromTimestamp(timestamp);
}
default: {
@@ -139,7 +133,7 @@ abstract class ScalarTypeBaseDateTime<T> extends ScalarTypeBase<T> {
}
@Override
public DocPropertyType getDocType() {
public DocPropertyType docType() {
return DocPropertyType.DATETIME;
}
@@ -160,11 +154,6 @@ abstract class ScalarTypeBaseDateTime<T> extends ScalarTypeBase<T> {
}
}
@Override
public boolean isDateTimeCapable() {
return true;
}
@Override
public T readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
@@ -1,11 +1,7 @@
package io.ebeaninternal.server.type;
package io.ebean.core.type;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.DocPropertyType;
import io.ebean.text.TextException;
import java.io.DataInput;
import java.io.DataOutput;
@@ -17,13 +13,13 @@ import java.sql.Types;
* Base ScalarType for types which converts to and from a VARCHAR database
* column.
*/
abstract class ScalarTypeBaseVarchar<T> extends ScalarTypeBase<T> {
public abstract class ScalarTypeBaseVarchar<T> extends ScalarTypeBase<T> {
ScalarTypeBaseVarchar(Class<T> type) {
public ScalarTypeBaseVarchar(Class<T> type) {
super(type, false, Types.VARCHAR);
}
ScalarTypeBaseVarchar(Class<T> type, boolean jdbcNative, int jdbcType) {
public ScalarTypeBaseVarchar(Class<T> type, boolean jdbcNative, int jdbcType) {
super(type, jdbcNative, jdbcType);
}
@@ -88,12 +84,6 @@ abstract class ScalarTypeBaseVarchar<T> extends ScalarTypeBase<T> {
return format(value);
}
@Override
@SuppressWarnings("unchecked")
public String format(Object value) {
return formatValue((T) value);
}
@Override
public T readData(DataInput dataInput) throws IOException {
if (!dataInput.readBoolean()) {
@@ -108,7 +98,8 @@ abstract class ScalarTypeBaseVarchar<T> extends ScalarTypeBase<T> {
if (value == null) {
dataOutput.writeBoolean(false);
} else {
ScalarHelp.writeUTF(dataOutput, convertToDbString(value));
dataOutput.writeBoolean(true);
dataOutput.writeUTF(convertToDbString(value));
}
}
@@ -123,7 +114,7 @@ abstract class ScalarTypeBaseVarchar<T> extends ScalarTypeBase<T> {
}
@Override
public DocPropertyType getDocType() {
public DocPropertyType docType() {
return DocPropertyType.TEXT;
}
@@ -0,0 +1,179 @@
package io.ebean.core.type;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.Duration;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.UUID;
/**
* Utilities to aid in the translation of decimal types to/from multiple parts.
*
* @author Nick Williams
* @since 2.2.0
*/
public final class ScalarTypeUtils {
private static final char[] ZEROES = new char[]{'0', '0', '0', '0', '0', '0', '0', '0', '0'};
private static final BigDecimal ONE_BILLION = new BigDecimal(1000000000L);
private static final DateTimeFormatter ISO_MILLIS = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendInstant(3)
.toFormatter();
/**
* Parse using ISO8601.
*/
public static Instant parseInstant(String jsonDateTime) {
return Instant.parse(jsonDateTime);
}
/**
* Format using ISO8601.
*/
public static String formatInstant(Instant value) {
return ISO_MILLIS.format(value);
}
/**
* Convert decimal to duration with nanos.
*/
public static Duration toDuration(BigDecimal value) {
long seconds = value.longValue();
int nanoseconds = extractNanosecondDecimal(value, seconds);
return Duration.ofSeconds(seconds, nanoseconds);
}
/**
* Convert duration to decimal with nanos.
*/
public static BigDecimal toDecimal(Duration instant) {
return new BigDecimal(toDecimal(instant.getSeconds(), instant.getNano()));
}
/**
* Convert decimal to timestamp with nanos.
*/
public static Timestamp toTimestamp(BigDecimal value) {
long seconds = value.longValue();
int nanoseconds = extractNanosecondDecimal(value, seconds);
Timestamp ts = new Timestamp(seconds * 1000);
ts.setNanos(nanoseconds);
return ts;
}
/**
* Convert timestamp to decimal with nanos.
*/
public static BigDecimal toDecimal(Timestamp instant) {
long millis = instant.getTime();
long secs = millis / 1000;
return new BigDecimal(toDecimal(secs, instant.getNanos()));
}
/**
* Convert to decimal string with nanos.
*/
public static String toDecimal(long seconds, int nanoseconds) {
StringBuilder string = new StringBuilder(Integer.toString(nanoseconds));
if (string.length() < 9)
string.insert(0, ZEROES, 0, 9 - string.length());
return seconds + "." + string;
}
private static int extractNanosecondDecimal(BigDecimal value, long integer) {
return value.subtract(new BigDecimal(integer)).multiply(ONE_BILLION).intValue();
}
/**
* Convert from byte[] to UUID.
*/
public static UUID uuidFromBytes(byte[] bytes, boolean optimized) {
int usableBytes = Math.min(bytes.length, 16);
// Need exactly 16 bytes - pad the input if not enough bytes are provided
// Use provided bytes in the least significant position; if more than 16 bytes are given,
// then use the first 16 bytes from the array;
byte[] barr = new byte[16];
for (int i = 15, j = usableBytes - 1; j >= 0; i--, j--) {
barr[i] = bytes[j];
}
long msb;
if (optimized) {
msb = ((long)barr[4] << 56) + // XXXXXXXX-____-____-...
((long)(barr[5] & 255) << 48) + // -> put at end 4..7 of buf
((long)(barr[6] & 255) << 40) +
((long)(barr[7] & 255) << 32) +
((long)(barr[2] & 255) << 24) + // ________-XXXX-____-...
((barr[3] & 255) << 16) + // put at 2..3 in buf
((barr[0] & 255) << 8) + // ________-____-XXXX-...
((barr[1] & 255) << 0); // put at 0..1 in buf
} else {
msb = ((long)barr[0] << 56) + // XXXXXXXX-____-____-...
((long)(barr[1] & 255) << 48) +
((long)(barr[2] & 255) << 40) +
((long)(barr[3] & 255) << 32) +
((long)(barr[4] & 255) << 24) + // ________-XXXX-____-...
((barr[5] & 255) << 16) +
((barr[6] & 255) << 8) + // ________-____-XXXX-...
((barr[7] & 255) << 0);
}
long lsb = ((long)barr[8] << 56) +
((long)(barr[9] & 255) << 48) +
((long)(barr[10] & 255) << 40) +
((long)(barr[11] & 255) << 32) +
((long)(barr[12] & 255) << 24) +
((barr[13] & 255) << 16) +
((barr[14] & 255) << 8) +
((barr[15] & 255) << 0);
return new UUID(msb, lsb);
}
/**
* Convert from UUID to byte[].
*/
public static byte[] uuidToBytes(UUID uuid, boolean optimized) {
byte[] ret = new byte[16];
long l = uuid.getMostSignificantBits();
if (optimized) {
ret[0] = (byte) (l >>> 8); // was 6/7
ret[1] = (byte) (l >>> 0);
ret[2] = (byte) (l >>> 24); // was 4/5
ret[3] = (byte) (l >>> 16);
ret[4] = (byte) (l >>> 56); // was 0..3
ret[5] = (byte) (l >>> 48);
ret[6] = (byte) (l >>> 40);
ret[7] = (byte) (l >>> 32);
} else {
ret[0] = (byte) (l >>> 56);
ret[1] = (byte) (l >>> 48);
ret[2] = (byte) (l >>> 40);
ret[3] = (byte) (l >>> 32);
ret[4] = (byte) (l >>> 24);
ret[5] = (byte) (l >>> 16);
ret[6] = (byte) (l >>> 8);
ret[7] = (byte) (l >>> 0);
}
l = uuid.getLeastSignificantBits();
ret[8] = (byte) (l >>> 56);
ret[9] = (byte) (l >>> 48);
ret[10] = (byte) (l >>> 40);
ret[11] = (byte) (l >>> 32);
ret[12] = (byte) (l >>> 24);
ret[13] = (byte) (l >>> 16);
ret[14] = (byte) (l >>> 8);
ret[15] = (byte) (l >>> 0);
return ret;
}
}
@@ -0,0 +1,36 @@
package io.ebean.core.type;
import org.junit.jupiter.api.Test;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.Duration;
import java.time.Instant;
import static org.junit.jupiter.api.Assertions.assertEquals;
class DecimalUtilsTest {
@Test
void testToDecimal() {
Instant now = Instant.now();
Timestamp sourceTimestamp = Timestamp.from(now);
BigDecimal decimal = ScalarTypeUtils.toDecimal(sourceTimestamp);
Timestamp timestamp = ScalarTypeUtils.toTimestamp(decimal);
assertEquals(now, timestamp.toInstant());
assertEquals(sourceTimestamp, timestamp);
}
@Test
void testDuration() {
Duration duration = Duration.ofSeconds(323, 1500000);
BigDecimal bigDecimal = ScalarTypeUtils.toDecimal(duration);
Duration duration1 = ScalarTypeUtils.toDuration(bigDecimal);
assertEquals(duration, duration1);
assertEquals("PT5M23.0015S", duration1.toString());
}
}
@@ -1,5 +1,4 @@
package io.ebeaninternal.server.type;
package io.ebean.core.type;
import org.junit.jupiter.api.Test;
@@ -7,43 +6,43 @@ import java.time.Instant;
import static org.assertj.core.api.Assertions.assertThat;
public class IsoJsonDateTimeParserTest {
class IsoJsonDateTimeParserTest {
private IsoJsonDateTimeParser parser = new IsoJsonDateTimeParser();
private ScalarTypeUtils parser = new ScalarTypeUtils();
@Test
public void parseFormat_when_hasMillis() {
void parseFormat_when_hasMillis() {
parseAndFormat("2016-02-28T20:39:00.123Z", "2016-02-28T20:39:00.123Z");
}
@Test
public void parseFormat_when_noMillis() {
void parseFormat_when_noMillis() {
parseAndFormat("2016-02-28T20:39:00Z", "2016-02-28T20:39:00.000Z");
}
@Test
public void parseFormat_when_millis_1dp() {
void parseFormat_when_millis_1dp() {
parseAndFormat("2016-02-28T20:39:00.0Z", "2016-02-28T20:39:00.000Z");
}
@Test
public void parseFormat_when_millis_2dp() {
void parseFormat_when_millis_2dp() {
parseAndFormat("2016-02-28T20:39:00.00Z", "2016-02-28T20:39:00.000Z");
}
@Test
public void parseFormat_when_millis_3dp() {
void parseFormat_when_millis_3dp() {
parseAndFormat("2016-02-28T20:39:00.000Z", "2016-02-28T20:39:00.000Z");
}
@Test
public void parseFormat_when_millis_3dp_2() {
void parseFormat_when_millis_3dp_2() {
parseAndFormat("2016-02-28T20:39:32.999000Z", "2016-02-28T20:39:32.999Z");
}
private void parseAndFormat(String input, String expected) {
Instant timestamp = parser.parseIso(input);
String format = parser.formatIso(timestamp);
Instant timestamp = parser.parseInstant(input);
String format = parser.formatInstant(timestamp);
assertThat(format).isEqualTo(expected);
}
}
@@ -0,0 +1,33 @@
package io.ebean.core.type;
import org.junit.jupiter.api.Test;
import java.util.UUID;
import static org.junit.jupiter.api.Assertions.assertEquals;
class ScalarTypeUtilsUuidBytesTest {
@Test
void testConversion() {
UUID id = UUID.randomUUID();
byte[] bytes = ScalarTypeUtils.uuidToBytes(id, false);
assertEquals(16, bytes.length);
UUID id2 = ScalarTypeUtils.uuidFromBytes(bytes, false);
assertEquals(id, id2);
}
@Test
void testConversionOptimized() {
UUID id = UUID.randomUUID();
byte[] bytes = ScalarTypeUtils.uuidToBytes(id, true);
assertEquals(16, bytes.length);
UUID id2 = ScalarTypeUtils.uuidFromBytes(bytes, true);
assertEquals(id, id2);
}
}
+9 -9
View File
@@ -3,7 +3,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.6.5</version>
<version>13.9.0</version>
</parent>
<artifactId>ebean-core</artifactId>
@@ -15,7 +15,7 @@
<scm>
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
<tag>ebean-parent-13.6.5</tag>
<tag>ebean-parent-13.9.0</tag>
</scm>
<dependencies>
@@ -41,19 +41,19 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-externalmapping-api</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
</dependency>
<dependency>
@@ -136,7 +136,7 @@
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.3.3</version>
<version>42.4.1</version>
<optional>true</optional>
</dependency>
@@ -144,21 +144,21 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlserver</artifactId>
<version>13.6.5</version>
<version>13.9.0</version>
<scope>test</scope>
</dependency>
@@ -228,10 +228,9 @@ public final class BindParams implements Serializable {
/**
* Set a named In parameter that is multi-valued.
*/
public Param setArrayParameter(String name, Collection<?> value) {
public void setArrayParameter(String name, Collection<?> value) {
Param p = getParam(name);
p.setInValue(new MultiValueWrapper(value));
return p;
}
/**
@@ -9,7 +9,7 @@ public interface CQueryPlanKey {
* Used by read audit such that we can log read audit entries without the full sql
* (which would make the read audit logs verbose).
*/
String getPartialKey();
String partialKey();
/**
* Return a query plan key taking into account persist cascading.
@@ -1,13 +1,12 @@
package io.ebeaninternal.api;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.avaje.applog.AppLog;
/**
* Common loggers used in ebean-core.
*/
public final class CoreLog {
public static final Logger log = LoggerFactory.getLogger("io.ebean.core");
public static final Logger internal = LoggerFactory.getLogger("io.ebean.internal");
public static final System.Logger log = AppLog.getLogger("io.ebean.core");
public static final System.Logger internal = AppLog.getLogger("io.ebean.internal");
}
@@ -7,17 +7,18 @@ import io.ebeaninternal.server.core.BindPadding;
import io.ebeaninternal.server.core.OrmQueryRequest;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
import org.slf4j.Logger;
import java.util.ArrayList;
import java.util.List;
import static java.lang.System.Logger.Level.DEBUG;
/**
* Request for loading Associated Many Beans.
*/
public final class LoadManyRequest extends LoadRequest {
private static final Logger log = CoreLog.log;
private static final System.Logger log = CoreLog.log;
private final List<BeanCollection<?>> batch;
private final LoadManyBuffer loadContext;
@@ -113,10 +114,10 @@ public final class LoadManyRequest extends LoadRequest {
// in the +query or +lazy load due to no rows (predicates)
for (BeanCollection<?> bc : batch) {
if (bc.checkEmptyLazyLoad()) {
if (log.isDebugEnabled()) {
if (log.isLoggable(DEBUG)) {
EntityBean ownerBean = bc.getOwnerBean();
Object parentId = desc.getId(ownerBean);
log.debug("BeanCollection after lazy load was empty. type:" + ownerBean.getClass().getName() + " id:" + parentId + " owner:" + ownerBean);
log.log(DEBUG, "BeanCollection after lazy load was empty. type:{0} id:{1} owner:{2}", ownerBean.getClass().getName(), parentId, ownerBean);
}
} else if (loadCache && many.isUseCache()) {
desc.cacheManyPropPut(many, bc, desc.getId(bc.getOwnerBean()));
@@ -50,7 +50,6 @@ public final class ManyWhereJoins implements Serializable {
* Add a many where join.
*/
public void add(ElPropertyDeploy elProp) {
String join = elProp.elPrefix();
BeanProperty p = elProp.beanProperty();
if (p instanceof BeanPropertyAssocMany<?>) {
@@ -111,7 +110,6 @@ public final class ManyWhereJoins implements Serializable {
* Return the set of property names for the many where joins.
*/
public TreeSet<String> getPropertyNames() {
TreeSet<String> propertyNames = new TreeSet<>();
for (PropertyJoin join : joins.values()) {
propertyNames.add(join.getProperty());
@@ -142,7 +142,9 @@ public final class NaturalKeyQueryData<T> {
*/
private boolean matchProperties() {
if (naturalKey.isSingleProperty()) {
naturalKey.matchSingleProperty((inProperty != null) ? inProperty : eqList.get(0).property);
if (naturalKey.matchSingleProperty((inProperty != null) ? inProperty : eqList.get(0).property)) {
return true;
}
}
// multiple properties case
@@ -1,6 +1,6 @@
package io.ebeaninternal.api;
import io.ebeaninternal.server.type.bindcapture.BindCapture;
import io.ebeaninternal.server.bind.capture.BindCapture;
final class NoopQueryBindCapture implements SpiQueryBindCapture {
@@ -87,13 +87,13 @@ public final class ScopeTrans {
@Override
public String toString() {
return "ScopeTrans[" + transaction + "]";
return "ScopeTrans " + transaction;
}
/**
* Return the current/active transaction.
*/
protected SpiTransaction getTransaction() {
SpiTransaction getTransaction() {
return transaction;
}
@@ -124,7 +124,7 @@ public final class ScopeTrans {
}
}
protected void commitTransaction() {
void commitTransaction() {
if (created) {
transaction.commit();
} else {
@@ -175,7 +175,7 @@ public final class ScopeTrans {
return e;
}
protected void rollback(Throwable e) {
void rollback(Throwable e) {
if (transaction != null && transaction.isActive()) {
// transaction is null for NOT_SUPPORTED and sometimes SUPPORTS
// and Inactive (already rolled back) if nested REQUIRED
@@ -7,7 +7,7 @@ import javax.persistence.PersistenceException;
/**
* Manage scoped (typically thread local) transactions.
*
* <p>
* These can be nested and internally they are pushed and popped from a stack.
*/
public final class ScopedTransaction extends SpiTransactionProxy {
@@ -30,7 +30,7 @@ public final class ScopedTransaction extends SpiTransactionProxy {
@Override
public String toString() {
return "ScopedTransaction[" + current + "]";
return "ScopedTransaction " + current;
}
/**
@@ -25,6 +25,11 @@ import java.util.stream.Stream;
*/
public interface SpiEbeanServer extends SpiServer, ExtendedServer, BeanCollectionLoader {
/**
* Return the NOW time from the Clock.
*/
long clockNow();
/**
* Return true if the L2 cache has been disabled.
*/
@@ -13,8 +13,8 @@ import java.io.IOException;
*/
public interface SpiExpression extends Expression {
static final String SQL_TRUE = "1=1";
static final String SQL_FALSE = "1=0";
String SQL_TRUE = "1=1";
String SQL_FALSE = "1=0";
/**
* Simplify nested expressions if possible.
@@ -110,4 +110,11 @@ public interface SpiExpression extends Expression {
* Apply property prefix when filterMany expressions included into main query.
*/
void prefixProperty(String path);
/**
* Return a copy of the expression (as part of creating a query copy).
*/
default SpiExpression copy() {
return this;
}
}
@@ -314,7 +314,7 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
* Return true if select all properties was used to ensure the property
* invoking a lazy load was included in the query.
*/
boolean selectAllForLazyLoadProperty();
void selectAllForLazyLoadProperty();
/**
* Set the select properties.
@@ -417,6 +417,8 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
/**
* Return a copy of the query.
* <p>
* Note that this does NOT copy the forUpdate property. See #2762.
*/
@Override
SpiQuery<T> copy();
@@ -1,6 +1,6 @@
package io.ebeaninternal.api;
import io.ebeaninternal.server.type.bindcapture.BindCapture;
import io.ebeaninternal.server.bind.capture.BindCapture;
/**
* Capture query bind values and with those actual database query plans.
@@ -10,27 +10,27 @@ public interface SpiQueryPlan {
/**
* The related entity bean type
*/
Class<?> getBeanType();
Class<?> beanType();
/**
* The plan name.
*/
String getName();
String name();
/**
* The hash of the sql.
*/
String getHash();
String hash();
/**
* The SQL for the query plan.
*/
String getSql();
String sql();
/**
* The related profile location.
*/
ProfileLocation getProfileLocation();
ProfileLocation profileLocation();
/**
* Initiate bind capture with the give threshold.
@@ -1,10 +1,17 @@
package io.ebeaninternal.api;
import io.avaje.lang.Nullable;
import io.ebean.SqlQuery;
import io.ebean.Transaction;
/**
* SQL query - Internal extension to SqlQuery.
*/
public interface SpiSqlQuery extends SqlQuery, SpiSqlBinding {
/**
* Return the transaction explicitly associated to the query.
*/
@Nullable
Transaction transaction();
}
@@ -139,7 +139,7 @@ public final class TransactionEvent implements Serializable {
/**
* Return the CacheChangeSet that we add cache notification messages to.
*
* <p>
* We want to add to this change set as we process requests allowing the
* PersistRequestBean to be garbage collected for large transactions.
*/
@@ -2,7 +2,7 @@ package io.ebeaninternal.api;
/**
* Event codes used in transaction profiling.
*
* <p>
* These appear in verbose transaction profile logs.
*/
public interface TxnProfileEventCodes {
@@ -12,7 +12,7 @@ import java.util.Map;
public interface SpiJsonReader {
PersistenceContext getPersistenceContext();
PersistenceContext persistenceContext();
SpiJsonReader forJson(JsonParser moreJson);
@@ -20,9 +20,9 @@ public interface SpiJsonReader {
Object persistenceContextPutIfAbsent(Object id, EntityBean bean, BeanDescriptor<?> beanDesc);
ObjectMapper getObjectMapper();
ObjectMapper mapper();
JsonParser getParser();
JsonParser parser();
JsonToken nextToken() throws IOException;
@@ -33,4 +33,6 @@ public interface SpiJsonReader {
void beanVisitor(Object bean, Map<String, Object> unmappedProperties);
Object readValueUsingObjectMapper(Class<?> propertyType) throws IOException;
boolean intercept();
}
@@ -20,7 +20,7 @@ public interface SpiJsonWriter extends JsonWriter {
/**
* Return true if the value is a parent bean.
*/
boolean isParentBean(Object value);
boolean parentBean(Object value);
/**
* Start an assoc one path.
@@ -1,25 +1,18 @@
package io.ebeaninternal.server.type;
package io.ebeaninternal.server.bind;
import io.ebean.core.type.DataBinder;
import io.ebeaninternal.api.CoreLog;
import io.ebeaninternal.server.core.timezone.DataTimeZone;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.io.*;
import java.math.BigDecimal;
import java.sql.Array;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.*;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import static java.lang.System.Logger.Level.WARNING;
public class DataBind implements DataBinder {
private final DataTimeZone dataTimeZone;
@@ -109,7 +102,7 @@ public class DataBind implements DataBinder {
try {
inputStream.close();
} catch (IOException e) {
CoreLog.log.warn("Error closing InputStream that was bound to PreparedStatement", e);
CoreLog.log.log(WARNING, "Error closing InputStream that was bound to PreparedStatement", e);
}
}
inputStreams = null;
@@ -1,8 +1,8 @@
package io.ebeaninternal.server.type;
package io.ebeaninternal.server.bind;
import io.ebeaninternal.server.core.timezone.DataTimeZone;
import io.ebeaninternal.server.type.bindcapture.BindCapture;
import io.ebeaninternal.server.type.bindcapture.BindCaptureStatement;
import io.ebeaninternal.server.bind.capture.BindCapture;
import io.ebeaninternal.server.bind.capture.BindCaptureStatement;
/**
* Special DataBind used to capture bind values for obtaining explain plans.
@@ -1,4 +1,4 @@
package io.ebeaninternal.server.type.bindcapture;
package io.ebeaninternal.server.bind.capture;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -1,4 +1,4 @@
package io.ebeaninternal.server.type.bindcapture;
package io.ebeaninternal.server.bind.capture;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -1,4 +1,4 @@
package io.ebeaninternal.server.type.bindcapture;
package io.ebeaninternal.server.bind.capture;
import java.io.InputStream;
import java.io.Reader;
@@ -1,4 +1,4 @@
package io.ebeaninternal.server.type.bindcapture;
package io.ebeaninternal.server.bind.capture;
import java.io.InputStream;
import java.io.Reader;
@@ -1,4 +1,4 @@
package io.ebeaninternal.server.type.bindcapture;
package io.ebeaninternal.server.bind.capture;
import java.io.ByteArrayInputStream;
import java.io.StringReader;
@@ -1,5 +1,6 @@
package io.ebeaninternal.server.cache;
import io.avaje.applog.AppLog;
import io.ebean.annotation.Cache;
import io.ebean.annotation.CacheBeanTuning;
import io.ebean.annotation.CacheQueryTuning;
@@ -7,20 +8,21 @@ import io.ebean.cache.*;
import io.ebean.config.CurrentTenantProvider;
import io.ebean.meta.MetricVisitor;
import io.ebean.util.AnnotationUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
import java.util.concurrent.locks.ReentrantLock;
import static java.lang.System.Logger.Level.DEBUG;
import static java.lang.System.Logger.Level.TRACE;
/**
* Manages the construction of caches.
*/
final class DefaultCacheHolder {
private static final Logger log = LoggerFactory.getLogger("io.ebean.cache.ALL");
private static final System.Logger log = AppLog.getLogger("io.ebean.cache.ALL");
private final ReentrantLock lock = new ReentrantLock();
private final ConcurrentHashMap<String, ServerCache> allCaches = new ConcurrentHashMap<>();
@@ -89,7 +91,7 @@ final class DefaultCacheHolder {
}
void clearAll() {
log.debug("clearAll");
log.log(DEBUG, "clearAll");
for (ServerCache serverCache : allCaches.values()) {
serverCache.clear();
}
@@ -97,7 +99,7 @@ final class DefaultCacheHolder {
public void clear(String name) {
log.debug("clear {}", name);
log.log(DEBUG, "clear {0}", name);
clearIfExists(key(name, ServerCacheType.QUERY));
clearIfExists(key(name, ServerCacheType.BEAN));
clearIfExists(key(name, ServerCacheType.NATURAL_KEY));
@@ -112,7 +114,7 @@ final class DefaultCacheHolder {
private void clearIfExists(String fullKey) {
ServerCache cache = allCaches.get(fullKey);
if (cache != null) {
log.trace("clear cache {}", fullKey);
log.log(TRACE, "clear cache {0}", fullKey);
cache.clear();
}
}
@@ -1,13 +1,12 @@
package io.ebeaninternal.server.cache;
import io.avaje.applog.AppLog;
import io.ebean.BackgroundExecutor;
import io.ebean.cache.ServerCache;
import io.ebean.cache.ServerCacheStatistics;
import io.ebean.meta.MetricVisitor;
import io.ebean.metric.CountMetric;
import io.ebean.metric.MetricFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
import java.lang.ref.SoftReference;
@@ -16,6 +15,9 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
import static java.lang.System.Logger.Level.TRACE;
import static java.lang.System.Logger.Level.WARNING;
/**
* The default cache implementation.
* <p>
@@ -25,7 +27,7 @@ import java.util.concurrent.locks.ReentrantLock;
*/
public class DefaultServerCache implements ServerCache {
protected static final Logger logger = LoggerFactory.getLogger(DefaultServerCache.class);
protected static final System.Logger logger = AppLog.getLogger(DefaultServerCache.class);
/**
* Compare by last access time (for LRU eviction).
@@ -287,13 +289,13 @@ public class DefaultServerCache implements ServerCache {
evictCount.add(trimmedByGC);
evictCount.add(trimmedByTTL);
evictCount.add(trimmedByLRU);
if (logger.isTraceEnabled()) {
if (logger.isLoggable(TRACE)) {
long exeMicros = TimeUnit.MICROSECONDS.convert(System.nanoTime() - startNanos, TimeUnit.NANOSECONDS);
logger.trace("Executed trim of cache {} in [{}]millis idle[{}] timeToLive[{}] accessTime[{}] gc[{}]",
logger.log(TRACE, "Executed trim of cache {0} in [{1}]millis idle[{2}] timeToLive[{3}] accessTime[{4}] gc[{5}]",
name, exeMicros, trimmedByIdle, trimmedByTTL, trimmedByLRU, trimmedByGC);
}
} catch (Throwable e) {
logger.warn("Error during trim of DefaultServerCache [" + name + "]. Cache might be bigger than desired.", e);
logger.log(WARNING, "Error during trim of DefaultServerCache [" + name + "]. Cache might be bigger than desired.", e);
}
} finally {
lock.unlock();
@@ -1,5 +1,6 @@
package io.ebeaninternal.server.cache;
import io.avaje.applog.AppLog;
import io.ebean.cache.ServerCache;
import io.ebean.cache.ServerCacheRegion;
import io.ebean.cache.ServerCacheType;
@@ -7,17 +8,18 @@ import io.ebean.meta.MetricVisitor;
import io.ebeaninternal.api.SpiCacheRegion;
import io.ebeaninternal.server.cluster.ClusterManager;
import io.ebeaninternal.server.deploy.DCacheRegion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import static java.lang.System.Logger.Level.DEBUG;
import static java.lang.System.Logger.Level.INFO;
/**
* Manages the bean and query caches.
*/
public final class DefaultServerCacheManager implements SpiCacheManager {
private static final Logger log = LoggerFactory.getLogger("io.ebean.cache.REGION");
private static final System.Logger log = AppLog.getLogger("io.ebean.cache.REGION");
private final Map<String, SpiCacheRegion> regionMap = new HashMap<>();
private final ClusterManager clusterManager;
@@ -65,23 +67,23 @@ public final class DefaultServerCacheManager implements SpiCacheManager {
enabled.add(region.name());
if (!region.isEnabled()) {
region.setEnabled(true);
log.debug("Cache region[{}] enabled", region.name());
log.log(DEBUG, "Cache region[{0}] enabled", region.name());
}
} else {
disabled.add(region.name());
if (region.isEnabled()) {
region.setEnabled(false);
log.debug("Cache region[{}] disabled", region.name());
log.log(DEBUG, "Cache region[{0}] disabled", region.name());
}
}
}
log.info("Cache regions enabled:{} disabled:{}", enabled, disabled);
log.log(INFO, "Cache regions enabled:{0} disabled:{1}", enabled, disabled);
}
}
@Override
public void setAllRegionsEnabled(boolean enabled) {
log.debug("All cache regions enabled[{}]", enabled);
log.log(DEBUG, "All cache regions enabled[{0}]", enabled);
for (SpiCacheRegion region : regionMap.values()) {
region.setEnabled(enabled);
}
@@ -52,7 +52,7 @@ public final class RemoteCacheEvent implements BinaryWritable {
@Override
public String toString() {
return "CacheEvent[ clearAll:" + clearAll + " caches:" + clearCaches + "]";
return "CacheEvent clearAll:" + clearAll + " caches:" + clearCaches;
}
public static RemoteCacheEvent readBinaryMessage(BinaryReadContext dataInput) throws IOException {
@@ -1,5 +1,6 @@
package io.ebeaninternal.server.changelog;
import io.avaje.applog.AppLog;
import io.ebean.event.changelog.BeanChange;
import io.ebean.event.changelog.ChangeLogListener;
import io.ebean.event.changelog.ChangeSet;
@@ -7,12 +8,13 @@ import io.ebean.event.changelog.ChangeType;
import io.ebean.plugin.Plugin;
import io.ebean.plugin.SpiServer;
import io.ebeaninternal.api.CoreLog;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.StringWriter;
import java.util.Properties;
import static java.lang.System.Logger.Level.ERROR;
import static java.lang.System.Logger.Level.INFO;
/**
* Simply logs the change sets in JSON form to logger named <code>io.ebean.ChangeLog</code>.
*/
@@ -21,7 +23,7 @@ public final class DefaultChangeLogListener implements ChangeLogListener, Plugin
/**
* The named logger we send the change set payload to. Can be externally configured as desired.
*/
private static final Logger changeLog = LoggerFactory.getLogger("io.ebean.ChangeLog");
private static final System.Logger changeLog = AppLog.getLogger("io.ebean.ChangeLog");
/**
* Used to build the JSON.
@@ -65,9 +67,9 @@ public final class DefaultChangeLogListener implements ChangeLogListener, Plugin
try {
StringWriter writer = new StringWriter(getBufferSize(beanChange));
jsonBuilder.writeBeanJson(writer, beanChange, changeSet);
changeLog.info(writer.toString());
changeLog.log(INFO, writer.toString());
} catch (Exception e) {
CoreLog.log.error("Exception logging beanChange " + beanChange, e);
CoreLog.log.log(ERROR, "Exception logging beanChange " + beanChange, e);
}
}
}
@@ -32,7 +32,7 @@ public class BinaryTransactionEventReader {
String serverName = dataInput.readUTF();
SpiEbeanServer server = (SpiEbeanServer) serverLookup.getServer(serverName);
if (server == null) {
throw new IllegalStateException("EbeanServer not found for name [" + serverName + "]");
throw new IllegalStateException("Database not found for name " + serverName);
}
RemoteTransactionEvent event = new RemoteTransactionEvent(server);
event.readBinary(dataInput);
@@ -1,22 +1,23 @@
package io.ebeaninternal.server.cluster;
import io.avaje.applog.AppLog;
import io.ebean.Database;
import io.ebean.config.ContainerConfig;
import io.ebeaninternal.server.transaction.RemoteTransactionEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Iterator;
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
import static java.lang.System.Logger.Level.DEBUG;
/**
* Manages the cluster service.
*/
public class ClusterManager implements ServerLookup {
private static final Logger clusterLogger = LoggerFactory.getLogger("io.ebean.Cluster");
private static final System.Logger clusterLogger = AppLog.getLogger("io.ebean.Cluster");
private final ReentrantLock lock = new ReentrantLock();
@@ -112,8 +113,8 @@ public class ClusterManager implements ServerLookup {
*/
public void broadcast(RemoteTransactionEvent event) {
if (broadcast != null) {
if (clusterLogger.isDebugEnabled()) {
clusterLogger.debug("sending: {}", event);
if (clusterLogger.isLoggable(DEBUG)) {
clusterLogger.log(DEBUG, "sending: {0}", event);
}
broadcast.broadcast(event);
}
@@ -119,7 +119,7 @@ public abstract class AbstractSqlQueryRequest implements CancelableQuery {
int firstRow = query.getFirstRow();
int maxRows = query.getMaxRows();
if (firstRow > 0 || maxRows > 0) {
return server.databasePlatform().getBasicSqlLimiter().limit(sql, firstRow, maxRows);
return server.databasePlatform().basicSqlLimiter().limit(sql, firstRow, maxRows);
}
return sql;
}

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