Compare commits

...
Author SHA1 Message Date
Rob Bygrave ac3f4ca369 [maven-release-plugin] prepare release ebean-parent-13.11.1 2023-01-09 10:45:29 +13:00
Rob Bygrave 10133e6040 Bump agent to 13.11.1 2023-01-09 10:40:40 +13:00
Rob BygraveandGitHub 321fb26df3 Merge pull request #2927 from FOCONIS/findset-beancache
NEW: BeanCache for findSet
2023-01-09 10:29:15 +13:00
Rob BygraveandGitHub 28bd018d1f Merge pull request #2926 from FOCONIS/prepare-query
FIX: prepare FindMap query for proper bean cache / DB access
2023-01-09 10:28:09 +13:00
Rob BygraveandGitHub cceb29313b Merge pull request #2928 from ebean-orm/feature/2918-findEach-EmbeddedId-Memory
Fix memory leak with streaming queries with Id Embedded
2023-01-09 10:25:39 +13:00
Rob Bygrave 530bfa982e Fix memory leak with streaming queries with Id Embedded
- The Id Embedded beans do not need the embeddedOwner to be set. They do not need to propagate dirty state back to the owner.
2023-01-05 23:27:22 +13:00
Rob BygraveandGitHub 3cfa636e88 Merge pull request #2925 from FOCONIS/exclude-from-cp-scan
Ignore private/package private classes from CP-scan / FIX: Order of runServerConfigStartup
2023-01-05 20:16:40 +13:00
Roland Praml a2e8f098cf NEW: BeanCache for findSet 2023-01-04 17:11:24 +01:00
Roland Praml 9e42cfd7d7 FIX: prepare FindMap query for proper bean cache access 2023-01-04 16:59:31 +01:00
Roland Praml a3c54d4d20 FIX: Order of runServerConfigStartup 2023-01-04 14:00:16 +01:00
Roland Praml 1d48e2afb3 Ignore private/package private classes from CP-scan 2023-01-04 13:59:51 +01:00
Rob Bygrave d84c9dc1a9 Bump versions in test modules after release 2022-12-08 18:00:24 +13:00
Rob Bygrave 6165bf5a6c Bump versions in test modules after release 2022-12-08 17:06:41 +13:00
Rob Bygrave 712d3ea78f [maven-release-plugin] prepare for next development iteration 2022-12-08 15:31:04 +13:00
Rob Bygrave 96e3c95c29 [maven-release-plugin] prepare release ebean-parent-13.11.0 2022-12-08 15:30:51 +13:00
Rob Bygrave e6e25b979f Bump to 13.11.0-SNAPSHOT 2022-12-08 15:21:16 +13:00
Rob Bygrave 50fd0f6b1a Bump ebean-agent to 13.11.0 2022-12-08 15:19:30 +13:00
Rob Bygrave 0e9b83a1ce #2914 - Refactor ProcessingContext.getPropertyType() internals and whitespace 2022-12-08 11:37:10 +13:00
Rob Bygrave d2f629e7bb #2914 - Query bean generation support for @ElementCollection with validaiton annotations - NPE NullPointerException 2022-12-08 11:10:23 +13:00
Rob Bygrave e290f68b29 Revert "#2908 - Fix tests for Oracle and DB2 with maxRows and forUpdate() 2022-12-01 22:58:30 +13:00
Rob Bygrave a17e62b491 Revert "#2908 - [Oracle] Change OraclePlatform to use AnsiSqlLimiter (noting Oracle does not support FOR UPDATE with FETCH/OFFSET"
This reverts commit 62ed5a9f
2022-12-01 22:51:37 +13:00
Rob Bygrave 928db1f0f6 #2909 - [Hana] Replace HanaSqlLimitSqlLimiter with standard LimitOffsetSqlLimiter 2022-12-01 22:42:42 +13:00
Rob Bygrave c317092dc5 #2907 - Promote Db2SqlLimiter to be AnsiSqlRowsLimiter and move to ebean-api module 2022-12-01 22:40:13 +13:00
Rob Bygrave 95512d4851 #2906 - Tidy LimitOffsetSqlLimiter 2022-12-01 22:27:57 +13:00
Rob Bygrave 62ed5a9f2b #2908 - [Oracle] Change OraclePlatform to use AnsiSqlLimiter (noting Oracle does not support FOR UPDATE with FETCH/OFFSET 2022-12-01 22:24:35 +13:00
Rob Bygrave 37ba0b63e4 #2907 - Promote Db2SqlLimiter to be AnsiSqlRowsLimiter and move to ebean-api module 2022-12-01 22:18:16 +13:00
Rob Bygrave 22a5bd9b9d #2906 - Refactor tidy SqlLimiter implementations 2022-12-01 21:39:00 +13:00
Rob Bygrave 45529958ef #2904 MySql and MariaDB do not support OFFSET without LIMIT, ignore them for these tests 2022-12-01 21:27:44 +13:00
Rob Bygrave 7aa64f47c8 Fix test TestQueryCache for Oracle (not supporting READ_UNCOMMITTED as expected) 2022-12-01 10:46:26 +13:00
Rob BygraveandGitHub 919adf331a Merge pull request #2866 from FOCONIS/fix-formula-match-base-platform
FIX: @Formula / @Where Annotations should also match on base platform
2022-12-01 08:56:13 +13:00
Rob BygraveandGitHub 9f229e3cc2 Merge pull request #2904 from serg1236/bugfix/offset_without_limit
Fixed mandatory LIMIT generation in case of firstRow>0
2022-12-01 08:45:18 +13:00
Serhii Dakhnii 3277fe81a1 Fixed mandatory LIMIT generation in case of firstRow>0 2022-11-30 21:36:08 +02:00
Rob BygraveandGitHub 6c6ec3663a Merge pull request #2896 from ebean-orm/dependabot/maven/ebean-core/org.postgresql-postgresql-42.5.1
Bump postgresql from 42.5.0 to 42.5.1 in /ebean-core
2022-11-24 11:40:45 +13:00
Rob BygraveandGitHub 0461580d1c Merge pull request #2897 from ebean-orm/dependabot/maven/ebean-test/org.postgresql-postgresql-42.5.1
Bump postgresql from 42.5.0 to 42.5.1 in /ebean-test
2022-11-24 11:40:28 +13:00
Rob BygraveandGitHub 75dbb58c85 Merge pull request #2898 from ebean-orm/dependabot/maven/ebean-postgis/org.postgresql-postgresql-42.5.1
Bump postgresql from 42.5.0 to 42.5.1 in /ebean-postgis
2022-11-24 11:40:09 +13:00
Rob BygraveandGitHub 808f69cac1 Merge pull request #2899 from ebean-orm/dependabot/maven/platforms/postgres/org.postgresql-postgresql-42.5.1
Bump postgresql from 42.5.0 to 42.5.1 in /platforms/postgres
2022-11-24 11:39:52 +13:00
Rob BygraveandGitHub 974953a376 Merge pull request #2900 from ebean-orm/dependabot/maven/ebean-core-type/org.postgresql-postgresql-42.4.3
Bump postgresql from 42.4.1 to 42.4.3 in /ebean-core-type
2022-11-24 11:38:55 +13:00
dependabot[bot]andGitHub f85a367e98 Bump postgresql from 42.4.1 to 42.4.3 in /ebean-core-type
Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.4.1 to 42.4.3.
- [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.4.1...REL42.4.3)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-23 22:27:09 +00:00
dependabot[bot]andGitHub 87a3c58d93 Bump postgresql from 42.5.0 to 42.5.1 in /platforms/postgres
Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.5.0 to 42.5.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.5.0...REL42.5.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-23 22:24:12 +00:00
dependabot[bot]andGitHub 1d1aea77d0 Bump postgresql from 42.5.0 to 42.5.1 in /ebean-test
Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.5.0 to 42.5.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.5.0...REL42.5.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-23 22:21:01 +00:00
dependabot[bot]andGitHub 2a02935cee Bump postgresql from 42.5.0 to 42.5.1 in /ebean-postgis
Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.5.0 to 42.5.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.5.0...REL42.5.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-23 22:21:01 +00:00
dependabot[bot]andGitHub fd2e5c0fc7 Bump postgresql from 42.5.0 to 42.5.1 in /ebean-core
Bumps [postgresql](https://github.com/pgjdbc/pgjdbc) from 42.5.0 to 42.5.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.5.0...REL42.5.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-23 22:21:00 +00:00
Rob Bygrave 6d6b07bf87 Bump avaje-config to version 2.4 2022-11-23 08:35:04 +13:00
Rob Bygrave 2cac3cd0bb Bump test modules to 13.10.3-SNAPSHOT after release 2022-11-22 08:26:56 +13:00
Rob Bygrave d56098dbf0 [maven-release-plugin] prepare for next development iteration 2022-11-22 08:09:45 +13:00
Rob Bygrave 07682c97a7 [maven-release-plugin] prepare release ebean-parent-13.10.2 2022-11-22 08:09:37 +13:00
Rob Bygrave 331a9152aa Bump ebean-datasource to 8.4 and ebean-agent to 13.10.2 2022-11-21 17:49:01 +13:00
Rob Bygrave e87a06a713 #2894 - Lack of setNullParameter() functionality on io.ebean.DtoQuery interface 2022-11-21 17:00:55 +13:00
Rob Bygrave 3b5393dca6 Merge branch 'pen4-oscs_fix_cdsc95oau51t49so8cag' 2022-11-21 14:59:43 +13:00
Rob Bygrave 101c5e52b1 #2893 - Bump jackson-databind to 2.14.0 2022-11-21 14:59:27 +13:00
pen4 5d3bcf4008 update com.fasterxml.jackson.core:jackson-databind 2.13.3 to 2.14.0-rc1 2022-11-19 19:57:18 +08:00
Rob Bygrave dd7605ac3a #2888 - DatabaseFactory.create() fails with java.lang.InstantiationError: io.ebean.bean.EntityBeanIntercept in multi-module gradle setup 2022-11-15 14:50:34 +13:00
Rob Bygrave 47dfbb6157 #2864 - Not advertise services configurable via DatabaseConfig.putServiceObject() that are "internal"
"internal" meaning that in terms of module-path they are not in a properly exported package. For example,
they are in a subpackage of io.ebeaninternal
2022-11-10 13:11:08 +13:00
Rob BygraveandGitHub 013123c1a7 Merge pull request #2864 from FOCONIS/feature/override-service-objects
NEW: Override service objects with DatabaseConfig.putServiceObject
2022-11-10 13:05:22 +13:00
Rob Bygrave cbc463cd10 Merge branch 'FOCONIS-bug/transactional-affects-query-cache' 2022-11-10 12:32:49 +13:00
Rob Bygrave 6e9a8704b4 #2887 - Fix for Setting isolation level disables query cache
Use getInternalConnection() in order to set the queryOnly = false flag
which is done via connection()
2022-11-10 12:32:23 +13:00
Roland Praml 0fd2f34ed0 Possible bug: Setting isolation level disables query cache 2022-11-09 09:46:51 +01:00
Rob Bygrave 72f1ab18cc No effective change - rename parameter names only 2022-11-08 14:16:12 +13:00
Rob Bygrave b1bba9da5d #2774 - Tidy InExpression adding check and block for prop != null wrt prop.isDbEncrypted() and prop.isLocalEncrypted() 2022-11-08 11:12:46 +13:00
Rob Bygrave 8966faeb7e #2774 - Postgres ANY / MultiValueSupport with byte[]/binary data
Tidy up MultiValueBind.toArray() only
2022-11-08 09:33:09 +13:00
Rob Bygrave fed4413259 Merge branch 'master' of github.com:ebean-orm/ebean 2022-11-07 22:26:19 +13:00
Rob Bygrave 14dddb4866 #2774 - Postgres ANY / MultiValueSupport with byte[]/binary data
Add Postgres specific support for binding an array of byte[] with ANY(?)
which is used as with client side encryption where the bind values are
implicitly converted to byte[].

Fixes Postgres specific failure running TestEncryptClientSide.java
2022-11-07 22:25:32 +13:00
Rob BygraveandGitHub d7d6082038 Merge pull request #2885 from MarcusDunn/patch-1
Added platforms to BOM
2022-11-07 12:31:11 +13:00
Marcus DunnandGitHub c96357377b Added platforms to BOM
fixes #2884 

I'm a complete maven (especially bom) novice - but thought I could take a stab at making the change.
I also see you auto generate these with an action, is there anything needed there?
Feel free to completely disregard if this or the issue itself is way off the mark.
2022-11-04 11:56:48 -07:00
Rob Bygrave 2789d0f97c Bump snapshot version in test modules after release 2022-11-03 00:50:30 +13:00
Rob Bygrave 79cd1da9a4 [maven-release-plugin] prepare for next development iteration 2022-11-03 00:27:30 +13:00
Rob Bygrave 759cf18c41 [maven-release-plugin] prepare release ebean-parent-13.10.1 2022-11-03 00:27:22 +13:00
Rob Bygrave 0a61852711 #2847 - Add support for Sub-query EQ, NE, LT, LE, GT, GE expressions 2022-11-03 00:22:48 +13:00
Rob Bygrave 6f5e144a93 Refactor tidy sql generated by InQueryExpression
Remove excess padding and () around the property name
2022-11-02 22:41:06 +13:00
Rob BygraveandGitHub 391b33beae Merge pull request #2880 from FOCONIS/feature/improve-enc-support
ADD encryption support for Between and InRange
2022-11-02 22:26:37 +13:00
Rob BygraveandGitHub 08e1a05bc9 Merge pull request #2872 from FOCONIS/issue-2774/encryption-support-for-in
#2774 Locally encrypted properties can be used in "in" queries
2022-11-02 22:20:41 +13:00
Rob Bygrave f145aaa1e2 Bump ebean-agent to 13.10.1 2022-11-02 22:04:37 +13:00
Roland Praml 245ba9c6b3 ADD encryption support for Between and InRange 2022-11-02 09:52:56 +01:00
Roland Praml 66f4055b8f fix test 2022-11-02 08:24:26 +01:00
Roland Praml 5170b9f329 Merge branch 'master-rob2' into issue-2774/encryption-support-for-in 2022-11-02 08:15:10 +01:00
Roland Praml 3a2b20eb43 Merge remote-tracking branch 'upstream/master' into issue-2774/encryption-support-for-in 2022-11-02 07:53:32 +01:00
Rob Bygrave dd0ed8ea76 #2873 - Query Beans: Support more TQProperty's as target value for inRangeWith() 2022-11-02 17:35:00 +13:00
Rob Bygrave 600aa10453 #2877 - Query Beans: Add lt, le, gt, ge <other property> e.g. whenRegistered.gt(QCustomer.Alias.whenActivated) 2022-11-02 16:32:49 +13:00
Rob Bygrave f6b87ed0b4 #2876 & #2875 - Query Beans subquery exists/notExists + eq(other property), ne(other property) 2022-11-02 16:14:44 +13:00
Rob Bygrave b300db77ff Merge branch 'master' of github.com:ebean-orm/ebean 2022-11-02 15:18:22 +13:00
Rob Bygrave 3f5800da3b #2862 - Ebean 13.9.3 : org.postgresql.util.PSQLException: Cannot rollback when autoCommit is enabled 2022-11-02 15:18:07 +13:00
Roland Praml c5612d50fe #2774 Locally encrypted properties can be used in "in" queries 2022-10-27 14:38:41 +02:00
Rob BygraveandGitHub 30bdfc4755 Merge pull request #2870 from FOCONIS/fix-csvtest-german-locale
FIX: Run CsvReaderTest also in german locale
2022-10-26 17:41:04 +13:00
Rob BygraveandGitHub 8fd24491da Merge pull request #2869 from FOCONIS/fix-fallback-ebean11
FIX: Add fallback for Ebean 11 Jsons
2022-10-26 17:26:08 +13:00
Rob BygraveandGitHub 61deb2517c Merge pull request #2868 from FOCONIS/fix-tojsonnanos
FIX: toJsonNanos for calendar
2022-10-26 17:24:09 +13:00
Rob BygraveandGitHub faa58f0fe4 Merge pull request #2867 from FOCONIS/fix-flush-transaction
FIX: Flush transaction if it is modified in callback
2022-10-26 17:23:05 +13:00
Rob BygraveandGitHub d2bb985016 Merge pull request #2871 from FOCONIS/fix-whitespace
NOCODE: Fix Whitespace
2022-10-26 17:18:09 +13:00
Roland Praml d190cd3a08 NOCODE: Fix Whitespace 2022-10-25 14:19:26 +02:00
Roland Praml c8853cda58 FIX: Run CsvReaderTest also in german locale 2022-10-25 11:52:17 +02:00
Roland Praml e2d75f4c2e FIX: Add fallback for Ebean 11 Jsons 2022-10-25 11:37:49 +02:00
Roland Praml b56fa851e0 FIX: toJsonNanos for calendar 2022-10-25 11:04:26 +02:00
Roland Praml a82ba6d4aa FIX: Flush transaction if it is modified in callback 2022-10-25 10:58:06 +02:00
Roland Praml 359f8b41fe FIX: @Formula / @Where Annotations should also match on base platform
A property annotated with
```java
@Formula(select = "...", platforms = SQLSERVER)
```
should match for SQLSERVER17 and SQLSERVER19
2022-10-25 10:55:23 +02:00
Rob BygraveandGitHub 22e1403f43 Merge pull request #2865 from FOCONIS/fix-typo
FIX: Typo
2022-10-25 21:48:11 +13:00
Roland Praml 9d60ebd19e FIX: Typo 2022-10-25 10:43:10 +02:00
Rob BygraveandGitHub 87a27da2b9 Merge pull request #2863 from FOCONIS/fix-logformat
FIX: LogFormat for SystemLogger
2022-10-25 21:40:11 +13:00
Roland Praml f8c6a3c960 NEW: Ovverride service objects with DatabaseConfig.putServiceObject 2022-10-25 10:28:55 +02:00
Roland Praml f4c747c6af FIX: LogFormat for SystemLogger 2022-10-25 08:52:15 +02:00
Rob BygraveandGitHub 7152cf656b Merge pull request #2859 from FOCONIS/backgroundexecutor-memory-leak
Possible memory leak with BackgroundExecutor using BackgroundExecutorWrapper ThreadLocals (for scheduled tasks)
2022-10-18 22:49:22 +13:00
Noemi Praml c855df8b8d javadoc 2022-10-18 07:59:19 +02:00
Noemi Praml d710925cc7 possible Fix 2022-10-17 15:31:30 +02:00
Rob Bygrave f24f912693 Fix Postgres/Yugabyte test - TestDbArray_basic.asDto_withArray() for nullable DbArray #2855 2022-10-17 11:19:34 +13:00
Rob Bygrave 8f9772e493 Bump to 13.10.1-SNAPSHOT after release 2022-10-17 10:35:06 +13:00
Rob Bygrave 3c298a67ff [maven-release-plugin] prepare for next development iteration 2022-10-14 13:31:18 +13:00
Rob Bygrave 27504a4dae [maven-release-plugin] prepare release ebean-parent-13.10.0 2022-10-14 13:31:10 +13:00
Rob Bygrave 9c64a69b8c Bump to 13.10.0-SNAPSHOT 2022-10-14 13:13:09 +13:00
Rob Bygrave 6c354357ff Update and fix pom versions after merge of older PR 2022-10-14 12:57:45 +13:00
Rob BygraveandGitHub 19bbe6e860 Merge pull request #2828 from ebean-orm/feature/jackson-mapper-module
Extract jackson mapper module
2022-10-14 12:39:43 +13:00
Rob BygraveandGitHub 62adaa7527 Merge pull request #2826 from ebean-orm/feature/json-node-module
Refactor extract ebean-jackson-jsonnode module - support for Jackson JsonNode (into separate module)
2022-10-14 12:39:27 +13:00
Rob Bygrave 9a25fb584c #2855 - @DbArray not allowing null to be persisted, stores empty list instead
Currently, this bug fix needs to be enabled explicitly via ebean.mf with:

allow-nullable-dbarray: true

We will look to enable this bug fix by default shortly noting that some code
will see a behaviour change. We need to publicise it well when we do turn
this on by default.

This bug fix is actually in ebean-agent 13.10.0 and all this change in ebean-core
does is read the new `@DbArray(nullable=false)` attribute [as a new alternative to
using `@NotNull` or `@Column(nullable=false)`]
2022-10-14 11:14:12 +13:00
Rob Bygrave 475f937421 #2858 - Example for entity-field-access 2022-10-14 11:08:49 +13:00
Rob Bygrave 227968ef8e #2857 - @DbArray - slight performance optimisation for empty array 2022-10-14 08:16:43 +13:00
Rob Bygrave 8e02dedf9f #2856 - @DbArray - improve bind logging, non-null arrays auto bind null to [] so improve bind logging to reflect that 2022-10-14 08:14:12 +13:00
Rob Bygrave 5a49041a3b Tidy test UserInterestLiveKey, final with accessors 2022-09-23 13:54:17 +12:00
Rob Bygrave ea341a556d Bump postgresql to 42.5.0 2022-09-23 13:53:45 +12:00
Rob Bygrave 7affd20092 Bump ebean-agent to 13.9.4 2022-09-15 10:31:58 +12:00
Rob Bygrave 9d9960ded2 Bump test-java16 to use io.ebean.tile:enhancement:13.9.4
Plus add a @Transient field in there for the constructor to deal with
2022-09-15 08:41:05 +12:00
Rob Bygrave 62a055ef1f Bump to 13.9.4-SNAPSHOT after release 2022-09-14 11:37:52 +12:00
Rob Bygrave 993607ef4b [maven-release-plugin] prepare for next development iteration 2022-09-14 11:18:25 +12:00
Rob Bygrave 18765b3ac2 [maven-release-plugin] prepare release ebean-parent-13.9.3 2022-09-14 11:18:18 +12:00
Rob Bygrave ea8e195183 Update test-java16 to use updated agent 2022-09-14 11:12:45 +12:00
Rob Bygrave f54c212b67 #2833 - Fix PostgresPlatformProvider plaform sniffing query (Postgres vs Cockroach) 2022-09-14 11:10:10 +12:00
Rob Bygrave 14d11b1c70 Improve tests only - ExtendedServerTest and test-java16 2022-09-11 17:12:02 +12:00
Rob Bygrave 7f5f0f6b8e Extract ebean-jackson-mapper module - fix module-info with requires com.fasterxml.jackson.annotation; 2022-09-08 23:05:16 +12:00
Rob Bygrave 318b22448c Extract ebean-jackson-mapper module - refactor DefaultTypeManager.dbJsonType()
- When detected markerAnnotation (e.g. Jackson annotation) then go directly to createJsonObjectMapperType()
- Simplify for the simple List, Set and Map of Object cases.
2022-09-08 23:01:05 +12:00
Rob Bygrave 610b3f7dc8 Extract ebean-jackson-mapper module - Change checkJacksonAnnotations() to instead use ScalarJsonMapper.markerAnnotation() 2022-09-08 22:38:10 +12:00
Rob Bygrave 7a887d219f Extract ebean-jackson-mapper module - rename DeployBeanObtainJackson -> AnnotatedClassUtil and convert to static method 2022-09-08 22:14:16 +12:00
Rob Bygrave e74e4ba532 Extract ebean-jackson-mapper module - rename ScalarTypeJsonObjectMapper to ScalarJsonJacksonMapper and move 2022-09-08 22:09:10 +12:00
Rob Bygrave d5f753d110 Extract ebean-jackson-mapper module - initial step 2022-09-08 21:39:00 +12:00
Rob Bygrave c53ca6c16e Rename ebean-json-node module to ebean-jackson-jsonnode 2022-09-08 14:53:33 +12:00
Rob Bygrave 5981d313ae Rename ebean-json-node module to ebean-jackson-jsonnode 2022-09-08 14:50:58 +12:00
Rob Bygrave cba3d24df1 Refactor DeployUtil rename methods (change/improve method names) 2022-09-07 22:56:43 +12:00
Rob Bygrave 27beab2980 Refactor internal TypeManager change/improve its method names 2022-09-07 22:53:15 +12:00
Rob Bygrave aeb4b8ed25 Refactor TypeManager - remove unnecessary add() method from interface allowing it to be private 2022-09-07 22:41:56 +12:00
Rob Bygrave edddc935df Update DefaultTypeManager to reuse PostgresHelper.isPostgresCompatible() 2022-09-07 22:38:09 +12:00
Rob Bygrave 5c1b478085 Refactor extract ebean-json-node module - support for Jackson JsonNode (into separate module) 2022-09-07 21:39:36 +12:00
Rob Bygrave 39de9d56db #2825 - DB Migration - create schema migration is repeated unnecessarily 2022-09-07 19:55:43 +12:00
Rob Bygrave 94dbd9d6ad Bump to 13.9.3-SNAPSHOT after release 2022-09-05 19:28:41 +12:00
Rob Bygrave 7c23dd06f8 [maven-release-plugin] prepare for next development iteration 2022-09-05 17:44:35 +12:00
Rob Bygrave e813edae01 [maven-release-plugin] prepare release ebean-parent-13.9.2 2022-09-05 17:44:28 +12:00
Rob Bygrave 4218d5bd48 Bump ebean-agent to 13.9.2 (no effective change) 2022-09-05 17:29:36 +12:00
Rob BygraveandGitHub aaf7aa8386 Merge pull request #2822 from FOCONIS/call-reorg-after-drop-not-null
FIX: DB2 migration: call reorg after drop not null
2022-09-05 17:14:21 +12:00
Rob BygraveandGitHub fbe84a7c62 Merge pull request #2824 from ebean-orm/feature/2823-jdbcTransaction_isActive
#2823 - Revert JdbcTransaction.isActive() back to be non-final method
2022-09-05 17:03:29 +12:00
Rob Bygrave cbd213aad3 #2823 - Revert JdbcTransaction.isActive() back to be non-final method 2022-09-05 17:02:45 +12:00
Noemi Praml 13622f6b62 migrations scripts 2022-09-02 13:27:11 +02:00
Noemi Praml 8fe6de376d Fix sqlserver stored procedures - reserved keywords
(cherry picked from commit 09bcf6dbb9)
2022-09-02 12:58:02 +02:00
Noemi Praml 808ba719f4 Fix mariadb, mysql stored procedure usp_ebean_drop_column - reserved keywords
(cherry picked from commit b0df177509)
2022-09-02 11:53:33 +02:00
Noemi Praml 117844b5ee Fix Unittests with drop not null
(cherry picked from commit 98e0e3b9ca)
2022-09-02 10:49:39 +02:00
Noemi Praml fbb73d465c FIX DB2 migration: reorg table must be called after drop not null 2022-09-02 10:49:25 +02:00
Rob BygraveandGitHub a5c3bbb97e Merge pull request #2821 from ebean-orm/feature/minor-dependency-bump
Minor dependency bump for jackson, assertj-core, joda-time, h2database
2022-09-02 10:55:48 +12:00
Rob Bygrave 674150dc75 Minor dependency bump for jackson, assertj-core, joda-time, h2database 2022-09-02 10:50:23 +12:00
Rob Bygrave ad938b2ce2 Bump to 13.9.2-SNAPSHOT after release 2022-09-02 09:34:59 +12:00
Rob Bygrave 5b1ace8607 [maven-release-plugin] prepare for next development iteration 2022-09-02 09:16:08 +12:00
Rob Bygrave 74321277ff [maven-release-plugin] prepare release ebean-parent-13.9.1 2022-09-02 09:16:01 +12:00
Rob Bygrave c60362f6e1 Bump ebean-agent to 13.9.1 - no effective change 2022-09-02 09:10:15 +12:00
Rob BygraveandGitHub c1320e4184 Merge pull request #2815 from ebean-orm/feature/2814-nestedUseSavepoint
#2814 - Change setNestedUseSavepoint() to use 'ScopeTrans' rather than the underlying Transaction
2022-09-02 08:20:53 +12:00
Rob BygraveandGitHub a7ea2cf3ef Merge pull request #2820 from ebean-orm/feature/2818-fix-concurrentModOfTransactionEvent
#2818 - Fix Concurrent modification of listenerNotify TransactionEvent list
2022-09-02 08:19:03 +12:00
Rob BygraveandGitHub f86a0ac973 Merge pull request #2819 from ebean-orm/feature/enh-addRollbackAndContinue
ENH: Add Transaction.rollbackAndContinue()
2022-09-02 08:18:25 +12:00
Rob Bygrave bcc21b1c04 #2818 - Fix Concurrent modification of listenerNotify TransactionEvent list
The issue fixed here is that SavepointTransaction was effectively using the
TransactionEvent of the underlying 'parent' transaction. The fix is for
SavepointTransaction to have its own TransactionEvent.
2022-09-01 22:45:17 +12:00
Rob Bygrave d517dea27f ENH: Add Transaction.rollbackAndContinue() 2022-09-01 22:26:52 +12:00
Rob Bygrave 7df168f232 ENH: Add Transaction.rollbackAndContinue()
Typically useful for handling DuplicateKeyException where we expect
DuplicateKeyException to be thrown and catch it with the intention of
continuing processing using the same transaction.

Note that some databases like Oracle do not require this explicit
rollback() and would work without the rollbackAndContinue(). Postgres
in particular requires the rollback() call on the underlying connection
such that we can continue using that transaction/java.sql.Connection.

Note that in the existing test we can see that rollbackAndContinue()
is pretty close to being syntactic sugar. I think adding rollbackAndContinue()
is justified and complements the existing commitAndContinue().
2022-09-01 17:08:11 +12:00
Rob Bygrave 563340edbd Bump to 13.9.1-SNAPSHOT after release 2022-09-01 16:47:22 +12:00
Rob Bygrave 28d70cf9c4 [maven-release-plugin] prepare for next development iteration 2022-09-01 12:33:08 +12:00
Rob Bygrave 0dda3e0e93 #2814 - Change setNestedUseSavepoint() to use 'ScopeTrans' rather than the underlying Transaction
The reason for this is that ScopedTransaction holds a stack of ScopeTrans and Transaction, but
the actual transaction in this stack is often the same instance / shared when nesting. The issue
is that currently setNestedUseSavepoint() sets this flag on the *_underlying transaction_* and
this instance is the same / shared when 'nesting'.

This change moves the nestedUseSavepoint flag for ScopedTransaction to be on ScopeTrans
(from the underlying transaction).
2022-08-31 11:39:02 +12:00
358 changed files with 3613 additions and 1321 deletions
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.9.0</version>
<version>13.11.1</version>
</parent>
<name>ebean-clickhouse</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-clickhouse</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.9.0</tag>
<tag>ebean-parent-13.11.1</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.9.0</version>
<version>13.11.1</version>
</parent>
<name>ebean-cockroach</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.9.0</tag>
<tag>ebean-parent-13.11.1</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.9.0</version>
<version>13.11.1</version>
</parent>
<name>ebean-db2</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-db2</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.9.0</tag>
<tag>ebean-parent-13.11.1</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.9.0</version>
<version>13.11.1</version>
</parent>
<name>ebean-h2</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.9.0</tag>
<tag>ebean-parent-13.11.1</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.9.0</version>
<version>13.11.1</version>
</parent>
<name>ebean-hana</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-hana</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.9.0</tag>
<tag>ebean-parent-13.11.1</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.9.0</version>
<version>13.11.1</version>
</parent>
<name>ebean-mariadb</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mariadb</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.9.0</tag>
<tag>ebean-parent-13.11.1</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.9.0</version>
<version>13.11.1</version>
</parent>
<name>ebean-mysql</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mysql</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.9.0</tag>
<tag>ebean-parent-13.11.1</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.9.0</version>
<version>13.11.1</version>
</parent>
<name>ebean-nuodb</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-nuodb</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.9.0</tag>
<tag>ebean-parent-13.11.1</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.9.0</version>
<version>13.11.1</version>
</parent>
<name>ebean-oracle</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-oracle</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.9.0</tag>
<tag>ebean-parent-13.11.1</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.9.0</version>
<version>13.11.1</version>
</parent>
<name>ebean-postgres</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.9.0</tag>
<tag>ebean-parent-13.11.1</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.9.0</version>
<version>13.11.1</version>
</parent>
<name>ebean-sqlite</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlite</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.9.0</tag>
<tag>ebean-parent-13.11.1</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.9.0</version>
<version>13.11.1</version>
</parent>
<name>ebean-sqlserver</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlserver</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.9.0</tag>
<tag>ebean-parent-13.11.1</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.9.0</version>
<version>13.11.1</version>
</parent>
<name>ebean-yugabyte</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.9.0</tag>
<tag>ebean-parent-13.11.1</tag>
</scm>
</project>
+19 -7
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.9.0</version>
<version>13.11.1</version>
</parent>
<name>ebean (all platforms)</name>
@@ -16,19 +16,31 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-joda-time</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jackson-jsonnode</artifactId>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jackson-mapper</artifactId>
<version>13.11.1</version>
</dependency>
<dependency>
@@ -41,18 +53,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-all</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.9.0</tag>
<tag>ebean-parent-13.11.1</tag>
</scm>
</project>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.9.0</version>
<version>13.11.1</version>
</parent>
<artifactId>composites</artifactId>
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.9.0</version>
<version>13.11.1</version>
</parent>
<name>ebean api</name>
@@ -29,7 +29,7 @@
<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-config</artifactId>
<version>2.2</version>
<version>2.4</version>
</dependency>
<!--
@@ -129,6 +129,11 @@ public interface DtoQuery<T> extends CancelableQuery {
*/
DtoQuery<T> setParameter(String name, Object value);
/**
* Bind the named parameter to SQL NULL.
*/
DtoQuery<T> setNullParameter(String name, int jdbcType);
/**
* Bind the named multi-value array parameter which we would use with Postgres ANY.
* <p>
@@ -141,6 +146,11 @@ public interface DtoQuery<T> extends CancelableQuery {
*/
DtoQuery<T> setParameter(int position, Object value);
/**
* Set a positioned parameter to SQL NULL.
*/
DtoQuery<T> setNullParameter(int position, int jdbcType);
/**
* Set the index of the first row of the results to return.
*/
@@ -2,6 +2,28 @@ package io.ebean;
/**
* Thrown when a duplicate is attempted on a unique constraint.
* <p>
* In terms of catching this exception with the view of continuing processing
* using the same transaction look to use {@link Transaction#rollbackAndContinue()}.
*
* <pre>{@code
*
* try (Transaction txn = database.beginTransaction()) {
*
* try {
* ...
* database.save(bean);
* database.flush();
* } catch (DuplicateKeyException e) {
* // carry on processing using the transaction
* txn.rollbackAndContinue();
* ...
* }
*
* txn.commit();
* }
*
* }</pre>
*/
public class DuplicateKeyException extends DataIntegrityException {
private static final long serialVersionUID = -4771932723285724817L;
@@ -117,6 +117,11 @@ public interface ExpressionFactory {
*/
Expression arrayIsNotEmpty(String propertyName);
/**
* Equal To the result of a sub-query.
*/
Expression eq(String propertyName, Query<?> subQuery);
/**
* Equal To - property equal to the given value.
*/
@@ -127,6 +132,11 @@ public interface ExpressionFactory {
*/
Expression eqOrNull(String propertyName, Object value);
/**
* Not Equal To the result of a sub-query.
*/
Expression ne(String propertyName, Query<?> subQuery);
/**
* Not Equal To - property not equal to the given value.
*/
@@ -181,6 +191,23 @@ public interface ExpressionFactory {
*/
Expression inRangeWith(String lowProperty, String highProperty, Object value);
/**
* A Property is in Range between 2 properties.
*
* <pre>{@code
*
* .orderDate.inRangeWith(QOrder.Alias.product.startDate, QOrder.Alias.product.endDate)
*
* // which equates to
* product.startDate <= orderDate and (orderDate < product.endDate or product.endDate is null)
*
* }</pre>
*
* <p>
* This is a convenience expression combining a number of simple expressions.
*/
Expression inRangeWithProperties(String propertyName, String lowProperty, String highProperty);
/**
* Between - property between the two given values.
*/
@@ -207,11 +234,21 @@ public interface ExpressionFactory {
*/
Expression geOrNull(String propertyName, Object value);
/**
* Greater Than the result of a sub-query.
*/
Expression gt(String propertyName, Query<?> subQuery);
/**
* Greater Than - property greater than the given value.
*/
Expression gt(String propertyName, Object value);
/**
* Greater Than or Equal to the result of a sub-query.
*/
Expression ge(String propertyName, Query<?> subQuery);
/**
* Greater Than or Equal to - property greater than or equal to the given
* value.
@@ -234,11 +271,21 @@ public interface ExpressionFactory {
*/
Expression leOrNull(String propertyName, Object value);
/**
* Less Than the result of a sub-query.
*/
Expression lt(String propertyName, Query<?> subQuery);
/**
* Less Than - property less than the given value.
*/
Expression lt(String propertyName, Object value);
/**
* Less Than or Equal to the result of a sub-query.
*/
Expression le(String propertyName, Query<?> subQuery);
/**
* Less Than or Equal to - property less than or equal to the given value.
*/
@@ -830,6 +830,11 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> addAll(ExpressionList<T> exprList);
/**
* Equal To the result of a sub-query.
*/
ExpressionList<T> eq(String propertyName, Query<?> subQuery);
/**
* Equal To - property is equal to a given value.
*/
@@ -854,6 +859,11 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> eqOrNull(String propertyName, Object value);
/**
* Not Equal To the result of a sub-query.
*/
ExpressionList<T> ne(String propertyName, Query<?> subQuery);
/**
* Not Equal To - property not equal to the given value.
*/
@@ -890,6 +900,23 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> inRangeWith(String lowProperty, String highProperty, Object value);
/**
* A Property is in Range between 2 properties.
*
* <pre>{@code
*
* .orderDate.inRangeWith(QOrder.Alias.product.startDate, QOrder.Alias.product.endDate)
*
* // which equates to
* product.startDate <= orderDate and (orderDate < product.endDate or product.endDate is null)
*
* }</pre>
*
* <p>
* This is a convenience expression combining a number of simple expressions.
*/
ExpressionList<T> inRangeWithProperties(String propertyName, String lowProperty, String highProperty);
/**
* In Range - {@code property >= value1 and property < value2}.
* <p>
@@ -908,6 +935,11 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> betweenProperties(String lowProperty, String highProperty, Object value);
/**
* Greater Than the result of a sub-query.
*/
ExpressionList<T> gt(String propertyName, Query<?> subQuery);
/**
* Greater Than - property greater than the given value.
*/
@@ -923,12 +955,22 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> geOrNull(String propertyName, Object value);
/**
* Greater Than or Equal to the result of a sub-query.
*/
ExpressionList<T> ge(String propertyName, Query<?> subQuery);
/**
* Greater Than or Equal to - property greater than or equal to the given
* value.
*/
ExpressionList<T> ge(String propertyName, Object value);
/**
* Less Than the result of a sub-query.
*/
ExpressionList<T> lt(String propertyName, Query<?> subQuery);
/**
* Less Than - property less than the given value.
*/
@@ -944,6 +986,11 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> leOrNull(String propertyName, Object value);
/**
* Less Than or Equal to the result of a sub-query.
*/
ExpressionList<T> le(String propertyName, Query<?> subQuery);
/**
* Less Than or Equal to - property less than or equal to the given value.
*/
@@ -144,6 +144,35 @@ public interface Transaction extends AutoCloseable {
*/
void rollback(Throwable e) throws PersistenceException;
/**
* Performs a rollback on the underlying JDBC connection with the intention of
* continuing to use this same transaction and performing a commit or rollback
* later to complete the transaction.
* <p>
* Typically used when catching {@link DuplicateKeyException} where we wish to
* rollback work done at that point but carry on processing using the transaction.
*
* <pre>{@code
*
* try (Transaction txn = database.beginTransaction()) {
*
* try {
* ...
* database.save(bean);
* database.flush();
* } catch (DuplicateKeyException e) {
* // carry on processing using the transaction
* txn.rollbackAndContinue();
* ...
* }
*
* txn.commit();
* }
*
* }</pre>
*/
void rollbackAndContinue();
/**
* Set when we want nested transactions to use Savepoint's.
* <p>
@@ -6,7 +6,6 @@ import java.util.Set;
* Notification event that dependent tables have been modified.
* <p>
* This is sent to other interested servers (in the cluster).
* </p>
*/
public class ServerCacheNotification {
@@ -6,7 +6,6 @@ import io.ebean.config.DatabaseConfig;
* Plugin that provides a ServerCacheNotify implementation.
* <p>
* Is supplied this will be used to send the ServerCacheNotification event to other cluster members.
* </p>
*/
public interface ServerCacheNotifyPlugin {
@@ -6,6 +6,10 @@ import java.util.concurrent.Callable;
* BackgroundExecutorWrapper that can be used to wrap tasks that are sent to background (i.e. another thread).
* It should copy all necessary thread-local variables. See {@link MdcBackgroundExecutorWrapper} for implementation details.
*
* Note: only tasks that are executed immediately (submit, execute) are wrapped. Periodic or scheduled tasks are not wrapped,
* as these may keep copied variables in memory either forever or until the scheduled task is finished.
* The caller is responsible to handle these cases.
*
* @author Roland Praml, FOCONIS AG
*/
public interface BackgroundExecutorWrapper {
@@ -32,13 +32,11 @@ import java.util.function.Function;
* <p>
* Used to programmatically construct an Database and optionally register it
* with the DB singleton.
* </p>
* <p>
* If you just use DB thout this programmatic configuration Ebean will read
* the application.properties file and take the configuration from there. This usually
* includes searching the class path and automatically registering any entity
* classes and listeners etc.
* </p>
* <pre>{@code
*
* DatabaseConfig config = new DatabaseConfig();
@@ -58,7 +56,6 @@ import java.util.function.Function;
* <p>
* Note that DatabaseConfigProvider provides a standard Java ServiceLoader mechanism that can
* be used to apply configuration to the DatabaseConfig.
* </p>
*
* @author emcgreal
* @author rbygrave
@@ -615,7 +612,7 @@ public class DatabaseConfig {
}
/**
* Put a service object into configuration such that it can be passed to a plugin.
* Put a service object into configuration such that it can be used by ebean or a plugin.
* <p>
* For example, put IgniteConfiguration in to be passed to the Ignite plugin.
*/
@@ -623,6 +620,23 @@ public class DatabaseConfig {
serviceObject.put(key, configObject);
}
/**
* Put a service object into configuration such that it can be used by ebean or a plugin.
* <p>
* For example, put IgniteConfiguration in to be passed to the Ignite plugin.
* You can also override some SPI objects that should be used for that Database. Currently, the following
* objects are possible.
* <ul>
* <li>DataSourceAlertFactory (e.g. add different alert factories for different ebean instances)</li>
* <li>DocStoreFactory</li>
* <li>SlowQueryListener (e.g. add custom query listener for a certain ebean instance)</li>
* <li>ServerCacheNotifyPlugin</li>
* </ul>
*/
public <T> void putServiceObject(Class<T> iface, T configObject) {
serviceObject.put(serviceObjectKey(iface), configObject);
}
/**
* Return the service object given the key.
*/
@@ -631,7 +645,7 @@ public class DatabaseConfig {
}
/**
* Put a service object into configuration such that it can be passed to a plugin.
* Put a service object into configuration such that it can be used by ebean or a plugin.
*
* <pre>{@code
*
@@ -656,7 +670,7 @@ public class DatabaseConfig {
}
/**
* Used by plugins to obtain service objects.
* Used by ebean or plugins to obtain service objects.
*
* <pre>{@code
*
@@ -1,20 +1,16 @@
package io.ebean.platform.db2;
package io.ebean.config.dbplatform;
import io.ebean.config.dbplatform.SqlLimitRequest;
import io.ebean.config.dbplatform.SqlLimitResponse;
import io.ebean.config.dbplatform.SqlLimiter;
public class Db2SqlLimiter implements SqlLimiter {
public final class AnsiSqlRowsLimiter implements SqlLimiter {
@Override
public SqlLimitResponse limit(SqlLimitRequest request) {
StringBuilder sb = new StringBuilder(512);
String dbSql = request.getDbSql();
StringBuilder sb = new StringBuilder(50 + dbSql.length());
sb.append("select ");
if (request.isDistinct()) {
sb.append("distinct ");
}
sb.append(request.getDbSql());
sb.append(dbSql);
int firstRow = request.getFirstRow();
if (firstRow > 0) {
sb.append(" offset ").append(firstRow).append(" rows");
@@ -23,7 +19,6 @@ public class Db2SqlLimiter implements SqlLimiter {
if (maxRows > 0) {
sb.append(" fetch next ").append(maxRows).append(" rows only");
}
String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
return new SqlLimitResponse(sql);
}
@@ -3,42 +3,25 @@ package io.ebean.config.dbplatform;
/**
* Adds LIMIT OFFSET clauses to a SQL query.
*/
public class LimitOffsetSqlLimiter implements SqlLimiter {
/**
* LIMIT keyword.
*/
private static final String LIMIT = "limit";
/**
* OFFSET keyword.
*/
private static final String OFFSET = "offset";
public final class LimitOffsetSqlLimiter implements SqlLimiter {
@Override
public SqlLimitResponse limit(SqlLimitRequest request) {
String dbSql = request.getDbSql();
StringBuilder sb = new StringBuilder(50 + dbSql.length());
sb.append("select ");
if (request.isDistinct()) {
sb.append("distinct ");
}
sb.append(dbSql);
int firstRow = request.getFirstRow();
int maxRows = request.getMaxRows();
if (maxRows > 0 || firstRow > 0) {
sb.append(" ").append(LIMIT).append(" ").append(maxRows);
if (firstRow > 0) {
sb.append(" ").append(OFFSET).append(" ");
sb.append(firstRow);
}
if (maxRows > 0) {
sb.append(" limit ").append(maxRows);
}
int firstRow = request.getFirstRow();
if (firstRow > 0) {
sb.append(" offset ").append(firstRow);
}
String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
return new SqlLimitResponse(sql);
}
@@ -5,14 +5,6 @@ package io.ebean.config.dbplatform;
*/
public interface SqlLimiter {
/**
* the new line character used.
* <p>
* Note that this is removed for logging sql to the transaction log.
* </p>
*/
char NEW_LINE = '\n';
/**
* Add the SQL limiting statements around the query.
*/
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.9.0</version>
<version>13.11.1</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.9.0</tag>
<tag>ebean-parent-13.11.1</tag>
</scm>
<name>ebean autotune</name>
@@ -26,7 +26,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
<scope>provided</scope>
</dependency>
@@ -55,7 +55,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
<scope>test</scope>
</dependency>
@@ -70,7 +70,7 @@
<extensions>true</extensions>
<configuration>
<tiles>
<tile>io.ebean.tile:enhancement:13.6.5</tile>
<tile>io.ebean.tile:enhancement:13.10.1</tile>
</tiles>
</configuration>
</plugin>
@@ -148,7 +148,7 @@ public class BaseQueryTuner {
case UPDATE:
case DELETE:
case SQ_EXISTS:
case SQ_IN:
case SQ_EX:
return false;
default:
// not using autoTune when explicitly loading the l2 bean cache
+114 -16
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.9.0</version>
<version>13.11.1</version>
</parent>
<name>ebean bom</name>
@@ -89,94 +89,192 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-joda-time</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jackson-jsonnode</artifactId>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jackson-mapper</artifactId>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-ddl-generator</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-externalmapping-api</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-externalmapping-xml</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-autotune</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>querybean-generator</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>kotlin-querybean-generator</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgis</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-redis</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<!-- platforms -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-all</artifactId>
<version>13.11.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-clickhouse</artifactId>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-db2</artifactId>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-h2</artifactId>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-hana</artifactId>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-hsqldb</artifactId>
<version>13.11.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-mariadb</artifactId>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-mysql</artifactId>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-nuodb</artifactId>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-oracle</artifactId>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgres</artifactId>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-sqlanywhere</artifactId>
<version>13.11.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-sqlite</artifactId>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-sqlserver</artifactId>
<version>13.11.1</version>
</dependency>
</dependencies>
+10 -2
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.9.0</version>
<version>13.11.1</version>
</parent>
<artifactId>ebean-core-type</artifactId>
@@ -16,7 +16,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
@@ -26,6 +26,14 @@
<optional>true</optional>
</dependency>
<!-- Provided scope for Postgres JSON/JSONB support -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.4.3</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.avaje</groupId>
<artifactId>junit</artifactId>
@@ -1,5 +1,7 @@
package io.ebeaninternal.server.type;
package io.ebean.core.type;
import io.ebean.annotation.Platform;
import io.ebean.config.dbplatform.DatabasePlatform;
import org.postgresql.util.PGobject;
import java.sql.SQLException;
@@ -9,12 +11,12 @@ public final class PostgresHelper {
/**
* The Postgres JSON DB type.
*/
static final String JSON_TYPE = "json";
public static final String JSON_TYPE = "json";
/**
* The Postgres JSONB DB type.
*/
static final String JSONB_TYPE = "jsonb";
public static final String JSONB_TYPE = "jsonb";
static final String INET_TYPE = "inet";
@@ -31,4 +33,13 @@ public final class PostgresHelper {
pgo.setValue(rawJson);
return pgo;
}
/**
* Return true if the platform is Postgres or compatible like Yugabyte, Cockroach.
*/
public static boolean isPostgresCompatible(DatabasePlatform databasePlatform) {
return databasePlatform.isPlatform(Platform.POSTGRES)
|| databasePlatform.isPlatform(Platform.YUGABYTE)
|| databasePlatform.isPlatform(Platform.COCKROACH);
}
}
@@ -0,0 +1,24 @@
package io.ebean.core.type;
import io.ebean.annotation.MutationDetection;
/**
* Holds the configured mapper and default mutation detection mode to be used.
*/
public interface ScalarJsonManager {
/**
* Return the default mutation detection mode.
*/
MutationDetection mutationDetection();
/**
* Return the object mapper supplied in DatabaseConfig.
*/
Object mapper();
/**
* Return the Postgres type given the jdbc type.
*/
String postgresType(int dbType);
}
@@ -0,0 +1,23 @@
package io.ebean.core.type;
import io.avaje.lang.Nullable;
import java.lang.annotation.Annotation;
/**
* Supports JSON bean properties that use something like Jackson ObjectMapper to convert between
* JSON content and the logical bean property value.
*/
public interface ScalarJsonMapper {
/**
* Return a ScalarType for the given JSON property.
*/
ScalarType<?> createType(ScalarJsonRequest request);
/**
* Return a marker annotation to detect when the JSON mapper should be used explicitly.
*/
@Nullable
<A extends Annotation> Class<A> markerAnnotation();
}
@@ -0,0 +1,67 @@
package io.ebean.core.type;
import io.ebean.annotation.MutationDetection;
/**
* A request to create a ScalarType for a bean property (typically annotated with {@code @DbJson}).
*/
public final class ScalarJsonRequest {
private final ScalarJsonManager manager;
private final int dbType;
private final DocPropertyType docType;
private final Class<?> beanType;
private final MutationDetection mode;
private final String name;
public ScalarJsonRequest(ScalarJsonManager manager, int dbType, DocPropertyType docType, Class<?> beanType, MutationDetection mode, String name) {
this.manager = manager;
this.dbType = dbType;
this.docType = docType;
this.beanType = beanType;
this.mode = mode;
this.name = name;
}
/**
* Return the manager.
*/
public ScalarJsonManager manager() {
return manager;
}
/**
* Return the jdbc type this property maps to (e.g. JSON, JSONB etc).
*/
public int dbType() {
return dbType;
}
/**
* Return the document store docType.
*/
public DocPropertyType docType() {
return docType;
}
/**
* Return the type of the bean that this property belongs to.
*/
public Class<?> beanType() {
return beanType;
}
/**
* Return the mutation detection mode the property should use.
*/
public MutationDetection mode() {
return mode;
}
/**
* Return the property name.
*/
public String name() {
return name;
}
}
@@ -0,0 +1,28 @@
package io.ebean.core.type;
import io.avaje.lang.Nullable;
/**
* A ScalarType that has variations based on the mapped JDBC type (like VARCHAR, CLOB, JSON etc).
*/
public interface ScalarTypeSet<T> {
/**
* The property type these scalar types map to.
*/
Class<?> type();
/**
* Return a default ScalarType to use when no other annotations like {@code @DbJson} are present.
*/
@Nullable
ScalarType<?> defaultType();
/**
* Return the scalarType to use for the given jdbc type.
* <p>
* For example VARCHAR, CLOB, JSON etc.
*/
ScalarType<T> forType(int jdbcType);
}
@@ -0,0 +1,17 @@
package io.ebean.core.type;
import io.avaje.lang.Nullable;
import io.ebean.config.DatabaseConfig;
/**
* Factory to create ScalarTypeSet.
*/
public interface ScalarTypeSetFactory {
/**
* Create the ScalarTypeSet given the config and optional objectMapper.
*/
@Nullable
ScalarTypeSet<?> createTypeSet(DatabaseConfig config, @Nullable Object objectMapper);
}
@@ -4,6 +4,7 @@ module io.ebean.core.type {
requires transitive java.sql;
requires transitive io.ebean.api;
requires static org.postgresql.jdbc;
requires static com.fasterxml.jackson.core;
+14 -15
View File
@@ -3,7 +3,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.9.0</version>
<version>13.11.1</version>
</parent>
<artifactId>ebean-core</artifactId>
@@ -15,10 +15,15 @@
<scm>
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
<tag>ebean-parent-13.9.0</tag>
<tag>ebean-parent-13.11.1</tag>
</scm>
<dependencies>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
@@ -38,22 +43,16 @@
<version>${ebean-migration-auto.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.9.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-externalmapping-api</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
</dependency>
<dependency>
@@ -106,7 +105,7 @@
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.7</version>
<version>2.11.1</version>
<optional>true</optional>
</dependency>
@@ -136,7 +135,7 @@
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.4.1</version>
<version>42.5.1</version>
<optional>true</optional>
</dependency>
@@ -144,21 +143,21 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlserver</artifactId>
<version>13.9.0</version>
<version>13.11.1</version>
<scope>test</scope>
</dependency>
@@ -45,15 +45,14 @@ public final class ScopeTrans {
* Flag set when nested commit has occurred.
*/
private boolean nestedCommit;
private boolean nestedUseSavepoint;
public ScopeTrans(boolean rollbackOnChecked, boolean created, SpiTransaction transaction, TxScope txScope) {
this.rollbackOnChecked = rollbackOnChecked;
this.created = created;
this.transaction = transaction;
this.noRollbackFor = txScope.getNoRollbackFor();
this.rollbackFor = txScope.getRollbackFor();
if (transaction != null) {
if (!created && txScope.isBatchSet() || txScope.isBatchOnCascadeSet() || txScope.isBatchSizeSet()) {
restoreBatch = transaction.isBatchMode();
@@ -90,6 +89,14 @@ public final class ScopeTrans {
return "ScopeTrans " + transaction;
}
void setNestedUseSavepoint() {
nestedUseSavepoint = true;
}
boolean isNestedUseSavepoint() {
return nestedUseSavepoint;
}
/**
* Return the current/active transaction.
*/
@@ -101,7 +108,6 @@ public final class ScopeTrans {
* Complete the transaction from enhanced transactional. Try to commit.
*/
void complete(Object returnOrThrowable, int opCode) {
if (opCode == OPCODE_ATHROW) {
// exited with a Throwable
caughtThrowable((Throwable) returnOrThrowable);
@@ -168,7 +174,6 @@ public final class ScopeTrans {
* Returns the exception and this should be thrown by the calling code.
*/
public <T extends Throwable> T caughtThrowable(T e) {
if (isRollbackThrowable(e)) {
rollback(e);
}
@@ -188,21 +193,17 @@ public final class ScopeTrans {
* Return true if this throwable should cause a rollback to occur.
*/
private boolean isRollbackThrowable(Throwable e) {
if (e instanceof Error) {
return true;
}
if (noRollbackFor != null) {
for (Class<? extends Throwable> aNoRollbackFor : noRollbackFor) {
if (aNoRollbackFor.equals(e.getClass())) {
// explicit no rollback for this one
return false;
}
}
}
if (rollbackFor != null) {
for (Class<? extends Throwable> aRollbackFor : rollbackFor) {
if (aRollbackFor.equals(e.getClass())) {
@@ -211,7 +212,6 @@ public final class ScopeTrans {
}
}
}
// checked exceptions...
// EJB defaults this to false which is not intuitive IMO
// Ebean makes this configurable (default to true)
@@ -33,13 +33,26 @@ public final class ScopedTransaction extends SpiTransactionProxy {
return "ScopedTransaction " + current;
}
@Override
public void setNestedUseSavepoint() {
current.setNestedUseSavepoint();
}
@Override
public boolean isNestedUseSavepoint() {
return current.isNestedUseSavepoint();
}
/**
* Push the scope transaction.
*/
public void push(ScopeTrans scopeTrans) {
if (current != null) {
stack.push(current);
if (current.isNestedUseSavepoint()) {
// child scope 'inherits' nestedUseSavepoint
scopeTrans.setNestedUseSavepoint();
}
}
current = scopeTrans;
transaction = scopeTrans.getTransaction();
@@ -111,6 +124,11 @@ public final class ScopedTransaction extends SpiTransactionProxy {
}
}
@Override
public void rollbackAndContinue() {
transaction.rollbackAndContinue();
}
@Override
public void rollback() throws PersistenceException {
try {
@@ -103,14 +103,14 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
COUNT(FIND_COUNT, "findCount"),
/**
* A subquery used as part of an exists where clause.
* A sub-query used as part of an exists where clause.
*/
SQ_EXISTS(FIND_SUBQUERY, "sqExists", false, false),
/**
* A subquery used as part of an in where clause.
* A sub-query expression used as part of where clause.
*/
SQ_IN(FIND_SUBQUERY, "sqIn", false, false),
SQ_EX(FIND_SUBQUERY, "sqEx", false, false),
/**
* Delete query.
@@ -759,6 +759,11 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
*/
BindParams getBindParams();
/**
* Return the bind parameters ensuring it is initialised.
*/
BindParams initBindParams();
/**
* Replace the query detail. This is used by the AutoTune feature to as a
* fast way to set the query properties and joins.
@@ -115,88 +115,88 @@ public class DataBind implements DataBinder {
}
@Override
public void setString(String s) throws SQLException {
pstmt.setString(++pos, s);
public void setString(String value) throws SQLException {
pstmt.setString(++pos, value);
}
@Override
public final void setInt(int i) throws SQLException {
pstmt.setInt(++pos, i);
public final void setInt(int value) throws SQLException {
pstmt.setInt(++pos, value);
}
@Override
public final void setLong(long i) throws SQLException {
pstmt.setLong(++pos, i);
public final void setLong(long value) throws SQLException {
pstmt.setLong(++pos, value);
}
@Override
public final void setShort(short i) throws SQLException {
pstmt.setShort(++pos, i);
public final void setShort(short value) throws SQLException {
pstmt.setShort(++pos, value);
}
@Override
public final void setFloat(float i) throws SQLException {
pstmt.setFloat(++pos, i);
public final void setFloat(float value) throws SQLException {
pstmt.setFloat(++pos, value);
}
@Override
public final void setDouble(double i) throws SQLException {
pstmt.setDouble(++pos, i);
public final void setDouble(double value) throws SQLException {
pstmt.setDouble(++pos, value);
}
@Override
public final void setBigDecimal(BigDecimal v) throws SQLException {
pstmt.setBigDecimal(++pos, v);
public final void setBigDecimal(BigDecimal value) throws SQLException {
pstmt.setBigDecimal(++pos, value);
}
@Override
public final void setDate(java.sql.Date v) throws SQLException {
public final void setDate(java.sql.Date value) throws SQLException {
Calendar timeZone = dataTimeZone.getTimeComponentTimeZone();
if (timeZone != null) {
pstmt.setDate(++pos, v, timeZone);
pstmt.setDate(++pos, value, timeZone);
} else {
pstmt.setDate(++pos, v);
pstmt.setDate(++pos, value);
}
}
@Override
public final void setTimestamp(Timestamp v) throws SQLException {
public final void setTimestamp(Timestamp value) throws SQLException {
Calendar timeZone = dataTimeZone.getTimeZone();
if (timeZone != null) {
pstmt.setTimestamp(++pos, v, timeZone);
pstmt.setTimestamp(++pos, value, timeZone);
} else {
pstmt.setTimestamp(++pos, v);
pstmt.setTimestamp(++pos, value);
}
}
@Override
public final void setTime(Time v) throws SQLException {
public final void setTime(Time value) throws SQLException {
Calendar timeZone = dataTimeZone.getTimeComponentTimeZone();
if (timeZone != null) {
pstmt.setTime(++pos, v, timeZone);
pstmt.setTime(++pos, value, timeZone);
} else {
pstmt.setTime(++pos, v);
pstmt.setTime(++pos, value);
}
}
@Override
public void setBoolean(boolean v) throws SQLException {
pstmt.setBoolean(++pos, v);
public void setBoolean(boolean value) throws SQLException {
pstmt.setBoolean(++pos, value);
}
@Override
public void setBytes(byte[] v) throws SQLException {
pstmt.setBytes(++pos, v);
public void setBytes(byte[] value) throws SQLException {
pstmt.setBytes(++pos, value);
}
@Override
public void setByte(byte v) throws SQLException {
pstmt.setByte(++pos, v);
public void setByte(byte value) throws SQLException {
pstmt.setByte(++pos, value);
}
@Override
public void setChar(char v) throws SQLException {
pstmt.setString(++pos, String.valueOf(v));
public void setChar(char value) throws SQLException {
pstmt.setString(++pos, String.valueOf(value));
}
@Override
@@ -215,20 +215,17 @@ public class DataBind implements DataBinder {
@Override
public void setBlob(byte[] bytes) throws SQLException {
ByteArrayInputStream is = new ByteArrayInputStream(bytes);
pstmt.setBinaryStream(++pos, is, bytes.length);
pstmt.setBinaryStream(++pos, new ByteArrayInputStream(bytes), bytes.length);
}
@Override
public void setClob(String content) throws SQLException {
Reader reader = new StringReader(content);
pstmt.setCharacterStream(++pos, reader, content.length());
pstmt.setCharacterStream(++pos, new StringReader(content), content.length());
}
@Override
public void setArray(String arrayType, Object[] elements) throws SQLException {
Array array = connection.createArrayOf(arrayType, elements);
pstmt.setArray(++pos, array);
pstmt.setArray(++pos, connection.createArrayOf(arrayType, elements));
}
}
@@ -33,87 +33,87 @@ public final class BindCaptureStatement extends BindCaptureStatementBase impleme
}
@Override
public void setBoolean(int parameterIndex, boolean x) {
capture.add(new BindCaptureTypes.Boolean(parameterIndex, x));
public void setBoolean(int parameterIndex, boolean value) {
capture.add(new BindCaptureTypes.Boolean(parameterIndex, value));
}
@Override
public void setByte(int parameterIndex, byte x) {
capture.add(new BindCaptureTypes.Byte(parameterIndex, x));
public void setByte(int parameterIndex, byte value) {
capture.add(new BindCaptureTypes.Byte(parameterIndex, value));
}
@Override
public void setShort(int parameterIndex, short x) {
capture.add(new BindCaptureTypes.TShort(parameterIndex, x));
public void setShort(int parameterIndex, short value) {
capture.add(new BindCaptureTypes.TShort(parameterIndex, value));
}
@Override
public void setInt(int parameterIndex, int x) {
capture.add(new BindCaptureTypes.TInt(parameterIndex, x));
public void setInt(int parameterIndex, int value) {
capture.add(new BindCaptureTypes.TInt(parameterIndex, value));
}
@Override
public void setLong(int parameterIndex, long x) {
capture.add(new BindCaptureTypes.TLong(parameterIndex, x));
public void setLong(int parameterIndex, long value) {
capture.add(new BindCaptureTypes.TLong(parameterIndex, value));
}
@Override
public void setFloat(int parameterIndex, float x) {
capture.add(new BindCaptureTypes.TFloat(parameterIndex, x));
public void setFloat(int parameterIndex, float value) {
capture.add(new BindCaptureTypes.TFloat(parameterIndex, value));
}
@Override
public void setDouble(int parameterIndex, double x) {
capture.add(new BindCaptureTypes.TDouble(parameterIndex, x));
public void setDouble(int parameterIndex, double value) {
capture.add(new BindCaptureTypes.TDouble(parameterIndex, value));
}
@Override
public void setBigDecimal(int parameterIndex, BigDecimal x) {
capture.add(new BindCaptureTypes.TBigDecimal(parameterIndex, x));
public void setBigDecimal(int parameterIndex, BigDecimal value) {
capture.add(new BindCaptureTypes.TBigDecimal(parameterIndex, value));
}
@Override
public void setString(int parameterIndex, String x) {
capture.add(new BindCaptureTypes.TString(parameterIndex, x));
public void setString(int parameterIndex, String value) {
capture.add(new BindCaptureTypes.TString(parameterIndex, value));
}
@Override
public void setBytes(int parameterIndex, byte[] x) {
capture.add(new BindCaptureTypes.Bytes(parameterIndex, x));
public void setBytes(int parameterIndex, byte[] value) {
capture.add(new BindCaptureTypes.Bytes(parameterIndex, value));
}
@Override
public void setDate(int parameterIndex, Date x) {
capture.add(new BindCaptureTypes.TDate(parameterIndex, x));
public void setDate(int parameterIndex, Date value) {
capture.add(new BindCaptureTypes.TDate(parameterIndex, value));
}
@Override
public void setTime(int parameterIndex, Time x) {
capture.add(new BindCaptureTypes.TTime(parameterIndex, x));
public void setTime(int parameterIndex, Time value) {
capture.add(new BindCaptureTypes.TTime(parameterIndex, value));
}
@Override
public void setTimestamp(int parameterIndex, Timestamp x) {
capture.add(new BindCaptureTypes.TTimestamp(parameterIndex, x, null));
public void setTimestamp(int parameterIndex, Timestamp value) {
capture.add(new BindCaptureTypes.TTimestamp(parameterIndex, value, null));
}
@Override
public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) {
capture.add(new BindCaptureTypes.TTimestamp(parameterIndex, x, cal));
public void setTimestamp(int parameterIndex, Timestamp value, Calendar cal) {
capture.add(new BindCaptureTypes.TTimestamp(parameterIndex, value, cal));
}
@Override
public void setObject(int parameterIndex, Object x) {
capture.add(new BindCaptureTypes.TObject(parameterIndex, x));
public void setObject(int parameterIndex, Object value) {
capture.add(new BindCaptureTypes.TObject(parameterIndex, value));
}
@Override
public void setBinaryStream(int parameterIndex, InputStream x, int length) {
public void setBinaryStream(int parameterIndex, InputStream value, int length) {
capture.add(new BindCaptureTypes.BinaryStream(parameterIndex));
}
@Override
public void setCharacterStream(int parameterIndex, Reader reader, int length) {
public void setCharacterStream(int parameterIndex, Reader value, int length) {
capture.add(new BindCaptureTypes.CharacterStream(parameterIndex));
}
@@ -160,6 +160,8 @@ public final class DefaultContainer implements SpiContainer {
*/
private BootupClasses bootupClasses(DatabaseConfig config) {
BootupClasses bootup = bootupClasses1(config);
bootup.addServerConfigStartup(config.getServerConfigStartupListeners());
bootup.runServerConfigStartup(config);
bootup.addIdGenerators(config.getIdGenerators());
bootup.addPersistControllers(config.getPersistControllers());
bootup.addPostLoaders(config.getPostLoaders());
@@ -167,9 +169,7 @@ public final class DefaultContainer implements SpiContainer {
bootup.addFindControllers(config.getFindControllers());
bootup.addPersistListeners(config.getPersistListeners());
bootup.addQueryAdapters(config.getQueryAdapters());
bootup.addServerConfigStartup(config.getServerConfigStartupListeners());
bootup.addChangeLogInstances(config);
bootup.runServerConfigStartup(config);
return bootup;
}
@@ -307,7 +307,10 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
*/
public void start() {
if (config.isRunMigration() && TenantMode.DB != config.getTenantMode()) {
final AutoMigrationRunner migrationRunner = ServiceUtil.service(AutoMigrationRunner.class);
AutoMigrationRunner migrationRunner = config.getServiceObject(AutoMigrationRunner.class);
if (migrationRunner == null) {
migrationRunner = ServiceUtil.service(AutoMigrationRunner.class);
}
if (migrationRunner == null) {
throw new IllegalStateException("No AutoMigrationRunner found. Probably ebean-migration is not in the classpath?");
}
@@ -1088,7 +1091,13 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public <T> Set<T> findSet(Query<T> query, Transaction transaction) {
SpiOrmQueryRequest request = createQueryRequest(Type.SET, query, transaction);
SpiOrmQueryRequest request = buildQueryRequest(Type.SET, query, transaction);
request.resetBeanCacheAutoMode(false);
if ((transaction == null || !transaction.isSkipCache()) && request.getFromBeanCache()) {
// hit bean cache and got all results from cache
return request.beanCacheHitsAsSet();
}
request.prepareQuery();
Object result = request.getFromQueryCache();
if (result != null) {
return (Set<T>) result;
@@ -1104,12 +1113,13 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public <K, T> Map<K, T> findMap(Query<T> query, @Nullable Transaction transaction) {
SpiOrmQueryRequest request = createQueryRequest(Type.MAP, query, transaction);
SpiOrmQueryRequest request = buildQueryRequest(Type.MAP, query, transaction);
request.resetBeanCacheAutoMode(false);
if ((transaction == null || !transaction.isSkipCache()) && request.getFromBeanCache()) {
// hit bean cache and got all results from cache
return request.beanCacheHitsAsMap();
}
request.prepareQuery();
Object result = request.getFromQueryCache();
if (result != null) {
return (Map<K, T>) result;
@@ -117,7 +117,10 @@ final class InitDataSource {
* Attach DataSourceAlert via service loader if present.
*/
private void attachAlert(DataSourceConfig dsConfig) {
DataSourceAlertFactory alertFactory = ServiceUtil.service(DataSourceAlertFactory.class);
DataSourceAlertFactory alertFactory = config.getServiceObject(DataSourceAlertFactory.class);
if (alertFactory == null) {
alertFactory = ServiceUtil.service(DataSourceAlertFactory.class);
}
if (alertFactory != null) {
dsConfig.setAlert(alertFactory.createAlert());
}
@@ -144,7 +144,12 @@ public final class InternalConfiguration {
}
private <S> S service(Class<S> cls) {
return ServiceUtil.service(cls);
S service = config.getServiceObject(cls);
if (service != null) {
return service;
} else {
return ServiceUtil.service(cls);
}
}
private List<XmapEbean> readExternalMapping() {
@@ -515,12 +515,12 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
if (query.getType() == Type.MAP) {
mergeCacheHitsToMap(result);
} else {
mergeCacheHitsToList(result);
mergeCacheHitsToCollection(result);
}
}
}
private void mergeCacheHitsToList(BeanCollection<T> result) {
private void mergeCacheHitsToCollection(BeanCollection<T> result) {
for (T hit : cacheBeans) {
result.internalAdd(hit);
}
@@ -579,6 +579,15 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
return property;
}
@Override
public Set<T> beanCacheHitsAsSet() {
OrderBy<T> orderBy = query.getOrderBy();
if (orderBy != null && !orderBy.isEmpty()) {
beanDescriptor.sort(cacheBeans, orderBy.toStringFormat());
}
return new LinkedHashSet<>(cacheBeans);
}
@Override
public boolean getFromBeanCache() {
if (!query.isBeanCacheGet()) {
@@ -121,7 +121,7 @@ public interface SpiOrmQueryRequest<T> extends BeanQueryRequest<T>, DocQueryRequ
<K> Map<K, T> findMap();
/**
* Execute the findSingleAttributeList query.
* Execute the findSingleAttributeCollection query.
*/
<A extends Collection<?>> A findSingleAttributeCollection(A collection);
@@ -153,6 +153,11 @@ public interface SpiOrmQueryRequest<T> extends BeanQueryRequest<T>, DocQueryRequ
*/
<K> Map<K,T> beanCacheHitsAsMap();
/**
* Return the bean cache hits for findMap (when all hits / no misses).
*/
Set<T> beanCacheHitsAsSet();
/**
* Reset Bean cache mode AUTO - require explicit setting for bean cache use with findList().
*/
@@ -342,8 +342,9 @@ public class BootupClasses implements Predicate<Class<?>> {
*/
@SuppressWarnings("unchecked")
private boolean isInterestingInterface(Class<?> cls) {
if (Modifier.isAbstract(cls.getModifiers())) {
// do not include abstract classes as we can
if (Modifier.isAbstract(cls.getModifiers())
|| !(Modifier.isPublic(cls.getModifiers()) || Modifier.isProtected(cls.getModifiers()))) {
// do not include abstract and non pupbic/protected classes as we can
// not instantiate them
return false;
}
@@ -145,7 +145,7 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
this.dbIdentity = config.getDatabasePlatform().dbIdentity();
this.deplyInherit = config.getDeployInherit();
this.deployUtil = config.getDeployUtil();
this.typeManager = deployUtil.getTypeManager();
this.typeManager = deployUtil.typeManager();
this.beanManagerFactory = new BeanManagerFactory(config.getDatabasePlatform());
this.beanLifecycleAdapterFactory = new BeanLifecycleAdapterFactory(this.config);
this.persistControllerManager = new PersistControllerManager(bootupClasses);
@@ -184,12 +184,12 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
@Override
public ScalarType<?> scalarType(String cast) {
return typeManager.getScalarType(cast);
return typeManager.type(cast);
}
@Override
public ScalarType<?> scalarType(int jdbcType) {
return typeManager.getScalarType(jdbcType);
return typeManager.type(jdbcType);
}
/**
@@ -884,7 +884,7 @@ public final class BeanDescriptorManager implements BeanDescriptorMap, SpiBeanTy
private void makeOrderColumn(DeployBeanPropertyAssocMany<?> oneToMany) {
DeployBeanDescriptor<?> targetDesc = targetDescriptor(oneToMany);
DeployOrderColumn orderColumn = oneToMany.getOrderColumn();
final ScalarType<?> scalarType = typeManager.getScalarType(Integer.class);
final ScalarType<?> scalarType = typeManager.type(Integer.class);
DeployBeanProperty orderProperty = new DeployBeanProperty(targetDesc, Integer.class, scalarType, null);
orderProperty.setName(DeployOrderColumn.LOGICAL_NAME);
orderProperty.setDbColumn(orderColumn.getName());
@@ -65,7 +65,7 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
/**
* Flag to mark this is the id property.
*/
private final boolean id;
protected final boolean id;
private final boolean importedPrimaryKey;
/**
* Flag to make this as a dummy property for unidirecitonal relationships.
@@ -927,6 +927,10 @@ public class BeanProperty implements ElPropertyValue, Property, STreeProperty {
return alreadyDirty || value != null && scalarType.isDirty(value);
}
public boolean isArrayType() {
return scalarType instanceof ScalarTypeArray;
}
/**
* Return the scalarType.
*/
@@ -655,7 +655,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
@Override
public void setValue(EntityBean bean, Object value) {
super.setValue(bean, value);
if (embedded && value instanceof EntityBean) {
if (!id && embedded && value instanceof EntityBean) {
setEmbeddedOwner(bean, value);
}
}
@@ -663,7 +663,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
@Override
public void setValueIntercept(EntityBean bean, Object value) {
super.setValueIntercept(bean, value);
if (embedded && value instanceof EntityBean) {
if (!id && embedded && value instanceof EntityBean) {
setEmbeddedOwner(bean, value);
}
}
@@ -675,8 +675,10 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
Object emb = getValue(owner);
if (emb != null) {
EntityBean embeddedBean = (EntityBean) emb;
embeddedBean._ebean_getIntercept().setEmbeddedOwner(owner, propertyIndex);
targetDescriptor.setAllLoaded(embeddedBean);
if (!id) {
embeddedBean._ebean_getIntercept().setEmbeddedOwner(owner, propertyIndex);
}
}
}
@@ -152,7 +152,6 @@ public class DeployBeanDescriptor<T> {
private DocStoreMode docStoreDelete;
private DeployBeanProperty idProperty;
private TableJoin primaryKeyJoin;
private Object jacksonAnnotatedClass;
/**
* Construct the BeanDescriptor.
@@ -1130,14 +1129,4 @@ public class DeployBeanDescriptor<T> {
}
}
/**
* Returns the jackson annotated class, if jackson is present.
*/
@SuppressWarnings("unchecked")
Object /*AnnotatedClass*/ getJacksonAnnotatedClass() {
if (jacksonAnnotatedClass == null) {
jacksonAnnotatedClass = new DeployBeanObtainJackson(config, beanType).obtain();
}
return jacksonAnnotatedClass;
}
}
@@ -1042,20 +1042,6 @@ public class DeployBeanProperty {
this.elementProperty = true;
}
/**
* Returns the jackson annotated field, if jackson is present.
*/
public Object /*AnnotatedField*/ getJacksonField() {
com.fasterxml.jackson.databind.introspect.AnnotatedClass jac =
(com.fasterxml.jackson.databind.introspect.AnnotatedClass) getDesc().getJacksonAnnotatedClass();
for (com.fasterxml.jackson.databind.introspect.AnnotatedField candidate : jac.fields()) {
if (candidate.getName().equals(getName())) {
return candidate;
}
}
return null;
}
public void initMetaAnnotations(Set<Class<?>> metaAnnotationsFilter) {
metaAnnotations = AnnotationUtil.metaFindAllFor(field, metaAnnotationsFilter);
}
@@ -1137,7 +1123,7 @@ public class DeployBeanProperty {
private boolean matchPlatform(Platform[] platforms, Platform match) {
for (Platform platform : platforms) {
if (platform == match) {
if (platform == match || platform == match.base()) {
return true;
}
}
@@ -222,7 +222,7 @@ final class AnnotationAssocManys extends AnnotationAssoc {
dbKeyColumn = mapKeyColumn.name();
}
ScalarType<?> keyScalarType = util.getTypeManager().getScalarType(prop.getMapKeyType());
ScalarType<?> keyScalarType = util.typeManager().type(prop.getMapKeyType());
DeployBeanProperty keyProp = new DeployBeanProperty(elementDescriptor, elementType, keyScalarType, null);
setElementProperty(keyProp, "key", dbKeyColumn, sortOrder++);
@@ -234,10 +234,10 @@ final class AnnotationAssocManys extends AnnotationAssoc {
}
}
ScalarType<?> valueScalarType = util.getTypeManager().getScalarType(elementType);
ScalarType<?> valueScalarType = util.typeManager().type(elementType);
if (valueScalarType == null && elementType.isEnum()) {
Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>)elementType;
valueScalarType = util.getTypeManager().createEnumScalarType(enumClass, EnumType.STRING);
valueScalarType = util.typeManager().enumType(enumClass, EnumType.STRING);
}
boolean scalar = true;
@@ -52,9 +52,9 @@ abstract class AnnotationBase {
AnnotationBase(DeployUtil util) {
this.util = util;
this.databasePlatform = util.getDbPlatform();
this.databasePlatform = util.dbPlatform();
this.platform = databasePlatform.platform();
this.namingConvention = util.getNamingConvention();
this.namingConvention = util.namingConvention();
}
/**
@@ -301,7 +301,7 @@ final class AnnotationFields extends AnnotationParser {
private void initEncrypt(DeployBeanProperty prop) {
if (!prop.isTransient()) {
EncryptDeploy encryptDeploy = util.getEncryptDeploy(info.getDescriptor().getBaseTableFull(), prop.getDbColumn());
EncryptDeploy encryptDeploy = util.encryptDeploy(info.getDescriptor().getBaseTableFull(), prop.getDbColumn());
if (encryptDeploy == null || encryptDeploy.getMode() == Mode.MODE_ANNOTATION) {
Encrypted encrypted = get(prop, Encrypted.class);
if (encrypted != null) {
@@ -398,7 +398,7 @@ final class AnnotationFields extends AnnotationParser {
return;
}
if (dbEncString) {
DbEncrypt dbEncrypt = util.getDbPlatform().dbEncrypt();
DbEncrypt dbEncrypt = util.dbPlatform().dbEncrypt();
if (dbEncrypt != null) {
// check if we have a DB encryption function for this type
int jdbcType = prop.getScalarType().jdbcType();
@@ -427,7 +427,7 @@ final class AnnotationFields extends AnnotationParser {
private ScalarTypeBytesBase getDbEncryptType(DeployBeanProperty prop) {
int dbType = prop.isLob() ? Types.BLOB : Types.VARBINARY;
return (ScalarTypeBytesBase) util.getTypeManager().getScalarType(dbType);
return (ScalarTypeBytesBase) util.typeManager().type(dbType);
}
private DataEncryptSupport createDataEncryptSupport(DeployBeanProperty prop) {
@@ -108,7 +108,7 @@ public final class DeployCreateProperties {
@SuppressWarnings({"unchecked"})
private DeployBeanProperty createManyType(DeployBeanDescriptor<?> desc, Class<?> targetType, ManyType manyType) {
try {
ScalarType<?> scalarType = typeManager.getScalarType(targetType);
ScalarType<?> scalarType = typeManager.type(targetType);
if (scalarType != null) {
return new DeployBeanPropertySimpleCollection(desc, targetType, manyType);
}
@@ -141,7 +141,7 @@ public final class DeployCreateProperties {
if (propertyType.isEnum() || propertyType.isPrimitive()) {
return new DeployBeanProperty(desc, propertyType, null, null);
}
ScalarType<?> scalarType = typeManager.getScalarType(propertyType);
ScalarType<?> scalarType = typeManager.type(propertyType);
if (scalarType != null) {
return new DeployBeanProperty(desc, propertyType, scalarType, null);
}
@@ -60,15 +60,15 @@ public final class DeployUtil {
this.useValidationNotNull = config.isUseValidationNotNull();
}
public TypeManager getTypeManager() {
public TypeManager typeManager() {
return typeManager;
}
public DatabasePlatform getDbPlatform() {
public DatabasePlatform dbPlatform() {
return dbPlatform;
}
public NamingConvention getNamingConvention() {
public NamingConvention namingConvention() {
return namingConvention;
}
@@ -82,7 +82,7 @@ public final class DeployUtil {
}
}
EncryptDeploy getEncryptDeploy(TableName table, String column) {
EncryptDeploy encryptDeploy(TableName table, String column) {
if (encryptDeployManager == null) {
return EncryptDeploy.ANNOTATION;
}
@@ -102,7 +102,7 @@ public final class DeployUtil {
try {
Class<? extends Enum<?>> enumClass = (Class<? extends Enum<?>>) enumType;
EnumType type = enumerated != null ? enumerated.value() : null;
ScalarType<?> scalarType = typeManager.createEnumScalarType(enumClass, type);
ScalarType<?> scalarType = typeManager.enumType(enumClass, type);
prop.setScalarType(scalarType);
prop.setDbType(scalarType.jdbcType());
} catch (IllegalStateException e) {
@@ -123,7 +123,7 @@ public final class DeployUtil {
// this will be an Enum type...
return;
}
ScalarType<?> scalarType = getScalarType(property);
ScalarType<?> scalarType = scalarType(property);
if (scalarType != null) {
// set the jdbc type this maps to
property.setDbType(scalarType.jdbcType());
@@ -132,12 +132,12 @@ public final class DeployUtil {
}
}
private ScalarType<?> getScalarType(DeployBeanProperty property) {
private ScalarType<?> scalarType(DeployBeanProperty property) {
// Note that Temporal types already have dbType
// set via annotations
Class<?> propType = property.getPropertyType();
try {
ScalarType<?> scalarType = typeManager.getScalarType(propType, property.getDbType());
ScalarType<?> scalarType = typeManager.type(propType, property.getDbType());
if (scalarType != null || property.isTransient()) {
return scalarType;
}
@@ -155,7 +155,7 @@ public final class DeployUtil {
* Map to Postgres HSTORE type (with fallback to JSON storage in VARCHAR).
*/
void setDbMap(DeployBeanProperty prop, DbMap dbMap) {
ScalarType<?> scalarType = typeManager.getDbMapScalarType();
ScalarType<?> scalarType = typeManager.dbMapType();
int dbType = scalarType.jdbcType();
prop.setDbType(dbType);
prop.setScalarType(scalarType);
@@ -171,8 +171,13 @@ public final class DeployUtil {
* Set the DbArray type (effectively Postgres only).
*/
void setDbArray(DeployBeanProperty prop, DbArray dbArray) {
if (!dbArray.nullable()) {
// Non-nullable ScalarTypeArray's will auto bind null to empty array, we need to
// set nullable(false) before the ScalarTypeArray is determined and assigned
prop.setNullable(false);
}
Class<?> type = prop.getPropertyType();
ScalarType<?> scalarType = typeManager.getArrayScalarType(type, prop.getGenericType(), prop.isNullable());
ScalarType<?> scalarType = typeManager.dbArrayType(type, prop.getGenericType(), prop.isNullable());
if (scalarType == null) {
throw new RuntimeException("No ScalarType for @DbArray type for " + prop.getFullBeanName());
}
@@ -193,7 +198,7 @@ public final class DeployUtil {
}
void setDbJsonType(DeployBeanProperty prop, DbJson dbJsonType) {
int dbType = getDbJsonStorage(dbJsonType.storage());
int dbType = dbJsonStorage(dbJsonType.storage());
setDbJsonType(prop, dbType, dbJsonType.length(), dbJsonType.mutationDetection());
}
@@ -204,7 +209,7 @@ public final class DeployUtil {
private void setDbJsonType(DeployBeanProperty prop, int dbType, int dbLength, MutationDetection mutationDetection) {
prop.setDbType(dbType);
prop.setMutationDetection(mutationDetection);
ScalarType<?> scalarType = typeManager.getJsonScalarType(prop, dbType, dbLength);
ScalarType<?> scalarType = typeManager.dbJsonType(prop, dbType, dbLength);
if (scalarType == null) {
throw new RuntimeException("No ScalarType for JSON property " + prop + " dbType:" + dbType);
}
@@ -219,7 +224,7 @@ public final class DeployUtil {
/**
* Return the JDBC type for the JSON storage type.
*/
private int getDbJsonStorage(DbJsonType dbJsonType) {
private int dbJsonStorage(DbJsonType dbJsonType) {
switch (dbJsonType) {
case JSONB:
return DbPlatformType.JSONB;
@@ -248,7 +253,7 @@ public final class DeployUtil {
// this also sets the lob flag on DeployBeanProperty
int lobType = isClobType(type) ? dbCLOBType : dbBLOBType;
scalarType = typeManager.getScalarType(type, lobType);
scalarType = typeManager.type(type, lobType);
if (scalarType == null) {
// this should never occur actually
throw new RuntimeException("No ScalarType for LOB type " + type + " dbType:" + lobType);
@@ -21,7 +21,7 @@ final class DtoMetaConstructor {
this.types = constructor.getParameterTypes();
this.scalarTypes = new ScalarType[types.length];
for (int i = 0; i < types.length; i++) {
scalarTypes[i] = typeManager.getScalarType(types[i]);
scalarTypes[i] = typeManager.type(types[i]);
}
this.handle = LOOKUP.findConstructor(someClass, typeFor(types));
}
@@ -25,7 +25,7 @@ final class DtoMetaProperty implements DtoReadSet {
this.name = name;
if (writeMethod != null) {
this.setter = lookupMethodHandle(dtoType, writeMethod);
this.scalarType = typeManager.getScalarType(propertyType(writeMethod), propertyClass(writeMethod));
this.scalarType = typeManager.type(propertyType(writeMethod), propertyClass(writeMethod));
} else {
this.scalarType = null;
this.setter = null;
@@ -106,23 +106,23 @@ public final class DefaultBackgroundExecutor implements SpiBackgroundExecutor {
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long initialDelay, long delay, TimeUnit unit) {
return schedulePool.scheduleWithFixedDelay(wrap(logExceptions(task)), initialDelay, delay, unit);
return schedulePool.scheduleWithFixedDelay(logExceptions(task), initialDelay, delay, unit);
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long initialDelay, long delay, TimeUnit unit) {
return schedulePool.scheduleAtFixedRate(wrap(logExceptions(task)), initialDelay, delay, unit);
return schedulePool.scheduleAtFixedRate(logExceptions(task), initialDelay, delay, unit);
}
@Override
public ScheduledFuture<?> schedule(Runnable task, long delay, TimeUnit unit) {
return schedulePool.schedule(wrap(logExceptions(task)), delay, unit);
return schedulePool.schedule(logExceptions(task), delay, unit);
}
@Override
public <V> ScheduledFuture<V> schedule(Callable<V> task, long delay, TimeUnit unit) {
// Note: No "logExceptions" as we expect Future.get() by the invoker
return schedulePool.schedule(wrap(task), delay, unit);
return schedulePool.schedule(task, delay, unit);
}
@Override
@@ -3,6 +3,7 @@ package io.ebeaninternal.server.expression;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.server.el.ElPropertyValue;
import java.io.IOException;
@@ -34,13 +35,24 @@ final class BetweenExpression extends AbstractExpression {
@Override
public void addBindValues(SpiExpressionRequest request) {
ElPropertyValue prop = getElProp(request);
if (prop != null && prop.isDbEncrypted()) {
// bind the key as well as the value
String encryptKey = prop.beanProperty().encryptKey().getStringValue();
request.addBindEncryptKey(encryptKey);
}
request.addBindValue(low());
request.addBindValue(high());
}
@Override
public void addSql(SpiExpressionRequest request) {
request.append(propName).append(_BETWEEN);
String pname = propName;
ElPropertyValue prop = getElProp(request);
if (prop != null && prop.isDbEncrypted()) {
pname = prop.beanProperty().decryptProperty(propName);
}
request.append(pname).append(_BETWEEN);
}
@Override
@@ -1,21 +1,11 @@
package io.ebeaninternal.server.expression;
import io.ebean.ExampleExpression;
import io.ebean.Expression;
import io.ebean.ExpressionFactory;
import io.ebean.ExpressionList;
import io.ebean.Junction;
import io.ebean.LikeType;
import io.ebean.Pairs;
import io.ebean.Query;
import io.ebean.*;
import io.ebean.bean.EntityBean;
import io.ebean.search.Match;
import io.ebean.search.MultiMatch;
import io.ebean.search.TextCommonTerms;
import io.ebean.search.TextQueryString;
import io.ebean.search.TextSimple;
import io.ebean.search.*;
import io.ebeaninternal.api.SpiExpressionFactory;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.server.expression.SubQueryExpression.SQOp;
import io.ebeaninternal.server.grammer.EqlParser;
import java.util.Arrays;
@@ -157,6 +147,11 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
EqlParser.parseWhere(expressions, list, this, params);
}
@Override
public Expression eq(String propertyName, Query<?> subQuery) {
return new SubQueryExpression(SQOp.EQ, propertyName, (SpiQuery<?>) subQuery);
}
/**
* Equal To - property equal to the given value.
*/
@@ -173,6 +168,11 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
return or(eq(propertyName, value), isNull(propertyName));
}
@Override
public Expression ne(String propertyName, Query<?> subQuery) {
return new SubQueryExpression(SQOp.NE, propertyName, (SpiQuery<?>) subQuery);
}
/**
* Not Equal To - property not equal to the given value.
*/
@@ -237,6 +237,11 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
return and(le(lowProperty, value), gtOrNull(highProperty, value));
}
@Override
public Expression inRangeWithProperties(String propertyName, String lowProperty, String highProperty) {
return raw(lowProperty + " <= " + propertyName + " and (" + propertyName + " < " + highProperty + " or " + highProperty + " is null)");
}
/**
* Between - property between the two given values.
*/
@@ -253,6 +258,11 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
return new BetweenPropertyExpression(lowProperty, highProperty, value);
}
@Override
public Expression gt(String propertyName, Query<?> subQuery) {
return new SubQueryExpression(SQOp.GT, propertyName, (SpiQuery<?>) subQuery);
}
/**
* Greater Than - property greater than the given value.
*/
@@ -274,6 +284,11 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
return or(ge(propertyName, value), isNull(propertyName));
}
@Override
public Expression ge(String propertyName, Query<?> subQuery) {
return new SubQueryExpression(SQOp.GE, propertyName, (SpiQuery<?>) subQuery);
}
/**
* Greater Than or Equal to - property greater than or equal to the given
* value.
@@ -296,6 +311,11 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
return or(le(propertyName, value), isNull(propertyName));
}
@Override
public Expression lt(String propertyName, Query<?> subQuery) {
return new SubQueryExpression(SQOp.LT, propertyName, (SpiQuery<?>) subQuery);
}
/**
* Less Than - property less than the given value.
*/
@@ -304,6 +324,11 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
return new SimpleExpression(propertyName, Op.LT, value);
}
@Override
public Expression le(String propertyName, Query<?> subQuery) {
return new SubQueryExpression(SQOp.LE, propertyName, (SpiQuery<?>) subQuery);
}
/**
* Less Than or Equal to - property less than or equal to the given value.
*/
@@ -460,7 +485,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
*/
@Override
public Expression in(String propertyName, Query<?> subQuery) {
return new InQueryExpression(propertyName, (SpiQuery<?>) subQuery, false);
return new SubQueryExpression(SQOp.IN, propertyName, (SpiQuery<?>) subQuery);
}
/**
@@ -502,7 +527,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
*/
@Override
public Expression notIn(String propertyName, Query<?> subQuery) {
return new InQueryExpression(propertyName, (SpiQuery<?>) subQuery, true);
return new SubQueryExpression(SQOp.NOTIN, propertyName, (SpiQuery<?>) subQuery);
}
/**
@@ -788,6 +788,11 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
return add(expr.bitwiseAnd(propertyName, flags, match));
}
@Override
public ExpressionList<T> eq(String propertyName, Query<?> subQuery) {
return add(expr.eq(propertyName, subQuery));
}
@Override
public ExpressionList<T> eq(String propertyName, Object value) {
return add(expr.eq(propertyName, value));
@@ -813,6 +818,11 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
return add(expr.ine(propertyName, value));
}
@Override
public ExpressionList<T> ne(String propertyName, Query<?> subQuery) {
return add(expr.ne(propertyName, subQuery));
}
@Override
public ExpressionList<T> ne(String propertyName, Object value) {
return add(expr.ne(propertyName, value));
@@ -833,6 +843,11 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
return add(expr.inRangeWith(lowProperty, highProperty, value));
}
@Override
public ExpressionList<T> inRangeWithProperties(String propertyName, String lowProperty, String highProperty) {
return add(expr.inRangeWithProperties(propertyName, lowProperty, highProperty));
}
@Override
public ExpressionList<T> inRange(String propertyName, Object value1, Object value2) {
return add(expr.inRange(propertyName, value1, value2));
@@ -858,10 +873,19 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
return add(expr.endsWith(propertyName, value));
}
@Override
public ExpressionList<T> ge(String propertyName, Query<?> subQuery) {
return add(expr.ge(propertyName, subQuery));
}
@Override
public ExpressionList<T> ge(String propertyName, Object value) {
add(expr.ge(propertyName, value));
return this;
return add(expr.ge(propertyName, value));
}
@Override
public ExpressionList<T> gt(String propertyName, Query<?> subQuery) {
return add(expr.gt(propertyName, subQuery));
}
@Override
@@ -871,14 +895,12 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
@Override
public ExpressionList<T> gtOrNull(String propertyName, Object value) {
add(expr.gtOrNull(propertyName, value));
return this;
return add(expr.gtOrNull(propertyName, value));
}
@Override
public ExpressionList<T> geOrNull(String propertyName, Object value) {
add(expr.geOrNull(propertyName, value));
return this;
return add(expr.geOrNull(propertyName, value));
}
@Override
@@ -994,6 +1016,11 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
return add(expr.istartsWith(propertyName, value));
}
@Override
public ExpressionList<T> le(String propertyName, Query<?> subQuery) {
return add(expr.le(propertyName, subQuery));
}
@Override
public ExpressionList<T> le(String propertyName, Object value) {
return add(expr.le(propertyName, value));
@@ -1014,6 +1041,11 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
return add(expr.like(propertyName, value));
}
@Override
public ExpressionList<T> lt(String propertyName, Query<?> subQuery) {
return add(expr.lt(propertyName, subQuery));
}
@Override
public ExpressionList<T> lt(String propertyName, Object value) {
return add(expr.lt(propertyName, value));
@@ -14,17 +14,13 @@ import java.util.*;
public final class InExpression extends AbstractExpression implements IdInCommon {
private final boolean not;
/**
* Set to true when adding "1=1" predicate (due to null or empty sourceValues).
*/
private final boolean empty;
private final boolean not;
private final Collection<?> sourceValues;
private List<Object> bindValues;
private boolean multiValueSupported;
InExpression(String propertyName, Collection<?> sourceValues, boolean not) {
@@ -95,7 +91,7 @@ public final class InExpression extends AbstractExpression implements IdInCommon
public void prepareExpression(BeanQueryRequest<?> request) {
initBindValues();
if (bindValues.size() > 0) {
multiValueSupported = request.isMultiValueSupported((bindValues.get(0)).getClass());
multiValueSupported = request.isMultiValueSupported(bindValues.get(0).getClass());
}
}
@@ -117,29 +113,37 @@ public final class InExpression extends AbstractExpression implements IdInCommon
}
}
ElPropertyValue prop = getElProp(request);
if (prop != null && !prop.isAssocId()) {
prop = null;
}
if (prop == null) {
if (bindValues.size() > 0) {
// if we have no property, we wrap them in a multi value wrapper.
// later the binder will decide, which bind strategy to use.
request.addBindValue(new MultiValueWrapper(bindValues));
}
} else {
List<Object> idList = new ArrayList<>();
List<Object> values = bindValues;
if (prop != null && prop.isAssocId()) {
values = new ArrayList<>();
for (Object bindValue : bindValues) {
// extract the id values from the bean
Object[] ids = prop.assocIdValues((EntityBean) bindValue);
if (ids != null) {
Collections.addAll(idList, ids);
Collections.addAll(values, ids);
}
}
if (!idList.isEmpty()) {
request.addBindValue(new MultiValueWrapper(idList));
}
if (values.isEmpty()) {
// nothing in in-query
return;
}
if (prop != null) {
if (prop.isDbEncrypted()) {
// bind the key as well as the value
request.addBindEncryptKey(prop.beanProperty().encryptKey().getStringValue());
} else if (prop.isLocalEncrypted()) {
List<Object> encValues = new ArrayList<>(values.size());
for (Object value : values) {
encValues.add(prop.localEncrypt(value));
}
// this is most likely binary garbage, so don't add it to the bind log
request.addBindEncryptKey(new MultiValueWrapper(encValues));
return;
}
}
// wrap in a multi value wrapper, later the binder will decide the bind strategy to use
request.addBindValue(new MultiValueWrapper(values));
}
@Override
@@ -154,17 +158,20 @@ public final class InExpression extends AbstractExpression implements IdInCommon
}
ElPropertyValue prop = getElProp(request);
if (prop != null && !prop.isAssocId()) {
prop = null;
}
if (prop != null) {
request.append(prop.assocIdInExpr(propName));
request.append(prop.assocIdInValueExpr(not, bindValues.size()));
} else {
request.append(propName);
request.appendInExpression(not, bindValues);
if (prop.isAssocId()) {
request.append(prop.assocIdInExpr(propName));
request.append(prop.assocIdInValueExpr(not, bindValues.size()));
return;
}
if (prop.isDbEncrypted()) {
request.append(prop.beanProperty().decryptProperty(propName));
request.appendInExpression(not, bindValues);
return;
}
}
request.append(propName);
request.appendInExpression(not, bindValues);
}
/**
@@ -3,6 +3,7 @@ package io.ebeaninternal.server.expression;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.server.el.ElPropertyValue;
import java.io.IOException;
@@ -32,13 +33,29 @@ final class InRangeExpression extends AbstractExpression {
@Override
public void addBindValues(SpiExpressionRequest request) {
ElPropertyValue prop = getElProp(request);
if (prop != null && prop.isDbEncrypted()) {
// bind the key twice, for both values
String encryptKey = prop.beanProperty().encryptKey().getStringValue();
request.addBindEncryptKey(encryptKey);
request.addBindValue(low());
request.addBindEncryptKey(encryptKey);
request.addBindValue(high());
return;
}
request.addBindValue(low());
request.addBindValue(high());
}
@Override
public void addSql(SpiExpressionRequest request) {
request.append("(").append(propName).append(" >= ? and ").append(propName).append(" < ?)");
String pname = propName;
ElPropertyValue prop = getElProp(request);
if (prop != null && prop.isDbEncrypted()) {
pname = prop.beanProperty().decryptProperty(propName);
}
request.append("(").append(pname).append(" >= ? and ").append(pname).append(" < ?)");
}
@Override
@@ -279,6 +279,11 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
return exprList.inRangeWith(lowProperty, highProperty, value);
}
@Override
public ExpressionList<T> inRangeWithProperties(String propertyName, String lowProperty, String highProperty) {
return exprList.inRangeWithProperties(propertyName, lowProperty, highProperty);
}
@Override
public ExpressionList<T> inRange(String propertyName, Object value1, Object value2) {
return exprList.inRange(propertyName, value1, value2);
@@ -304,6 +309,11 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
return exprList.endsWith(propertyName, value);
}
@Override
public ExpressionList<T> eq(String propertyName, Query<?> subQuery) {
return exprList.eq(propertyName, subQuery);
}
@Override
public ExpressionList<T> eq(String propertyName, Object value) {
return exprList.eq(propertyName, value);
@@ -637,11 +647,21 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
return exprList.bitwiseNot(propertyName, flags);
}
@Override
public ExpressionList<T> ge(String propertyName, Query<?> subQuery) {
return exprList.ge(propertyName, subQuery);
}
@Override
public ExpressionList<T> ge(String propertyName, Object value) {
return exprList.ge(propertyName, value);
}
@Override
public ExpressionList<T> gt(String propertyName, Query<?> subQuery) {
return exprList.gt(propertyName, subQuery);
}
@Override
public ExpressionList<T> gt(String propertyName, Object value) {
return exprList.gt(propertyName, value);
@@ -782,6 +802,11 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
return exprList.istartsWith(propertyName, value);
}
@Override
public ExpressionList<T> le(String propertyName, Query<?> subQuery) {
return exprList.le(propertyName, subQuery);
}
@Override
public ExpressionList<T> le(String propertyName, Object value) {
return exprList.le(propertyName, value);
@@ -792,6 +817,11 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
return exprList.like(propertyName, value);
}
@Override
public ExpressionList<T> lt(String propertyName, Query<?> subQuery) {
return exprList.lt(propertyName, subQuery);
}
@Override
public ExpressionList<T> lt(String propertyName, Object value) {
return exprList.lt(propertyName, value);
@@ -807,6 +837,11 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
return exprList.leOrNull(propertyName, value);
}
@Override
public ExpressionList<T> ne(String propertyName, Query<?> subQuery) {
return exprList.ne(propertyName, subQuery);
}
@Override
public ExpressionList<T> ne(String propertyName, Object value) {
return exprList.ne(propertyName, value);
@@ -8,32 +8,47 @@ import io.ebeaninternal.server.query.CQuery;
import java.util.List;
/**
* In expression using a sub query.
* Sub-Query expression.
*/
final class InQueryExpression extends AbstractExpression implements UnsupportedDocStoreExpression {
final class SubQueryExpression extends AbstractExpression implements UnsupportedDocStoreExpression {
private final boolean not;
enum SQOp {
EQ(" = "),
NE(" <> "),
GT(" > "),
GE(" >= "),
LT(" < "),
LE(" <= "),
IN(" in "),
NOTIN(" not in ");
final String expression;
SQOp(String expression) {
this.expression = expression;
}
}
private final SQOp op;
private final SpiQuery<?> subQuery;
private List<Object> bindParams;
private String sql;
InQueryExpression(String propertyName, SpiQuery<?> subQuery, boolean not) {
SubQueryExpression(SQOp op, String propertyName, SpiQuery<?> subQuery) {
super(propertyName);
this.op = op;
this.subQuery = subQuery;
this.not = not;
}
InQueryExpression(String propertyName, boolean not, String sql, List<Object> bindParams) {
SubQueryExpression(SQOp op, String propertyName, String sql, List<Object> bindParams) {
super(propertyName);
this.op = op;
this.subQuery = null;
this.not = not;
this.sql = sql;
this.bindParams = bindParams;
}
@Override
public SpiExpression copy() {
return subQuery == null ? this : new InQueryExpression(propName, subQuery.copy(), not);
return subQuery == null ? this : new SubQueryExpression(op, propName, subQuery.copy());
}
@Override
@@ -55,8 +70,8 @@ final class InQueryExpression extends AbstractExpression implements UnsupportedD
@Override
public void queryPlanHash(StringBuilder builder) {
builder.append("InQuery[").append(propName)
.append(" not:").append(not).append(" sql:").append(sql)
builder.append("SubQuery[").append(propName).append(op.expression)
.append(" sql:").append(sql)
.append(" ?:").append(bindParams.size()).append("]");
}
@@ -65,7 +80,7 @@ final class InQueryExpression extends AbstractExpression implements UnsupportedD
*/
private CQuery<?> compileSubQuery(BeanQueryRequest<?> queryRequest) {
SpiEbeanServer ebeanServer = (SpiEbeanServer) queryRequest.database();
return ebeanServer.compileQuery(Type.SQ_IN, subQuery, queryRequest.transaction());
return ebeanServer.compileQuery(Type.SQ_EX, subQuery, queryRequest.transaction());
}
@Override
@@ -75,13 +90,7 @@ final class InQueryExpression extends AbstractExpression implements UnsupportedD
@Override
public void addSql(SpiExpressionRequest request) {
request.append(" (").append(propName).append(")");
if (not) {
request.append(" not");
}
request.append(" in (");
request.append(sql);
request.append(")");
request.append(propName).append(op.expression).append("(").append(sql).append(")");
}
@Override
@@ -93,7 +102,7 @@ final class InQueryExpression extends AbstractExpression implements UnsupportedD
@Override
public boolean isSameByBind(SpiExpression other) {
InQueryExpression that = (InQueryExpression) other;
SubQueryExpression that = (SubQueryExpression) other;
if (this.bindParams.size() != that.bindParams.size()) {
return false;
}
@@ -106,7 +106,7 @@ public class UuidV1RndIdGenerator implements PlatformIdGenerator {
delta = current - last;
if (delta < -10000 * 20000) {
log.log(INFO, "Clock skew of {} ms detected", delta / -10000);
log.log(INFO, "Clock skew of {0} ms detected", delta / -10000);
// The clock was adjusted back about 2 seconds, or we were generating a lot of ids too fast
// if so, we try to set the current as last and also increment the clockSeq.
lock.lock();
@@ -36,7 +36,7 @@ public final class DJsonScalar {
gen.writeRaw(']');
} else {
ScalarType scalarType = typeManager.getScalarType(value.getClass());
ScalarType scalarType = typeManager.type(value.getClass());
if (scalarType == null) {
throw new IllegalArgumentException("unhandled type " + value.getClass());
}
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.persist;
import io.ebean.config.dbplatform.DbPlatformType;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.PostgresHelper;
import io.ebean.core.type.ScalarType;
import io.ebeaninternal.api.BindParams;
import io.ebeaninternal.api.CoreLog;
@@ -37,7 +38,7 @@ public final class Binder {
public Binder(TypeManager typeManager, SpiLogManager logManager, int asOfBindCount, boolean asOfStandardsBased,
DbExpressionHandler dbExpressionHandler, DataTimeZone dataTimeZone, MultiValueBind multiValueBind) {
this.typeManager = typeManager;
this.geoTypeBinder = typeManager.getGeoTypeBinder();
this.geoTypeBinder = typeManager.geoTypeBinder();
this.asOfBindCount = asOfBindCount;
this.asOfStandardsBased = asOfStandardsBased;
this.dbExpressionHandler = dbExpressionHandler;
@@ -153,7 +154,7 @@ public final class Binder {
}
public ScalarType<?> getScalarType(Class<?> clazz) {
ScalarType<?> type = typeManager.getScalarType(clazz);
ScalarType<?> type = typeManager.type(clazz);
if (type == null) {
throw new PersistenceException("No ScalarType registered for " + clazz);
}
@@ -217,6 +217,8 @@ public abstract class DmlHandler implements PersistHandler, BindableRequest {
}
if (prop.isLob()) {
bindLog.append("[LOB]");
} else if (value == null && !prop.isNullable() && prop.isArrayType()) {
bindLog.append("[]"); // null bound as empty array
} else {
String sv = String.valueOf(value);
if (sv.length() > 50) {
@@ -7,25 +7,7 @@ import io.ebeaninternal.server.bind.DataBind;
import java.sql.SQLException;
import java.util.Collection;
import static java.sql.Types.BIGINT;
import static java.sql.Types.BIT;
import static java.sql.Types.BOOLEAN;
import static java.sql.Types.CHAR;
import static java.sql.Types.DATE;
import static java.sql.Types.DECIMAL;
import static java.sql.Types.DOUBLE;
import static java.sql.Types.FLOAT;
import static java.sql.Types.INTEGER;
import static java.sql.Types.NCHAR;
import static java.sql.Types.NUMERIC;
import static java.sql.Types.NVARCHAR;
import static java.sql.Types.REAL;
import static java.sql.Types.SMALLINT;
import static java.sql.Types.TIMESTAMP;
import static java.sql.Types.TIMESTAMP_WITH_TIMEZONE;
import static java.sql.Types.TIME_WITH_TIMEZONE;
import static java.sql.Types.TINYINT;
import static java.sql.Types.VARCHAR;
import static java.sql.Types.*;
/**
* Base MultiValueBind for platform specific support.
@@ -86,6 +68,8 @@ abstract class AbstractMultiValueBind extends MultiValueBind {
case ExtraDbTypes.UUID: // Postgres cast to uuid[]
case ExtraDbTypes.INET: // Postgres cast to inet[]
return "varchar";
case VARBINARY:
return "bytea";
default:
return null;
@@ -17,7 +17,7 @@ public class MultiValueBind {
}
Object[] toArray(Collection<?> values, ScalarType<?> type) {
Object[] array = new Object[values.size()];
Object[] array = type.binary() ? new byte[values.size()][] : new Object[values.size()];
int i = 0;
for (Object value : values) {
array[i++] = type.toJdbcType(value);
@@ -396,7 +396,7 @@ final class CQueryBuilder {
sql = nativeQueryPaging(query, sql);
}
query.setGeneratedSql(sql);
Connection connection = request.transaction().connection();
Connection connection = request.transaction().getInternalConnection();
BeanDescriptor<?> desc = request.descriptor();
try {
// For SqlServer we need either "selectMethod=cursor" in the connection string or fetch explicitly a cursorable
@@ -86,7 +86,7 @@ public final class SqlTreeBuilder {
this.disableLazyLoad = query.isDisableLazyLoading();
this.readOnly = Boolean.TRUE.equals(query.isReadOnly());
this.subQuery = Type.SQ_EXISTS == query.getType()
|| Type.SQ_IN == query.getType()
|| Type.SQ_EX == query.getType()
|| Type.ID_LIST == query.getType()
|| Type.DELETE == query.getType()
|| query.isCountDistinct();
@@ -129,6 +129,26 @@ public final class DefaultDtoQuery<T> extends AbstractQuery implements SpiDtoQue
return Optional.ofNullable(findOne());
}
@Override
public DtoQuery<T> setNullParameter(String name, int jdbcType) {
if (ormQuery != null) {
ormQuery.initBindParams().setNullParameter(name, jdbcType);
} else {
bindParams.setNullParameter(name, jdbcType);
}
return this;
}
@Override
public DtoQuery<T> setNullParameter(int position, int jdbcType) {
if (ormQuery != null) {
ormQuery.initBindParams().setNullParameter(position, jdbcType);
} else {
bindParams.setNullParameter(position, jdbcType);
}
return this;
}
@Override
public DtoQuery<T> setParameter(int position, Object value) {
if (ormQuery != null) {
@@ -1544,19 +1544,13 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
@Override
public final Query<T> setParameter(Object value) {
if (bindParams == null) {
bindParams = new BindParams();
}
bindParams.setNextParameter(value);
initBindParams().setNextParameter(value);
return this;
}
@Override
public final Query<T> setParameters(Object... values) {
if (bindParams == null) {
bindParams = new BindParams();
}
bindParams.setNextParameters(values);
initBindParams().setNextParameters(values);
return this;
}
@@ -1567,10 +1561,7 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
*/
@Override
public final Query<T> setParameter(int position, Object value) {
if (bindParams == null) {
bindParams = new BindParams();
}
bindParams.setParameter(position, value);
initBindParams().setParameter(position, value);
return this;
}
@@ -1586,10 +1577,7 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
return this;
}
}
if (bindParams == null) {
bindParams = new BindParams();
}
bindParams.setParameter(name, value);
initBindParams().setParameter(name, value);
return this;
}
@@ -1598,10 +1586,7 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
if (namedParams != null) {
throw new IllegalStateException("setArrayParameter() not supported when EQL parsed query");
}
if (bindParams == null) {
bindParams = new BindParams();
}
bindParams.setArrayParameter(name, values);
initBindParams().setArrayParameter(name, values);
}
@Override
@@ -1789,6 +1774,14 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
return bindParams;
}
@Override
public BindParams initBindParams() {
if (bindParams == null) {
bindParams = new BindParams();
}
return bindParams;
}
@Override
public final Query<T> where(Expression expression) {
where().add(expression);
@@ -240,7 +240,7 @@ final class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEve
@Override
public boolean isReadOnly() {
if (!isActive()) {
if (!active) {
throw new IllegalStateException(illegalStateMessage);
}
try {
@@ -252,7 +252,7 @@ final class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEve
@Override
public void setReadOnly(boolean readOnly) {
if (!isActive()) {
if (!active) {
throw new IllegalStateException(illegalStateMessage);
}
try {
@@ -403,7 +403,7 @@ final class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEve
*/
@Override
public void setPersistenceContext(SpiPersistenceContext context) {
if (!isActive()) {
if (!active) {
throw new IllegalStateException(illegalStateMessage);
}
this.persistenceContext = context;
@@ -465,7 +465,7 @@ final class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEve
*/
@Override
public Connection getInternalConnection() {
if (!isActive()) {
if (!active) {
throw new IllegalStateException(illegalStateMessage);
}
return connection;
@@ -508,7 +508,7 @@ final class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEve
*/
@Override
public void commit() {
if (!isActive()) {
if (!active) {
throw new IllegalStateException(illegalStateMessage);
}
// expect AutoCommit so just deactivate / put back into pool
@@ -532,6 +532,11 @@ final class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEve
throw new IllegalStateException(notExpectedMessage);
}
@Override
public void rollbackAndContinue() {
// do nothing
}
/**
* Rollback the transaction.
*/
@@ -546,7 +551,7 @@ final class ImplicitReadOnlyTransaction implements SpiTransaction, TxnProfileEve
*/
@Override
public void rollback(Throwable cause) throws PersistenceException {
if (!isActive()) {
if (!active) {
throw new IllegalStateException(illegalStateMessage);
}
// expect AutoCommit so it really has already committed
@@ -424,9 +424,6 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
@Override
public boolean isReadOnly() {
if (!isActive()) {
throw new IllegalStateException(illegalStateMessage);
}
try {
return connection.isReadOnly();
} catch (SQLException e) {
@@ -436,9 +433,6 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
@Override
public void setReadOnly(boolean readOnly) {
if (!isActive()) {
throw new IllegalStateException(illegalStateMessage);
}
try {
localReadOnly = readOnly;
connection.setReadOnly(readOnly);
@@ -459,9 +453,6 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
@Override
public final void setBatchMode(boolean batchMode) {
if (!isActive()) {
throw new IllegalStateException(illegalStateMessage);
}
this.batchMode = batchMode;
}
@@ -472,9 +463,6 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
@Override
public final void setBatchOnCascade(boolean batchMode) {
if (!isActive()) {
throw new IllegalStateException(illegalStateMessage);
}
this.batchOnCascadeMode = batchMode;
}
@@ -666,9 +654,6 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
*/
@Override
public final void flush() {
if (!isActive()) {
throw new IllegalStateException(illegalStateMessage);
}
internalBatchFlush();
}
@@ -707,9 +692,6 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
*/
@Override
public final void setPersistenceContext(SpiPersistenceContext context) {
if (!isActive()) {
throw new IllegalStateException(illegalStateMessage);
}
this.persistenceContext = context;
}
@@ -776,9 +758,6 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
*/
@Override
public Connection getInternalConnection() {
if (!isActive()) {
throw new IllegalStateException(illegalStateMessage);
}
return connection;
}
@@ -906,6 +885,9 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
public final void preCommit() {
internalBatchFlush();
firePreCommit();
// we must flush the batch queue again, because the callback can
// modify current transaction
internalBatchFlush();
}
/**
@@ -920,7 +902,7 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
if (rollbackOnly) {
return;
}
if (!isActive()) {
if (!active) {
throw new IllegalStateException(illegalStateMessage);
}
try {
@@ -945,7 +927,7 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
rollback();
return;
}
if (!isActive()) {
if (!active) {
throw new IllegalStateException(illegalStateMessage);
}
try {
@@ -1014,6 +996,22 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
this.nestedUseSavepoint = true;
}
@Override
public void rollbackAndContinue() {
if (!active) {
throw new IllegalStateException(illegalStateMessage);
}
internalBatchClear();
if (changeLogHolder != null) {
changeLogHolder.clear();
}
try {
performRollback();
} catch (SQLException ex) {
throw new PersistenceException(ex);
}
}
/**
* Rollback the transaction.
*/
@@ -1028,7 +1026,7 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
*/
@Override
public void rollback(Throwable cause) throws PersistenceException {
if (!isActive()) {
if (!active) {
throw new IllegalStateException(illegalStateMessage);
}
try {
@@ -1066,7 +1064,7 @@ class JdbcTransaction implements SpiTransaction, TxnProfileEventCodes {
*/
@Override
public void end() throws PersistenceException {
if (isActive()) {
if (active) {
rollback();
}
}
@@ -78,10 +78,14 @@ final class NoTransaction implements SpiTransaction {
}
@Override
public void rollback() throws PersistenceException {
public void rollbackAndContinue() {
// do nothing
}
@Override
public void rollback() throws PersistenceException {
// do nothing
}
@Override
public void rollback(Throwable e) throws PersistenceException {
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.transaction;
import io.ebeaninternal.api.SpiTransaction;
import io.ebeaninternal.api.SpiTransactionProxy;
import io.ebeaninternal.api.TransactionEvent;
import io.ebeaninternal.server.util.Str;
import javax.persistence.PersistenceException;
@@ -25,6 +26,7 @@ final class SavepointTransaction extends SpiTransactionProxy {
private boolean rollbackOnly;
private int state;
private TransactionEvent event;
SavepointTransaction(SpiTransaction transaction, TransactionManager manager) throws SQLException {
this.manager = manager;
@@ -40,6 +42,14 @@ final class SavepointTransaction extends SpiTransactionProxy {
this.logPrefix = transaction.getLogPrefix() + spPrefix;
}
@Override
public TransactionEvent getEvent() {
if (event == null) {
event = new TransactionEvent();
}
return event;
}
@Override
public String getLogPrefix() {
return logPrefix;
@@ -69,6 +79,11 @@ final class SavepointTransaction extends SpiTransactionProxy {
}
}
@Override
public void rollbackAndContinue() {
throw new UnsupportedOperationException();
}
@Override
public void rollback() throws PersistenceException {
rollbackSavepoint(null);
@@ -96,4 +96,7 @@ public final class TChangeLogHolder {
owner.sendChangeLog(changes);
}
void clear() {
changes.getChanges().clear();
}
}
@@ -35,7 +35,7 @@ abstract class TransactionFactory {
*/
final SpiTransaction setIsolationLevel(SpiTransaction t, boolean explicit, int isolationLevel) {
if (isolationLevel > -1) {
Connection connection = t.connection();
Connection connection = t.getInternalConnection();
try {
connection.setTransactionIsolation(isolationLevel);
} catch (SQLException e) {
@@ -573,7 +573,7 @@ public class TransactionManager implements SpiTransactionManager {
} else {
setToScope = false;
transaction = txnContainer.current();
nestedSavepoint = transaction.isNestedUseSavepoint();
nestedSavepoint = txnContainer.isNestedUseSavepoint();
}
TxType type = txScope.getType();
@@ -1,6 +1,5 @@
package io.ebeaninternal.server.type;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.ebean.annotation.*;
import io.ebean.config.DatabaseConfig;
@@ -9,9 +8,7 @@ import io.ebean.config.PlatformConfig;
import io.ebean.config.ScalarTypeConverter;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.config.dbplatform.DbPlatformType;
import io.ebean.core.type.DocPropertyType;
import io.ebean.core.type.ExtraTypeFactory;
import io.ebean.core.type.ScalarType;
import io.ebean.core.type.*;
import io.ebean.types.Cidr;
import io.ebean.types.Inet;
import io.ebean.util.AnnotationUtil;
@@ -40,6 +37,7 @@ import java.time.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import static io.ebean.core.type.PostgresHelper.isPostgresCompatible;
import static java.lang.System.Logger.Level.*;
/**
@@ -51,6 +49,7 @@ public final class DefaultTypeManager implements TypeManager {
private static final System.Logger log = CoreLog.internal;
private final Map<Class<?>, ScalarTypeSet<?>> typeSets = new HashMap<>();
private final ConcurrentHashMap<Class<?>, ScalarType<?>> typeMap;
private final ConcurrentHashMap<Integer, ScalarType<?>> nativeMap;
private final ConcurrentHashMap<String, ScalarType<?>> logicalMap;
@@ -66,36 +65,14 @@ public final class DefaultTypeManager implements TypeManager {
private final Object objectMapper;
private final boolean objectMapperPresent;
private final boolean postgres;
private final TypeJsonManager jsonManager;
private final ScalarJsonManager jsonManager;
private final boolean offlineMigrationGeneration;
private final EnumType defaultEnumType;
private final DatabasePlatform databasePlatform;
// OPTIONAL ScalarTypes registered if Jackson/JsonNode is in the classpath
/**
* Jackson's JsonNode storage to Clob.
*/
private ScalarType<?> jsonNodeClob;
/**
* Jackson's JsonNode storage to Blob.
*/
private ScalarType<?> jsonNodeBlob;
/**
* Jackson's JsonNode storage to Varchar.
*/
private ScalarType<?> jsonNodeVarchar;
/**
* Jackson's JsonNode storage to Postgres JSON or Clob.
*/
private ScalarType<?> jsonNodeJson;
/**
* Jackson's JsonNode storage to Postgres JSONB or Clob.
*/
private ScalarType<?> jsonNodeJsonb;
private final PlatformArrayTypeFactory arrayTypeListFactory;
private final PlatformArrayTypeFactory arrayTypeSetFactory;
private final ScalarJsonMapper jsonMapper;
private GeoTypeBinder geoTypeBinder;
/**
@@ -118,9 +95,11 @@ public final class DefaultTypeManager implements TypeManager {
this.offlineMigrationGeneration = DbOffline.isGenerateMigration();
this.defaultEnumType = config.getDefaultEnumType();
ServiceLoader<ScalarJsonMapper> mappers = ServiceLoader.load(ScalarJsonMapper.class);
jsonMapper = mappers.findFirst().orElse(null);
initialiseStandard(config);
initialiseJavaTimeTypes(config);
initialiseJacksonTypes();
loadTypesFromProviders(config, objectMapper);
loadGeoTypeBinder(config);
@@ -132,7 +111,10 @@ public final class DefaultTypeManager implements TypeManager {
}
private void loadGeoTypeBinder(DatabaseConfig config) {
final GeoTypeProvider provider = ServiceUtil.service(GeoTypeProvider.class);
GeoTypeProvider provider = config.getServiceObject(GeoTypeProvider.class);
if (provider == null) {
provider = ServiceUtil.service(GeoTypeProvider.class);
}
if (provider != null) {
geoTypeBinder = provider.createBinder(config);
}
@@ -160,22 +142,21 @@ public final class DefaultTypeManager implements TypeManager {
* Load custom scalar types registered via ExtraTypeFactory and ServiceLoader.
*/
private void loadTypesFromProviders(DatabaseConfig config, Object objectMapper) {
ServiceLoader<ExtraTypeFactory> factories = ServiceLoader.load(ExtraTypeFactory.class);
Iterator<ExtraTypeFactory> iterator = factories.iterator();
if (iterator.hasNext()) {
// use the cacheFactory (via classpath service loader)
ExtraTypeFactory plugin = iterator.next();
List<? extends ScalarType<?>> types = plugin.createTypes(config, objectMapper);
for (ScalarType<?> type : types) {
for (ExtraTypeFactory plugin : ServiceLoader.load(ExtraTypeFactory.class)) {
for (ScalarType<?> type : plugin.createTypes(config, objectMapper)) {
add(type);
}
}
}
private boolean isPostgresCompatible(DatabasePlatform databasePlatform) {
return databasePlatform.isPlatform(Platform.POSTGRES)
|| databasePlatform.isPlatform(Platform.YUGABYTE)
|| databasePlatform.isPlatform(Platform.COCKROACH);
for (ScalarTypeSetFactory factory : ServiceLoader.load(ScalarTypeSetFactory.class)) {
ScalarTypeSet<?> typeSet = factory.createTypeSet(config, objectMapper);
if (typeSet != null) {
typeSets.put(typeSet.type(), typeSet);
ScalarType<?> defaultType = typeSet.defaultType();
if (defaultType != null) {
typeMap.put(typeSet.type(), defaultType);
}
}
}
}
private boolean hstoreSupport() {
@@ -185,8 +166,7 @@ public final class DefaultTypeManager implements TypeManager {
/**
* Register a custom ScalarType.
*/
@Override
public void add(ScalarType<?> scalarType) {
private void add(ScalarType<?> scalarType) {
typeMap.put(scalarType.type(), scalarType);
logAdd(scalarType);
}
@@ -198,7 +178,7 @@ public final class DefaultTypeManager implements TypeManager {
}
@Override
public ScalarType<?> getScalarType(String cast) {
public ScalarType<?> type(String cast) {
return logicalMap.get(cast);
}
@@ -206,27 +186,27 @@ public final class DefaultTypeManager implements TypeManager {
* Return the ScalarType for the given jdbc type as per java.sql.Types.
*/
@Override
public ScalarType<?> getScalarType(int jdbcType) {
public ScalarType<?> type(int jdbcType) {
return nativeMap.get(jdbcType);
}
@Override
public ScalarType<?> getScalarType(Type propertyType, Class<?> propertyClass) {
public ScalarType<?> type(Type propertyType, Class<?> propertyClass) {
if (propertyType instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType)propertyType;
ParameterizedType pt = (ParameterizedType) propertyType;
Type rawType = pt.getRawType();
if (List.class == rawType || Set.class == rawType) {
return getArrayScalarType((Class<?>)rawType, propertyType, true);
return dbArrayType((Class<?>) rawType, propertyType, true);
}
}
return getScalarType(propertyClass);
return type(propertyClass);
}
/**
* This can return null if no matching ScalarType is found.
*/
@Override
public ScalarType<?> getScalarType(Class<?> type) {
public ScalarType<?> type(Class<?> type) {
ScalarType<?> found = typeMap.get(type);
if (found == null) {
if (type.getName().equals("org.joda.time.LocalTime")) {
@@ -260,7 +240,7 @@ public final class DefaultTypeManager implements TypeManager {
return found;
}
// second step - loop through interfaces of this type
for (Class<?> iface: parent.getInterfaces()) {
for (Class<?> iface : parent.getInterfaces()) {
found = checkInheritedTypes(iface);
if (found != null && found != ScalarTypeNotFound.INSTANCE) {
typeMap.put(type, found); // store type for next lookup
@@ -274,37 +254,37 @@ public final class DefaultTypeManager implements TypeManager {
}
@Override
public GeoTypeBinder getGeoTypeBinder() {
public GeoTypeBinder geoTypeBinder() {
return geoTypeBinder;
}
@Override
public ScalarType<?> getDbMapScalarType() {
public ScalarType<?> dbMapType() {
return hstoreSupport() ? hstoreType : ScalarTypeJsonMap.typeFor(false, Types.VARCHAR, false);
}
@Override
public ScalarType<?> getArrayScalarType(Class<?> type, Type genericType, boolean nullable) {
Type valueType = getValueType(genericType);
public ScalarType<?> dbArrayType(Class<?> type, Type genericType, boolean nullable) {
Type valueType = valueType(genericType);
if (type.equals(List.class)) {
return getArrayScalarTypeList(valueType, nullable);
return dbArrayTypeList(valueType, nullable);
} else if (type.equals(Set.class)) {
return getArrayScalarTypeSet(valueType, nullable);
return dbArrayTypeSet(valueType, nullable);
} else {
throw new IllegalStateException("@DbArray does not support type " + type);
}
}
private ScalarType<?> getArrayScalarTypeSet(Type valueType, boolean nullable) {
private ScalarType<?> dbArrayTypeSet(Type valueType, boolean nullable) {
if (isEnumType(valueType)) {
return arrayTypeSetFactory.typeForEnum(createEnumScalarType(asEnumClass(valueType), null), nullable);
return arrayTypeSetFactory.typeForEnum(enumType(asEnumClass(valueType), null), nullable);
}
return arrayTypeSetFactory.typeFor(valueType, nullable);
}
private ScalarType<?> getArrayScalarTypeList(Type valueType, boolean nullable) {
private ScalarType<?> dbArrayTypeList(Type valueType, boolean nullable) {
if (isEnumType(valueType)) {
return arrayTypeListFactory.typeForEnum(createEnumScalarType(asEnumClass(valueType), null), nullable);
return arrayTypeListFactory.typeForEnum(enumType(asEnumClass(valueType), null), nullable);
}
return arrayTypeListFactory.typeFor(valueType, nullable);
}
@@ -318,67 +298,50 @@ public final class DefaultTypeManager implements TypeManager {
}
@Override
public ScalarType<?> getJsonScalarType(DeployBeanProperty prop, int dbType, int dbLength) {
public ScalarType<?> dbJsonType(DeployBeanProperty prop, int dbType, int dbLength) {
Class<?> type = prop.getPropertyType();
Type genericType = prop.getGenericType();
boolean hasJacksonAnnotations = objectMapperPresent && checkJacksonAnnotations(prop);
if (type.equals(String.class)) {
return ScalarTypeJsonString.typeFor(postgres, dbType);
}
if (type.equals(List.class)) {
DocPropertyType docType = getDocType(genericType);
if (!hasJacksonAnnotations && isValueTypeSimple(genericType)) {
return ScalarTypeJsonList.typeFor(postgres, dbType, docType, prop.isNullable(), jsonManager.keepSource(prop));
} else {
return createJsonObjectMapperType(prop, dbType, docType);
if (jsonMapper != null) {
var markerAnnotation = jsonMapper.markerAnnotation();
if (markerAnnotation != null && !prop.getMetaAnnotations(markerAnnotation).isEmpty()) {
return createJsonObjectMapperType(prop, dbType, docPropertyType(prop, type));
}
}
if (type.equals(Set.class)) {
DocPropertyType docType = getDocType(genericType);
if (!hasJacksonAnnotations && isValueTypeSimple(genericType)) {
return ScalarTypeJsonSet.typeFor(postgres, dbType, docType, prop.isNullable(), jsonManager.keepSource(prop));
} else {
return createJsonObjectMapperType(prop, dbType, docType);
}
Type genericType = prop.getGenericType();
if (type.equals(List.class) && isValueTypeSimple(genericType)) {
return ScalarTypeJsonList.typeFor(postgres, dbType, docType(genericType), prop.isNullable(), keepSource(prop));
}
if (type.equals(Map.class)) {
if (!hasJacksonAnnotations && isMapValueTypeObject(genericType)) {
return ScalarTypeJsonMap.typeFor(postgres, dbType, jsonManager.keepSource(prop));
} else {
return createJsonObjectMapperType(prop, dbType, DocPropertyType.OBJECT);
}
if (type.equals(Set.class) && isValueTypeSimple(genericType)) {
return ScalarTypeJsonSet.typeFor(postgres, dbType, docType(genericType), prop.isNullable(), keepSource(prop));
}
if (type.equals(Map.class) && isMapValueTypeObject(genericType)) {
return ScalarTypeJsonMap.typeFor(postgres, dbType, keepSource(prop));
}
if (objectMapperPresent && prop.getMutationDetection() == MutationDetection.DEFAULT) {
if (type.equals(JsonNode.class)) {
switch (dbType) {
case Types.VARCHAR:
return jsonNodeVarchar;
case Types.BLOB:
return jsonNodeBlob;
case Types.CLOB:
return jsonNodeClob;
case DbPlatformType.JSONB:
return jsonNodeJsonb;
default:
return jsonNodeJson;
}
ScalarTypeSet<?> typeSet = typeSets.get(type);
if (typeSet != null) {
return typeSet.forType(dbType);
}
}
return createJsonObjectMapperType(prop, dbType, DocPropertyType.OBJECT);
}
/**
* Returns TRUE, if there is any jackson annotation on that property. All jackson annotations
* are annotated with the &#64;JacksonAnnotation meta annotation. So detection is easy.
*/
private boolean checkJacksonAnnotations(DeployBeanProperty prop) {
return prop.getMetaAnnotation(com.fasterxml.jackson.annotation.JacksonAnnotation.class) != null;
private boolean keepSource(DeployBeanProperty prop) {
if (prop.getMutationDetection() == MutationDetection.DEFAULT) {
prop.setMutationDetection(jsonManager.mutationDetection());
}
return prop.getMutationDetection() == MutationDetection.SOURCE;
}
private DocPropertyType getDocType(Type genericType) {
private DocPropertyType docPropertyType(DeployBeanProperty prop, Class<?> type) {
return type.equals(List.class) || type.equals(Set.class) ? docType(prop.getGenericType()) : DocPropertyType.OBJECT;
}
private DocPropertyType docType(Type genericType) {
if (genericType instanceof Class<?>) {
ScalarType<?> found = getScalarType((Class<?>)genericType);
ScalarType<?> found = type((Class<?>) genericType);
if (found != null) {
return found.docType();
}
@@ -394,7 +357,7 @@ public final class DefaultTypeManager implements TypeManager {
return String.class.equals(typeArg) || Long.class.equals(typeArg);
}
private Type getValueType(Type collectionType) {
private Type valueType(Type collectionType) {
return TypeReflectHelper.getValueType(collectionType);
}
@@ -407,11 +370,14 @@ public final class DefaultTypeManager implements TypeManager {
}
private ScalarType<?> createJsonObjectMapperType(DeployBeanProperty prop, int dbType, DocPropertyType docType) {
Class<?> type = prop.getPropertyType();
if (objectMapper == null) {
throw new IllegalArgumentException("Type [" + type + "] unsupported for @DbJson mapping - Jackson ObjectMapper not present");
if (jsonMapper == null) {
throw new IllegalArgumentException("Unsupported @DbJson mapping - Jackson ObjectMapper not present for " + prop);
}
return ScalarTypeJsonObjectMapper.createTypeFor(jsonManager, prop, dbType, docType);
if (MutationDetection.DEFAULT == prop.getMutationDetection()) {
prop.setMutationDetection(jsonManager.mutationDetection());
}
var req = new ScalarJsonRequest(jsonManager, dbType, docType, prop.getDesc().getBeanType(), prop.getMutationDetection(), prop.getName());
return jsonMapper.createType(req);
}
/**
@@ -421,7 +387,7 @@ public final class DefaultTypeManager implements TypeManager {
* different jdbcTypes in a single system.
*/
@Override
public ScalarType<?> getScalarType(Class<?> type, int jdbcType) {
public ScalarType<?> type(Class<?> type, int jdbcType) {
// File is a special Lob so check for that first
if (File.class.equals(type)) {
return fileType;
@@ -430,13 +396,13 @@ public final class DefaultTypeManager implements TypeManager {
// check for Clob, LongVarchar etc ...
// the reason being that String maps to multiple jdbc types
// varchar, clob, longVarchar.
ScalarType<?> scalarType = getLobTypes(jdbcType);
ScalarType<?> scalarType = lobTypes(jdbcType);
if (scalarType != null) {
// it is a specific Lob type...
return scalarType;
}
scalarType = getScalarType(type);
scalarType = type(type);
if (scalarType != null) {
if (jdbcType == 0 || scalarType.jdbcType() == jdbcType) {
// matching type
@@ -462,8 +428,8 @@ public final class DefaultTypeManager implements TypeManager {
* types - like String - Varchar, LongVarchar, Clob. For this reason I check
* for the specific Lob types first before looking for a matching type.
*/
private ScalarType<?> getLobTypes(int jdbcType) {
return getScalarType(jdbcType);
private ScalarType<?> lobTypes(int jdbcType) {
return type(jdbcType);
}
/**
@@ -507,7 +473,7 @@ public final class DefaultTypeManager implements TypeManager {
* <p>
* Return null if the EnumValue annotations are not present/used.
*/
private ScalarTypeEnum<?> createEnumScalarType2(Class<?> enumType) {
private ScalarTypeEnum<?> enumTypeEnumValue(Class<?> enumType) {
boolean integerType = true;
Map<String, String> nameValueMap = new LinkedHashMap<>();
for (Field field : enumType.getDeclaredFields()) {
@@ -536,8 +502,8 @@ public final class DefaultTypeManager implements TypeManager {
* much shorter codes used in the DB.
*/
@Override
public ScalarType<?> createEnumScalarType(Class<? extends Enum<?>> enumType, EnumType type) {
ScalarType<?> scalarType = getScalarType(enumType);
public ScalarType<?> enumType(Class<? extends Enum<?>> enumType, EnumType type) {
ScalarType<?> scalarType = type(enumType);
if (scalarType instanceof ScalarTypeWrapper) {
// no override or further mapping required
return scalarType;
@@ -549,16 +515,16 @@ public final class DefaultTypeManager implements TypeManager {
}
return scalarEnum;
}
scalarEnum = createEnumScalarTypePerExtentions(enumType);
scalarEnum = enumTypePerExtensions(enumType);
if (scalarEnum == null) {
// use JPA normal Enum type (without mapping)
scalarEnum = createEnumScalarTypePerSpec(enumType, type);
scalarEnum = enumTypePerSpec(enumType, type);
}
add(scalarEnum);
return scalarEnum;
}
private ScalarTypeEnum<?> createEnumScalarTypePerSpec(Class<?> enumType, EnumType type) {
private ScalarTypeEnum<?> enumTypePerSpec(Class<?> enumType, EnumType type) {
if (type == null) {
if (defaultEnumType == EnumType.ORDINAL) {
return new ScalarTypeEnumStandard.OrdinalEnum(enumType);
@@ -572,16 +538,16 @@ public final class DefaultTypeManager implements TypeManager {
}
}
private ScalarTypeEnum<?> createEnumScalarTypePerExtentions(Class<? extends Enum<?>> enumType) {
private ScalarTypeEnum<?> enumTypePerExtensions(Class<? extends Enum<?>> enumType) {
for (Method method : enumType.getMethods()) {
DbEnumValue dbValue = AnnotationUtil.get(method, DbEnumValue.class);
if (dbValue != null) {
boolean integerValues = DbEnumType.INTEGER == dbValue.storage();
return createEnumScalarTypeDbValue(enumType, method, integerValues, dbValue.length(), dbValue.withConstraint());
return enumTypeDbValue(enumType, method, integerValues, dbValue.length(), dbValue.withConstraint());
}
}
// look for EnumValue annotations instead
return createEnumScalarType2(enumType);
return enumTypeEnumValue(enumType);
}
/**
@@ -589,7 +555,7 @@ public final class DefaultTypeManager implements TypeManager {
* <p>
* Return null if the EnumValue annotations are not present/used.
*/
private ScalarTypeEnum<?> createEnumScalarTypeDbValue(Class<? extends Enum<?>> enumType, Method method, boolean integerType, int length, boolean withConstraint) {
private ScalarTypeEnum<?> enumTypeDbValue(Class<? extends Enum<?>> enumType, Method method, boolean integerType, int length, boolean withConstraint) {
Map<String, String> nameValueMap = new LinkedHashMap<>();
for (Enum<?> enumConstant : enumType.getEnumConstants()) {
try {
@@ -671,7 +637,7 @@ public final class DefaultTypeManager implements TypeManager {
}
Class<?> logicalType = paramTypes[0];
Class<?> persistType = paramTypes[1];
ScalarType<?> wrappedType = getScalarType(persistType);
ScalarType<?> wrappedType = type(persistType);
if (wrappedType == null) {
throw new IllegalStateException("Could not find ScalarType for: " + paramTypes[1]);
}
@@ -695,7 +661,7 @@ public final class DefaultTypeManager implements TypeManager {
}
Class<?> logicalType = paramTypes[0];
Class<?> persistType = paramTypes[1];
ScalarType<?> wrappedType = getScalarType(persistType);
ScalarType<?> wrappedType = type(persistType);
if (wrappedType == null) {
throw new IllegalStateException("Could not find ScalarType for: " + paramTypes[1]);
}
@@ -709,29 +675,9 @@ public final class DefaultTypeManager implements TypeManager {
}
}
/**
* Add support for Jackson's JsonNode mapping to Clob, Blob, Varchar, JSON and JSONB.
*/
private void initialiseJacksonTypes() {
if (objectMapper != null) {
ObjectMapper mapper = (ObjectMapper) objectMapper;
jsonNodeClob = new ScalarTypeJsonNode.Clob(mapper);
jsonNodeBlob = new ScalarTypeJsonNode.Blob(mapper);
jsonNodeVarchar = new ScalarTypeJsonNode.Varchar(mapper);
jsonNodeJson = jsonNodeClob; // Default for non-Postgres databases
jsonNodeJsonb = jsonNodeClob; // Default for non-Postgres databases
if (postgres) {
jsonNodeJson = new ScalarTypeJsonNodePostgres.JSON(mapper);
jsonNodeJsonb = new ScalarTypeJsonNodePostgres.JSONB(mapper);
}
// add as default mapping for JsonNode (when not annotated with @DbJson etc)
typeMap.put(JsonNode.class, jsonNodeJson);
}
}
private void initialiseJavaTimeTypes(DatabaseConfig config) {
ZoneId zoneId = getZoneId(config);
ZoneId zoneId = zoneId(config);
typeMap.put(java.nio.file.Path.class, new ScalarTypePath());
addType(java.time.Period.class, new ScalarTypePeriod());
@@ -758,7 +704,7 @@ public final class DefaultTypeManager implements TypeManager {
addType(Duration.class, (durationNanos) ? new ScalarTypeDurationWithNanos() : new ScalarTypeDuration());
}
private ZoneId getZoneId(DatabaseConfig config) {
private ZoneId zoneId(DatabaseConfig config) {
final String dataTimeZone = config.getDataTimeZone();
return (dataTimeZone == null) ? ZoneOffset.systemDefault() : TimeZone.getTimeZone(dataTimeZone).toZoneId();
}
@@ -10,6 +10,8 @@ import java.sql.Types;
abstract class ScalarTypeArrayBase<T> extends ScalarTypeJsonCollection<T> {
static final Object[] EMPTY_ARRAY = new Object[]{};
ScalarTypeArrayBase(Class<T> type, int dbType, DocPropertyType docPropertyType, boolean nullable) {
super(type, dbType, docPropertyType, nullable);
}
@@ -16,15 +16,9 @@ import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
import static java.util.Collections.EMPTY_LIST;
/**
* Type mapped for DB ARRAY type (Postgres only effectively).
*/
@@ -136,7 +130,7 @@ class ScalarTypeArrayList extends ScalarTypeArrayBase<List> implements ScalarTyp
if (nullable) {
binder.setNull(Types.ARRAY);
} else {
binder.setArray(arrayType, toArray(EMPTY_LIST));
binder.setArray(arrayType, EMPTY_ARRAY);
}
}
@@ -14,8 +14,6 @@ import java.util.Map;
import java.util.UUID;
import java.util.concurrent.locks.ReentrantLock;
import static java.util.Collections.EMPTY_LIST;
/**
* H2 database support for DB ARRAY.
*/
@@ -90,7 +88,7 @@ final class ScalarTypeArrayListH2 extends ScalarTypeArrayList {
if (nullable) {
binder.setNull(Types.ARRAY);
} else {
binder.setObject(toArray(EMPTY_LIST));
binder.setObject(EMPTY_ARRAY);
}
}
}
@@ -15,16 +15,9 @@ import java.io.IOException;
import java.lang.reflect.Type;
import java.sql.SQLException;
import java.sql.Types;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
import static java.util.Collections.EMPTY_SET;
/**
* Type mapped for DB ARRAY type (Postgres only effectively).
*/
@@ -125,7 +118,7 @@ class ScalarTypeArraySet extends ScalarTypeArrayBase<Set> implements ScalarTypeA
if (nullable) {
binder.setNull(Types.ARRAY);
} else {
binder.setArray(arrayType, toArray(EMPTY_SET));
binder.setArray(arrayType, EMPTY_ARRAY);
}
}
@@ -13,8 +13,6 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.locks.ReentrantLock;
import static java.util.Collections.EMPTY_SET;
/**
* H2 database support for DB ARRAY.
*/
@@ -84,7 +82,7 @@ final class ScalarTypeArraySetH2 extends ScalarTypeArraySet {
if (nullable) {
binder.setNull(Types.ARRAY);
} else {
binder.setObject(toArray(EMPTY_SET));
binder.setObject(EMPTY_ARRAY);
}
}
}
@@ -61,7 +61,7 @@ final class ScalarTypeCalendar extends ScalarTypeBaseDateTime<Calendar> {
@Override
protected String toJsonNanos(Calendar value) {
return String.valueOf(value.getTime());
return String.valueOf(value.getTime().getTime());
}
@Override
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.type;
import io.ebean.config.dbplatform.ExtraDbTypes;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.PostgresHelper;
import io.ebean.core.type.ScalarTypeBaseVarchar;
import io.ebean.types.Cidr;
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.type;
import io.ebean.config.dbplatform.ExtraDbTypes;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.PostgresHelper;
import io.ebean.core.type.ScalarTypeBaseVarchar;
import io.ebean.types.Inet;
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.type;
import io.ebean.config.dbplatform.ExtraDbTypes;
import io.ebean.core.type.DataBinder;
import io.ebean.core.type.PostgresHelper;
import io.ebean.core.type.ScalarTypeBaseVarchar;
import io.ebean.text.TextException;

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