Compare commits

..
Author SHA1 Message Date
Rob Bygrave 7e3d39ac1a [maven-release-plugin] prepare release ebean-parent-13.6.5 2022-07-06 20:59:04 +12:00
Rob Bygrave ce19837649 Bump avaje-lang to 1.1 with the only change being the removal of maven pom descriptors from META-INF/maven 2022-07-06 20:49:49 +12:00
Rob Bygrave 11e20edb59 #2741 - Bump avaje-config to 2.1 and modify ebean-test to support use of ${docker.host} in test container jdbc urls 2022-07-06 20:47:54 +12:00
Rob Bygrave 88b6a60feb #2730 - Secondary @OneToMany fetch query is not happening if the same Entity type is fetched 2022-07-06 20:19:41 +12:00
Rob Bygrave 43dac07d5b #2740 - Bump ebean-test-containers to 6.2 2022-07-06 14:41:24 +12:00
Rob Bygrave 04434215d0 #2740 - Bump ebean-test-containers to 6.2 2022-07-06 14:27:28 +12:00
Rob Bygrave 52e6c0c625 #2736 - findDto nonsupport setter chain (accessor style setters, both fluid style and non fluid style) 2022-07-05 10:37:55 +12:00
Rob Bygrave 745fbe883e #2737 - Mapping of TimeZone doesn't have enough characters 2022-07-05 09:05:13 +12:00
Rob Bygrave 283e0b66fa #2734 - maven build - excluding maven descriptor (pom and properties) from built artifacts 2022-07-04 17:53:28 +12:00
Rob Bygrave 523deb20f4 #2732 - ebean-agent - skip transactional profiling aware enhancement on query beans 2022-07-04 17:05:25 +12:00
Rob Bygrave 23d52ca192 #2731 - Change ebean-querybean annotations from Retention RUNTIME to CLASS 2022-07-04 16:58:06 +12:00
Rob Bygrave d20d276d56 #2728 - Fix for stateless update with orphanRemoval=true and softDelete 2022-07-04 12:22:27 +12:00
Rob Bygrave 5b92ac6e02 Merge branch 'deleted_one_to_many_children_bug' of https://github.com/Ichtil/ebean into Ichtil-deleted_one_to_many_children_bug 2022-07-01 17:12:45 +12:00
Jan Klička 6392f90f32 Add more failing test cases 2022-06-29 18:41:19 +02:00
Jan Klička bb8f3831b8 Testcase demonstrating stateless update resulting in a delete 2022-06-29 16:09:51 +02:00
Rob Bygrave 4bb43814b7 Run build with -T 8 2022-06-28 10:30:30 +12:00
Rob Bygrave 95c1554642 Run build with -T 8, clean test only for main build 2022-06-28 10:24:35 +12:00
Rob Bygrave 2cd59c5166 Run build with -T 8 2022-06-28 09:59:37 +12:00
Rob Bygrave afdb1df7ce Testing nuodb 4.3.2, but it isn't supporting getGeneratedKeys for jdbc batch inserts
That breaks a lot of tests
2022-06-16 23:32:04 +12:00
Rob Bygrave fa6fdf124d Fix test BasicProfileLocationTest 2022-06-16 13:52:27 +12:00
Rob Bygrave 1e044f03ed Adjust test DefaultPersistenceContextTest 2022-06-15 22:25:46 +12:00
Rob Bygrave 7989fcd6ce Bump to 13.6.5-SNAPSHOT after release 2022-06-15 22:22:04 +12:00
Rob Bygrave a5256df6f2 [maven-release-plugin] prepare for next development iteration 2022-06-14 16:14:25 +12:00
Rob Bygrave fa11dac2b2 [maven-release-plugin] prepare release ebean-parent-13.6.4 2022-06-14 16:14:18 +12:00
Rob Bygrave c40ca2fad7 Bump agent to 13.6.4 (no effective change) 2022-06-14 16:09:13 +12:00
Rob BygraveandGitHub 5b9359f509 Merge pull request #2719 from ebean-orm/feature/postgres-default-table-partition-refactor
DDL - Refactor DDL for Postgres and YugabyteDB to just create a default partition table
2022-06-14 16:08:28 +12:00
Rob Bygrave 403556d8b2 DDL - Refactor DDL for Postgres and YugabyteDB to just create a default partition table
Removes the need and use of  PostgresPlatform.tablePartitionsExist() and PostgresPlatform.tablePartitionInit() altogether.
2022-06-14 16:00:54 +12:00
Rob Bygrave 06ad2edfc1 #2718 - [Yugabyte] Fix such that builtin table partition functions are included in DDL (when we use table partitioning) 2022-06-14 15:39:34 +12:00
Rob BygraveandGitHub 16e2489ba0 Merge pull request #2717 from ebean-orm/feature/string-jsonb
Support Postgres JSONB/JSON with String - @DbJsonb String content;
2022-06-14 15:09:05 +12:00
Rob Bygrave 162b3449e8 Put ebean.properties back to default to h2 2022-06-14 15:03:35 +12:00
Rob Bygrave 8c3ed6996e Put postgresql jdbc back to 42.3.3 2022-06-14 14:59:39 +12:00
Rob Bygrave 583c5f74eb Support Postgres JSONB/JSON with String - @DbJsonb String content; 2022-06-14 14:57:50 +12:00
Rob Bygrave ab047996d2 Add build badge for Oracle 2022-06-14 09:18:17 +12:00
Rob Bygrave 239f87bb5d Rename Oracle GH WF build 2022-06-13 22:39:35 +12:00
Rob Bygrave 5be3b7717c #2716 - Refactor ScalarType interface to make use of default methods 2022-06-13 22:38:15 +12:00
Rob Bygrave e29d83a379 #2710 - Update PersistRequestBean with checkAllMutableProperties() and checkAnyMutableProperties() 2022-06-13 18:58:38 +12:00
Rob Bygrave 8301fd5e74 #2710 - JSONB fields are not considered dirty after modified in BeanPersistController preUpdate 2022-06-13 18:35:42 +12:00
Rob Bygrave 3e3647816d #2715 - [ebean-test-containers] Fix for Postgis to support extraDb (second database), Update Oracle container 2022-06-13 15:44:52 +12:00
Rob Bygrave 9aa7ae79e2 #2713 - Improve javadoc of Finder, BeanFinder, BeanRepository - deprecate use of BeanFinder server field (migrate to database) 2022-06-09 13:26:48 +12:00
Rob Bygrave 168c940b79 #2712 - Bump jedis to 4.2.3 (from 4.2.2) 2022-06-09 12:29:52 +12:00
Rob Bygrave 1ee18a1823 #2711 - Gradle: Change querybean generator from isolating to aggregating 2022-06-09 12:26:36 +12:00
Rob BygraveandGitHub c02ab7340c Merge pull request #2708 from FOCONIS/fix-localtime
Part 1: Fix read/write/query LocalTime values
2022-06-09 12:00:06 +12:00
Rob BygraveandGitHub c67773505d Merge pull request #2706 from FOCONIS/findsingleattributeset
ENH: Add support for findSingleAttributeSet()
2022-06-09 11:50:04 +12:00
Noemi Praml 9c354919e5 refactoring
(cherry picked from commit 43e28c4f5c747cdda2e3547a8db593eab490ceec)
2022-05-31 10:49:09 +02:00
Noemi Praml c8be59fd95 it fixes the test
(cherry picked from commit d2e21aa3dcbd4ae59dd8d1ff5404d94c298f087b)
2022-05-31 10:47:32 +02:00
Noemi Praml d1a40b4739 failing test 2022-05-31 10:47:08 +02:00
Noemi Praml bb9cfe9d0f add support for findSingleAttributeSet 2022-05-24 11:09:56 +02:00
Rob Bygrave ede2ad4d54 Bump test modules to 13.6.4-SNAPSHOT after release 2022-05-24 14:01:05 +12:00
Rob Bygrave 1060503fe1 [maven-release-plugin] prepare for next development iteration 2022-05-24 13:46:16 +12:00
Rob Bygrave 2edfc33d00 [maven-release-plugin] prepare release ebean-parent-13.6.3 2022-05-24 13:46:09 +12:00
Rob Bygrave 37902c75eb Bump ebean-agent to 13.6.3 2022-05-24 13:41:13 +12:00
Rob BygraveandGitHub 14abb34739 Merge pull request #2704 from ebean-orm/feature/2702-renameTable
#2702 - IllegalArgumentException: No rule for io.ebeaninternal.dbmigration.migration.RenameTable
2022-05-24 10:55:11 +12:00
Rob Bygrave 68680ffd34 #2702 - IllegalArgumentException: No rule for io.ebeaninternal.dbmigration.migration.RenameTable
Add support for applying the RenameTable change to the model.
2022-05-24 10:48:38 +12:00
Rob Bygrave 8106ffd73d #2703 - Bump ebean-test-containers to 6.0 (Java 11 and System.Logger) 2022-05-24 10:20:04 +12:00
Rob BygraveandGitHub d00cb854fc Merge pull request #2703 from ebean-orm/feature/ebean-test-containers
ebean-test-docker was renamed to ebean-test-containers
2022-05-24 09:03:22 +12:00
Rob Bygrave ca445b5226 ebean-test-docker was renamed to ebean-test-containers
- Migrate from io.ebean:ebean-test-docker -> io.ebean:ebean-test-containers
- Migrate (with 5.8) package from io.ebean.docker.commands -> io.ebean.test.containers
2022-05-24 08:54:58 +12:00
Rob Bygrave 74b4994221 #2701 -[DDL] Postgres DDL generation for table partitioning with schema - helper method to add partitions does not work
This also removes the helper partition_init() stored function as it isn't really needed now that postgres has default partition support (since PG11 actually, partition_init predates PG11).
2022-05-23 20:39:45 +12:00
Rob Bygrave 62106935f4 Bump test modules to 13.6.3-SNAPSHOT after release 2022-05-18 21:01:40 +12:00
Rob Bygrave bf034eb2a1 Bump test modules to 13.6.3-SNAPSHOT after release 2022-05-18 20:26:30 +12:00
Rob Bygrave c5e980991e [maven-release-plugin] prepare for next development iteration 2022-05-18 20:11:18 +12:00
Rob Bygrave 1004675a0b [maven-release-plugin] prepare release ebean-parent-13.6.2 2022-05-18 20:11:12 +12:00
Rob Bygrave 12e508ab48 Merge branch 'master' of github.com:ebean-orm/ebean 2022-05-18 18:25:38 +12:00
Rob Bygrave be0e1116a7 Bump ebean-agent to 13.6.2 2022-05-18 18:25:24 +12:00
Rob BygraveandGitHub 4b03c8a00a Merge pull request #2698 from ebean-orm/feature/tidy-beancollection
No effective change - tidy BeanList etc, BeanCollectionHelpFactory to use specific CQueryCollectionAdd for List and Set
2022-05-18 18:03:09 +12:00
Rob Bygrave 0db93bc82d No effective change - tidy BeanList etc, BeanCollectionHelpFactory to use specific CQueryCollectionAdd for List and Set 2022-05-18 17:33:08 +12:00
Rob Bygrave e04a1baabe Bump tile enhancement to 13.6.0 2022-05-18 15:35:38 +12:00
Rob BygraveandGitHub 506e2f5625 Merge pull request #2697 from ebean-orm/feature/postgres-table-partitioning-pk
Postgres DDL - With Postgres table partitioning, add partition column to primary key
2022-05-17 22:18:55 +12:00
Rob Bygrave 7fbc1f8111 Postgres DDL - With Postgres table partitioning, add partition column to primary key
- Postgres DDL generation
- Using table partitioning
- There is a primary key defined that doesn't contain the partition column

In DDL generation, automatically add the partition column to the DB primary key.
2022-05-17 21:39:06 +12:00
Rob Bygrave 4f3c9adf6f #2695 - DDL Generation for @UniqueConstraint ignores the name - should be the index name when given 2022-05-16 22:06:14 +12:00
Rob Bygrave ceac2d12b1 #2694 - Postgres DDL - For Postgres table partitioning, remove the "suppressPrimaryKeyOnPartition" mode 2022-05-16 21:48:19 +12:00
Rob Bygrave cc7f3d49a4 No effective change, tidy whitespace 2022-05-16 21:35:46 +12:00
Rob BygraveandGitHub 091c40867e Merge pull request #2693 from ebean-orm/feature/add-schema-support
DDL - Add support for creating schema via database migrations (and create all ddl)
2022-05-16 21:28:59 +12:00
Rob Bygrave 71b7aa5946 DDL - Add support for creating schema via database migrations (and create all ddl)
Initially for H2 and Postgres, with commented out DDL for other platforms.
2022-05-16 21:17:41 +12:00
Rob Bygrave 9dea51b7a0 #2692 - [querybean generation] Compile error, incorrect generation with nested inner class/record @Embeddable and @IdClass 2022-05-16 18:48:42 +12:00
Rob Bygrave b7d6374370 Improve error message when no platform providers are in the classpath 2022-05-16 18:47:48 +12:00
Rob Bygrave 195cb9c86c Adjust postgis build test container - use specific containerName 2022-05-16 16:36:32 +12:00
Rob Bygrave 1329a4775c Bump test modules to 13.6.2-SNAPSHOT after release 2022-05-16 12:35:41 +12:00
Rob Bygrave cc91ca5c2a [maven-release-plugin] prepare for next development iteration 2022-05-16 12:22:31 +12:00
Rob Bygrave c863fe7781 [maven-release-plugin] prepare release ebean-parent-13.6.1 2022-05-16 12:22:25 +12:00
Rob Bygrave 8dec17c1f3 Bump ebean-agent to 13.6.1 - #2687 2022-05-16 12:05:54 +12:00
Rob Bygrave 36d589d4f3 #2691 - Improve logging summary when insert bean with no @Id ... 2022-05-16 11:30:36 +12:00
Rob Bygrave dedafa0b93 Modify GH WF EA builds adding mvn --version ... for info on versions used for build 2022-05-13 13:58:13 +12:00
Rob BygraveandGitHub 7b91b9ec48 Merge pull request #2690 from ebean-orm/bug/orphan-collection-replacement
Bug - OneToMany orphanRemoval = true, replace collection adding back …
2022-05-13 12:13:19 +12:00
Rob BygraveandGitHub c5940dacf1 Merge pull request #2688 from ebean-orm/feature/test-docker-52
Bump to ebean-test-docker 5.3
2022-05-13 11:42:33 +12:00
Rob Bygrave a4df643d82 #2690 - Refactor internals, tidy SaveManyBeans
- Introduce hasOrderColumn field
- Add clearedParent flag to only clear the parent bean from persistence context once (not per detail bean)
2022-05-13 11:38:39 +12:00
Rob Bygrave 74174444bb Bug - OneToMany orphanRemoval = true, replace collection adding back original collection entry
- Adding back a bean from the original collection
- Expect that bean to exist in the final result but, it's missing

Fix here is in SaveManyBeans to add a insertAllChildren and use ebi.setNew(); for beans to force them to insert for this case.
2022-05-12 23:14:26 +12:00
Rob Bygrave 317ad8de9c Bump to ebean-test-docker 5.3
- Supports random ports
- Simplified shutdownMode
- Improved logging on shutdown
2022-05-12 18:43:38 +12:00
Rob Bygrave 4b260483ce Test only - Adjust timing in TestHistoryInsert.mariadb_simple_history() 2022-05-12 17:14:20 +12:00
Rob Bygrave 6a575cb1bf Change ebean-test postgis image to postgis/postgis from mdillon/postgis
- Also bump default version to 14
2022-05-12 17:05:23 +12:00
Rob Bygrave a13e1cf074 Bump to ebean-test-docker 5.2
- Supports random ports
- Simplified shutdownMode
2022-05-12 16:43:41 +12:00
Rob Bygrave c59475084a #2686 - [ebean-test] Allow docker configuration options to be at ebean.test.X as well as ebean.test.<platform>.X 2022-05-05 20:54:07 +12:00
Rob Bygrave f41704b58c #2685 - Bump ebean-test-docker to 5.1 with newBuilder() -> builder() with deprecation 2022-05-05 09:17:35 +12:00
Rob Bygrave 5bb9745b3c Bump to 13.6.1-SNAPSHOT after release 2022-05-03 15:36:03 +12:00
Rob Bygrave 1c072f1d0a [maven-release-plugin] prepare for next development iteration 2022-05-03 15:13:20 +12:00
Rob Bygrave bac7eb11bd [maven-release-plugin] prepare release ebean-parent-13.6.0 2022-05-03 15:13:13 +12:00
Rob Bygrave a8c2e4db3f Our release profile is now called "central" 2022-05-03 15:09:34 +12:00
Rob Bygrave 67a4e66b00 [maven-release-plugin] rollback the release of ebean-parent-13.6.0 2022-05-03 15:07:55 +12:00
Rob Bygrave 0d1d212f9f [maven-release-plugin] prepare for next development iteration 2022-05-03 14:59:36 +12:00
Rob Bygrave f44c77f5f5 [maven-release-plugin] prepare release ebean-parent-13.6.0 2022-05-03 14:59:29 +12:00
Rob Bygrave 65d07f4af9 Merge branch 'master' of github.com:ebean-orm/ebean 2022-05-03 14:48:52 +12:00
Rob Bygrave c74de4c221 Bump ebean-agent to 13.6.0 2022-05-03 14:48:38 +12:00
Rob BygraveandGitHub ebbef86def Merge pull request #2626 from ebean-orm/wip/EntityBeanIntercept-interface
Support EntityBeanIntercept as an interface with InterceptReadWrite and InterceptReadOnly options
2022-05-03 14:15:49 +12:00
Rob Bygrave 3fab465a13 #2649 - Bump avaje-config to 2.0 (uses System.Logger and not slf4j-api) 2022-05-03 13:50:22 +12:00
Rob BygraveandGitHub ff662bff58 Merge pull request #2683 from ebean-orm/feature/bump-datasource
Bump ebean-datasource to 8.0 with use of System.Logger (from slf4j-api)
2022-05-03 13:46:18 +12:00
Rob Bygrave cc7acd4761 Bump ebean-datasource to 8.0 with use of System.Logger (from slf4j-api) 2022-05-03 13:45:35 +12:00
Rob BygraveandGitHub 1365e39e94 Merge pull request #2681 from ebean-orm/feature/2647
#2647 - When Postgres + isAllQuotedIdentifiers true + using DataSourceConfig THEN `datasourceConfig.addProperty("quoteReturningIdentifiers", false);`
2022-05-03 13:38:10 +12:00
Rob BygraveandGitHub a73eb1c42f Merge pull request #2648 from ebean-orm/feature/bump-classpathscanner
Bump avaje classpath scanner to 7.1, ignores module-info, uses System.Logger (not slf4j-api)
2022-05-03 13:36:39 +12:00
Rob BygraveandGitHub 3f5a610df1 Merge pull request #2650 from ebean-orm/feature/bump-ddlrunner
Bump ebean-ddl-runner (sync version with ebean-migration)
2022-05-03 13:36:29 +12:00
Rob BygraveandGitHub d96e28991c Merge pull request #2682 from ebean-orm/feature/ebean-migration-system-logger
Bump ebean-migration to 13.6.0 (bumps classpath scanner and ebean-ddl-runner)
2022-05-03 13:36:16 +12:00
Rob Bygrave e84d12dad8 Bump ebean-migration to 13.6.0 (bumps classpath scanner and ebean-ddl-runner) 2022-05-03 13:30:09 +12:00
Rob Bygrave 1d4f2ad856 #2626 - Add final modifier to methods - For readOnly disableLazyLoad using Collections.EMPTY_LIST etc 2022-05-03 12:23:22 +12:00
Rob Bygrave 84042397b6 #2626 - For readOnly disableLazyLoad using Collections.EMPTY_LIST etc for reference collections 2022-05-03 12:12:47 +12:00
Rob Bygrave a70461d779 Update InterceptReadWrite with file content diff detection 2022-05-03 10:46:22 +12:00
Rob Bygrave d1b5400f2c Merge branch 'master' into wip/EntityBeanIntercept-interface 2022-05-03 10:45:45 +12:00
Rob Bygrave 244f336f54 #2647 - When Postgres + isAllQuotedIdentifiers true + using DataSourceConfig THEN datasourceConfig.addProperty("quoteReturningIdentifiers", false);
I think there is not a case where we do NOT want to do this. allQuotedIdentifiers + Postgres is almost not usable without this.
2022-05-03 10:15:07 +12:00
Rob Bygrave f92887b2f0 #2680 - Bump parent to java11-oss 3.8 which moves nexus-staging-maven-plugin and distributionManagement under "central" profile
This means that the nexus-staging-maven-plugin should not be used for forks looking to deploy into their own local nexus/archiva maven repo.
2022-05-03 09:06:27 +12:00
Rob Bygrave f49b93a845 Bump to 13.6.0-SNAPSHOT 2022-05-03 08:55:50 +12:00
Rob Bygrave a6f3a4f922 Bump to 13.6.0-SNAPSHOT 2022-05-03 08:37:29 +12:00
Rob Bygrave d6a65e4e66 Bump to 13.6.0-SNAPSHOT 2022-05-02 22:31:32 +12:00
Rob BygraveandGitHub ea5b4e9271 Merge pull request #2662 from ebean-orm/feature/deprecated-remove-Ebean
Remove deprecated Ebean, EbeanServer, EbeanServerFactory, ServerConfig migrate to DB, Database, DatabaseFactory, DatabaseConfig
2022-05-02 22:27:57 +12:00
Rob BygraveandGitHub ffa50b3176 Merge pull request #2679 from ebean-orm/feature/2677
#2677 - Fix for trim failing on mutation of lastAccessTime
2022-05-02 22:25:13 +12:00
Rob Bygrave 2cf83278ea #2677 - Change trimOnPut to be 10% of max or 1_000.
Can look to provide an explicit option via `@CacheBeanTuning` later.
2022-05-02 22:19:37 +12:00
Rob Bygrave 5c332286b6 #2677 - Add ReentrantLock for DefaultServerCache.runEviction() and trigger runEviction() via mutationCounter
If we get a lot of cache mutation (puts) between background trims then also trigger runEviction() in foreground using mutationCounter.
2022-05-02 21:48:58 +12:00
Rob Bygrave 1cd319c495 #2677 - Add try catch around DefaultServerCache.runEviction()
If there is an unexpected error we expect it to be temporary and want runEviction() to keep executing.
2022-05-02 20:51:33 +12:00
Rob BygraveandGitHub cec8a2e482 Merge pull request #2678 from focbenz/patch-1
Fixed typo Junit -> JUnit in README
2022-05-02 20:33:01 +12:00
Rob Bygrave d036edf7fd #2677 - Fix for trim failing on mutation of lastAccessTime
Currently, lastAccessTime can mutate during cache trim processing. This fixes this issue by taking a copy of the lastAccessTime storing as lastAccessSort and using that for sorting for cache trim.
2022-05-02 20:31:10 +12:00
Michael BenzandGitHub 2fefb5c7ef Merge branch 'ebean-orm:master' into patch-1 2022-05-02 10:10:34 +02:00
Michael BenzandGitHub 4278aa46f5 Junit -> JUnit
Just one more change ... verified in Intellij:
Junit -> JUnit
2022-05-02 10:08:46 +02:00
Rob BygraveandGitHub 7873a2b327 Merge pull request #2676 from focbenz/patch-1
Fix grammar in README.md
2022-05-02 20:08:04 +12:00
Rob BygraveandGitHub 9d3a3ddfeb Merge pull request #2675 from ebean-orm/feature/DefaultOrmQuery-final
Modify DefaultOrmQuery to have non-final copy() methods to allow ebean-mocker to be updated
2022-05-02 20:07:40 +12:00
Michael BenzandGitHub ac0b9aa025 Fix grammar in README.md
Just some grammatical fixes and uppercasings in README. No code changes here!
2022-05-02 08:40:34 +02:00
Rob Bygrave 4d4f8e2c4b Modify DefaultOrmQuery to have non-final copy() methods to allow ebean-mocker to be updated 2022-05-02 18:01:25 +12:00
Rob Bygrave 2b581fb148 Update README with details on building ebean from source 2022-05-02 16:36:59 +12:00
Rob BygraveandGitHub 35bd98c14f Merge pull request #2674 from ebean-orm/feature/ebean-test-container-5
Bump to ebean-test-docker 5.0-RC1
2022-05-02 16:36:02 +12:00
Rob Bygrave 8db9991ea3 Bump to ebean-test-docker 5.0 2022-05-02 16:04:42 +12:00
Rob Bygrave fac69f75d0 Bump to ebean-test-docker 5.0-RC2 2022-05-02 15:40:01 +12:00
Rob Bygrave b18226711b Bump to ebean-test-docker 5.0-RC1 2022-04-29 16:43:48 +12:00
Rob Bygrave 4bdb48d340 Bump to 13.5.1-SNAPSHOT after release 2022-04-28 17:58:58 +12:00
Rob Bygrave d2a742fefb [maven-release-plugin] prepare for next development iteration 2022-04-28 17:42:12 +12:00
Rob Bygrave 22de23ddf4 [maven-release-plugin] prepare release ebean-parent-13.5.0 2022-04-28 17:42:05 +12:00
Rob Bygrave 496d9674d2 #2672 - Bump ebean-agent to 13.5.0 for - ToStringBuilder enhancement does not use toString() of the abstract class 2022-04-28 10:50:34 +12:00
Rob Bygrave 4ece9fe6cc Bump to 13.5.0-SNAPSHOT 2022-04-28 10:46:14 +12:00
Rob Bygrave 62f162e4fb Bump to 13.5.0-SNAPSHOT 2022-04-28 10:44:56 +12:00
Rob Bygrave 38803aa7f8 Bump to 13.5.0-SNAPSHOT 2022-04-28 10:33:41 +12:00
Rob Bygrave f9943f14b7 Adjust test ebean.properties 2022-04-28 10:32:27 +12:00
Rob Bygrave 1b24c888ee Put back test jdbc driver for MariaDB ... need to look at changes in newer driver wrt forwardOnlyHintOnFindIterate
That is, forwardOnlyHintOnFindIterate is a hack to support poor MySql jdbc driver behavior but maybe we can remove this
hack in later versions of MariaDB at least
2022-04-27 23:13:28 +12:00
Rob Bygrave 45233e96ab #2673 - Bug introduced in 13.3.1 via #2652 - incorrect binding of history query with SQL2011 standards based queries 2022-04-27 22:48:02 +12:00
Rob Bygrave 517556bfe3 For sql server tests add jdbc parameters ;integratedSecurity=false;trustServerCertificate=true 2022-04-27 20:02:02 +12:00
Rob Bygrave 07101d1528 #2671 - Bump ebean-test-docker to 4.7 2022-04-27 19:53:52 +12:00
Rob Bygrave 9fa1def22b Bump test jdbc drivers 2022-04-27 18:43:27 +12:00
Rob Bygrave dd9d49cfa2 #2671 - Bump ebean-test-docker to 4.7 2022-04-27 18:39:49 +12:00
Rob Bygrave 7680a75ca9 Bump test modules to 13.4.2-SNAPSHOT after release 2022-04-27 09:48:13 +12:00
Rob Bygrave 786286421d [maven-release-plugin] prepare for next development iteration 2022-04-27 09:13:48 +12:00
Rob Bygrave b517551352 [maven-release-plugin] prepare release ebean-parent-13.4.1 2022-04-27 09:13:41 +12:00
Rob Bygrave 507ba7da1c Bump ebean-agent to 13.4.1 2022-04-27 09:09:48 +12:00
Rob Bygrave 835796f614 #2670 - Missing implementation of loadIgnore in ScalarTypePgisBase 2022-04-27 08:43:06 +12:00
Rob Bygrave ab9a6fb69a git push origin masterMerge branch 'FOCONIS-toString-with-map' 2022-04-27 08:35:38 +12:00
Jonas PöhlerandNoemi Szemenyei 4d7a3d135c FIX: StackOverflowError when using recursive relation within Map
(cherry picked from commit d06bc13b4e1e421546f4997900d5fdc6aa980257)
2022-04-26 13:53:51 +02:00
Rob Bygrave 937b15c07a Modify EA builds to use EA,GA rather than specific versions 2022-04-26 09:30:20 +12:00
Rob Bygrave 47cf81fef9 Bump test modules to 13.4.0-SNAPSHOT after release 2022-04-21 13:47:29 +12:00
Rob Bygrave b21123343f [maven-release-plugin] prepare for next development iteration 2022-04-21 13:30:00 +12:00
Rob Bygrave d34da06840 Remove deprecated Ebean, EbeanServer, EbeanServerFactory, ServerConfig migrate to DB, Database, DatabaseFactory, DatabaseConfig 2022-04-20 20:46:53 +12:00
Rob Bygrave 8432fa1320 Bump ebean-ddl-runner (sync version with ebean-migration) 2022-04-14 14:48:37 +12:00
Rob Bygrave 6b81dbbaa2 Bump avaje classpath scanner to 7.1, ignores module-info, uses System.Logger (not slf4j-api) 2022-04-14 12:40:49 +12:00
Rob BygraveandGitHub 9862526352 Merge branch 'master' into wip/EntityBeanIntercept-interface 2022-04-13 10:43:13 +12:00
Rob BygraveandGitHub 45003b3d5f Merge branch 'master' into wip/EntityBeanIntercept-interface 2022-04-12 21:09:58 +12:00
Rob Bygrave bed4721823 Bump ebean-agent to 13.0.1-RC2 with ASM 9.3 - support for Java 19 2022-04-06 16:28:44 +12:00
Rob Bygrave 307832edae Fix test modules in terms of enhancement plugins 2022-04-04 14:04:15 +12:00
Rob Bygrave 1f684107b6 Fix test modules in terms of enhancement plugins 2022-04-04 13:52:37 +12:00
Rob Bygrave 5ab02715ef Support EntityBeanIntercept as an interface with InterceptReadWrite and InterceptReadOnly options
With the view that we can optimise the readOnly + disableLazyLoad case by using InterceptReadOnly which doesn't need to support any of the flags used as part of mutation.
2022-04-04 13:30:26 +12:00
320 changed files with 6531 additions and 5682 deletions
+1 -1
View File
@@ -36,5 +36,5 @@ jobs:
# - name: Maven single test
# run: mvn --batch-mode clean verify -Dtest="io.ebeaninternal.server.core.DefaultServer_getReferenceTest" -DfailIfNoTests=false
- name: Build with Maven
run: mvn clean package
run: mvn -T 8 clean test
+1 -1
View File
@@ -35,4 +35,4 @@ jobs:
~/.m2
key: build-${{ env.cache-name }}
- name: db2
run: mvn clean test -Dprops.file=testconfig/ebean-db2.properties
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-db2.properties
+1 -1
View File
@@ -37,5 +37,5 @@ jobs:
- name: Maven version
run: mvn --version
- name: H2Database
run: mvn clean package
run: mvn -T 8 clean package
+1 -1
View File
@@ -35,5 +35,5 @@ jobs:
~/.m2
key: build-${{ env.cache-name }}
- name: Build with Maven
run: mvn package
run: mvn -T 8 test
+4 -2
View File
@@ -18,7 +18,7 @@ jobs:
matrix:
## valhalla - failing on javadoc with:
## javadoc: error - The code being documented uses packages in the unnamed module, but the packages defined in https://ebean.io/platforms/ebean-platform-h2/apidocs/ are in named modules.
java_version: [17,18,19,loom,metropolis,panama]
java_version: [GA,EA,loom,metropolis,panama]
os: [ubuntu-latest]
steps:
@@ -36,6 +36,8 @@ jobs:
path:
~/.m2
key: build-${{ env.cache-name }}
- name: Maven version
run: mvn --version
- name: Build with Maven
run: mvn package
run: mvn -T 8 test
+1 -1
View File
@@ -35,4 +35,4 @@ jobs:
~/.m2
key: build-${{ env.cache-name }}
- name: mariadb 10.6
run: mvn clean test -Dprops.file=testconfig/ebean-mariadb.properties
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-mariadb.properties
+1 -1
View File
@@ -35,4 +35,4 @@ jobs:
~/.m2
key: build-${{ env.cache-name }}
- name: mysql
run: mvn clean test -Dprops.file=testconfig/ebean-mysql.properties
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-mysql.properties
@@ -1,5 +1,5 @@
name: Oracle18
name: Oracle
on:
workflow_dispatch:
@@ -35,4 +35,4 @@ jobs:
~/.m2
key: build-${{ env.cache-name }}
- name: oracle
run: mvn clean test -Dprops.file=testconfig/ebean-oracle.properties
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-oracle.properties
+1 -1
View File
@@ -35,4 +35,4 @@ jobs:
~/.m2
key: build-${{ env.cache-name }}
- name: postgres
run: mvn clean test -Dprops.file=testconfig/ebean-postgres.properties
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-postgres.properties
+1 -1
View File
@@ -35,4 +35,4 @@ jobs:
~/.m2
key: build-${{ env.cache-name }}
- name: sqlserver 2017
run: mvn clean test -Dprops.file=testconfig/ebean-sqlserver17.properties
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-sqlserver17.properties
+31 -1
View File
@@ -8,6 +8,7 @@
[![Postgres](https://github.com/ebean-orm/ebean/actions/workflows/postgres.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/postgres.yml)
[![MySql](https://github.com/ebean-orm/ebean/actions/workflows/mysql.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/mysql.yml)
[![MariaDB](https://github.com/ebean-orm/ebean/actions/workflows/mariadb.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/mariadb.yml)
[![Oracle](https://github.com/ebean-orm/ebean/actions/workflows/oracle.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/oracle.yml)
[![SqlServer](https://github.com/ebean-orm/ebean/actions/workflows/sqlserver.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/sqlserver.yml)
[![Yugabyte](https://github.com/ebean-orm/ebean/actions/workflows/yugabyte.yml/badge.svg)](https://github.com/ebean-orm/ebean/actions/workflows/yugabyte.yml)
@@ -55,9 +56,38 @@ Post questions or issues to the Ebean google group - https://groups.google.com/f
## Documentation
Goto [https://ebean.io/docs/](https://ebean.io/docs/)
## Maven central
[Maven central - io.ebean](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22io.ebean%22%20)
## Building Ebean from source
- JDK 11 or higher installed
- Maven installed
- `git clone git@github.com:ebean-orm/ebean.git`
- `mvn clean install`
Ebean 13 uses Java modules with module-info. This means that there are stricter compilation
rules in place now than when building with classpath pre version 13.
For Maven Surefire testing we use `<surefire.useModulePath>false</surefire.useModulePath>` such
that tests run using classpath and not module-path. We are doing this until all the tooling
(Maven, IDE) improves in the area of testing with module-info.
#### Eclipse IDE
Right now we can't use Eclipse IDE to build Ebean and run its tests due to its poor support
for java modules. See [ebean/issues/2653](https://github.com/ebean-orm/ebean/issues/2653)
The current recommendation is to use IntelliJ IDEA as the IDE to build and hack Ebean.
#### IntelliJ IDEA
We want to get IntelliJ to run tests using classpath similar to Maven Surefire. To do this set:
`JUnit -> modify options -> Do not use module-path option`
To set this option as the global default for IntelliJ use:
`Run - Edit Configurations -> Edit configuration templates -> JUnit -> modify options - Do not use module-path option`
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.4.0</version>
<version>13.6.5</version>
</parent>
<name>ebean-clickhouse</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-clickhouse</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.4.0</tag>
<tag>ebean-parent-13.6.5</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.4.0</version>
<version>13.6.5</version>
</parent>
<name>ebean-cockroach</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.4.0</tag>
<tag>ebean-parent-13.6.5</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.4.0</version>
<version>13.6.5</version>
</parent>
<name>ebean-db2</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-db2</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.4.0</tag>
<tag>ebean-parent-13.6.5</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.4.0</version>
<version>13.6.5</version>
</parent>
<name>ebean-h2</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.4.0</tag>
<tag>ebean-parent-13.6.5</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.4.0</version>
<version>13.6.5</version>
</parent>
<name>ebean-hana</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-hana</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.4.0</tag>
<tag>ebean-parent-13.6.5</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.4.0</version>
<version>13.6.5</version>
</parent>
<name>ebean-mariadb</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mariadb</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.4.0</tag>
<tag>ebean-parent-13.6.5</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.4.0</version>
<version>13.6.5</version>
</parent>
<name>ebean-mysql</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-mysql</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.4.0</tag>
<tag>ebean-parent-13.6.5</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.4.0</version>
<version>13.6.5</version>
</parent>
<name>ebean-nuodb</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-nuodb</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.4.0</tag>
<tag>ebean-parent-13.6.5</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.4.0</version>
<version>13.6.5</version>
</parent>
<name>ebean-oracle</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-oracle</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.4.0</tag>
<tag>ebean-parent-13.6.5</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.4.0</version>
<version>13.6.5</version>
</parent>
<name>ebean-postgres</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.4.0</tag>
<tag>ebean-parent-13.6.5</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.4.0</version>
<version>13.6.5</version>
</parent>
<name>ebean-sqlite</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlite</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.4.0</tag>
<tag>ebean-parent-13.6.5</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.4.0</version>
<version>13.6.5</version>
</parent>
<name>ebean-sqlserver</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlserver</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.4.0</tag>
<tag>ebean-parent-13.6.5</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.4.0</version>
<version>13.6.5</version>
</parent>
<name>ebean-yugabyte</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.4.0</tag>
<tag>ebean-parent-13.6.5</tag>
</scm>
</project>
+6 -6
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>composites</artifactId>
<groupId>io.ebean</groupId>
<version>13.4.0</version>
<version>13.6.5</version>
</parent>
<name>ebean (all platforms)</name>
@@ -16,13 +16,13 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
@@ -35,18 +35,18 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-all</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
</dependencies>
<scm>
<tag>ebean-parent-13.4.0</tag>
<tag>ebean-parent-13.6.5</tag>
</scm>
</project>
+1 -1
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.4.0</version>
<version>13.6.5</version>
</parent>
<artifactId>composites</artifactId>
+23 -4
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.4.0</version>
<version>13.6.5</version>
</parent>
<name>ebean api</name>
@@ -20,14 +20,14 @@
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
<version>1.7.36</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-config</artifactId>
<version>1.7</version>
<version>2.1</version>
</dependency>
<!--
@@ -37,7 +37,7 @@
<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-lang</artifactId>
<version>1.0</version>
<version>1.1</version>
</dependency>
<dependency>
@@ -103,4 +103,23 @@
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/ebean-maven-version.txt</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<excludes>
<exclude>**/ebean-maven-version.txt</exclude>
</excludes>
</resource>
</resources>
</build>
</project>
@@ -12,6 +12,7 @@ import java.util.Optional;
* </p>
* <pre>{@code
*
* @Component
* public class CustomerFinder extends BeanFinder<Long,Customer> {
*
* @Inject
@@ -26,29 +27,37 @@ import java.util.Optional;
*
* @param <I> The ID type
* @param <T> The Bean type
*
* @see BeanRepository
*/
@NonNullApi
public abstract class BeanFinder<I,T> {
/**
* Migrate to using database rather than server.
*/
@Deprecated
protected final Database server;
protected final Database database;
protected final Class<T> type;
/**
* Create with the given bean type and Database instance.
*
* @param type The bean type
* @param server The Database instance typically created via Spring factory or equivalent.
* @param database The Database instance typically created via Spring factory or equivalent.
*/
protected BeanFinder(Class<T> type, Database server) {
protected BeanFinder(Class<T> type, Database database) {
this.type = type;
this.server = server;
this.database = database;
this.server = database;
}
/**
* Return the Database to use.
*/
public Database db() {
return server;
return database;
}
/**
@@ -70,10 +79,10 @@ public abstract class BeanFinder<I,T> {
* <p>
* This is equivalent to {@link DB#byName(String)}
*
* @param server The name of the Database. If this is null then the default Database is returned.
* @param name The name of the Database. If this is null then the default Database is returned.
*/
public Database db(String server) {
return DB.byName(server);
public Database db(String name) {
return DB.byName(name);
}
/**
@@ -6,11 +6,15 @@ import io.ebean.bean.EntityBean;
import java.util.Collection;
/**
* Provides finder functionality for use with "Dependency Injection style" use of Ebean.
* Provides find and persist functionality for use with "Dependency Injection style" use of Ebean.
* <p>
* Extend the BeanRepository with additional finder and persisting methods as needed by the
* application. The intention is to keep all the related logic together, for example, all the
* persisting and finding logic for Customer would be in CustomerRepository.
*
* <pre>{@code
*
* @Repository
* @Component
* public class CustomerRepository extends BeanRepository<Long,Customer> {
*
* @Inject
@@ -50,10 +54,10 @@ public abstract class BeanRepository<I, T> extends BeanFinder<I, T> {
* }</pre>
*
* @param type The bean type
* @param server The Database instance typically created via Spring factory or equivalent
* @param database The Database instance typically created via Spring factory or equivalent
*/
protected BeanRepository(Class<T> type, Database server) {
super(type, server);
protected BeanRepository(Class<T> type, Database database) {
super(type, database);
}
/**
@@ -122,8 +126,8 @@ public abstract class BeanRepository<I, T> extends BeanFinder<I, T> {
/**
* Save all the beans in the collection.
*/
public int saveAll(Collection<T> bean) {
return db().saveAll(bean);
public int saveAll(Collection<T> beans) {
return db().saveAll(beans);
}
/**
File diff suppressed because it is too large Load Diff
@@ -1,15 +0,0 @@
package io.ebean;
/**
* Deprecated - please migrate to <code>io.ebean.Database</code>.
* Provides the API for fetching and saving beans to a particular Database.
* <p>
* Effectively this is an alias for {@link Database} which is now the new
* and improved name for EbeanServer.
* <p>
* The preference is to use DB and Database rather than Ebean and EbeanServer.
*/
@Deprecated
public interface EbeanServer extends Database {
}
@@ -1,70 +0,0 @@
package io.ebean;
import io.ebean.config.ContainerConfig;
import io.ebean.config.ServerConfig;
/**
* Deprecated - please migrate to DatabaseFactory.
* <p>
* Creates EbeanServer instances.
* <p>
* This uses either a ServerConfig or properties in the ebean.properties file to
* configure and create a EbeanServer instance.
* </p>
* <p>
* The EbeanServer instance can either be registered with the Ebean singleton or
* not. The Ebean singleton effectively holds a map of EbeanServers by a name.
* If the EbeanServer is registered with the Ebean singleton you can retrieve it
* later via {@link Ebean#getServer(String)}.
* </p>
* <p>
* One EbeanServer can be nominated as the 'default/primary' EbeanServer. Many
* methods on the Ebean singleton such as {@link Ebean#find(Class)} are just a
* convenient way of using the 'default/primary' EbeanServer.
* </p>
*/
@Deprecated
public class EbeanServerFactory {
/**
* Initialise the container with clustering configuration.
* <p>
* Call this prior to creating any EbeanServer instances or alternatively set the
* ContainerConfig on the ServerConfig when creating the first EbeanServer instance.
*/
public static void initialiseContainer(ContainerConfig containerConfig) {
DatabaseFactory.initialiseContainer(containerConfig);
}
/**
* Create using ebean.properties to configure the database.
*/
public static EbeanServer create(String name) {
return (EbeanServer)DatabaseFactory.create(name);
}
/**
* Create using the ServerConfig object to configure the database.
*/
public static EbeanServer create(ServerConfig config) {
return (EbeanServer)DatabaseFactory.create(config);
}
/**
* Create using the ServerConfig additionally specifying a classLoader to use as the context class loader.
*/
public static EbeanServer createWithContextClassLoader(ServerConfig config, ClassLoader classLoader) {
return (EbeanServer)DatabaseFactory.createWithContextClassLoader(config, classLoader);
}
/**
* Shutdown gracefully all EbeanServers cleaning up any resources as required.
* <p>
* This is typically invoked via JVM shutdown hook and not explicitly called.
* </p>
*/
public static void shutdown() {
DatabaseFactory.shutdown();
}
}
@@ -3,8 +3,7 @@ package io.ebean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.*;
import java.util.Properties;
/**
@@ -29,9 +28,11 @@ public final class EbeanVersion {
private static void readVersion() {
try {
try (InputStream in = ClassLoader.getSystemResourceAsStream("META-INF/maven/io.ebean/ebean-api/pom.properties")) {
try (InputStream in = ClassLoader.getSystemResourceAsStream("META-INF/ebean-maven-version.txt")) {
if (in != null) {
version = readVersion(in);
try (LineNumberReader reader = new LineNumberReader(new InputStreamReader(in))) {
version = reader.readLine();
}
}
}
log.info("ebean version: {}", version);
@@ -88,7 +89,7 @@ public final class EbeanVersion {
}
/**
* Returns the ebean version (read from /META-INF/maven/io.ebean/ebean/pom.properties)
* Returns the ebean version (read from META-INF/ebean-maven-version.txt)
*/
public static String getVersion() {
return version;
@@ -383,6 +383,15 @@ public interface ExpressionList<T> {
*/
<A> List<A> findSingleAttributeList();
/**
* Executes the query returning a set of values for a single property.
*
* This can be used to cache sets.
*
* @return a HashSet of values for the selegted property
*/
<A> Set<A> findSingleAttributeSet();
/**
* Execute a query returning a single value of a single property/column.
* <pre>{@code
@@ -368,6 +368,11 @@ public interface ExtendedServer {
*/
<A, T> List<A> findSingleAttributeList(Query<T> query, Transaction transaction);
/**
* Execute the query returning a hashset of values for a single property.
*/
<A, T> Set<A> findSingleAttributeSet(Query<T> query, Transaction transaction);
/**
* Execute the query returning at most one entity bean or null (if no matching
* bean is found).
@@ -8,6 +8,9 @@ import java.util.List;
* Intended to be used as a base class for 'Finder' implementations that can then
* be injected or used as public static fields on the associated entity bean.
* <p>
* When using dependency injection {@link BeanRepository} and {@link BeanFinder}
* are expected to be used rather than this Finder.
* <p>
* These 'finders' are a place to organise all the finder methods for that bean type
* and specific finder methods are expected to be added (find by unique properties etc).
* </p>
@@ -54,6 +57,8 @@ import java.util.List;
*
* }</pre>
*
* @see BeanRepository
* @see BeanFinder
*/
@NonNullApi
public class Finder<I, T> {
@@ -925,6 +925,11 @@ public interface Query<T> extends CancelableQuery {
*/
<A> List<A> findSingleAttributeList();
/**
* Execute the query returning a hashset of values for a single property.
*/
<A> Set<A> findSingleAttributeSet();
/**
* Execute a query returning a single value of a single property/column.
* <p>
@@ -34,6 +34,13 @@ public interface EntityBean extends Serializable, ToStringAware {
throw new NotEnhancedException();
}
/**
* Create and return a new entity bean instance optimised for read only no interception use.
*/
default Object _ebean_newInstanceReadOnly() {
throw new NotEnhancedException();
}
/**
* Generated method that sets the loaded state on all the embedded beans on
* this entity bean by using EntityBeanIntercept.setEmbeddedLoaded(Object o);
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,536 @@
package io.ebean.bean;
import io.ebean.ValuePair;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
public class InterceptReadOnly implements EntityBeanIntercept {
private final EntityBean owner;
public InterceptReadOnly(Object ownerBean) {
this.owner = (EntityBean) ownerBean;
}
@Override
public EntityBean getOwner() {
return owner;
}
@Override
public PersistenceContext getPersistenceContext() {
return null;
}
@Override
public void setPersistenceContext(PersistenceContext persistenceContext) {
}
@Override
public void setNodeUsageCollector(NodeUsageCollector usageCollector) {
}
@Override
public Object getOwnerId() {
return null;
}
@Override
public void setOwnerId(Object ownerId) {
}
@Override
public Object getEmbeddedOwner() {
return null;
}
@Override
public int getEmbeddedOwnerIndex() {
return 0;
}
@Override
public void clearGetterCallback() {
}
@Override
public void registerGetterCallback(PreGetterCallback getterCallback) {
}
@Override
public void setEmbeddedOwner(EntityBean parentBean, int embeddedOwnerIndex) {
}
@Override
public void setBeanLoader(BeanLoader beanLoader, PersistenceContext ctx) {
}
@Override
public void setBeanLoader(BeanLoader beanLoader) {
}
@Override
public boolean isFullyLoadedBean() {
return false;
}
@Override
public void setFullyLoadedBean(boolean fullyLoadedBean) {
}
@Override
public boolean isPartial() {
return false;
}
@Override
public boolean isDirty() {
return false;
}
@Override
public void setEmbeddedDirty(int embeddedProperty) {
}
@Override
public void setDirty(boolean dirty) {
}
@Override
public boolean isNew() {
return false;
}
@Override
public boolean isNewOrDirty() {
return false;
}
@Override
public boolean hasIdOnly(int idIndex) {
return false;
}
@Override
public boolean isReference() {
return false;
}
@Override
public void setReference(int idPos) {
}
@Override
public void setLoadedFromCache(boolean loadedFromCache) {
}
@Override
public boolean isLoadedFromCache() {
return false;
}
@Override
public boolean isReadOnly() {
return true;
}
@Override
public void setReadOnly(boolean readOnly) {
}
@Override
public void setForceUpdate(boolean forceUpdate) {
}
@Override
public boolean isUpdate() {
return false;
}
@Override
public boolean isLoaded() {
return true;
}
@Override
public void setNew() {
}
@Override
public void setLoaded() {
}
@Override
public void setLoadedLazy() {
}
@Override
public void setLazyLoadFailure(Object ownerId) {
}
@Override
public boolean isLazyLoadFailure() {
return false;
}
@Override
public boolean isDisableLazyLoad() {
return false;
}
@Override
public void setDisableLazyLoad(boolean disableLazyLoad) {
}
@Override
public void setEmbeddedLoaded(Object embeddedBean) {
}
@Override
public boolean isEmbeddedNewOrDirty(Object embeddedBean) {
return false;
}
@Override
public Object getOrigValue(int propertyIndex) {
return null;
}
@Override
public int findProperty(String propertyName) {
return 0;
}
@Override
public String getProperty(int propertyIndex) {
return null;
}
@Override
public int getPropertyLength() {
return 0;
}
@Override
public void setPropertyLoaded(String propertyName, boolean loaded) {
}
@Override
public void setPropertyUnloaded(int propertyIndex) {
}
@Override
public void setLoadedProperty(int propertyIndex) {
}
@Override
public void setLoadedPropertyAll() {
}
@Override
public boolean isLoadedProperty(int propertyIndex) {
return false;
}
@Override
public boolean isChangedProperty(int propertyIndex) {
return false;
}
@Override
public boolean isDirtyProperty(int propertyIndex) {
return false;
}
@Override
public void markPropertyAsChanged(int propertyIndex) {
}
@Override
public void setChangedProperty(int propertyIndex) {
}
@Override
public void setChangeLoaded(int propertyIndex) {
}
@Override
public void setEmbeddedPropertyDirty(int propertyIndex) {
}
@Override
public void setOriginalValue(int propertyIndex, Object value) {
}
@Override
public void setOriginalValueForce(int propertyIndex, Object value) {
}
@Override
public void setNewBeanForUpdate() {
}
@Override
public Set<String> getLoadedPropertyNames() {
return Collections.emptySet();
}
@Override
public boolean[] getDirtyProperties() {
return new boolean[0];
}
@Override
public Set<String> getDirtyPropertyNames() {
return Collections.emptySet();
}
@Override
public void addDirtyPropertyNames(Set<String> props, String prefix) {
}
@Override
public boolean hasDirtyProperty(Set<String> propertyNames) {
return false;
}
@Override
public Map<String, ValuePair> getDirtyValues() {
return Collections.emptyMap();
}
@Override
public void addDirtyPropertyValues(Map<String, ValuePair> dirtyValues, String prefix) {
}
@Override
public void addDirtyPropertyValues(BeanDiffVisitor visitor) {
}
@Override
public StringBuilder getDirtyPropertyKey() {
return null;
}
@Override
public void addDirtyPropertyKey(StringBuilder sb) {
}
@Override
public StringBuilder getLoadedPropertyKey() {
return null;
}
@Override
public boolean[] getLoaded() {
return new boolean[0];
}
@Override
public int getLazyLoadPropertyIndex() {
return 0;
}
@Override
public String getLazyLoadProperty() {
return null;
}
@Override
public void loadBean(int loadProperty) {
}
@Override
public void loadBeanInternal(int loadProperty, BeanLoader loader) {
}
@Override
public void initialisedMany(int propertyIndex) {
}
@Override
public void preGetterCallback(int propertyIndex) {
}
@Override
public void preGetId() {
}
@Override
public void preGetter(int propertyIndex) {
}
@Override
public void preSetterMany(boolean interceptField, int propertyIndex, Object oldValue, Object newValue) {
}
@Override
public void setChangedPropertyValue(int propertyIndex, boolean setDirtyState, Object origValue) {
}
@Override
public void setDirtyStatus() {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, Object oldValue, Object newValue) {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, boolean oldValue, boolean newValue) {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, int oldValue, int newValue) {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, long oldValue, long newValue) {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, double oldValue, double newValue) {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, float oldValue, float newValue) {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, short oldValue, short newValue) {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, char oldValue, char newValue) {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, byte oldValue, byte newValue) {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, char[] oldValue, char[] newValue) {
}
@Override
public void preSetter(boolean intercept, int propertyIndex, byte[] oldValue, byte[] newValue) {
}
@Override
public void setOldValue(int propertyIndex, Object oldValue) {
}
@Override
public int getSortOrder() {
return 0;
}
@Override
public void setSortOrder(int sortOrder) {
}
@Override
public void setDeletedFromCollection(boolean deletedFromCollection) {
}
@Override
public boolean isOrphanDelete() {
return false;
}
@Override
public void setLoadError(int propertyIndex, Exception t) {
}
@Override
public Map<String, Exception> getLoadErrors() {
return null;
}
@Override
public boolean isChangedProp(int i) {
return false;
}
@Override
public MutableValueInfo mutableInfo(int propertyIndex) {
return null;
}
@Override
public void mutableInfo(int propertyIndex, MutableValueInfo info) {
}
@Override
public void mutableNext(int propertyIndex, MutableValueNext next) {
}
@Override
public String mutableNext(int propertyIndex) {
return null;
}
}
File diff suppressed because it is too large Load Diff
@@ -1,7 +1,10 @@
package io.ebean.bean;
import io.ebean.common.BeanMap;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.Map;
/**
* Helps build toString content taking into account recursion.
@@ -104,6 +107,8 @@ public final class ToStringBuilder {
}
} else if (value instanceof Collection) {
addCollection((Collection<?>) value);
} else if (value instanceof Map) {
addMap(((Map<?, ?>) value));
} else {
String content = String.valueOf(value);
if (content.length() > TRIM_LENGTH) {
@@ -117,6 +122,28 @@ public final class ToStringBuilder {
}
}
public void addMap(Map<?,?> map) {
if (map == null || map.isEmpty()) {
sb.append("{}");
} else {
boolean firstElement = true;
sb.append("{");
for (Map.Entry<?, ?> entry : map.entrySet()) {
if (firstElement) {
firstElement = false;
} else {
sb.append(", ");
}
sb.append(entry.getKey()).append(":");
value(entry.getValue());
if (counter > MAX) {
return;
}
}
sb.append("}");
}
}
/**
* Add a collection of values.
*/
@@ -29,9 +29,10 @@ public final class TenantAwareCache implements ServerCache {
/**
* Return the underlying ServerCache that is being delegated to.
*/
@SuppressWarnings("unchecked")
@Override
public <T> T unwrap(Class<T> cls) {
return (T)delegate;
return (T) delegate;
}
@Override
@@ -17,39 +17,28 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
private static final long serialVersionUID = 3365725236140187588L;
protected final ReentrantLock lock = new ReentrantLock();
protected boolean readOnly;
protected boolean disableLazyLoad;
/**
* The Database this is associated with. (used for lazy fetch).
*/
protected transient BeanCollectionLoader loader;
protected transient ExpressionList<?> filterMany;
/**
* Flag set when registered with the batch loading context.
*/
protected boolean registeredWithLoadContext;
protected String ebeanServerName;
/**
* The owning bean (used for lazy fetch).
*/
protected EntityBean ownerBean;
/**
* The name of this property in the owning bean (used for lazy fetch).
*/
protected String propertyName;
protected ModifyHolder<E> modifyHolder;
protected ModifyListenMode modifyListenMode;
protected boolean modifyListening;
/**
@@ -126,8 +115,7 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
void checkReadOnly() {
if (readOnly) {
String msg = "This collection is in ReadOnly mode";
throw new IllegalStateException(msg);
throw new IllegalStateException("This collection is in ReadOnly mode");
}
}
@@ -11,7 +11,7 @@ import java.util.List;
import java.util.ListIterator;
/**
* List capable of lazy loading.
* List capable of lazy loading and modification awareness.
*/
public final class BeanList<E> extends AbstractBeanCollection<E> implements List<E>, BeanCollectionAdd {
@@ -150,7 +150,6 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
* Set the actual underlying list.
* <p>
* This is primarily for the deferred fetching function.
* </p>
*/
@SuppressWarnings("unchecked")
public void setActualList(List<?> list) {
@@ -206,12 +205,11 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
* Specifically obj does not need to be a BeanList but any list. This does not
* use the FindMany, fetchedMaxRows or finishedFetch properties in the equals
* test.
* </p>
*/
@Override
public boolean equals(Object obj) {
public boolean equals(Object other) {
init();
return list.equals(obj);
return list.equals(other);
}
@Override
@@ -244,40 +242,40 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
}
@Override
public boolean add(E o) {
public boolean add(E bean) {
checkReadOnly();
init();
if (modifyListening) {
if (list.add(o)) {
modifyAddition(o);
if (list.add(bean)) {
modifyAddition(bean);
return true;
} else {
return false;
}
}
return list.add(o);
return list.add(bean);
}
@Override
public boolean addAll(Collection<? extends E> c) {
public boolean addAll(Collection<? extends E> beans) {
checkReadOnly();
init();
if (modifyListening) {
// all elements in c are added (no contains checking)
getModifyHolder().modifyAdditionAll(c);
getModifyHolder().modifyAdditionAll(beans);
}
return list.addAll(c);
return list.addAll(beans);
}
@Override
public boolean addAll(int index, Collection<? extends E> c) {
public boolean addAll(int index, Collection<? extends E> beans) {
checkReadOnly();
init();
if (modifyListening) {
// all elements in c are added (no contains checking)
getModifyHolder().modifyAdditionAll(c);
getModifyHolder().modifyAdditionAll(beans);
}
return list.addAll(index, c);
return list.addAll(index, beans);
}
@Override
@@ -287,23 +285,23 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
// and fetch just the Id's
initClear();
if (modifyListening) {
for (E aList : list) {
getModifyHolder().modifyRemoval(aList);
for (E element : list) {
getModifyHolder().modifyRemoval(element);
}
}
list.clear();
}
@Override
public boolean contains(Object o) {
public boolean contains(Object bean) {
init();
return list.contains(o);
return list.contains(bean);
}
@Override
public boolean containsAll(Collection<?> c) {
public boolean containsAll(Collection<?> beans) {
init();
return list.containsAll(c);
return list.containsAll(beans);
}
@Override
@@ -313,9 +311,9 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
}
@Override
public int indexOf(Object o) {
public int indexOf(Object bean) {
init();
return list.indexOf(o);
return list.indexOf(bean);
}
@Override
@@ -327,31 +325,29 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
@Override
public Iterator<E> iterator() {
init();
if (isReadOnly()) {
if (readOnly) {
return new ReadOnlyListIterator<>(list.listIterator());
}
if (modifyListening) {
Iterator<E> it = list.iterator();
return new ModifyIterator<>(this, it);
return new ModifyIterator<>(this, list.iterator());
}
return list.iterator();
}
@Override
public int lastIndexOf(Object o) {
public int lastIndexOf(Object bean) {
init();
return list.lastIndexOf(o);
return list.lastIndexOf(bean);
}
@Override
public ListIterator<E> listIterator() {
init();
if (isReadOnly()) {
if (readOnly) {
return new ReadOnlyListIterator<>(list.listIterator());
}
if (modifyListening) {
ListIterator<E> it = list.listIterator();
return new ModifyListIterator<>(this, it);
return new ModifyListIterator<>(this, list.listIterator());
}
return list.listIterator();
}
@@ -359,12 +355,11 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
@Override
public ListIterator<E> listIterator(int index) {
init();
if (isReadOnly()) {
if (readOnly) {
return new ReadOnlyListIterator<>(list.listIterator(index));
}
if (modifyListening) {
ListIterator<E> it = list.listIterator(index);
return new ModifyListIterator<>(this, it);
return new ModifyListIterator<>(this, list.listIterator(index));
}
return list.listIterator(index);
}
@@ -389,17 +384,17 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
}
@Override
public boolean remove(Object o) {
public boolean remove(Object bean) {
checkReadOnly();
init();
if (modifyListening) {
boolean isRemove = list.remove(o);
boolean isRemove = list.remove(bean);
if (isRemove) {
modifyRemoval(o);
modifyRemoval(bean);
}
return isRemove;
}
return list.remove(o);
return list.remove(bean);
}
@Override
@@ -463,7 +458,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
@Override
public List<E> subList(int fromIndex, int toIndex) {
init();
if (isReadOnly()) {
if (readOnly) {
return Collections.unmodifiableList(list.subList(fromIndex, toIndex));
}
if (modifyListening) {
@@ -479,13 +474,13 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
}
@Override
public <T> T[] toArray(T[] a) {
public <T> T[] toArray(T[] array) {
init();
//noinspection SuspiciousToArrayCall
return list.toArray(a);
return list.toArray(array);
}
private static class ReadOnlyListIterator<E> implements ListIterator<E>, Serializable {
private static final class ReadOnlyListIterator<E> implements ListIterator<E>, Serializable {
private static final long serialVersionUID = 3097271091406323699L;
@@ -12,7 +12,7 @@ import java.util.Map;
import java.util.Set;
/**
* Map capable of lazy loading.
* Map capable of lazy loading and modification aware.
*/
public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Map<K, E> {
@@ -247,7 +247,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
@Override
public Set<Entry<K, E>> entrySet() {
init();
if (isReadOnly()) {
if (readOnly) {
return Collections.unmodifiableSet(map.entrySet());
}
return modifyListening ? new ModifyEntrySet<>(this, map.entrySet()) : map.entrySet();
@@ -268,7 +268,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
@Override
public Set<K> keySet() {
init();
if (isReadOnly()) {
if (readOnly) {
return Collections.unmodifiableSet(map.keySet());
}
return modifyListening ? new ModifyKeySet<>(this, map.keySet()) : map.keySet();
@@ -339,7 +339,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
@Override
public Collection<E> values() {
init();
if (isReadOnly()) {
if (readOnly) {
return Collections.unmodifiableCollection(map.values());
}
return modifyListening ? new ModifyCollection<>(this, map.values()) : map.values();
@@ -9,7 +9,7 @@ import java.util.LinkedHashSet;
import java.util.Set;
/**
* Set capable of lazy loading.
* Set capable of lazy loading and modification aware.
*/
public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E>, BeanCollectionAdd {
@@ -210,27 +210,27 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
// -----------------------------------------------------//
@Override
public boolean add(E o) {
public boolean add(E bean) {
checkReadOnly();
init();
if (modifyListening) {
if (set.add(o)) {
modifyAddition(o);
if (set.add(bean)) {
modifyAddition(bean);
return true;
} else {
return false;
}
}
return set.add(o);
return set.add(bean);
}
@Override
public boolean addAll(Collection<? extends E> addCollection) {
public boolean addAll(Collection<? extends E> beans) {
checkReadOnly();
init();
if (modifyListening) {
boolean changed = false;
for (E bean : addCollection) {
for (E bean : beans) {
if (set.add(bean)) {
// register the addition of the bean
modifyAddition(bean);
@@ -239,7 +239,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
}
return changed;
}
return set.addAll(addCollection);
return set.addAll(beans);
}
@Override
@@ -255,15 +255,15 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
}
@Override
public boolean contains(Object o) {
public boolean contains(Object bean) {
init();
return set.contains(o);
return set.contains(bean);
}
@Override
public boolean containsAll(Collection<?> c) {
public boolean containsAll(Collection<?> beans) {
init();
return set.containsAll(c);
return set.containsAll(beans);
}
@Override
@@ -275,7 +275,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
@Override
public Iterator<E> iterator() {
init();
if (isReadOnly()) {
if (readOnly) {
return new ReadOnlyIterator<>(set.iterator());
}
if (modifyListening) {
@@ -285,17 +285,17 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
}
@Override
public boolean remove(Object o) {
public boolean remove(Object bean) {
checkReadOnly();
init();
if (modifyListening) {
if (set.remove(o)) {
modifyRemoval(o);
if (set.remove(bean)) {
modifyRemoval(bean);
return true;
}
return false;
}
return set.remove(o);
return set.remove(bean);
}
@Override
@@ -349,13 +349,13 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
}
@Override
public <T> T[] toArray(T[] a) {
public <T> T[] toArray(T[] array) {
init();
//noinspection SuspiciousToArrayCall
return set.toArray(a);
return set.toArray(array);
}
private static class ReadOnlyIterator<E> implements Iterator<E>, Serializable {
private static final class ReadOnlyIterator<E> implements Iterator<E>, Serializable {
private static final long serialVersionUID = 2577697326745352605L;
@@ -1,47 +0,0 @@
package io.ebean.config;
import io.ebean.DatabaseFactory;
/**
* Deprecated - please migrate to <code>io.ebean.DatabaseConfig</code>.
*
* The configuration used for creating a Database.
* <p>
* Used to programmatically construct a Database and optionally register it
* with the DB singleton.
* </p>
* <p>
* If you just use DB without this programmatic configuration DB 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
*
* ServerConfig config = new ServerConfig();
*
* // read the ebean.properties and load
* // those settings into this serverConfig object
* config.loadFromProperties();
*
* // explicitly register the entity beans to avoid classpath scanning
* config.addClass(Customer.class);
* config.addClass(User.class);
*
* Database database = DatabaseFactory.create(config);
*
* }</pre>
*
* <p>
* Note that ServerConfigProvider provides a standard Java ServiceLoader mechanism that can
* be used to apply configuration to the ServerConfig.
* </p>
*
* @author emcgreal
* @author rbygrave
* @see DatabaseFactory
*/
@Deprecated
public class ServerConfig extends DatabaseConfig {
}
@@ -1,41 +0,0 @@
package io.ebean.config;
/**
* Deprecated - migrate to DatabaseConfigProvider.
* <p>
* Provides a ServiceLoader based mechanism to configure a ServerConfig.
* <p>
* Provide an implementation and register it via the standard Java ServiceLoader mechanism
* via a file at <code>META-INF/services/io.ebean.config.ServerConfigProvider</code>.
* <p>
* If you are using a DI container like Spring or Guice you are unlikely to use this but instead use a
* spring specific configuration. When we are not using a DI container we may use this mechanism to
* explicitly register the entity beans and avoid classpath scanning.
* </p>
* <pre>{@code
*
* public class EbeanConfigProvider implements ServerConfigProvider {
*
* @Override
* public void apply(ServerConfig config) {
*
* // register the entity bean classes explicitly
* config.addClass(Customer.class);
* config.addClass(User.class);
* ...
* }
* }
*
* }</pre>
*/
@Deprecated
public interface ServerConfigProvider {
/**
* Apply the configuration to the ServerConfig.
* <p>
* Typically we explicitly register entity bean classes and thus avoid classpath scanning.
* </p>
*/
void apply(ServerConfig config);
}
@@ -802,20 +802,6 @@ public class DatabasePlatform {
}
}
/**
* Return true if partitions exist for the given table.
*/
public boolean tablePartitionsExist(Connection connection, String table) throws SQLException {
return true;
}
/**
* Return the SQL to create an initial partition for the given table.
*/
public String tablePartitionInit(String tableName, PartitionMode mode, String property, String singlePrimaryKey) {
return null;
}
/**
* Escapes the like string for this DB-Platform
*/
@@ -63,7 +63,6 @@ public final class SplitName {
}
private static String[] split(String name, boolean last) {
int pos = last ? name.lastIndexOf('.') : name.indexOf('.');
if (pos == -1) {
if (last) {
@@ -0,0 +1 @@
${project.version}
@@ -166,12 +166,76 @@ class ToStringBuilderTest {
assertThat(toStringFor(list)).isEqualTo("{a:Recurse@1(id:1, nm:a), b:Recurse@2(id:2, nm:b)}");
}
@Test
void map_recurse() {
final ParamStore paramStore = new ParamStore(1);
paramStore.map.put("aaa", new ParamValue(1, paramStore));
paramStore.map.put("bbb", new ParamValue(2, paramStore));
assertThat(toStringFor(paramStore))
.isEqualTo("ParamStore@0(id:1, map:{aaa:ParamValue@1(id:1, pm:ParamStore@0), bbb:ParamValue@2(id:2, pm:ParamStore@0)})");
}
private String toStringFor(ToStringAware aware) {
ToStringBuilder builder = new ToStringBuilder();
aware.toString(builder);
return builder.toString();
}
static final class ParamValue implements ToStringAware {
final int id;
final ParamStore parentModel;
ParamValue(final int id, final ParamStore parentModel) {
this.id = id;
this.parentModel = parentModel;
}
public String toString() {
ToStringBuilder builder = new ToStringBuilder();
toString(builder);
return builder.toString();
}
@Override
public void toString(ToStringBuilder builder) {
builder.start(this);
builder.add("id", id);
builder.add("pm", parentModel);
builder.end();
}
}
static final class ParamStore implements ToStringAware {
final int id;
final Map<String, ParamValue> map = new HashMap<>();
ParamStore(final int id) {
this.id = id;
}
public String toString() {
ToStringBuilder builder = new ToStringBuilder();
toString(builder);
return builder.toString();
}
@Override
public void toString(ToStringBuilder builder) {
builder.start(this);
builder.add("id", id);
builder.add("map", map);
builder.end();
}
}
static final class Recurse implements ToStringAware {
final int id;
+5 -5
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.4.0</version>
<version>13.6.5</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.4.0</tag>
<tag>ebean-parent-13.6.5</tag>
</scm>
<name>ebean autotune</name>
@@ -26,7 +26,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
<scope>provided</scope>
</dependency>
@@ -55,7 +55,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
<scope>test</scope>
</dependency>
@@ -70,7 +70,7 @@
<extensions>true</extensions>
<configuration>
<tiles>
<tile>io.ebean.tile:enhancement:13.3.0</tile>
<tile>io.ebean.tile:enhancement:13.6.5</tile>
</tiles>
</configuration>
</plugin>
@@ -143,6 +143,7 @@ public class BaseQueryTuner {
switch (type) {
case COUNT:
case ATTRIBUTE:
case ATTRIBUTE_SET:
case ID_LIST:
case UPDATE:
case DELETE:
+17 -17
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.4.0</version>
<version>13.6.5</version>
</parent>
<name>ebean bom</name>
@@ -62,8 +62,8 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test-docker</artifactId>
<version>${ebean-test-docker.version}</version>
<artifactId>ebean-test-containers</artifactId>
<version>${ebean-test-containers.version}</version>
</dependency>
<!-- modules -->
@@ -71,88 +71,88 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-ddl-generator</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-externalmapping-api</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-externalmapping-xml</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-autotune</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>querybean-generator</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>kotlin-querybean-generator</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgis</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-redis</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
</dependencies>
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.4.0</version>
<version>13.6.5</version>
</parent>
<artifactId>ebean-core-type</artifactId>
@@ -16,7 +16,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
@@ -16,25 +16,24 @@ import java.sql.SQLException;
* <p>
* Scalar in the sense that the types are not compound types. Scalar types only
* map to a single database column.
* </p>
* <p>
* These types fall into two categories. Types that are mapped natively to JDBC
* types and the rest. Types that map to native JDBC types do not require any
* data type conversion to be persisted to the database. These are java types
* that map via java.sql.Types.
* </p>
* <p>
* Types that are not native to JDBC require some conversion. These include some
* common java types such as java.util.Date, java.util.Calendar,
* java.math.BigInteger.
* </p>
* <p>
* Note that Booleans may be native for some databases and require conversion on
* other databases.
* </p>
*/
public interface ScalarType<T> extends StringParser, StringFormatter, ScalarDataReader<T> {
/**
* Return true for types that do mutation detection based on json content.
*/
default boolean isJsonMapper() {
return false;
}
@@ -43,38 +42,40 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
* Return true if this is a binary type and can not support parse() and format() from/to string.
* This allows Ebean to optimise marshalling types to string.
*/
boolean isBinaryType();
default boolean isBinaryType() {
return false;
}
/**
* Return true if this is a mutable scalar type (like hstore).
*/
boolean isMutable();
default boolean isMutable() {
return false;
}
/**
* For mutable scalarType's return true if the value is dirty.
* Non-dirty properties may be excluded from updates.
*/
boolean isDirty(Object value);
default boolean isDirty(Object value) {
return false;
}
/**
* Return the default DB column length for this type.
* <p>
* If a BeanProperty has no explicit length defined then this length should
* be assigned.
* </p>
* <p>
* This is primarily to support defining a length on Enum types (to
* supplement defining the length on the BeanProperty directly).
* </p>
*/
int getLength();
default int getLength() {
return 0;
}
/**
* Return true if the type is native to JDBC.
* <p>
* If it is native to JDBC then its values/instances do not need to be
* converted to and from an associated JDBC type.
* </p>
*/
boolean isJdbcNative();
@@ -83,16 +84,13 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
* <p>
* This type should be consistent with the toJdbcType() method in converting
* the type to the appropriate type for binding to preparedStatements.
* </p>
*/
int getJdbcType();
/**
* Return the type that matches the bean property type.
* <p>
* This represents the 'logical' type rather than the JDBC type this maps
* to.
* </p>
* This represents the 'logical' type rather than the JDBC type this maps to.
*/
Class<T> getType();
@@ -104,7 +102,7 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
T read(DataReader reader) throws SQLException;
/**
* Ignore the reading of this value. Typically this means moving the index
* Ignore the reading of this value. Typically, this means moving the index
* position in the ResultSet.
*/
void loadIgnore(DataReader reader);
@@ -114,20 +112,16 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
* <p>
* value may need to be converted from the logical bean property type to the
* JDBC type.
* </p>
*/
void bind(DataBinder binder, T value) throws SQLException;
/**
* Convert the value as necessary to the JDBC type.
* <p>
* Note that this should also match the type as per the getJdbcType()
* method.
* </p>
* Note that this should also match the type as per the getJdbcType() method.
* <p>
* This is typically used when the matching type is used in a where clause
* and we use this to ensure it is an appropriate jdbc type.
* </p>
*/
Object toJdbcType(Object value);
@@ -135,19 +129,14 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
* Convert the value as necessary to the logical Bean type.
* <p>
* The type as per the bean property.
* </p>
* <p>
* This is used to automatically convert id values (typically from a string
* to a int, long or UUID).
* </p>
*/
T toBeanType(Object value);
/**
* Convert the type into a string representation.
* <p>
* Reciprocal of parse().
* </p>
*/
String formatValue(T value);
@@ -155,10 +144,8 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
* Convert the type into a string representation.
* <p>
* This assumes the value is of the correct type.
* </p>
* <p>
* This is so that ScalarType also implements the StringFormatter interface.
* </p>
*/
@Override
String format(Object value);
@@ -167,10 +154,6 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
* Convert the string value to the appropriate java object.
* <p>
* Mostly used to support CSV, JSON and XML parsing.
* </p>
* <p>
* Reciprocal of formatValue().
* </p>
*/
@Override
T parse(String value);
@@ -183,29 +166,32 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
/**
* Return true if the type can accept long systemTimeMillis input.
* <p>
* This is used to determine if is is sensible to use the
* This is used to determine if it is sensible to use the
* {@link #convertFromMillis(long)} method.
* </p>
* <p>
* This includes the Date, Calendar, sql Date, Time, Timestamp, JODA types
* as well as Long, BigDecimal and String (although it generally is not
* expected to parse systemTimeMillis to a String or BigDecimal).
* </p>
*/
boolean isDateTimeCapable();
default boolean isDateTimeCapable() {
return false;
}
/**
* Convert the value into a long version value.
*/
long asVersion(T value);
default long asVersion(T value) {
throw new UnsupportedOperationException();
}
/**
* Convert the systemTimeMillis into the appropriate java object.
* <p>
* For non dateTime types this will throw an exception.
* </p>
*/
T convertFromMillis(long dateTime);
default T convertFromMillis(long dateTime) {
throw new UnsupportedOperationException();
}
/**
* Read the value from binary input.
@@ -215,7 +201,7 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
/**
* Write the value to binary output.
*/
void writeData(DataOutput dataOutput, T v) throws IOException;
void writeData(DataOutput dataOutput, T value) throws IOException;
/**
* Read the value from JsonParser.
+9 -9
View File
@@ -3,7 +3,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>13.4.0</version>
<version>13.6.5</version>
</parent>
<artifactId>ebean-core</artifactId>
@@ -15,7 +15,7 @@
<scm>
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
<tag>ebean-parent-13.4.0</tag>
<tag>ebean-parent-13.6.5</tag>
</scm>
<dependencies>
@@ -29,7 +29,7 @@
<dependency>
<groupId>io.avaje</groupId>
<artifactId>classpath-scanner</artifactId>
<version>6.2</version>
<version>7.1</version>
</dependency>
<dependency>
@@ -41,19 +41,19 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-externalmapping-api</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
</dependency>
<dependency>
@@ -144,21 +144,21 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-h2</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-postgres</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-platform-sqlserver</artifactId>
<version>13.4.0</version>
<version>13.6.5</version>
<scope>test</scope>
</dependency>
@@ -23,7 +23,7 @@ import java.util.stream.Stream;
/**
* Service Provider extension to EbeanServer.
*/
public interface SpiEbeanServer extends SpiServer, ExtendedServer, EbeanServer, BeanCollectionLoader {
public interface SpiEbeanServer extends SpiServer, ExtendedServer, BeanCollectionLoader {
/**
* Return true if the L2 cache has been disabled.
@@ -55,7 +55,6 @@ public interface SpiEbeanServer extends SpiServer, ExtendedServer, EbeanServer,
* <p>
* Typically used to identify the origin of queries for AutoTune and object
* graph costing.
* </p>
*/
CallOrigin createCallOrigin();
@@ -92,6 +92,11 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
*/
ATTRIBUTE(FIND_ATTRIBUTE, "findAttribute", false, false),
/**
* Find single attribute set.
*/
ATTRIBUTE_SET(FIND_ATTRIBUTE_SET, "findAttributeSet", false, false),
/**
* Find rowCount.
*/
@@ -28,6 +28,7 @@ public interface TxnProfileEventCodes {
String FIND_ID_LIST = "fi";
String FIND_EXISTS = "ex";
String FIND_ATTRIBUTE = "fa";
String FIND_ATTRIBUTE_SET = "fas";
String FIND_COUNT = "fc";
String FIND_SUBQUERY = "fs";
@@ -13,6 +13,8 @@ import java.io.Serializable;
import java.lang.ref.SoftReference;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
/**
* The default cache implementation.
@@ -43,10 +45,13 @@ public class DefaultServerCache implements ServerCache {
protected final String name;
protected final String shortName;
private final int maxSize;
private final int trimFrequency;
private final int maxIdleSecs;
private final int maxSecsToLive;
protected final int maxSize;
protected final int trimFrequency;
protected final int maxIdleSecs;
protected final int maxSecsToLive;
protected final long trimOnPut;
protected final ReentrantLock lock = new ReentrantLock();
protected final AtomicLong mutationCounter = new AtomicLong();
public DefaultServerCache(DefaultServerCacheConfig config) {
this.name = config.getName();
@@ -56,6 +61,7 @@ public class DefaultServerCache implements ServerCache {
this.maxIdleSecs = config.getMaxIdleSecs();
this.maxSecsToLive = config.getMaxSecsToLive();
this.trimFrequency = config.determineTrimFrequency();
this.trimOnPut = config.determineTrimOnPut();
MetricFactory factory = MetricFactory.get();
String prefix = "l2n.";
@@ -187,6 +193,9 @@ public class DefaultServerCache implements ServerCache {
public void put(Object key, Object value) {
map.put(key, new SoftReference<>(new CacheEntry(key, value)));
putCount.increment();
if (mutationCounter.incrementAndGet() > trimOnPut) {
runEviction();
}
}
/**
@@ -222,62 +231,72 @@ public class DefaultServerCache implements ServerCache {
* Run the eviction based on Idle time, Time to live and LRU last access.
*/
public void runEviction() {
long trimForMaxSize;
if (maxSize == 0) {
trimForMaxSize = 0;
} else {
trimForMaxSize = size() - maxSize;
}
if (maxIdleSecs == 0 && maxSecsToLive == 0 && trimForMaxSize < 0) {
// nothing to trim on this cache
return;
}
long startNanos = System.nanoTime();
long trimmedByIdle = 0;
long trimmedByGC = 0;
long trimmedByTTL = 0;
long trimmedByLRU = 0;
List<CacheEntry> activeList = new ArrayList<>(map.size());
long idleExpireNano = startNanos - TimeUnit.SECONDS.toNanos(maxIdleSecs);
long ttlExpireNano = startNanos - TimeUnit.SECONDS.toNanos(maxSecsToLive);
Iterator<SoftReference<CacheEntry>> it = map.values().iterator();
while (it.hasNext()) {
SoftReference<CacheEntry> ref = it.next();
final CacheEntry cacheEntry = ref.get();
if (cacheEntry == null) {
it.remove();
trimmedByGC++;
} else if (maxIdleSecs > 0 && idleExpireNano > cacheEntry.getLastAccessTime()) {
it.remove();
trimmedByIdle++;
} else if (maxSecsToLive > 0 && ttlExpireNano > cacheEntry.getCreateTime()) {
it.remove();
trimmedByTTL++;
} else if (trimForMaxSize > 0) {
activeList.add(cacheEntry);
lock.lock();
try {
long trimForMaxSize;
if (maxSize == 0) {
trimForMaxSize = 0;
} else {
trimForMaxSize = size() - maxSize;
}
}
if (trimForMaxSize > 0 && activeList.size() > maxSize) {
// sort into last access time ascending
activeList.sort(BY_LAST_ACCESS);
int trimSize = getTrimSize();
for (int i = trimSize; i < activeList.size(); i++) {
// remove if still in the cache
if (map.remove(activeList.get(i).getKey()) != null) {
trimmedByLRU++;
if (maxIdleSecs == 0 && maxSecsToLive == 0 && trimForMaxSize < 0) {
// nothing to trim on this cache
mutationCounter.set(0);
return;
}
long startNanos = System.nanoTime();
long trimmedByIdle = 0;
long trimmedByGC = 0;
long trimmedByTTL = 0;
long trimmedByLRU = 0;
try {
List<CacheEntry> activeList = new ArrayList<>(map.size());
long idleExpireNano = startNanos - TimeUnit.SECONDS.toNanos(maxIdleSecs);
long ttlExpireNano = startNanos - TimeUnit.SECONDS.toNanos(maxSecsToLive);
Iterator<SoftReference<CacheEntry>> it = map.values().iterator();
while (it.hasNext()) {
SoftReference<CacheEntry> ref = it.next();
final CacheEntry cacheEntry = ref.get();
if (cacheEntry == null) {
it.remove();
trimmedByGC++;
} else if (maxIdleSecs > 0 && idleExpireNano > cacheEntry.getLastAccessTime()) {
it.remove();
trimmedByIdle++;
} else if (maxSecsToLive > 0 && ttlExpireNano > cacheEntry.getCreateTime()) {
it.remove();
trimmedByTTL++;
} else if (trimForMaxSize > 0) {
activeList.add(cacheEntry.forSort());
}
}
if (trimForMaxSize > 0 && activeList.size() > maxSize) {
// sort into last access time ascending
activeList.sort(BY_LAST_ACCESS);
int trimSize = getTrimSize();
for (int i = trimSize; i < activeList.size(); i++) {
// remove if still in the cache
if (map.remove(activeList.get(i).getKey()) != null) {
trimmedByLRU++;
}
}
}
mutationCounter.set(0);
evictCount.add(trimmedByIdle);
evictCount.add(trimmedByGC);
evictCount.add(trimmedByTTL);
evictCount.add(trimmedByLRU);
if (logger.isTraceEnabled()) {
long exeMicros = TimeUnit.MICROSECONDS.convert(System.nanoTime() - startNanos, TimeUnit.NANOSECONDS);
logger.trace("Executed trim of cache {} in [{}]millis idle[{}] timeToLive[{}] accessTime[{}] gc[{}]",
name, exeMicros, trimmedByIdle, trimmedByTTL, trimmedByLRU, trimmedByGC);
}
} catch (Throwable e) {
logger.warn("Error during trim of DefaultServerCache [" + name + "]. Cache might be bigger than desired.", e);
}
}
evictCount.add(trimmedByIdle);
evictCount.add(trimmedByGC);
evictCount.add(trimmedByTTL);
evictCount.add(trimmedByLRU);
if (logger.isTraceEnabled()) {
long exeMicros = TimeUnit.MICROSECONDS.convert(System.nanoTime() - startNanos, TimeUnit.NANOSECONDS);
logger.trace("Executed trim of cache {} in [{}]millis idle[{}] timeToLive[{}] accessTime[{}] gc[{}]",
name, exeMicros, trimmedByIdle, trimmedByTTL, trimmedByLRU, trimmedByGC);
} finally {
lock.unlock();
}
}
@@ -293,7 +312,7 @@ public class DefaultServerCache implements ServerCache {
}
/**
* Comparator for sorting by last access time.
* Comparator for sorting by last access sort, a copy of last access time that should not mutate during trim processing.
*/
public static final class CompareByLastAccess implements Comparator<CacheEntry>, Serializable {
@@ -301,7 +320,7 @@ public class DefaultServerCache implements ServerCache {
@Override
public int compare(CacheEntry e1, CacheEntry e2) {
return Long.compare(e1.getLastAccessTime(), e2.getLastAccessTime());
return Long.compare(e1.lastAccessSort, e2.lastAccessSort);
}
}
@@ -314,6 +333,7 @@ public class DefaultServerCache implements ServerCache {
private final Object value;
private final long createTime;
private long lastAccessTime;
private long lastAccessSort;
public CacheEntry(Object key, Object value) {
this.key = key;
@@ -322,6 +342,14 @@ public class DefaultServerCache implements ServerCache {
this.lastAccessTime = createTime;
}
/**
* Store a copy of lastAccessTime used for sorting. This value should not change during trim processing.
*/
public CacheEntry forSort() {
this.lastAccessSort = lastAccessTime;
return this;
}
/**
* Return the entry key.
*/
@@ -76,4 +76,14 @@ public final class DefaultServerCacheConfig {
}
return 0;
}
/**
* Determine the number of mutations/puts required to trigger a runEviction() in the foreground.
*/
public long determineTrimOnPut() {
if (maxSize > 0) {
return maxSize / 10;
}
return 1000;
}
}
@@ -1,6 +1,6 @@
package io.ebeaninternal.server.cluster;
import io.ebean.EbeanServer;
import io.ebean.Database;
import io.ebean.config.ContainerConfig;
import io.ebeaninternal.server.transaction.RemoteTransactionEvent;
import org.slf4j.Logger;
@@ -20,7 +20,7 @@ public class ClusterManager implements ServerLookup {
private final ReentrantLock lock = new ReentrantLock();
private final ConcurrentHashMap<String, EbeanServer> serverMap = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, Database> serverMap = new ConcurrentHashMap<>();
private final Object monitor = new Object();
@@ -53,7 +53,7 @@ public class ClusterManager implements ServerLookup {
return factory;
}
public void registerServer(EbeanServer server) {
public void registerServer(Database server) {
lock.lock();
try {
serverMap.put(server.name(), server);
@@ -66,7 +66,7 @@ public class ClusterManager implements ServerLookup {
}
@Override
public EbeanServer getServer(String name) {
public Database getServer(String name) {
lock.lock();
try {
return serverMap.get(name);
@@ -1,14 +1,14 @@
package io.ebeaninternal.server.cluster;
import io.ebean.EbeanServer;
import io.ebean.Database;
/**
* Returns EbeanServer instances for remote message reading.
* Returns Database instances for remote message reading.
*/
public interface ServerLookup {
/**
* Return the EbeanServer instance by name.
*/
EbeanServer getServer(String name);
Database getServer(String name);
}
@@ -93,6 +93,11 @@ public class DatabasePlatformFactory {
return provider.create(majorVersion, minorVersion, metaData, connection);
}
}
if (providers.isEmpty()) {
throw new IllegalStateException("There are no ebean platform providers in the classpath. " +
"Add a missing dependency like ebean-h2, ebean-postgres, ebean-mysql etc to support the database [" + dbProductName
+ "]. Adding a dependency on io.ebean:ebean will add support for all platforms.");
}
throw new IllegalStateException("Unable to determine the appropriate ebean platform given database product name [" + dbProductName
+ "] and ebean platform providers " + providers + ". With ebean 13+ we now have separate platforms (ebean-postgres, ebean-mysql etc)"
+ " and should use database specific platform dependency like ebean-postgres. Note that we can use ebean-platform-all to include"
@@ -5,8 +5,6 @@ import io.ebean.config.ContainerConfig;
import io.ebean.config.DatabaseConfig;
import io.ebean.config.DatabaseConfigProvider;
import io.ebean.config.ModuleInfoLoader;
import io.ebean.config.ServerConfig;
import io.ebean.config.ServerConfigProvider;
import io.ebean.config.TenantMode;
import io.ebean.config.UnderscoreNamingConvention;
import io.ebean.config.dbplatform.DatabasePlatform;
@@ -124,15 +122,8 @@ public final class DefaultContainer implements SpiContainer {
private void applyConfigServices(DatabaseConfig config) {
if (config.isDefaultServer()) {
boolean appliedConfig = false;
for (DatabaseConfigProvider configProvider : ServiceLoader.load(DatabaseConfigProvider.class)) {
configProvider.apply(config);
appliedConfig = true;
}
if (!appliedConfig && config instanceof ServerConfig) {
for (ServerConfigProvider configProvider : ServiceLoader.load(ServerConfigProvider.class)) {
configProvider.apply((ServerConfig)config);
}
}
}
if (config.isAutoLoadModuleInfo()) {
@@ -1193,7 +1193,23 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
try {
request.initTransIfRequired();
return request.findSingleAttributeList();
return request.findSingleAttributeCollection(new ArrayList<>());
} finally {
request.endTransIfRequired();
}
}
@Override
@SuppressWarnings("unchecked")
public <A, T> Set<A> findSingleAttributeSet(Query<T> query, Transaction transaction) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ATTRIBUTE_SET, query, transaction);
Object result = request.getFromQueryCache();
if (result != null) {
return (Set<A>) result;
}
try {
request.initTransIfRequired();
return request.findSingleAttributeCollection(new LinkedHashSet<>());
} finally {
request.endTransIfRequired();
}
@@ -1,5 +1,6 @@
package io.ebeaninternal.server.core;
import io.ebean.annotation.Platform;
import io.ebean.config.DatabaseConfig;
import io.ebean.datasource.DataSourceAlertFactory;
import io.ebean.datasource.DataSourceConfig;
@@ -97,10 +98,16 @@ final class InitDataSource {
dsConfig.setReadOnly(true);
dsConfig.setDefaults(config.getDataSourceConfig());
dsConfig.setIsolationLevel(config.getDataSourceConfig().getIsolationLevel());
} else if (isPostgresAllQuotedIdentifiers()) {
dsConfig.addProperty("quoteReturningIdentifiers", false);
}
return create(dsConfig, readOnly);
}
boolean isPostgresAllQuotedIdentifiers() {
return config.isAllQuotedIdentifiers() && Platform.POSTGRES == config.getDatabasePlatform().getPlatform().base();
}
private DataSource create(DataSourceConfig dsConfig, boolean readOnly) {
String poolName = config.getName() + (readOnly ? "-ro" : "");
return DataSourceFactory.create(poolName, dsConfig);
@@ -6,6 +6,7 @@ import io.ebean.bean.BeanCollection;
import javax.persistence.PersistenceException;
import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
/**
@@ -29,9 +30,9 @@ public interface OrmQueryEngine {
<T> BeanCollection<T> findMany(OrmQueryRequest<T> request);
/**
* Execute the findSingleAttributeList query.
* Execute the findSingleAttributeCollection query.
*/
<A> List<A> findSingleAttributeList(OrmQueryRequest<?> request);
<A extends Collection<?>> A findSingleAttributeCollection(OrmQueryRequest<?> request, A collection);
/**
* Execute the findVersions query.
@@ -431,8 +431,8 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
}
@Override
public <A> List<A> findSingleAttributeList() {
return queryEngine.findSingleAttributeList(this);
public <A extends Collection<?>> A findSingleAttributeCollection(A collection) {
return queryEngine.findSingleAttributeCollection(this, collection);
}
/**
@@ -9,25 +9,12 @@ import io.ebean.event.BeanPersistController;
import io.ebean.event.BeanPersistListener;
import io.ebean.event.BeanPersistRequest;
import io.ebean.event.changelog.BeanChange;
import io.ebeaninternal.api.ConcurrencyMode;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.SpiProfileTransactionEvent;
import io.ebeaninternal.api.SpiTransaction;
import io.ebeaninternal.api.TransactionEvent;
import io.ebeaninternal.api.*;
import io.ebeaninternal.server.cache.CacheChangeSet;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.BeanManager;
import io.ebeaninternal.server.deploy.BeanProperty;
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
import io.ebeaninternal.server.deploy.BeanPropertyAssocOne;
import io.ebeaninternal.server.deploy.*;
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedProperty;
import io.ebeaninternal.server.deploy.id.ImportedId;
import io.ebeaninternal.server.persist.BatchControl;
import io.ebeaninternal.server.persist.BatchedSqlException;
import io.ebeaninternal.server.persist.DeleteMode;
import io.ebeaninternal.server.persist.Flags;
import io.ebeaninternal.server.persist.PersistExecute;
import io.ebeaninternal.server.persist.SaveMany;
import io.ebeaninternal.server.persist.*;
import io.ebeaninternal.server.transaction.BeanPersistIdMap;
import io.ebeanservice.docstore.api.DocStoreUpdate;
import io.ebeanservice.docstore.api.DocStoreUpdateContext;
@@ -38,11 +25,7 @@ import javax.persistence.OptimisticLockException;
import javax.persistence.PersistenceException;
import java.io.IOException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
/**
* PersistRequest for insert update or delete of a bean.
@@ -94,8 +77,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
*/
private List<BeanPropertyAssocMany<?>> updatedManys;
/**
* Need to get and store the updated properties because the persist listener is notified
* later on a different thread and the bean has been reset at that point.
* Store the updated properties to notify persist listener.
*/
private Set<String> updatedProperties;
/**
@@ -139,7 +121,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
*/
private boolean complete;
/**
* Many to many intersection table changes that are held for later batch processing.
* Many-to-many intersection table changes that are held for later batch processing.
*/
private List<SaveMany> saveMany;
@@ -165,9 +147,10 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
// 'stateless update' - set loaded properties as dirty
intercept.setNewBeanForUpdate();
statelessUpdate = true;
} else if (!intercept.isDirty()) {
// check if any mutable scalar properties are dirty
beanDescriptor.checkAnyMutableProperties(intercept);
}
// Mark Mutable scalar properties (like Hstore) as dirty where necessary
beanDescriptor.checkMutableProperties(intercept);
}
this.concurrencyMode = beanDescriptor.concurrencyMode(intercept);
this.publish = Flags.isPublish(flags);
@@ -743,10 +726,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
executeInsert();
return -1;
case UPDATE:
if (beanPersistListener != null) {
// store the updated properties for sending later
updatedProperties = updatedProperties();
}
executeUpdate();
return -1;
case DELETE_SOFT:
@@ -953,7 +932,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
String name = beanDescriptor.name();
switch (type) {
case INSERT:
transaction.logSummary("Inserted [" + name + "] [" + idValue + "]" + draft);
transaction.logSummary("Inserted [" + name + "] [" + (idValue == null ? "" : idValue) + "]" + draft);
break;
case UPDATE:
transaction.logSummary("Updated [" + name + "] [" + idValue + "]" + draft);
@@ -1225,6 +1204,11 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
private void executeUpdate() {
setTenantId();
if (controller == null || controller.preUpdate(this)) {
// check dirty state for all mutable scalar properties (like DbJson, Hstore)
beanDescriptor.checkAllMutableProperties(intercept);
if (beanPersistListener != null) {
updatedProperties = updatedProperties();
}
postControllerPrepareUpdate();
beanManager.getBeanPersister().update(this);
}
@@ -7,6 +7,7 @@ import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeanservice.docstore.api.DocQueryRequest;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -122,7 +123,7 @@ public interface SpiOrmQueryRequest<T> extends BeanQueryRequest<T>, DocQueryRequ
/**
* Execute the findSingleAttributeList query.
*/
<A> List<A> findSingleAttributeList();
<A extends Collection<?>> A findSingleAttributeCollection(A collection);
/**
* Execute returning the ResultSet.
@@ -13,11 +13,10 @@ public interface DataTimeZone {
Calendar getTimeZone();
/**
* Return the Calendar to use for Timezone information when reading/writing date.
* A 'date' only value has normally no timezone information, but some platforms (like MySQL)
* reqire this.
* Return the Calendar to use for Timezone information when reading/writing a time component (date only/time only).
* A time component has normally no timezone information, but some platforms (like MySQL) reqire this.
*/
default Calendar getDateTimeZone() {
default Calendar getTimeComponentTimeZone() {
return null;
}
}
@@ -19,7 +19,7 @@ public class MySqlDataTimeZone implements DataTimeZone {
}
@Override
public Calendar getDateTimeZone() {
public Calendar getTimeComponentTimeZone() {
return zone;
}
}
@@ -28,7 +28,7 @@ abstract class BaseCollectionHelp<T> implements BeanCollectionHelp<T> {
}
@Override
public void setLoader(BeanCollectionLoader loader) {
public final void setLoader(BeanCollectionLoader loader) {
this.loader = loader;
}
@@ -43,7 +43,7 @@ abstract class BaseCollectionHelp<T> implements BeanCollectionHelp<T> {
@SuppressWarnings("rawtypes")
@Override
public Collection underlying(Object value) {
public final Collection underlying(Object value) {
if (value instanceof BeanCollection) {
return ((BeanCollection)value).getActualDetails();
} else {
@@ -51,7 +51,7 @@ abstract class BaseCollectionHelp<T> implements BeanCollectionHelp<T> {
}
}
void jsonWriteCollection(SpiJsonWriter ctx, String name, Collection<?> list) throws IOException {
final void jsonWriteCollection(SpiJsonWriter ctx, String name, Collection<?> list) throws IOException {
if (!list.isEmpty() || ctx.isIncludeEmpty()) {
ctx.beginAssocMany(name);
for (Object bean : list) {
@@ -47,6 +47,11 @@ public interface BeanCollectionHelp<T> extends CQueryCollectionAdd<T> {
*/
BeanCollection<T> createEmpty(EntityBean bean);
/**
* Create and return an empty 'vanilla' collection that does not support lazy loading.
*/
Object createEmptyReference();
/**
* Add a bean to the List Set or Map.
*/
@@ -1,5 +1,9 @@
package io.ebeaninternal.server.deploy;
import io.ebean.bean.BeanCollection;
import io.ebean.bean.EntityBean;
import io.ebean.common.BeanList;
import io.ebean.common.BeanSet;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.server.core.OrmQueryRequest;
import io.ebeaninternal.server.el.ElPropertyValue;
@@ -12,18 +16,17 @@ import io.ebeaninternal.server.query.CQueryCollectionAdd;
public final class BeanCollectionHelpFactory {
@SuppressWarnings("rawtypes")
private static final BeanListHelp LIST_HELP = new BeanListHelp();
private static final CQueryCollectionAdd LIST_HELP = new ListAdd();
@SuppressWarnings("rawtypes")
private static final BeanSetHelp SET_HELP = new BeanSetHelp();
private static final CQueryCollectionAdd SET_HELP = new SetAdd();
/**
* Create the helper based on the many property.
*/
public static <T> BeanCollectionHelp<T> create(BeanPropertyAssocMany<T> many) {
boolean elementCollection = many.isElementCollection();
ManyType manyType = many.manyType();
switch (manyType) {
switch (many.manyType()) {
case LIST:
return elementCollection ? new BeanListHelpElement<>(many) : new BeanListHelp<>(many);
case SET:
@@ -31,7 +34,7 @@ public final class BeanCollectionHelpFactory {
case MAP:
return elementCollection ? new BeanMapHelpElement<>(many) : new BeanMapHelp<>(many);
default:
throw new RuntimeException("Invalid type " + manyType);
throw new RuntimeException("Invalid type " + many.manyType());
}
}
@@ -53,4 +56,30 @@ public final class BeanCollectionHelpFactory {
}
}
private static final class ListAdd<T> implements CQueryCollectionAdd<T> {
@Override
public BeanCollection<T> createEmptyNoParent() {
return new BeanList<>();
}
@Override
public void add(BeanCollection<?> collection, EntityBean bean, boolean withCheck) {
collection.internalAdd(bean);
}
}
private static final class SetAdd<T> implements CQueryCollectionAdd<T> {
@Override
public BeanCollection<T> createEmptyNoParent() {
return new BeanSet<>();
}
@Override
public void add(BeanCollection<?> collection, EntityBean bean, boolean withCheck) {
collection.internalAdd(bean);
}
}
}
@@ -86,7 +86,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
private final ConcurrentHashMap<String, ElPropertyDeploy> elDeployCache = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, ElComparator<T>> comparatorCache = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, STreeProperty> dynamicProperty = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, Map<String,String>> pathMaps = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, Map<String, String>> pathMaps = new ConcurrentHashMap<>();
private final Map<String, SpiRawSql> namedRawSql;
private final Map<String, String> namedQuery;
@@ -1765,6 +1765,14 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
return createEntityBean(false);
}
@Override
public EntityBean createEntityBean2(boolean readOnlyNoIntercept) {
if (readOnlyNoIntercept) {
return (EntityBean) prototypeEntityBean._ebean_newInstanceReadOnly();
}
return createEntityBean(false);
}
/**
* Create an entity bean for JSON marshalling (which differs for the element collection case).
*/
@@ -2879,7 +2887,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
for (BeanPropertyAssocMany<?> many : propertiesManySave) {
if (ebi.isLoadedProperty(many.propertyIndex())) {
final Object value = many.getValue(bean);
if (value instanceof BeanCollection && ((BeanCollection<?>)value).hasModifications() || value != null) {
if (value instanceof BeanCollection && ((BeanCollection<?>) value).hasModifications() || value != null) {
return true;
}
}
@@ -3132,9 +3140,9 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
}
/**
* Check for mutable scalar types and mark as dirty if necessary.
* Check all mutable scalar types and mark as dirty if necessary.
*/
public void checkMutableProperties(EntityBeanIntercept ebi) {
public void checkAllMutableProperties(EntityBeanIntercept ebi) {
for (BeanProperty beanProperty : propertiesMutable) {
int propertyIndex = beanProperty.propertyIndex();
if (ebi.isLoadedProperty(propertyIndex)) {
@@ -3148,6 +3156,23 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
}
}
/**
* Return true if any mutable properties are dirty.
*/
public boolean checkAnyMutableProperties(EntityBeanIntercept ebi) {
for (BeanProperty beanProperty : propertiesMutable) {
int propertyIndex = beanProperty.propertyIndex();
if (ebi.isLoadedProperty(propertyIndex)) {
Object value = beanProperty.getValue(ebi.getOwner());
if (beanProperty.checkMutable(value, ebi.isDirtyProperty(propertyIndex), ebi)) {
ebi.markPropertyAsChanged(propertyIndex);
return true;
}
}
}
return false;
}
public ConcurrencyMode concurrencyMode(EntityBeanIntercept ebi) {
if (!hasVersionProperty(ebi)) {
return ConcurrencyMode.NONE;
@@ -11,6 +11,7 @@ import io.ebeaninternal.api.json.SpiJsonWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
@@ -27,8 +28,7 @@ public class BeanListHelp<T> extends BaseCollectionHelp<T> {
}
@Override
public BeanCollectionAdd getBeanCollectionAdd(Object bc, String mapKey) {
public final BeanCollectionAdd getBeanCollectionAdd(Object bc, String mapKey) {
if (bc instanceof BeanList<?>) {
BeanList<?> bl = (BeanList<?>) bc;
if (bl.getActualList() == null) {
@@ -42,12 +42,17 @@ public class BeanListHelp<T> extends BaseCollectionHelp<T> {
}
@Override
public BeanCollection<T> createEmptyNoParent() {
public final Object createEmptyReference() {
return Collections.EMPTY_LIST;
}
@Override
public final BeanCollection<T> createEmptyNoParent() {
return new BeanList<>();
}
@Override
public BeanCollection<T> createEmpty(EntityBean parentBean) {
public final BeanCollection<T> createEmpty(EntityBean parentBean) {
BeanList<T> beanList = new BeanList<>(loader, parentBean, propertyName);
if (many != null) {
beanList.setModifyListening(many.modifyListenMode());
@@ -56,29 +61,23 @@ public class BeanListHelp<T> extends BaseCollectionHelp<T> {
}
@Override
public BeanCollection<T> createReference(EntityBean parentBean) {
public final BeanCollection<T> createReference(EntityBean parentBean) {
BeanList<T> beanList = new BeanList<>(loader, parentBean, propertyName);
beanList.setModifyListening(many.modifyListenMode());
return beanList;
}
@Override
public void refresh(SpiEbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
public final void refresh(SpiEbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
BeanList<?> newBeanList = (BeanList<?>) server.findList(query, t);
refresh(newBeanList, parentBean);
}
@Override
public void refresh(BeanCollection<?> bc, EntityBean parentBean) {
public final void refresh(BeanCollection<?> bc, EntityBean parentBean) {
BeanList<?> newBeanList = (BeanList<?>) bc;
List<?> currentList = (List<?>) many.getValue(parentBean);
newBeanList.setModifyListening(many.modifyListenMode());
if (currentList == null) {
// the currentList is null? Not really expecting this...
many.setValue(parentBean, newBeanList);
@@ -96,8 +95,7 @@ public class BeanListHelp<T> extends BaseCollectionHelp<T> {
}
@Override
public void jsonWrite(SpiJsonWriter ctx, String name, Object collection, boolean explicitInclude) throws IOException {
public final void jsonWrite(SpiJsonWriter ctx, String name, Object collection, boolean explicitInclude) throws IOException {
List<?> list;
if (collection instanceof BeanCollection<?>) {
BeanList<?> beanList = (BeanList<?>) collection;
@@ -114,7 +112,6 @@ public class BeanListHelp<T> extends BaseCollectionHelp<T> {
} else {
list = (List<?>) collection;
}
jsonWriteCollection(ctx, name, list);
}
@@ -10,6 +10,7 @@ import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.json.SpiJsonWriter;
import java.io.IOException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
@@ -36,13 +37,11 @@ public class BeanMapHelp<T> extends BaseCollectionHelp<T> {
@Override
@SuppressWarnings("unchecked")
public BeanCollectionAdd getBeanCollectionAdd(Object bc, String mapKey) {
public final BeanCollectionAdd getBeanCollectionAdd(Object bc, String mapKey) {
if (mapKey == null) {
mapKey = many.mapKey();
}
BeanProperty beanProp = targetDescriptor.beanProperty(mapKey);
if (bc instanceof BeanMap<?, ?>) {
BeanMap<Object, Object> bm = (BeanMap<Object, Object>) bc;
Map<Object, Object> actualMap = bm.getActualMap();
@@ -57,10 +56,9 @@ public class BeanMapHelp<T> extends BaseCollectionHelp<T> {
}
}
static class Adder implements BeanCollectionAdd {
static final class Adder implements BeanCollectionAdd {
private final BeanProperty beanProperty;
private final Map<Object, Object> map;
Adder(BeanProperty beanProperty, Map<Object, Object> map) {
@@ -76,13 +74,17 @@ public class BeanMapHelp<T> extends BaseCollectionHelp<T> {
}
@Override
public BeanCollection<T> createEmptyNoParent() {
public final Object createEmptyReference() {
return Collections.EMPTY_MAP;
}
@Override
public final BeanCollection<T> createEmptyNoParent() {
return new BeanMap<>();
}
@Override
public BeanCollection<T> createEmpty(EntityBean ownerBean) {
public final BeanCollection<T> createEmpty(EntityBean ownerBean) {
BeanMap<?, T> beanMap = new BeanMap<>(loader, ownerBean, propertyName);
if (many != null) {
beanMap.setModifyListening(many.modifyListenMode());
@@ -92,7 +94,6 @@ public class BeanMapHelp<T> extends BaseCollectionHelp<T> {
@Override
public void add(BeanCollection<?> collection, EntityBean bean, boolean withCheck) {
if (bean == null) {
((BeanMap<?, ?>) collection).internalPutNull();
} else {
@@ -104,8 +105,7 @@ public class BeanMapHelp<T> extends BaseCollectionHelp<T> {
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public BeanCollection<T> createReference(EntityBean parentBean) {
public final BeanCollection<T> createReference(EntityBean parentBean) {
BeanMap beanMap = new BeanMap(loader, parentBean, propertyName);
if (many != null) {
beanMap.setModifyListening(many.modifyListenMode());
@@ -114,14 +114,13 @@ public class BeanMapHelp<T> extends BaseCollectionHelp<T> {
}
@Override
public void refresh(SpiEbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
public final void refresh(SpiEbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
BeanMap<?, ?> newBeanMap = (BeanMap<?, ?>) server.findMap(query, t);
refresh(newBeanMap, parentBean);
}
@Override
public void refresh(BeanCollection<?> bc, EntityBean parentBean) {
public final void refresh(BeanCollection<?> bc, EntityBean parentBean) {
BeanMap<?, ?> newBeanMap = (BeanMap<?, ?>) bc;
Map<?, ?> current = (Map<?, ?>) many.getValue(parentBean);
@@ -143,8 +142,7 @@ public class BeanMapHelp<T> extends BaseCollectionHelp<T> {
}
@Override
public void jsonWrite(SpiJsonWriter ctx, String name, Object collection, boolean explicitInclude) throws IOException {
public final void jsonWrite(SpiJsonWriter ctx, String name, Object collection, boolean explicitInclude) throws IOException {
Map<?, ?> map;
if (collection instanceof BeanCollection<?>) {
BeanMap<?, ?> bc = (BeanMap<?, ?>) collection;
@@ -15,7 +15,6 @@ public final class BeanMapHelpElement<T> extends BeanMapHelp<T> {
public void add(BeanCollection<?> collection, EntityBean bean, boolean withCheck) {
Object key = bean._ebean_getField(0);
Object val = bean._ebean_getField(1);
BeanMap<?, ?> map = ((BeanMap<?, ?>) collection);
if (withCheck) {
map.internalPutWithCheck(key, val);
@@ -601,6 +601,11 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
return mapKey;
}
@Override
public void createEmptyReference(EntityBean localBean) {
setValue(localBean, help.createEmptyReference());
}
@Override
public BeanCollection<?> createReference(EntityBean localBean, boolean forceNewReference) {
return forceNewReference ? createReference(localBean) : createReferenceIfNull(localBean);
@@ -10,6 +10,7 @@ import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.api.json.SpiJsonWriter;
import java.io.IOException;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
@@ -33,7 +34,7 @@ public class BeanSetHelp<T> extends BaseCollectionHelp<T> {
}
@Override
public BeanCollectionAdd getBeanCollectionAdd(Object bc, String mapKey) {
public final BeanCollectionAdd getBeanCollectionAdd(Object bc, String mapKey) {
if (bc instanceof BeanSet<?>) {
BeanSet<?> beanSet = (BeanSet<?>) bc;
if (beanSet.getActualSet() == null) {
@@ -46,12 +47,17 @@ public class BeanSetHelp<T> extends BaseCollectionHelp<T> {
}
@Override
public BeanCollection<T> createEmptyNoParent() {
public final Object createEmptyReference() {
return Collections.EMPTY_SET;
}
@Override
public final BeanCollection<T> createEmptyNoParent() {
return new BeanSet<>();
}
@Override
public BeanCollection<T> createEmpty(EntityBean ownerBean) {
public final BeanCollection<T> createEmpty(EntityBean ownerBean) {
BeanSet<T> beanSet = new BeanSet<>(loader, ownerBean, propertyName);
if (many != null) {
beanSet.setModifyListening(many.modifyListenMode());
@@ -60,20 +66,20 @@ public class BeanSetHelp<T> extends BaseCollectionHelp<T> {
}
@Override
public BeanCollection<T> createReference(EntityBean parentBean) {
public final BeanCollection<T> createReference(EntityBean parentBean) {
BeanSet<T> beanSet = new BeanSet<>(loader, parentBean, propertyName);
beanSet.setModifyListening(many.modifyListenMode());
return beanSet;
}
@Override
public void refresh(SpiEbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
public final void refresh(SpiEbeanServer server, Query<?> query, Transaction t, EntityBean parentBean) {
BeanSet<?> newBeanSet = (BeanSet<?>) server.findSet(query, t);
refresh(newBeanSet, parentBean);
}
@Override
public void refresh(BeanCollection<?> bc, EntityBean parentBean) {
public final void refresh(BeanCollection<?> bc, EntityBean parentBean) {
BeanSet<?> newBeanSet = (BeanSet<?>) bc;
Set<?> current = (Set<?>) many.getValue(parentBean);
newBeanSet.setModifyListening(many.modifyListenMode());
@@ -94,7 +100,7 @@ public class BeanSetHelp<T> extends BaseCollectionHelp<T> {
}
@Override
public void jsonWrite(SpiJsonWriter ctx, String name, Object collection, boolean explicitInclude) throws IOException {
public final void jsonWrite(SpiJsonWriter ctx, String name, Object collection, boolean explicitInclude) throws IOException {
Set<?> set;
if (collection instanceof BeanCollection<?>) {
BeanSet<?> bc = (BeanSet<?>) collection;
@@ -6,7 +6,6 @@ import io.ebean.bean.EntityBeanIntercept;
import io.ebean.bean.PersistenceContext;
import io.ebean.core.type.DataReader;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.server.query.STreePropertyAssocMany;
import java.util.Map;
@@ -70,11 +69,6 @@ public interface DbReadContext {
*/
void register(BeanPropertyAssocMany<?> many, BeanCollection<?> bc);
/**
* Return the property that is associated with the many. There can only be
* one. This can be null.
*/
STreePropertyAssocMany getManyProperty();
/**
* Set back the bean that has just been loaded with its id.
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.deploy;
import io.ebean.bean.EntityBean;
import io.ebean.bean.EntityBeanIntercept;
import io.ebean.bean.InterceptReadWrite;
final class ElementEntityBean implements EntityBean {
@@ -13,7 +14,7 @@ final class ElementEntityBean implements EntityBean {
ElementEntityBean(String[] properties) {
this.properties = properties;
this.intercept = new EntityBeanIntercept(this);
this.intercept = new InterceptReadWrite(this);
}
@Override
@@ -29,10 +29,10 @@ public final class IndexDefinition {
/**
* Create a unique constraint given the column names.
*/
public IndexDefinition(String[] columns) {
public IndexDefinition(String name, String[] columns) {
this.columns = columns;
this.unique = true;
this.name = null;
this.name = name;
this.platforms = null;
this.concurrent = false;
this.definition = null;
@@ -16,11 +16,17 @@ public final class PartitionMeta {
return mode;
}
/**
* Originally the property name but replaced with the db column.
*/
public String getProperty() {
return property;
}
public void setProperty(String dbColumn) {
/**
* Set the db column being partitioned on.
*/
public void setColumn(String dbColumn) {
this.property = dbColumn;
}
}
@@ -249,12 +249,12 @@ public class DeployBeanDescriptor<T> {
if (partitionMeta != null) {
DeployBeanProperty beanProperty = getBeanProperty(partitionMeta.getProperty());
if (beanProperty != null) {
partitionMeta.setProperty(beanProperty.getDbColumn());
partitionMeta.setColumn(beanProperty.getDbColumn());
}
}
return partitionMeta;
}
public void setTablespaceMeta(TablespaceMeta tablespaceMeta) {
this.tablespaceMeta = tablespaceMeta;
}
@@ -135,7 +135,7 @@ final class AnnotationClass extends AnnotationParser {
UniqueConstraint uc = typeGet(cls, UniqueConstraint.class);
if (uc != null) {
descriptor.addIndex(new IndexDefinition(convertColumnNames(uc.columnNames())));
descriptor.addIndex(new IndexDefinition(uc.name(), convertColumnNames(uc.columnNames())));
}
View view = typeGet(cls, View.class);
if (view != null) {
@@ -145,7 +145,7 @@ final class AnnotationClass extends AnnotationParser {
if (table != null) {
UniqueConstraint[] uniqueConstraints = table.uniqueConstraints();
for (UniqueConstraint c : uniqueConstraints) {
descriptor.addIndex(new IndexDefinition(convertColumnNames(c.columnNames())));
descriptor.addIndex(new IndexDefinition(c.name(), convertColumnNames(c.columnNames())));
}
}
StorageEngine storage = typeGet(cls, StorageEngine.class);
@@ -46,20 +46,29 @@ final class DtoMetaBuilder {
}
static String propertyName(String methodName) {
final String name = methodName.substring(3);
return Character.toLowerCase(name.charAt(0)) + name.substring(1);
if (isTraditionalSetterMethod(methodName)) {
final String name = methodName.substring(3);
return Character.toLowerCase(name.charAt(0)) + name.substring(1);
} else {
// accessor style setter method
return methodName;
}
}
private static boolean isTraditionalSetterMethod(String methodName) {
return methodName.startsWith("set") && methodName.length() > 3 && Character.isUpperCase(methodName.charAt(3));
}
/**
* Include a public "setter" method - 1 argument, returns void.
*/
static boolean includeMethod(Method method) {
String name = method.getName();
final int modifiers = method.getModifiers();
return Modifier.isPublic(modifiers)
&& !Modifier.isStatic(modifiers)
&& Void.TYPE.equals(method.getReturnType())
&& method.getParameterTypes().length == 1
&& method.getName().startsWith("set") && method.getName().length() > 3;
&& (!name.equals("wait") && !name.equals("equals"));
}
private void readConstructors() {
@@ -467,6 +467,11 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
return query.findSingleAttributeList();
}
@Override
public <A> Set<A> findSingleAttributeSet() {
return query.findSingleAttributeSet();
}
@Override
public boolean exists() {
return query.exists();
@@ -464,6 +464,11 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
return exprList.findSingleAttributeList();
}
@Override
public <A> Set<A> findSingleAttributeSet() {
return exprList.findSingleAttributeSet();
}
@Override
public PagedList<T> findPagedList() {
return exprList.findPagedList();
@@ -24,7 +24,7 @@ import static io.ebeaninternal.server.persist.DmlUtil.isNullOrZero;
/**
* Saves the details for a OneToMany or ManyToMany relationship (entity beans).
*/
public final class SaveManyBeans extends SaveManyBase {
final class SaveManyBeans extends SaveManyBase {
private final boolean cascade;
private final boolean publish;
@@ -34,7 +34,9 @@ public final class SaveManyBeans extends SaveManyBase {
private final DeleteMode deleteMode;
private final boolean untouchedBeanCollection;
private final Collection<?> collection;
private final boolean hasOrderColumn;
private int sortOrder;
private boolean insertAllChildren;
SaveManyBeans(DefaultPersister persister, boolean insertedParent, BeanPropertyAssocMany<?> many, EntityBean parentBean, PersistRequestBean<?> request) {
super(persister, insertedParent, many, parentBean, request);
@@ -46,6 +48,7 @@ public final class SaveManyBeans extends SaveManyBase {
this.deleteMode = targetDescriptor.isSoftDelete() ? DeleteMode.SOFT : DeleteMode.HARD;
this.untouchedBeanCollection = untouchedBeanCollection();
this.collection = cascade ? BeanCollectionUtil.getActualEntries(value) : null;
this.hasOrderColumn = many.hasOrderColumn();
}
/**
@@ -73,7 +76,7 @@ public final class SaveManyBeans extends SaveManyBase {
resetModifyState();
}
} else {
if (isModifyListenMode() || many.hasOrderColumn()) {
if (isModifyListenMode() || hasOrderColumn) {
// delete any removed beans / orphans
removeAssocManyOrphans();
}
@@ -90,6 +93,7 @@ public final class SaveManyBeans extends SaveManyBase {
private boolean isSaveIntersection() {
if (!many.isManyToMany()) {
// OneToMany JoinTable
return true;
}
return transaction.isSaveAssocManyIntersection(many.intersectionTableJoin().getTable(), many.descriptor().rootName());
@@ -112,26 +116,22 @@ public final class SaveManyBeans extends SaveManyBase {
private void processDetails() {
BeanProperty orderColumn = null;
boolean hasOrderColumn = many.hasOrderColumn();
if (hasOrderColumn) {
if (!insertedParent && canSkipForOrderColumn() && saveRecurseSkippable) {
return;
}
orderColumn = targetDescriptor.orderColumn();
}
if (insertedParent) {
// performance optimisation for large collections
targetDescriptor.preAllocateIds(collection.size());
}
if (!insertedParent && many.isOrphanRemoval() && request.isForcedUpdate()) {
if (forcedUpdateOrphanRemoval()) {
// collect the Id's (to exclude from deleteManyDetails)
List<Object> detailIds = collectIds(collection, targetDescriptor, isMap);
// deleting missing children - children not in our collected detailIds
persister.deleteManyDetails(transaction, many.descriptor(), parentBean, many, detailIds, deleteMode);
}
transaction.depth(+1);
saveAllBeans(orderColumn);
if (hasOrderColumn) {
@@ -140,17 +140,18 @@ public final class SaveManyBeans extends SaveManyBase {
transaction.depth(-1);
}
private void saveAllBeans(BeanProperty orderColumn) {
// if a map, then we get the key value and
// set it to the appropriate property on the
// detail bean before we save it
private boolean forcedUpdateOrphanRemoval() {
return !insertedParent && many.isOrphanRemoval() && request.isForcedUpdate();
}
private void saveAllBeans(final BeanProperty orderColumn) {
Object mapKeyValue = null;
boolean skipSavingThisBean;
boolean clearedParent = false;
for (Object detailBean : collection) {
sortOrder++;
if (isMap) {
// its a map so need the key and value
// a map so need the key and value
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) detailBean;
mapKeyValue = entry.getKey();
detailBean = entry.getValue();
@@ -169,25 +170,28 @@ public final class SaveManyBeans extends SaveManyBase {
ebi.setDirty(true);
}
}
if (targetDescriptor.isReference(ebi) && originalOrder == 0) {
if (originalOrder == 0 && targetDescriptor.isReference(ebi)) {
// we can skip this one
skipSavingThisBean = true;
} else if (ebi.isNewOrDirty()) {
skipSavingThisBean = false;
// set the parent bean to detailBean
many.setJoinValuesToChild(parentBean, detail, mapKeyValue);
} else if (insertAllChildren) {
ebi.setNew();
skipSavingThisBean = false;
many.setJoinValuesToChild(parentBean, detail, mapKeyValue);
} else {
// unmodified so skip depending on prop.isSaveRecurseSkippable();
skipSavingThisBean = saveRecurseSkippable;
}
}
if (!skipSavingThisBean) {
persister.saveRecurse(detail, transaction, parentBean, request.flags());
if (many.hasOrderColumn()) {
// Clear the bean from the PersistenceContext (L1 cache), because the order of referenced beans might have changed
if (hasOrderColumn && !clearedParent) {
// Clear the parent bean from the PersistenceContext (L1 cache), because the order of referenced beans might have changed
final BeanDescriptor<?> beanDescriptor = many.descriptor();
beanDescriptor.contextClear(transaction.getPersistenceContext(), beanDescriptor.getId(parentBean));
clearedParent = true;
}
}
}
@@ -340,8 +344,9 @@ public final class SaveManyBeans extends SaveManyBase {
return;
}
if (!(value instanceof BeanCollection<?>)) {
if (!insertedParent && cascade && isChangedProperty()) {
if (!forcedUpdateOrphanRemoval() && (!insertedParent && cascade && isChangedProperty())) {
persister.addToFlushQueue(many.deleteByParentId(request.beanId(), null), transaction, 0);
insertAllChildren = true;
}
} else {
BeanCollection<?> c = (BeanCollection<?>) value;
@@ -351,7 +356,7 @@ public final class SaveManyBeans extends SaveManyBase {
c.setModifyListening(many.modifyListenMode());
}
// We must not reset when we still have to update other entities in the collection and set their new orderColumn value
if (!many.hasOrderColumn()) {
if (!hasOrderColumn) {
c.modifyReset();
}
if (modifyRemovals != null && !modifyRemovals.isEmpty()) {
@@ -605,14 +605,6 @@ public final class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfi
return logWhereSql;
}
/**
* Return the property that is associated with the many. There can only be one
* per SqlSelect. This can be null.
*/
@Override
public STreePropertyAssocMany getManyProperty() {
return manyProperty;
}
public String getBindLog() {
return bindLog;
@@ -644,10 +644,12 @@ final class CQueryBuilder {
}
private void appendHistoryAsOfPredicate() {
if (query.isAsOfBaseTable() && !historySupport.isStandardsBased()) {
appendAndOrWhere();
sb.append(historySupport.getAsOfPredicate(request.baseTableAlias()));
if (query.isAsOfBaseTable()) {
query.incrementAsOfTableCount();
if (!historySupport.isStandardsBased()){
appendAndOrWhere();
sb.append(historySupport.getAsOfPredicate(request.baseTableAlias()));
}
}
}
@@ -24,11 +24,7 @@ import org.slf4j.Logger;
import javax.persistence.PersistenceException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* Handles the Object Relational fetching.
@@ -91,16 +87,16 @@ public final class CQueryEngine {
/**
* Build and execute the findSingleAttributeList query.
*/
public <A> List<A> findSingleAttributeList(OrmQueryRequest<?> request) {
public <A extends Collection<?>> A findSingleAttributeList(OrmQueryRequest<?> request, A collection) {
CQueryFetchSingleAttribute rcQuery = queryBuilder.buildFetchAttributeQuery(request);
request.setCancelableQuery(rcQuery);
return findAttributeList(request, rcQuery);
return findAttributeCollection(request, rcQuery, collection);
}
@SuppressWarnings("unchecked")
private <A> List<A> findAttributeList(OrmQueryRequest<?> request, CQueryFetchSingleAttribute rcQuery) {
private <A extends Collection<?>> A findAttributeCollection(OrmQueryRequest<?> request, CQueryFetchSingleAttribute rcQuery, A collection) {
try {
List<A> list = (List<A>) rcQuery.findList();
rcQuery.findCollection(collection);
if (request.logSql()) {
logGeneratedSql(request, rcQuery.getGeneratedSql(), rcQuery.getBindLog(), rcQuery.micros());
}
@@ -109,13 +105,21 @@ public final class CQueryEngine {
}
if (request.isQueryCachePut()) {
request.addDependentTables(rcQuery.getDependentTables());
list = Collections.unmodifiableList(list);
request.putToQueryCache(list);
if (Boolean.FALSE.equals(request.query().isReadOnly())) {
list = new ArrayList<>(list);
if (collection instanceof List) {
collection = (A) Collections.unmodifiableList((List<?>) collection);
request.putToQueryCache(collection);
if (Boolean.FALSE.equals(request.query().isReadOnly())) {
collection = (A) new ArrayList<>(collection);
}
} else if (collection instanceof Set) {
collection = (A) Collections.unmodifiableSet((Set<?>) collection);
request.putToQueryCache(collection);
if (Boolean.FALSE.equals(request.query().isReadOnly())) {
collection = (A) new LinkedHashSet<>(collection);
}
}
}
return list;
return collection;
} catch (SQLException e) {
throw translate(request, rcQuery.getBindLog(), rcQuery.getGeneratedSql(), e);
}
@@ -144,7 +148,7 @@ public final class CQueryEngine {
public <A> List<A> findIds(OrmQueryRequest<?> request) {
CQueryFetchSingleAttribute rcQuery = queryBuilder.buildFetchIdsQuery(request);
request.setCancelableQuery(rcQuery);
return findAttributeList(request, rcQuery);
return findAttributeCollection(request, rcQuery, new ArrayList<>());
}
private <T> void logGeneratedSql(OrmQueryRequest<T> request, String sql, String bindLog, long micros) {
@@ -16,6 +16,7 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
@@ -76,11 +77,10 @@ final class CQueryFetchSingleAttribute implements SpiProfileTransactionEvent, Ca
/**
* Execute the query returning the row count.
*/
List<Object> findList() throws SQLException {
void findCollection(Collection result) throws SQLException {
long startNano = System.nanoTime();
try {
prepareExecute();
List<Object> result = new ArrayList<>();
while (dataReader.next()) {
Object value = reader.read(dataReader);
if (containsCounts) {
@@ -95,7 +95,6 @@ final class CQueryFetchSingleAttribute implements SpiProfileTransactionEvent, Ca
queryPlan.captureBindForQueryPlan(predicates, executionTimeMicros);
}
getTransaction().profileEvent(this);
return result;
} finally {
close();
}
@@ -134,6 +134,9 @@ final class DefaultDbSqlContext implements DbSqlContext {
String asOfView = historySupport.getAsOfView(table);
appendTable(table, asOfView);
if (asOfView != null) {
if (historySupport.isStandardsBased()) {
asOfTableCount++;
}
addAsOfOnClause = !historySupport.isStandardsBased();
}
}

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