Compare commits

..
Author SHA1 Message Date
rbygrave aa27aedca9 [maven-release-plugin] prepare release ebean-parent-12.11.2 2021-08-31 17:21:52 +12:00
rbygrave 172c1d10a1 Tidy test only - tidy TestDbArray_asSet 2021-08-31 14:28:54 +12:00
rbygrave da6f7d671b #2336 - @DbArray List or Set of UUID or enum returned as String (not converted) when DB does not support ARRAY 2021-08-31 14:26:52 +12:00
rbygrave 6e10d641b2 Merge branch 'master' of github.com:ebean-orm/ebean 2021-08-30 22:43:06 +12:00
rbygrave c5dca69482 Tests only - update tests for sql server 2021-08-30 22:42:12 +12:00
rob 371a50176e Tidy tests only - ClusterTest and TestAggregateFormula 2021-08-30 22:39:11 +12:00
Rob BygraveandGitHub 56fed3ad87 Merge pull request #2331 from FOCONIS/pr/bugfix/npe_mutableNext_call
Fix for NPE in mutableNext in EBI
2021-08-25 10:38:32 +12:00
Rob BygraveandGitHub 9a65731be9 Merge pull request #2330 from FOCONIS/pr/enh/sort_order_in_bean_state
Make getSortOrder accessible in BeanState API
2021-08-25 10:36:29 +12:00
Rob BygraveandGitHub 34b011f683 Merge pull request #2329 from FOCONIS/pr/bugfix/oder_column_cache
@OrderdColum did not work properly with cached beans
2021-08-25 10:29:45 +12:00
Jonas Pöhler 69c721b66e ADD: getSortOrder accessible in BeanState API 2021-08-24 14:48:22 +02:00
Jonas Pöhler f2a578cd76 FIX: OrderdColums did not work properly with cache 2021-08-24 14:28:21 +02:00
rbygrave 1e34d65675 Tests only - update ddl review for Postgres 2021-08-24 15:59:58 +12:00
rbygrave 60db0b0999 #2328 - Postgres JSONB dirty checking - trim json 2021-08-24 15:58:29 +12:00
rbygrave 3bfb6dbc20 #2327 - Follow up and fix test TestQueryFilterMany 2021-08-24 15:04:52 +12:00
rbygrave d4d9bb204d #2327 - findSingleAttribute() on a ToMany path includes the id column
Follow up refactor SqlTreeBuilder
2021-08-24 15:04:23 +12:00
rbygrave bedb841fa9 #2327 - findSingleAttribute() on a ToMany path includes the id column
Follow up test changes
2021-08-24 14:52:54 +12:00
rbygrave c4c4663144 #2327 - findSingleAttribute() on a ToMany path includes the id column 2021-08-24 14:31:30 +12:00
rbygrave b392db866c Update tests for multi-platform testing 2021-08-22 17:48:19 +12:00
rbygrave 3556f9a42b Rename test helper StartPostgres (start docker postgres) 2021-08-22 16:39:44 +12:00
rbygrave 0345ca9f18 Update ddl review only - for #2326 2021-08-22 16:38:50 +12:00
rbygrave eacc4b907d Update ddl review only - for #2326 2021-08-22 15:55:45 +12:00
rbygrave 09cb5da3d3 #2326 - [ddl generator] Primary key constraint not generated for @IdClass 2021-08-22 15:55:08 +12:00
rbygrave b22791c15b Update ddl review for h2 2021-08-22 15:29:27 +12:00
rbygrave df3eda411a #2318 - Refactor internals - trim whitespace in deploy package 2021-08-22 13:59:08 +12:00
Jonas Pöhler 5b10c053de FIX: NPE when accessing mutableNext in EBI 2021-08-20 15:13:42 +02:00
rbygrave bf2d75e55e #2318 - Refactor internals - trim whitespace in deploy package 2021-08-20 17:51:01 +12:00
rbygrave 6f7efe6922 #2318 - Refactor internals - trim whitespace in deploy package 2021-08-20 17:39:11 +12:00
rbygrave 90e321ddbd #2318 - Refactor internals - trim whitespace in deploy package 2021-08-20 16:58:37 +12:00
Rob BygraveandGitHub 9649d71082 Merge pull request #2325 from FOCONIS/pr/bugfix/ordere_list_modify_listen_mode
Modification of a OneToMany-Relation with @OrderColumn was not detected
2021-08-20 15:29:22 +12:00
rbygrave 932337d83d Bump ebean-agent to 12.11.2 relating to fix for #2325 2021-08-20 13:09:59 +12:00
Jonas Pöhler 7e4bde8d34 FIX: Modification of a OneToMany-Relation with @OrderColumn was not detected 2021-08-19 17:11:31 +02:00
rbygrave 01e8b5f471 #2323 - Fallback to database query if redis connection fails 2021-08-18 20:41:09 +12:00
rbygrave 68a6da22be Fix imports on test TestQueryExists 2021-08-18 09:41:36 +12:00
rbygrave 986f3b5bca Merge branch 'master' of github.com:ebean-orm/ebean 2021-08-18 09:32:30 +12:00
rbygrave 4b1bb9d1ee #2324 - Bump ebean-datasource to 7.2 2021-08-18 09:11:24 +12:00
rbygrave ec340c0abe #2320 - Tidy only changes 2021-08-18 09:10:27 +12:00
rbygrave b062ec050c #2320 - Tidy only changes 2021-08-18 09:05:28 +12:00
rbygrave 965f4c6227 #2320 - Tidy only changes 2021-08-18 09:05:18 +12:00
Rob BygraveandGitHub bdc4022211 Merge pull request #2322 from FOCONIS/pr/bugfix/subquery_without_where
Fix for subqueries without where condition
2021-08-18 08:53:34 +12:00
rbygrave 7edfe3607d #2320 - When I use Redis for L2 cache, can I set the TTL of the cache key? 2021-08-18 08:43:06 +12:00
Jonas Pöhler e1731b87ec Merge remote-tracking branch 'ebean/master' into pr/bugfix/subquery_without_where 2021-08-17 16:07:02 +02:00
rbygrave ebadc92f63 #2319 - redis - ReentrantLock to replace synchronized(this) 2021-08-17 22:07:31 +12:00
rbygrave ea56ec7435 #2319 - redis - final classes 2021-08-17 22:06:48 +12:00
rbygrave 3b990fb6e1 #2319 - redis - remove unused PrefixKey 2021-08-17 22:03:33 +12:00
rbygrave 96b4fbea4b #2319 - redis - tidy whitespace 2021-08-17 22:02:57 +12:00
rbygrave 9161e17476 #2318 - Refactor internals - final classes in querybean package 2021-08-17 21:39:57 +12:00
rbygrave 190a2c47e9 #2318 - Refactor internals - final classes in cache package 2021-08-17 21:24:56 +12:00
rbygrave d096706685 #2318 - Refactor internals - final classes in internal api package 2021-08-17 21:03:53 +12:00
rbygrave 7521cb530e #2318 - Refactor internals - final classes in type packages 2021-08-17 20:48:15 +12:00
rbygrave dde9b507ce #2318 - Refactor internals - final classes in type packages 2021-08-17 20:09:27 +12:00
rbygrave 183416a640 #2318 - Delete unused ScalarTypeLongToTimestamp 2021-08-17 20:09:02 +12:00
rbygrave 826e8518ea #2318 - Refactor internals - final classes in type packages 2021-08-17 19:46:08 +12:00
rbygrave 55587b12aa #2318 - Refactor internals - final classes in el packages 2021-08-17 19:15:35 +12:00
rbygrave 285a94e5fe #2318 - Refactor internals - final classes in dto packages 2021-08-17 19:06:54 +12:00
rbygrave 16a05528b7 #2318 - Refactor internals - final classes in deploy packages etc 2021-08-17 19:00:55 +12:00
rbygrave b4f4ef3c1b #2318 - Refactor internals - final classes in server packages 2021-08-17 18:24:28 +12:00
rbygrave cd407ee467 #2318 - Refactor internals - final classes in changelog packages 2021-08-16 23:32:26 +12:00
rbygrave 9ee63144e5 #2318 - Refactor internals - final classes in core packages 2021-08-16 23:32:05 +12:00
rbygrave 0413d89a9e #2318 - Refactor internals - final classes in expression packages 2021-08-16 23:19:02 +12:00
rbygrave f33e54d8ba #2318 - Refactor internals - final classes in id and generated property packages 2021-08-16 22:53:38 +12:00
Rob BygraveandGitHub a2b19d46e1 Merge pull request #2316 from FOCONIS/pr/bugfix/json-null-formatValue
Fix: setting json values to null was throwing a NPE when persisting
2021-08-16 22:31:47 +12:00
rbygrave 4163b4dc25 #2317 - Plus test changes due to tidy whitespace on sql generation 2021-08-16 22:23:58 +12:00
rbygrave 12220d4322 #2317 - Incorrect SQL generated for @IdClass with fetch() on ToMany path 2021-08-16 22:21:49 +12:00
rbygrave 14262d4c25 #2317 - Incorrect SQL generated for @IdClass with fetch() on ToMany path 2021-08-16 22:20:21 +12:00
Jonas Pöhler (JPo) f3ec4a78c9 FIX: setting json values to null was throwing a NPE when persisting 2021-08-16 12:02:47 +02:00
rbygrave f7a0ae8b4a [maven-release-plugin] prepare for next development iteration 2021-08-16 09:23:18 +12:00
rbygrave 3c6d17c9a5 [maven-release-plugin] prepare release ebean-parent-12.11.1 2021-08-16 09:23:11 +12:00
rbygrave 885ba0fdd2 Set autoReleaseAfterClose true 2021-08-16 09:18:31 +12:00
rbygrave f3b0e34b67 #2315 - Refactor internals - make more classes final in transaction packages 2021-08-16 09:16:31 +12:00
rbygrave 4109fab0d8 #2313 - Refactor internals - make more classes final in query packages 2021-08-15 15:22:02 +12:00
rbygrave 0688061f5c Speed up TestUuidGenerator 2021-08-15 15:17:19 +12:00
rbygrave 82c12b1565 #2312 - Refactor internals - make more classes final in persist packages 2021-08-15 14:50:43 +12:00
rbygrave ebc0fabbdb #2311 - Fix BindPadding for empty list 2021-08-15 14:15:03 +12:00
rbygrave 587b2e3075 #2310 Tidy to only cast once 2021-08-15 14:09:44 +12:00
Rob BygraveandGitHub ec82dd3da9 Merge pull request #2310 from FOCONIS/nutation-on-cache
FIX: mutation info is not restored on cache hit
2021-08-15 13:50:19 +12:00
rbygrave 3e190b34f5 Merge branch 'master' of github.com:ebean-orm/ebean 2021-08-15 13:48:43 +12:00
rbygrave e059ad9172 Merge branch 'FOCONIS-mutationdetection-source-special-json-types' 2021-08-15 13:48:27 +12:00
rbygrave 1297324fa9 Fix where using JDK 10 Reader.transferTo() method plus add final to methods and classes 2021-08-15 13:47:46 +12:00
rbygrave e2b7434d98 Merge branch 'mutationdetection-source-special-json-types' of https://github.com/FOCONIS/ebean into FOCONIS-mutationdetection-source-special-json-types 2021-08-15 12:06:12 +12:00
rbygrave ada8df5755 Improve startup logging messages 2021-08-15 12:05:30 +12:00
Roland Praml 843b90cbba FIX: mutation info is not restored on cache hit 2021-08-13 11:52:31 +02:00
Roland Praml 6b263919d5 handle also JsonNode 2021-08-13 11:19:24 +02:00
Roland Praml 965c1e803f FIX: mutationDetection = SOURCE works also for special json types 2021-08-13 10:47:14 +02:00
Rob BygraveandGitHub a13bc481b8 Merge pull request #2306 from FOCONIS/pr/enh/softreference_in_cache
Use SoftReferences in Cache
2021-08-13 09:35:38 +12:00
rbygrave fc7379aabc Tidy internals - server.persist.dml package for whitespace and typos 2021-08-13 09:18:31 +12:00
rbygrave a17683c549 #2307 - Tidy ShutdownManager DatabaseFactory only 2021-08-12 16:32:12 +12:00
rbygrave eeacad0fb9 #2307 - ENH: Add DatabaseFactory.disableShutdownHook() ... [ alias for ShutdownManager.deregisterShutdownHook() ] 2021-08-12 14:36:14 +12:00
rbygrave c51140b59a Add DefaultServer.toString() and tidy DbOffline remove unnecessary log message 2021-08-12 13:01:07 +12:00
Jonas Pöhler f1817a0dbb Merge remote-tracking branch 'ebean/master' into pr/enh/softreference_in_cache 2021-08-11 15:26:42 +02:00
Jonas Pöhler 5b05510bb9 Merge remote-tracking branch 'ebean/master' into pr/enh/softreference_in_cache 2021-08-11 14:08:55 +02:00
rbygrave b676476cd2 Add SpiQuery.Type.defaultSelect() for ATTRIBUTE and sub-query type queries 2021-08-11 20:51:46 +12:00
rbygrave 709f8ed05f Merge branch 'master' of github.com:ebean-orm/ebean 2021-08-11 20:21:26 +12:00
rbygrave 31282416d8 Merge branch 'FOCONIS-subquery-with-fetch-path' 2021-08-11 20:16:33 +12:00
Rob BygraveandGitHub 385c84ae6f Merge pull request #2302 from FOCONIS/feature/switch-db2-driver
Switch DB2 driver to the publicly available JCC driver
2021-08-11 19:43:09 +12:00
Roland Praml 2d24020202 Added / enhanced test case 2021-08-11 09:32:21 +02:00
Roland Praml 1a2aba3f56 Distinguish between exists and in subquery 2021-08-11 08:54:40 +02:00
Thomas Fellner f50f0192d1 Switch DB2 driver to the publicly available JCC driver 2021-08-11 08:47:49 +02:00
Roland Praml 12b8b4b955 Merge remote-tracking branch 'upstream/master' into subquery-with-fetch-path 2021-08-11 07:42:11 +02:00
rbygrave c267366578 Refactor tidy internals - aList -> expr in for loops etc. No functional change. 2021-08-11 15:32:54 +12:00
Rob BygraveandGitHub 18e49cc1ce Merge pull request #2300 from FOCONIS/exists-with-dynamic
Enables select + exists for dynamic formula properties
2021-08-11 14:01:46 +12:00
Rob BygraveandGitHub 1ce4b1a994 Merge pull request #2299 from FOCONIS/push-pops-in-wrong-order
PushJson/PopJson did not work correctly, if null beans were involved
2021-08-11 13:48:00 +12:00
Rob BygraveandGitHub f3c87e488a Merge pull request #2301 from FOCONIS/bugfix/update-ddl-generator-version
Updating ebean-ddl-generator version in ebean-core
2021-08-11 13:46:19 +12:00
Rob BygraveandGitHub f24c698cd5 Merge pull request #2298 from ebean-orm/FOCONIS-md5-for-querybindhash
Foconis md5 for querybindhash
2021-08-11 13:29:44 +12:00
rbygrave 144a3b54bb Refactor rename method queryBindHash() to queryBindKey() 2021-08-11 13:25:04 +12:00
rbygrave ec7c7048db Refactor rename BindHash to BindValuesKey 2021-08-11 13:19:44 +12:00
rbygrave fd2e542c0b Change BindHash from interface to implementation, Delete unused server persist BindValues 2021-08-11 12:43:58 +12:00
rbygrave 11e8e3696f BindParams does not need encryptionKey in equals/hashCode 2021-08-11 12:24:36 +12:00
Thomas Fellner d08f7af1e0 update ebean-ddl-generator version in ebean-core 2021-08-10 18:31:02 +02:00
Roland Praml 60dfaab22c Enables select + exists for dynamic formula properties 2021-08-10 15:29:10 +02:00
Roland Praml 75fa7cb7fd PushJson/PopJson did not work correctly, if null beans were involved 2021-08-10 13:24:13 +02:00
rbygrave e47b1737a8 Add HashCodeBindHashTest 2021-08-10 22:28:31 +12:00
rbygrave e1ad210bb0 Tidy JunctionExpression 2021-08-10 22:18:33 +12:00
rbygrave ac3edbedf4 Remove MdBindHash, tidy DefaultOrmQuery 2021-08-10 22:07:48 +12:00
rbygrave 2dc48cf08d ArrayContainsExpression equals() to use enhanced for loop 2021-08-10 22:00:46 +12:00
rbygrave ede1ad0a4c Fix BindParams equals() and hashCode() 2021-08-10 21:58:41 +12:00
rbygrave 3e8f76cd6d Update HashCodeBindHash to use values for equals() 2021-08-10 21:49:31 +12:00
rbygrave cd6df2be39 Merge branch 'md5-for-querybindhash' of https://github.com/FOCONIS/ebean into FOCONIS-md5-for-querybindhash 2021-08-10 21:18:43 +12:00
Rob BygraveandGitHub 7091e972fc Merge pull request #2297 from FOCONIS/fix-mutable-next-changelog
FIX: Changelog-oldValue did not work for Json mutable properties
2021-08-10 21:10:15 +12:00
Roland Praml c8ae3c5ef6 FIX: Changelog-oldValue did not work for Json mutable properties 2021-08-10 09:30:25 +02:00
Rob BygraveandGitHub 54e8c4df8a Merge pull request #2296 from FOCONIS/fix-test-for-java-8
Fix the test to run with java 8
2021-08-10 17:04:14 +12:00
Roland Praml e18c190905 Fix the test to run with java 8 2021-08-09 09:46:49 +02:00
Roland Praml 181dc73d39 Use MD5 for QueryBindHash 2021-08-09 09:19:53 +02:00
rbygrave 7ed2de9178 Update github issue template 2021-08-09 16:57:43 +12:00
rbygrave 8c101fd0a4 #2268 - Feature request/question: Query execution time for debugging 2021-08-09 16:48:59 +12:00
rbygrave 43213ead05 #2291 - ENH: Explicit option for fast-failing or not fast-failing (skipDataSourceCheck config option) 2021-08-09 15:10:59 +12:00
Rob BygraveandGitHub 0ef5c65c94 Merge pull request #2294 from ebean-orm/feature/metric-hash-2
#2293 - Metric hash back to MD5 of sql + name + loc (minus location file and line source) ~= Revert of #2288
2021-08-09 14:49:17 +12:00
rbygrave c610f95b2d #2293 - Metric hash back to MD5 of sql + name + loc (minus location file and line source) ~= Revert of #2288 2021-08-09 14:05:10 +12:00
rbygrave c4484c758e [maven-release-plugin] prepare for next development iteration 2021-08-06 14:56:15 +12:00
rbygrave ee615836ba [maven-release-plugin] prepare release ebean-parent-12.11.0 2021-08-06 14:56:09 +12:00
rbygrave fea7de42d5 #2290 - Add MetaTimedMetric locationHash() which is a crc32 checksum of package + type + method (excludes line number) 2021-08-06 14:48:42 +12:00
Rob BygraveandGitHub 4787303160 Merge pull request #2289 from ebean-orm/feature/meta-api
Refactor io.ebean.meta API, method rename with deprecation
2021-08-06 13:17:08 +12:00
rbygrave 801d419f51 Refactor io.ebean.meta API, method rename with deprecation 2021-08-06 13:14:29 +12:00
Rob BygraveandGitHub 3579557200 Merge pull request #2288 from ebean-orm/feature/sql-hash
Change query metric hash from MD5 of sql + name + loc to Checksum of sql (+ rename to sqlHash)
2021-08-06 12:52:42 +12:00
rbygrave 202d785710 Rename hash to sqlHash to better reflect what it is (CRC32 checksum of the sql) 2021-08-06 12:06:43 +12:00
rbygrave 7ca72a39b1 Change query metric hash from MD5 of sql + name + loc to Checksum of sql 2021-08-06 11:52:38 +12:00
rbygrave f34e0f5f2b #2287 - ebean-migration: For multiple platforms automatically run the correct migrations 2021-08-05 23:03:02 +12:00
rbygrave d98a31fa6b Bump to 12.11.0-SNAPSHOT 2021-08-05 16:53:51 +12:00
rbygrave 9a82dbb3e6 Bump parent to java8-oss 3.2 with GPG maven plugin active only with "release" profile
The GPG maven plugin is now only active with the "release" profile
use -P release when we want to release with GPG signing
2021-08-05 13:17:32 +12:00
rbygrave a76442641b Tidy test only - rename ServerConfigTest to DatabaseConfigTest and tidy 2021-08-05 13:14:00 +12:00
rbygrave 2043fdf7e1 #2274 Add DatabaseConfig jsonMutationDetection property setting the global default mode 2021-08-05 13:12:18 +12:00
rbygrave a06f7bea41 Tidy javadoc for MutableValueInfo 2021-08-05 12:55:42 +12:00
rbygrave db34afe867 #2284 - ENH: ddl-generator - add optional generation of idx_<platform>.migrations file 2021-08-03 00:03:02 +12:00
rbygrave 589ee7a5ea #2284 - ENH: ddl-generator - add optional generation of idx_<platform>.migrations file 2021-08-02 23:59:49 +12:00
rbygrave 4ba26ee7b7 #2283 - ddl-generator - Refactor tidy DefaultDbMigration etc 2021-08-02 20:49:30 +12:00
rbygrave 71223895ac #2283 - ddl-generator - Refactor tidy whitespace etc 2021-08-02 20:38:05 +12:00
rbygrave 928b90122f #2283 - ddl-generator - Add DbMigration.addPlatform(Platform) with default sub-directory based on Platform 2021-08-02 20:15:51 +12:00
rbygrave d601a88d82 #2278 - Move null to empty json collections check to BeanPropertyJsonBasic 2021-07-30 23:53:28 +12:00
rbygrave 443e826f61 #2278 - Embedded bean override with DbJson property 2021-07-30 23:22:06 +12:00
rbygrave 2691221168 #2278 - Do not override empty json collections, when database value is null 2021-07-30 22:53:51 +12:00
rbygrave e62bb3dc6b Merge branch 'pr/bugfix/null_to_empty_json_collection' of https://github.com/FOCONIS/ebean into FOCONIS-pr/bugfix/null_to_empty_json_collection 2021-07-30 22:51:40 +12:00
Rob BygraveandGitHub 604099429e Merge pull request #2282 from ebean-orm/feature/json-mutable-collections
Treat json Jackson collections the same wrt mutation detection
2021-07-30 21:15:04 +12:00
Rob BygraveandGitHub 11dc7f64ba Merge pull request #2274 from ebean-orm/feature/json-dirty-detection-md5
Add support for JSON bean mutation detection via HASH and SOURCE of JSON string content
2021-07-30 21:11:42 +12:00
rbygrave ceea705a76 Treat json Jackson collections the same wrt mutation detection 2021-07-30 20:20:03 +12:00
rbygrave d9f7531e81 Tidy tests only - TestDbJson_Jackson3 TestJacksonPlainBean 2021-07-30 17:26:46 +12:00
rbygrave 7bd7640c63 Update test TestDbJson_Jackson3 showing HASH mode is used even on ModifyAwareType 2021-07-30 17:18:28 +12:00
rbygrave ca1636ff9e Fix when json/jackson bean inserted as null and not changed
Expectation is that it is not included in update (still null, no change)
2021-07-30 17:16:05 +12:00
rbygrave ea741d0169 Update TestDbJson_Jackson3 with comments 2021-07-30 15:41:52 +12:00
rbygrave c43e2e6956 Update TestDbJson_Jackson3 2021-07-30 15:34:54 +12:00
rbygrave 03004452ac ebean.mf set back to synthetic: true 2021-07-30 14:53:32 +12:00
rbygrave a470877017 Update kotlin-querybean-generator pom to make kotlin in IntelliJ happy 2021-07-30 14:52:49 +12:00
rbygrave 777d322222 #2279 - Remove _ebean_getMarker() from EntityBean interface - not actually required 2021-07-30 14:51:38 +12:00
Jonas Pöhler 4cebb367de FIX: subquery could not not have a where clause 2021-07-29 17:09:24 +02:00
Jonas Pöhler 1f0ac1f1c1 ADD: Testcases for List and Map as well 2021-07-29 16:50:08 +02:00
Jonas Pöhler (JPo) 1fad6e910c FIX: do not override empty (json) collections with null
Original: https://github.com/ebean-orm/ebean/commit/5551c35ec2496a9d62ab0afcaecbed739f17aa7c
Signed-off-by: Jonas Pöhler (JPo) <jonas.poehler@foconis.de>
2021-07-29 15:53:44 +02:00
rbygrave 822fb7325a Due to mutableNext handling, with checkMutableProperties() even when known dirty go into beanProperty.checkMutable()
As per rPraml's PR and comment

Due to handling of mutableNext we need  checkMutableProperties() to call into what is now beanProperty.checkMutable() even when we already know it's dirty.
2021-07-29 23:37:29 +12:00
rbygrave 20e0eb1021 Re-enable TestDbJson_Jackson3 via adding mutationDetection = HASH to beanList property
@DbJsonB(mutationDetection = HASH)
  List<PlainBean> beanList;
2021-07-29 23:17:11 +12:00
rbygrave 20becf951d Use MutationDetection replacing dirtyDetection and keepSource
Also adds NoMutationDetection to support NONE
2021-07-29 23:11:42 +12:00
rbygrave 5aa8557168 Update tests only - TestJacksonPlainBean with dirtyDetection = false property 2021-07-29 16:29:10 +12:00
rbygrave c66d248e96 Add MutableValueNext to replace mutableContent such that hash compute is only done once
Adds MutableValueInfo.nextDirty() to replace the isEqualToJson() method. The next is computed once and stored. BindablePropertyJsonUpdate makes the .mutableNext(propertyIndex) call to move the next MutableValueInfo and return the json content.
2021-07-29 15:42:16 +12:00
rbygrave 0d8e7c852b Change Checksum to use CRC32 2021-07-29 15:32:06 +12:00
rbygrave 991c6d6b5c No effective change - tidy FactoryProperty 2021-07-29 13:30:15 +12:00
rbygrave 2bc5d3d325 Refactor rename MutableHash to MutableValueInfo (and subsequent rename on methods etc) 2021-07-29 13:20:30 +12:00
rbygrave 5ad8e7ead4 Use new @DbJson dirtyDetection and keepSource attributes
- Bump ebean-annotation with new @DbJson dirtyDetection and keepSource attributes
- Get those to BeanPropertyJsonMapper to chose MutableHash implementation
- Modify MD5MutableHash to include check for isDirty()
- EBasicJsonList needs keepSource=true to pass that test with oldValue
2021-07-29 12:47:10 +12:00
rbygrave 8832bbc57f No effective change - format EntityBeanIntercept only
Plus adjust timing on SqlQueryCancelTest
2021-07-29 12:43:37 +12:00
rbygrave 86483ff947 Use scalarType.format(value) removing scalarType.jsonMapper(value)
Remove scalarType.jsonMapper(value) as we can just use format(value) instead
2021-07-29 11:52:15 +12:00
rbygrave 92d7a7562f Tidy only - no functional change to MutableHash and BeanPropertyJsonMapper 2021-07-29 11:49:01 +12:00
rbygrave 52fe3cf3c8 Change from MD5 to Checksum (Adler32) for json content dirty detection 2021-07-29 11:40:05 +12:00
rbygrave 94fb6414fa Refactor move createMutableHash() method from ScalarType to BeanProperty / BeanPropertyJsonMapper 2021-07-29 11:28:25 +12:00
rbygrave d0270dbc6a Temporarily disable TestDbJson_Jackson3 updateIncludesJsonColumn_when_list_loadedAndNotDirtyAware()
BeanState state = DB.getBeanState(found);
    assertThat(state.getChangedProps()).containsExactlyInAnyOrder("beanList");
    // this test fails, because we have a OmList instead of a GenericObject
    // TODO: Can/Should we enhance the @DbJson/@DbJsonB annotations with a property "dirtyDetection"
2021-07-29 11:21:38 +12:00
rbygrave 11a047bf8e Merge branch 'FOCONIS-feature/json-dirty-detection-md5' into feature/json-dirty-detection-md5 2021-07-29 10:27:28 +12:00
Roland Praml eb70c7e196 some javadoc and refactored getOrigValue 2021-07-28 17:36:53 +02:00
Roland Praml b497b8635b some refactor and tidying 2021-07-28 17:22:29 +02:00
Roland Praml 5e595ec5f8 Proof of concept to support also bean change detection / changelog on mutable properties 2021-07-28 14:54:56 +02:00
rbygrave 49b86d07d3 Modify SqlBeanLoad to use readSet()
Note that we don't need to use readSetIntercept() now as there is no property change listener support
2021-07-28 22:48:29 +12:00
rbygrave 11eed4cfe9 Add BeanPropertyJsonMapper for JSON dirty detection 2021-07-28 21:43:57 +12:00
rbygrave 4aef0ad459 #2275 - Change Query<?> to Query<T> on ExtendedServer exists() method 2021-07-28 17:23:37 +12:00
Rob BygraveandGitHub 21cd74d0ca Merge pull request #2273 from ebean-orm/feature/2272
#2272 Fix for collection with orphanRemoval (such that equals/hashCode isn't use)
2021-07-28 17:14:09 +12:00
rbygrave 6c262f1df5 JSON bean dirty detection via MD5 of JSON string content
- MD5 of json content stored on EntityBeanIntercept for dirty detection
- Only convert to JSON once (at dirty detection time). Store this json content on EntityBeanIntercept to later push to ScalarTypeJsonObjectMapper for bind

Should consider alternative to extend BeanProperty rather than have these if blocks.
2021-07-23 16:50:24 +12:00
rbygrave f32ace4e5a Refactor EntityBeanIntercept replacing owner._ebean_getPropertyNames().length with flags.length 2021-07-23 13:54:29 +12:00
rbygrave e54b7052e0 #2272 Fix for collection with orphanRemoval (such that equals/hashCode isn't use)
- Changes ModifyHolder to use IdentityHashMap such that equals/hashcode isn't invoked
- Change SaveManyBeans such that M2M intersection deletes execute before inserts

The SaveManyBeans change is required to pass TestM2MModifyTest. With that test we get a delete/insert pair that we somewhat expect because we clear() the collection. Previously equals/hashCode meant we didn't get that delete/insert pair.

The test changes from containsExactly() to containsOnly() as we now can't guarantee the ordering with IdentityHashMap.
2021-07-23 12:18:06 +12:00
rbygrave b40d448955 #2272 No effective change, tidy test TestM2MModifyTest only
Noting that this test fails with the fix for 2272 as M2M intersection deletes are currently executed after inserts. We need a fix to SaveManyBeans to change that so that deletes to intersection table execute after inserts.
2021-07-23 12:01:36 +12:00
rbygrave 33bccd3bcb [maven-release-plugin] prepare for next development iteration 2021-07-22 19:03:54 +12:00
Jonas Pöhler 60ef87b269 Merge remote-tracking branch 'ebean/master' into pr/enh/softreference_in_cache 2021-07-16 15:29:33 +02:00
Roland Praml 7e265f7bde FIX: SubQuery with fetch-path does not work correctly 2021-07-13 09:09:30 +02:00
Jonas Pöhler (JPo) bd7499a505 Use SoftReference in Cache, so it can be gc'ed if the jvm runs out of memory
Signed-off-by: Jonas Pöhler (JPo) <jonas.poehler@foconis.de>
2021-03-29 13:23:56 +02:00
915 changed files with 8092 additions and 6306 deletions
-6
View File
@@ -1,9 +1,3 @@
GITHUB ISSUES ARE STRICTLY CONTROLLED FOR THIS PROJECT.
Refer to http://ebean-orm.github.io/support for the policies controlling the use of github issues.
Please post issues to the Ebean group https://groups.google.com/forum/#!forum/ebean first.
## Expected behavior
## Actual behavior
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>12.10.0</version>
<version>12.11.2</version>
</parent>
<name>ebean api</name>
@@ -50,7 +50,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-annotation</artifactId>
<version>7.0</version>
<version>7.2</version>
</dependency>
<dependency>
@@ -118,4 +118,9 @@ public interface BeanState {
*/
@Nullable
Map<String, Exception> getLoadErrors();
/**
* Return the sort order value for an order column.
*/
int getSortOrder();
}
@@ -16,18 +16,15 @@ import java.util.concurrent.locks.ReentrantLock;
* <p>
* This uses either DatabaseConfig or properties in the application.properties file to
* configure and create a Database instance.
* </p>
* <p>
* The Database instance can either be registered with the DB singleton or
* not. The DB singleton effectively holds a map of Database by a name.
* If the Database is registered with the DB singleton you can retrieve it
* later via {@link DB#byName(String)}.
* </p>
* <p>
* One Database can be nominated as the 'default/primary' Database. Many
* methods on the DB singleton such as {@link DB#find(Class)} are just a
* convenient way of using the 'default/primary' Database.
* </p>
*/
public class DatabaseFactory {
@@ -48,7 +45,7 @@ public class DatabaseFactory {
public static void initialiseContainer(ContainerConfig containerConfig) {
lock.lock();
try {
getContainer(containerConfig);
container(containerConfig);
} finally {
lock.unlock();
}
@@ -60,7 +57,7 @@ public class DatabaseFactory {
public static Database create(String name) {
lock.lock();
try {
return getContainer(null).createServer(name);
return container(null).createServer(name);
} finally {
lock.unlock();
}
@@ -68,6 +65,16 @@ public class DatabaseFactory {
/**
* Create using the DatabaseConfig object to configure the database.
*
* <pre>{@code
*
* DatabaseConfig config = new DatabaseConfig();
* config.setName("db");
* config.loadProperties();
*
* Database database = DatabaseFactory.create(config);
*
* }</pre>
*/
public static Database create(DatabaseConfig config) {
lock.lock();
@@ -115,7 +122,6 @@ public class DatabaseFactory {
* Shutdown gracefully all Database instances cleaning up any resources as required.
* <p>
* This is typically invoked via JVM shutdown hook and not explicitly called.
* </p>
*/
public static void shutdown() {
lock.lock();
@@ -127,15 +133,15 @@ public class DatabaseFactory {
}
private static Database createInternal(DatabaseConfig config) {
return getContainer(config.getContainerConfig()).createServer(config);
return container(config.getContainerConfig()).createServer(config);
}
/**
* Get the EbeanContainer initialising it if necessary.
* Return the SpiContainer initialising it if necessary.
*
* @param containerConfig the configuration controlling clustering communication
*/
private static SpiContainer getContainer(ContainerConfig containerConfig) {
private static SpiContainer container(ContainerConfig containerConfig) {
// thread safe in that all calling methods hold lock
if (container != null) {
return container;
@@ -67,7 +67,7 @@ public interface ExtendedServer {
*
* @return True if the query finds a matching row in the database
*/
<T> boolean exists(Query<?> ormQuery, Transaction transaction);
<T> boolean exists(Query<T> ormQuery, Transaction transaction);
/**
* Return the number of 'top level' or 'root' entities this query should return.
@@ -27,17 +27,6 @@ public interface EntityBean extends Serializable {
throw new NotEnhancedException();
}
/**
* Return the enhancement marker value.
* <p>
* This is the class name of the enhanced class and used to check that all
* entity classes are enhanced (specifically not just a super class).
* </p>
*/
default String _ebean_getMarker() {
throw new NotEnhancedException();
}
/**
* Create and return a new entity bean instance.
*/
@@ -51,6 +51,11 @@ public final class EntityBeanIntercept implements Serializable {
*/
private static final byte FLAG_ORIG_VALUE_SET = 8;
/**
* Flags indicating if the mutable hash is set.
*/
private static final byte FLAG_MUTABLE_HASH_SET = 16;
private transient final ReentrantLock lock = new ReentrantLock();
private transient NodeUsageCollector nodeUsageCollector;
private transient PersistenceContext persistenceContext;
@@ -91,6 +96,17 @@ public final class EntityBeanIntercept implements Serializable {
private Object ownerId;
private int sortOrder;
/**
* Holds information of json loaded jackson beans (e.g. the original json or checksum).
*/
private MutableValueInfo[] mutableInfo;
/**
* Holds json content determined at point of dirty check.
* Stored here on dirty check such that we only convert to json once.
*/
private MutableValueNext[] mutableNext;
/**
* Create a intercept with a given entity.
*/
@@ -228,6 +244,17 @@ public final class EntityBeanIntercept implements Serializable {
* if any embedded beans are either new or dirty (and hence need saving).
*/
public boolean isDirty() {
if (dirty) {
return true;
}
if (mutableInfo != null) {
for (int i = 0; i < mutableInfo.length; i++) {
if (mutableInfo[i] != null && !mutableInfo[i].isEqualToObject(owner._ebean_getField(i))) {
dirty = true;
break;
}
}
}
return dirty;
}
@@ -368,8 +395,18 @@ public final class EntityBeanIntercept implements Serializable {
this.owner._ebean_setEmbeddedLoaded();
this.lazyLoadProperty = -1;
this.origValues = null;
// after save, transfer the mutable next values back to mutable info
if (mutableNext != null) {
for (int i = 0; i < mutableNext.length; i++) {
MutableValueNext next = mutableNext[i];
if (next != null) {
mutableInfo(i, next.info());
}
}
}
this.mutableNext = null;
for (int i = 0; i < flags.length; i++) {
flags[i] &= ~(FLAG_CHANGED_PROP + FLAG_ORIG_VALUE_SET);
flags[i] &= ~(FLAG_CHANGED_PROP | FLAG_ORIG_VALUE_SET);
}
this.dirty = false;
}
@@ -442,6 +479,10 @@ public final class EntityBeanIntercept implements Serializable {
* Return the original value that was changed via an update.
*/
public Object getOrigValue(int propertyIndex) {
if ((flags[propertyIndex] & (FLAG_ORIG_VALUE_SET | FLAG_MUTABLE_HASH_SET)) == FLAG_MUTABLE_HASH_SET) {
// mutable hash set, but not ORIG_VALUE
setOriginalValue(propertyIndex, mutableInfo[propertyIndex].get());
}
if (origValues == null) {
return null;
}
@@ -476,7 +517,7 @@ public final class EntityBeanIntercept implements Serializable {
* Return the number of properties.
*/
public int getPropertyLength() {
return owner._ebean_getPropertyNames().length;
return flags.length;
}
/**
@@ -564,7 +605,7 @@ public final class EntityBeanIntercept implements Serializable {
private void setOriginalValue(int propertyIndex, Object value) {
if (origValues == null) {
origValues = new Object[owner._ebean_getPropertyNames().length];
origValues = new Object[flags.length];
}
if ((flags[propertyIndex] & FLAG_ORIG_VALUE_SET) == 0) {
flags[propertyIndex] |= FLAG_ORIG_VALUE_SET;
@@ -577,7 +618,7 @@ public final class EntityBeanIntercept implements Serializable {
*/
private void setOriginalValueForce(int propertyIndex, Object value) {
if (origValues == null) {
origValues = new Object[owner._ebean_getPropertyNames().length];
origValues = new Object[flags.length];
}
origValues[propertyIndex] = value;
}
@@ -638,7 +679,7 @@ public final class EntityBeanIntercept implements Serializable {
public void addDirtyPropertyNames(Set<String> props, String prefix) {
int len = getPropertyLength();
for (int i = 0; i < len; i++) {
if ((flags[i] & FLAG_CHANGED_PROP) != 0) {
if (isChangedProp(i)) {
// the property has been changed on this bean
props.add((prefix == null ? getProperty(i) : prefix + getProperty(i)));
} else if ((flags[i] & FLAG_EMBEDDED_DIRTY) != 0) {
@@ -656,7 +697,7 @@ public final class EntityBeanIntercept implements Serializable {
String[] names = owner._ebean_getPropertyNames();
int len = getPropertyLength();
for (int i = 0; i < len; i++) {
if ((flags[i] & FLAG_CHANGED_PROP) != 0) {
if (isChangedProp(i)) {
if (propertyNames.contains(names[i])) {
return true;
}
@@ -684,7 +725,7 @@ public final class EntityBeanIntercept implements Serializable {
public void addDirtyPropertyValues(Map<String, ValuePair> dirtyValues, String prefix) {
int len = getPropertyLength();
for (int i = 0; i < len; i++) {
if ((flags[i] & FLAG_CHANGED_PROP) != 0) {
if (isChangedProp(i)) {
// the property has been changed on this bean
String propName = (prefix == null ? getProperty(i) : prefix + getProperty(i));
Object newVal = owner._ebean_getField(i);
@@ -706,7 +747,7 @@ public final class EntityBeanIntercept implements Serializable {
public void addDirtyPropertyValues(BeanDiffVisitor visitor) {
int len = getPropertyLength();
for (int i = 0; i < len; i++) {
if ((flags[i] & FLAG_CHANGED_PROP) != 0) {
if (isChangedProp(i)) {
// the property has been changed on this bean
Object newVal = owner._ebean_getField(i);
Object oldVal = getOrigValue(i);
@@ -741,7 +782,7 @@ public final class EntityBeanIntercept implements Serializable {
}
int len = getPropertyLength();
for (int i = 0; i < len; i++) {
if ((flags[i] & FLAG_CHANGED_PROP) != 0) {
if ((flags[i] & FLAG_CHANGED_PROP) != 0) { // we do not check against mutablecontent here.
sb.append(i).append(',');
} else if ((flags[i] & FLAG_EMBEDDED_DIRTY) != 0) {
// an embedded property has been changed - recurse
@@ -1112,7 +1153,7 @@ public final class EntityBeanIntercept implements Serializable {
*/
public void setLoadError(int propertyIndex, Exception t) {
if (loadErrors == null) {
loadErrors = new Exception[owner._ebean_getPropertyNames().length];
loadErrors = new Exception[flags.length];
}
loadErrors[propertyIndex] = t;
flags[propertyIndex] |= FLAG_LOADED_PROP;
@@ -1138,4 +1179,61 @@ public final class EntityBeanIntercept implements Serializable {
}
return ret;
}
private boolean isChangedProp(int i) {
if ((flags[i] & FLAG_CHANGED_PROP) != 0) {
return true;
} else if (mutableInfo == null || mutableInfo[i] == null || mutableInfo[i].isEqualToObject(owner._ebean_getField(i))) {
return false;
} else {
// mark for change
flags[i] |= FLAG_CHANGED_PROP;
dirty = true; // this makes the bean automatically dirty!
return true;
}
}
/**
* Return the MutableValueInfo for the given property or null.
*/
public MutableValueInfo mutableInfo(int propertyIndex) {
return mutableInfo == null ? null : mutableInfo[propertyIndex];
}
/**
* Set the MutableValueInfo for the given property.
*/
public void mutableInfo(int propertyIndex, MutableValueInfo info) {
if (mutableInfo == null) {
mutableInfo = new MutableValueInfo[flags.length];
}
flags[propertyIndex] |= FLAG_MUTABLE_HASH_SET;
mutableInfo[propertyIndex] = info;
}
/**
* Dirty detection set the next mutable property content and info .
* <p>
* Set here as the mutable property dirty detection is based on json content comparison.
* We only want to perform the json serialisation once so storing it here as part of
* dirty detection so that we can get it back to bind in insert or update etc.
*/
public void mutableNext(int propertyIndex, MutableValueNext next) {
if (mutableNext == null) {
mutableNext = new MutableValueNext[flags.length];
}
mutableNext[propertyIndex] = next;
}
/**
* Update the 'next' mutable info returning the content that was obtained via dirty detection.
*/
public String mutableNext(int propertyIndex) {
if (mutableNext == null) {
return null;
}
final MutableValueNext next = mutableNext[propertyIndex];
return next != null ? next.content() : null;
}
}
@@ -0,0 +1,42 @@
package io.ebean.bean;
/**
* Holds information on mutable values (like plain beans stored as json).
* <p>
* Used internally in EntityBeanIntercept for dirty detection on mutable values.
* Typically, mutation detection is based on a hash/checksum of json content or the
* original json content itself.
* <p>
* Refer to the mapping options {@code @DbJson(mutationDetection)}.
*/
public interface MutableValueInfo {
/**
* Compares the given json returning null if deemed unchanged or returning
* the MutableValueNext to use if deemed dirty/changed.
* <p>
* Returning MutableValueNext allows an implementation based on hash/checksum
* to only perform that computation once.
*
* @return Null if deemed unchanged or the MutableValueNext if deemed changed.
*/
MutableValueNext nextDirty(String json);
/**
* Compares the given object to an internal value.
* <p>
* This is used to support changelog/beanState. The implementation can serialize the
* object into json form and compare it against the original json.
*/
boolean isEqualToObject(Object obj);
/**
* Creates a new instance from the internal json string.
* <p>
* This is used to provide an original/old value for change logging / persist listeners.
* This is only available for properties that have {@code @DbJson(keepSource=true)}.
*/
default Object get() {
return null;
}
}
@@ -0,0 +1,17 @@
package io.ebean.bean;
/**
* Represents a next value to use for mutable content properties (DbJson with jackson beans).
*/
public interface MutableValueNext {
/**
* Return the next content to use. Provided such that we serialise to json once.
*/
String content();
/**
* Return the next MutableValueInfo to use after an update.
*/
MutableValueInfo info();
}
@@ -3,9 +3,7 @@ package io.ebean.common;
import io.ebean.bean.EntityBean;
import java.io.Serializable;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.*;
/**
* Holds sets of additions and deletions from a 'owner' List Set or Map.
@@ -23,19 +21,19 @@ class ModifyHolder<E> implements Serializable {
/**
* Deletions list for manyToMany persistence.
*/
private Set<E> modifyDeletions = new LinkedHashSet<>();
private Map<E,Object> modifyDeletions = new IdentityHashMap<>();
/**
* Additions list for manyToMany persistence.
*/
private Set<E> modifyAdditions = new LinkedHashSet<>();
private Map<E,Object> modifyAdditions = new IdentityHashMap<>();
private boolean touched;
void reset() {
touched = false;
modifyDeletions = new LinkedHashSet<>();
modifyAdditions = new LinkedHashSet<>();
modifyDeletions = new IdentityHashMap<>();
modifyAdditions = new IdentityHashMap<>();
}
/**
@@ -50,51 +48,46 @@ class ModifyHolder<E> implements Serializable {
}
private boolean undoDeletion(E bean) {
return (bean != null) && modifyDeletions.remove(bean);
return (bean != null) && modifyDeletions.remove(bean) != null;
}
void modifyAddition(E bean) {
if (bean != null) {
touched = true;
if (bean instanceof EntityBean) {
((EntityBean) bean)._ebean_getIntercept().setDeletedFromCollection(false);
}
// If it is to delete then just remove the deletion
if (!undoDeletion(bean)) {
// Insert
modifyAdditions.add(bean);
modifyAdditions.put(bean, bean);
}
}
}
private boolean undoAddition(Object bean) {
return (bean != null) && modifyAdditions.remove(bean);
return (bean != null) && modifyAdditions.remove(bean) != null;
}
@SuppressWarnings("unchecked")
void modifyRemoval(Object bean) {
if (bean != null) {
touched = true;
if (bean instanceof EntityBean) {
((EntityBean) bean)._ebean_getIntercept().setDeletedFromCollection(true);
}
// If it is to be added then just remove the addition
if (!undoAddition(bean)) {
modifyDeletions.add((E) bean);
modifyDeletions.put((E) bean, bean);
}
}
}
Set<E> getModifyAdditions() {
return modifyAdditions;
return modifyAdditions.keySet();
}
Set<E> getModifyRemovals() {
return modifyDeletions;
return modifyDeletions.keySet();
}
/**
@@ -7,9 +7,7 @@ import io.ebean.EbeanVersion;
import io.ebean.PersistenceContextScope;
import io.ebean.Query;
import io.ebean.Transaction;
import io.ebean.annotation.Encrypted;
import io.ebean.annotation.PersistBatch;
import io.ebean.annotation.Platform;
import io.ebean.annotation.*;
import io.ebean.cache.ServerCachePlugin;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.config.dbplatform.DbEncrypt;
@@ -194,10 +192,9 @@ public class DatabaseConfig {
private JsonConfig.Include jsonInclude = JsonConfig.Include.ALL;
/**
* When true then by default DbJson beans are assumed to be dirty.
* I believe we want to change this default to false in the future.
* The default mode used for {@code @DbJson} with Jackson ObjectMapper.
*/
private boolean jsonDirtyByDefault = true;
private MutationDetection jsonMutationDetection = MutationDetection.HASH;
/**
* The database platform name. Used to imply a DatabasePlatform to use.
@@ -322,6 +319,8 @@ public class DatabaseConfig {
*/
private ExternalTransactionManager externalTransactionManager;
private boolean skipDataSourceCheck;
/**
* The data source (if programmatically provided).
*/
@@ -744,23 +743,21 @@ public class DatabaseConfig {
}
/**
* Return true if DbJson beans are assumed dirty by default.
* <p>
* That is, when true beans that do not implement ModifyAwareType are by
* default assumed to be dirty and included in updates.
* Return the default MutableDetection to use with {@code @DbJson} using Jackson.
*
* @see DbJson#mutationDetection()
*/
public boolean isJsonDirtyByDefault() {
return jsonDirtyByDefault;
public MutationDetection getJsonMutationDetection() {
return jsonMutationDetection;
}
/**
* Set to false if we want DbJson beans to not be assumed to be dirty.
* <p>
* That is, when true beans that do not implement ModifyAwareType are by
* default assumed to be dirty and included in updates.
* Set the default MutableDetection to use with {@code @DbJson} using Jackson.
*
* @see DbJson#mutationDetection()
*/
public void setJsonDirtyByDefault(boolean jsonDirtyByDefault) {
this.jsonDirtyByDefault = jsonDirtyByDefault;
public void setJsonMutationDetection(MutationDetection jsonMutationDetection) {
this.jsonMutationDetection = jsonMutationDetection;
}
/**
@@ -1656,6 +1653,20 @@ public class DatabaseConfig {
this.autoTuneConfig = autoTuneConfig;
}
/**
* Return true if the startup DataSource check should be skipped.
*/
public boolean skipDataSourceCheck() {
return skipDataSourceCheck;
}
/**
* Set to true to skip the startup DataSource check.
*/
public void setSkipDataSourceCheck(boolean skipDataSourceCheck) {
this.skipDataSourceCheck = skipDataSourceCheck;
}
/**
* Return the DataSource.
*/
@@ -2935,8 +2946,9 @@ public class DatabaseConfig {
jsonInclude = p.getEnum(JsonConfig.Include.class, "jsonInclude", jsonInclude);
jsonDateTime = p.getEnum(JsonConfig.DateTime.class, "jsonDateTime", jsonDateTime);
jsonDate = p.getEnum(JsonConfig.Date.class, "jsonDate", jsonDate);
jsonDirtyByDefault = p.getBoolean("jsonDirtyByDefault", jsonDirtyByDefault);
jsonMutationDetection = p.getEnum(MutationDetection.class, "jsonMutationDetection", jsonMutationDetection);
skipDataSourceCheck = p.getBoolean("skipDataSourceCheck", skipDataSourceCheck);
runMigration = p.getBoolean("migration.run", runMigration);
ddlGenerate = p.getBoolean("ddl.generate", ddlGenerate);
ddlRun = p.getBoolean("ddl.run", ddlRun);
@@ -14,10 +14,9 @@ import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
/**
* Manages the shutdown of the JVM Runtime.
* Manages the shutdown of Ebean.
* <p>
* Makes sure all the resources are shutdown properly and in order.
* </p>
*/
public final class ShutdownManager {
@@ -44,6 +43,9 @@ public final class ShutdownManager {
private ShutdownManager() {
}
/**
* Registers the container (potentially with cluster management).
*/
public static void registerContainer(SpiContainer ebeanContainer) {
container = ebeanContainer;
}
@@ -94,7 +96,7 @@ public final class ShutdownManager {
/**
* Register the shutdown hook with the Runtime.
*/
protected static void registerShutdownHook() {
private static void registerShutdownHook() {
lock.lock();
try {
String value = System.getProperty("ebean.registerShutdownHook");
@@ -123,13 +125,10 @@ public final class ShutdownManager {
// Already run shutdown...
return;
}
if (logger.isDebugEnabled()) {
logger.debug("Shutting down");
}
stopping = true;
deregisterShutdownHook();
String shutdownRunner = System.getProperty("ebean.shutdown.runnable");
@@ -147,7 +146,6 @@ public final class ShutdownManager {
// shutdown cluster networking if active
container.shutdown();
}
// shutdown any registered servers that have not
// already been shutdown manually
for (Database server : databases) {
@@ -158,7 +156,6 @@ public final class ShutdownManager {
ex.printStackTrace();
}
}
if ("true".equalsIgnoreCase(System.getProperty("ebean.datasource.deregisterAllDrivers", "false"))) {
deregisterAllJdbcDrivers();
}
@@ -168,15 +165,15 @@ public final class ShutdownManager {
}
private static void deregisterAllJdbcDrivers() {
// This manually deregisters all JDBC drivers
// This manually de-registers all JDBC drivers
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = drivers.nextElement();
try {
logger.info("Deregistering jdbc driver: " + driver);
logger.info("De-registering jdbc driver: " + driver);
DriverManager.deregisterDriver(driver);
} catch (SQLException e) {
logger.error("Error deregistering driver " + driver, e);
logger.error("Error de-registering driver " + driver, e);
}
}
}
@@ -209,6 +206,9 @@ public final class ShutdownManager {
}
private static class ShutdownHook extends Thread {
private ShutdownHook() {
super("EbeanHook");
}
@Override
public void run() {
ShutdownManager.shutdown();
@@ -18,22 +18,22 @@ public abstract class AbstractMetricVisitor implements MetricVisitor {
}
@Override
public boolean isReset() {
public boolean reset() {
return reset;
}
@Override
public boolean isCollectTransactionMetrics() {
public boolean collectTransactionMetrics() {
return collectTransactionMetrics;
}
@Override
public boolean isCollectQueryMetrics() {
public boolean collectQueryMetrics() {
return collectQueryMetrics;
}
@Override
public boolean isCollectL2Metrics() {
public boolean collectL2Metrics() {
return collectL2Metrics;
}
@@ -27,17 +27,17 @@ public class BasicMetricVisitor extends AbstractMetricVisitor implements ServerM
}
@Override
public List<MetaTimedMetric> getTimedMetrics() {
public List<MetaTimedMetric> timedMetrics() {
return timed;
}
@Override
public List<MetaQueryMetric> getQueryMetrics() {
public List<MetaQueryMetric> queryMetrics() {
return query;
}
@Override
public List<MetaCountMetric> getCountMetrics() {
public List<MetaCountMetric> countMetrics() {
return count;
}
@@ -8,6 +8,13 @@ public interface MetaCountMetric extends MetaMetric {
/**
* Return the total count.
*/
long getCount();
long count();
/**
* Migrate to count()
*/
@Deprecated
default long getCount() {
return count();
}
}
@@ -8,6 +8,13 @@ public interface MetaMetric {
/**
* Return the metric name.
*/
String getName();
String name();
/**
* Migrate to name().
*/
@Deprecated
default String getName() {
return name();
}
}
@@ -8,21 +8,45 @@ public interface MetaQueryMetric extends MetaTimedMetric {
/**
* The type of entity or DTO bean.
*/
Class<?> getType();
Class<?> type();
/**
* Migrate to type().
*/
@Deprecated
default Class<?> getType() {
return type();
}
/**
* The label for the query (can be null).
*/
String getLabel();
String label();
/**
* Migrate to label().
*/
@Deprecated
default String getLabel() {
return label();
}
/**
* The actual SQL of the query.
*/
String getSql();
String sql();
/**
* Migrate to sql().
*/
@Deprecated
default String getSql() {
return sql();
}
/**
* Return the hash of the plan.
*/
String getHash();
String hash();
}
@@ -10,45 +10,45 @@ public interface MetaQueryPlan {
/**
* Return the bean type for the query.
*/
Class<?> getBeanType();
Class<?> beanType();
/**
* Return the label of the query.
*/
String getLabel();
String label();
/**
* Return the profile location for the query.
*/
ProfileLocation getProfileLocation();
ProfileLocation profileLocation();
/**
* Return the sql of the query.
*/
String getSql();
String sql();
/**
* Return the hash of the plan.
*/
String getHash();
String hash();
/**
* Return a description of the bind values.
*/
String getBind();
String bind();
/**
* Return the raw plan.
*/
String getPlan();
String plan();
/**
* Return the query execution time associated with the bind values capture.
*/
long getQueryTimeMicros();
long queryTimeMicros();
/**
* Return the total count of times bind capture has occurred.
*/
long getCaptureCount();
long captureCount();
}
@@ -9,27 +9,68 @@ public interface MetaTimedMetric extends MetaMetric {
/**
* Return the metric location if defined.
*/
String getLocation();
String location();
/**
* Migrate to location()
*/
@Deprecated
default String getLocation() {
return location();
}
/**
* Return the total count.
*/
long getCount();
long count();
/**
* Migrate to count()
*/
@Deprecated
default long getCount() {
return count();
}
/**
* Return the total execution time in micros.
*/
long getTotal();
long total();
/**
* Migrate to total()
*/
@Deprecated
default long getTotal() {
return total();
}
/**
* Return the max execution time in micros.
*/
long getMax();
long max();
/**
* Migrate to max()
*/
@Deprecated
default long getMax() {
return max();
}
/**
* Return the mean execution time in micros.
*/
long getMean();
long mean();
/**
* Migrate to mean()
*/
@Deprecated
default long getMean() {
return mean();
}
/**
* Return true if this is the first metrics collection for this query.
@@ -8,22 +8,22 @@ public interface MetricVisitor {
/**
* Return true if the metrics should be reset.
*/
boolean isReset();
boolean reset();
/**
* Return true if we should visit the transaction metrics.
*/
boolean isCollectTransactionMetrics();
boolean collectTransactionMetrics();
/**
* Return true if we should visit the ORM and SQL query metrics.
*/
boolean isCollectQueryMetrics();
boolean collectQueryMetrics();
/**
* Return true if we should visit the L2 cache metrics.
*/
boolean isCollectL2Metrics();
boolean collectL2Metrics();
/**
* Visit has started.
@@ -32,7 +32,7 @@ public class QueryPlanInit {
* Return the query execution time threshold which must be exceeded to initiate
* query plan collection.
*/
public long getThresholdMicros() {
public long thresholdMicros() {
return thresholdMicros;
}
@@ -40,7 +40,7 @@ public class QueryPlanInit {
* Set the query execution time threshold which must be exceeded to initiate
* query plan collection.
*/
public void setThresholdMicros(long thresholdMicros) {
public void thresholdMicros(long thresholdMicros) {
this.thresholdMicros = thresholdMicros;
}
@@ -54,14 +54,14 @@ public class QueryPlanInit {
/**
* Return the specific hashes that we want to collect query plans on.
*/
public Set<String> getHashes() {
public Set<String> hashes() {
return hashes;
}
/**
* Set the specific hashes that we want to collect query plans on.
*/
public void setHashes(Set<String> hashes) {
public void hashes(Set<String> hashes) {
this.hashes = hashes;
}
}
@@ -18,7 +18,7 @@ public class QueryPlanRequest {
* have been around for a while (e.g. 5 mins) and so reasonably represent
* bind values that match the slowest execution for this query plan.
*/
public long getSince() {
public long since() {
return since;
}
@@ -28,14 +28,14 @@ public class QueryPlanRequest {
*
* @param since The minimum age of the bind values capture.
*/
public void setSince(long since) {
public void since(long since) {
this.since = since;
}
/**
* Return the maximum number of plans to capture.
*/
public int getMaxCount() {
public int maxCount() {
return maxCount;
}
@@ -45,7 +45,7 @@ public class QueryPlanRequest {
* Use this to limit how much query plan capturing is done as query
* plan capture is actual database load.
*/
public void setMaxCount(int maxCount) {
public void maxCount(int maxCount) {
this.maxCount = maxCount;
}
@@ -54,7 +54,7 @@ public class QueryPlanRequest {
* <p>
* Query plan collection will stop once this time is exceeded.
*/
public long getMaxTimeMillis() {
public long maxTimeMillis() {
return maxTimeMillis;
}
@@ -65,7 +65,7 @@ public class QueryPlanRequest {
* this to ensure the query plan capture does not use excessive amount
* of time - put too much load on the database.
*/
public void setMaxTimeMillis(long maxTimeMillis) {
public void maxTimeMillis(long maxTimeMillis) {
this.maxTimeMillis = maxTimeMillis;
}
}
@@ -10,16 +10,39 @@ public interface ServerMetrics {
/**
* Return timed metrics for Transactions, labelled SqlQuery, labelled SqlUpdate.
*/
List<MetaTimedMetric> getTimedMetrics();
List<MetaTimedMetric> timedMetrics();
/**
* Migrate to timedMetrics().
*/
@Deprecated
default List<MetaTimedMetric> getTimedMetrics() {
return timedMetrics();
}
/**
* Return the query metrics.
*/
List<MetaQueryMetric> getQueryMetrics();
List<MetaQueryMetric> queryMetrics();
/**
* Migrate to queryMetrics().
*/
@Deprecated
default List<MetaQueryMetric> getQueryMetrics() {
return queryMetrics();
}
/**
* Return the Counter metrics.
*/
List<MetaCountMetric> getCountMetrics();
List<MetaCountMetric> countMetrics();
/**
* Migrate to countMetrics().
*/
@Deprecated
default List<MetaCountMetric> getCountMetrics() {
return countMetrics();
}
}
@@ -8,12 +8,12 @@ import java.util.Comparator;
public interface ServerMetricsAsJson {
/**
* Set to false to exclude profile location and sql.
* Set to false in order to exclude profile location and sql.
*/
ServerMetricsAsJson withExtraAttributes(boolean withLocation);
/**
* Set to false to exclude SQL hash.
* Set to false in order to exclude SQL hash.
*/
ServerMetricsAsJson withHash(boolean withHash);
@@ -32,7 +32,7 @@ public class SortMetric {
@Override
public int compare(MetaCountMetric o1, MetaCountMetric o2) {
return stringCompare(o1.getName(), o2.getName());
return stringCompare(o1.name(), o2.name());
}
}
@@ -43,8 +43,8 @@ public class SortMetric {
@Override
public int compare(MetaTimedMetric o1, MetaTimedMetric o2) {
int i = stringCompare(o1.getName(), o2.getName());
return i != 0 ? i : Long.compare(o1.getCount(), o2.getCount());
int i = stringCompare(o1.name(), o2.name());
return i != 0 ? i : Long.compare(o1.count(), o2.count());
}
}
@@ -55,7 +55,7 @@ public class SortMetric {
@Override
public int compare(MetaTimedMetric o1, MetaTimedMetric o2) {
return Long.compare(o2.getCount(), o1.getCount());
return Long.compare(o2.count(), o1.count());
}
}
@@ -66,7 +66,7 @@ public class SortMetric {
@Override
public int compare(MetaTimedMetric o1, MetaTimedMetric o2) {
return Long.compare(o2.getTotal(), o1.getTotal());
return Long.compare(o2.total(), o1.total());
}
}
@@ -77,7 +77,7 @@ public class SortMetric {
@Override
public int compare(MetaTimedMetric o1, MetaTimedMetric o2) {
return Long.compare(o2.getMean(), o1.getMean());
return Long.compare(o2.mean(), o1.mean());
}
}
@@ -88,7 +88,7 @@ public class SortMetric {
@Override
public int compare(MetaTimedMetric o1, MetaTimedMetric o2) {
return Long.compare(o2.getMax(), o1.getMax());
return Long.compare(o2.max(), o1.max());
}
}
}
+3 -3
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>12.10.0</version>
<version>12.11.2</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-12.10.0</tag>
<tag>ebean-parent-12.11.2</tag>
</scm>
<name>ebean autotune</name>
@@ -26,7 +26,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>12.10.0</version>
<version>12.11.2</version>
<scope>provided</scope>
</dependency>
@@ -146,7 +146,8 @@ public class BaseQueryTuner {
case ID_LIST:
case UPDATE:
case DELETE:
case SUBQUERY:
case SQ_EXISTS:
case SQ_IN:
return false;
default:
// not using autoTune when explicitly loading the l2 bean cache
+15 -25
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>12.10.0</version>
<version>12.11.2</version>
</parent>
<name>ebean bom</name>
@@ -12,16 +12,6 @@
<artifactId>ebean-bom</artifactId>
<packaging>pom</packaging>
<properties>
<ebean-ddl-runner.version>1.0</ebean-ddl-runner.version>
<ebean-migration-auto.version>1.0</ebean-migration-auto.version>
<ebean-migration.version>12.4.0</ebean-migration.version>
<ebean-test-docker.version>4.1</ebean-test-docker.version>
<ebean-datasource.version>7.0</ebean-datasource.version>
<ebean-agent.version>12.10.0</ebean-agent.version>
<ebean-maven-plugin.version>12.10.0</ebean-maven-plugin.version>
</properties>
<dependencyManagement>
<dependencies>
@@ -81,88 +71,88 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean</artifactId>
<version>12.10.0</version>
<version>12.11.2</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>12.10.0</version>
<version>12.11.2</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>12.10.0</version>
<version>12.11.2</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>12.10.0</version>
<version>12.11.2</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-ddl-generator</artifactId>
<version>12.10.0</version>
<version>12.11.2</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-externalmapping-api</artifactId>
<version>12.10.0</version>
<version>12.11.2</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-externalmapping-xml</artifactId>
<version>12.10.0</version>
<version>12.11.2</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-autotune</artifactId>
<version>12.10.0</version>
<version>12.11.2</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>12.10.0</version>
<version>12.11.2</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>querybean-generator</artifactId>
<version>12.10.0</version>
<version>12.11.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>kotlin-querybean-generator</artifactId>
<version>12.10.0</version>
<version>12.11.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test</artifactId>
<version>12.10.0</version>
<version>12.11.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgis</artifactId>
<version>12.10.0</version>
<version>12.11.2</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-redis</artifactId>
<version>12.10.0</version>
<version>12.11.2</version>
</dependency>
</dependencies>
+2 -2
View File
@@ -4,7 +4,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>12.10.0</version>
<version>12.11.2</version>
</parent>
<artifactId>ebean-core-type</artifactId>
@@ -16,7 +16,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>12.10.0</version>
<version>12.11.2</version>
</dependency>
<dependency>
@@ -163,4 +163,15 @@ public interface DataBinder {
* Bind an array value.
*/
void setArray(String arrayType, Object[] elements) throws SQLException;
/**
* Push json from dirty detection to be available for binding.
*/
void pushJson(String json);
/**
* Pop json made during dirty detection for scalarType binding.
*/
String popJson();
}
@@ -48,4 +48,14 @@ public interface DataReader {
Object getObject() throws SQLException;
InputStream getBinaryStream() throws SQLException;
/**
* Push json from dirty detection to be available for binding.
*/
void pushJson(String json);
/**
* Pop json made during dirty detection for scalarType binding.
*/
String popJson();
}
@@ -2,6 +2,7 @@ package io.ebean.core.type;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import io.ebean.text.StringFormatter;
import io.ebean.text.StringParser;
@@ -34,6 +35,10 @@ import java.sql.SQLException;
*/
public interface ScalarType<T> extends StringParser, StringFormatter, ScalarDataReader<T> {
default boolean isJsonMapper() {
return false;
}
/**
* 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.
+13 -22
View File
@@ -3,7 +3,7 @@
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>12.10.0</version>
<version>12.11.2</version>
</parent>
<artifactId>ebean-core</artifactId>
@@ -15,27 +15,18 @@
<scm>
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
<tag>ebean-parent-12.10.0</tag>
<tag>ebean-parent-12.11.2</tag>
</scm>
<profiles>
<profile>
<!-- Note: to use this profile, you need to download manually the db2jcc4 driver.
After that, install it into your local maven repository:
mvn install:install-file \
-Dfile=db2jcc4.jar \
-DgroupId=com.ibm.jdbc \
-DartifactId=db2jcc4 \
-Dversion=4.23.42 \
-Dpackaging=jar
-->
<id>db2</id>
<dependencies>
<!-- https://mvnrepository.com/artifact/com.ibm.db2/jcc -->
<dependency>
<groupId>com.ibm.jdbc</groupId>
<artifactId>db2jcc4</artifactId>
<version>4.23.42</version>
<groupId>com.ibm.db2</groupId>
<artifactId>jcc</artifactId>
<version>11.5.5.0</version>
<scope>test</scope>
</dependency>
</dependencies>
@@ -52,13 +43,13 @@
<dependency>
<groupId>io.avaje</groupId>
<artifactId>classpath-scanner</artifactId>
<version>4.2</version>
<version>6.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration-auto</artifactId>
<version>1.0</version>
<version>1.1</version>
</dependency>
<!-- keep testing in core using ebean-ddl-generator & ebean-migration -->
@@ -72,7 +63,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-ddl-generator</artifactId>
<version>12.9.4-RC1</version>
<version>12.11.0</version>
<scope>test</scope>
</dependency>
@@ -87,19 +78,19 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>12.10.0</version>
<version>12.11.2</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>12.10.0</version>
<version>12.11.2</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-externalmapping-api</artifactId>
<version>12.10.0</version>
<version>12.11.2</version>
</dependency>
<dependency>
@@ -302,7 +293,7 @@
<plugin>
<groupId>io.ebean</groupId>
<artifactId>ebean-maven-plugin</artifactId>
<version>12.10.0</version>
<version>${ebean-maven-plugin.version}</version>
<executions>
<execution>
<id>test</id>
@@ -6,7 +6,7 @@ import java.util.List;
/**
* The results of bean cache hit.
*/
public class BeanCacheResult<T> {
public final class BeanCacheResult<T> {
private final List<Entry<T>> list = new ArrayList<>();
@@ -27,7 +27,7 @@ public class BeanCacheResult<T> {
/**
* Bean and cache key pair.
*/
static class Entry<T> {
static final class Entry<T> {
private final T bean;
private final Object key;
@@ -7,7 +7,7 @@ import java.io.IOException;
/**
* Context used to read binary format messages.
*/
public class BinaryReadContext {
public final class BinaryReadContext {
private final DataInputStream in;
@@ -6,10 +6,9 @@ import java.io.IOException;
/**
* Context used to write binary message (like RemoteTransactionEvent).
*/
public class BinaryWriteContext {
public final class BinaryWriteContext {
private final DataOutputStream out;
private long counter;
public BinaryWriteContext(DataOutputStream out) {
@@ -4,11 +4,7 @@ import io.ebeaninternal.server.persist.MultiValueWrapper;
import io.ebeaninternal.server.querydefn.NaturalKeyBindParam;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.Map.Entry;
/**
@@ -17,35 +13,28 @@ import java.util.Map.Entry;
* Supports ordered or named parameters.
* </p>
*/
public class BindParams implements Serializable {
public final class BindParams implements Serializable {
private static final long serialVersionUID = 4541081933302086285L;
private final List<Param> positionedParameters = new ArrayList<>();
private final Map<String, Param> namedParameters = new LinkedHashMap<>();
/**
* This is the sql. For named parameters this is the sql after the named
* parameters have been replaced with question mark place holders and the
* parameters have been ordered by addNamedParamInOrder().
*/
private String preparedSql;
/**
* Bind hash and count used to detect when the bind values have changed such
* that the generated SQL (with named parameters) needs to be recalculated.
*/
private String bindHash;
/**
* Helper to add positioned parameters in order.
*/
private int addPos;
public BindParams() {
}
/**
* Reset positioned parameters (usually due to bind parameter expansion).
*/
@@ -54,12 +43,11 @@ public class BindParams implements Serializable {
positionedParameters.clear();
}
public int queryBindHash() {
int hc = namedParameters.hashCode();
for (Param positionedParameter : positionedParameters) {
hc = hc * 92821 + positionedParameter.hashCode();
public void queryBindHash(BindValuesKey key) {
key.add(positionedParameters.size());
for (Param param : positionedParameters) {
param.queryBindHash(key);
}
return hc;
}
/**
@@ -424,7 +412,14 @@ public class BindParams implements Serializable {
@Override
public boolean equals(Object o) {
return o != null && (o == this || (o instanceof Param) && hashCode() == o.hashCode());
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Param param = (Param) o;
return isInParam == param.isInParam && isOutParam == param.isOutParam && type == param.type && Objects.equals(inValue, param.inValue);
}
void queryBindHash(BindValuesKey key) {
key.add(isInParam).add(isOutParam).add(type).add(inValue);
}
/**
@@ -0,0 +1,35 @@
package io.ebeaninternal.api;
import java.util.ArrayList;
import java.util.List;
/**
* BindValues used for L2 query cache key matching.
* <p>
* The equals/hashCode implementation must meet the requirement that the query bind values
* match for L2 query cache hit (given the query plan hash is already a match).
*/
public final class BindValuesKey {
private final List<Object> values = new ArrayList<>();
/**
* Add a bind value.
*/
public BindValuesKey add(Object value) {
values.add(value);
return this;
}
@Override
public boolean equals(Object obj) {
return obj instanceof BindValuesKey && ((BindValuesKey) obj).values.equals(values);
}
@Override
public int hashCode() {
return values.hashCode();
}
}
@@ -11,10 +11,9 @@ import java.util.Set;
/**
* Used for bean cache lookup with where ids in expression.
*/
public class CacheIdLookupMany<T> implements CacheIdLookup<T> {
public final class CacheIdLookupMany<T> implements CacheIdLookup<T> {
private final IdInExpression idInExpression;
private int remaining;
public CacheIdLookupMany(IdInExpression idInExpression) {
@@ -7,7 +7,7 @@ import java.util.List;
/**
* Used for bean cache lookup with a single id value.
*/
public class CacheIdLookupSingle<T> implements CacheIdLookup<T> {
public final class CacheIdLookupSingle<T> implements CacheIdLookup<T> {
private final Object idValue;
private boolean found;
@@ -1,16 +1,12 @@
package io.ebeaninternal.api;
import io.ebean.annotation.Platform;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Helper to indicate that an EbeanServer should come up offline
* typically for DDL generation purposes.
*/
public class DbOffline {
private static final Logger logger = LoggerFactory.getLogger(DbOffline.class);
public final class DbOffline {
private static final String KEY = "ebean.dboffline";
@@ -73,7 +69,6 @@ public class DbOffline {
public static void reset() {
generateMigration = false;
System.clearProperty(KEY);
logger.debug("reset");
}
}
@@ -8,7 +8,7 @@ import io.ebean.metric.TimedMetric;
/**
* Extra metrics collected to measure internal behaviour.
*/
public class ExtraMetrics {
public final class ExtraMetrics {
private final TimedMetric bindCapture;
private final TimedMetric planCollect;
@@ -3,18 +3,17 @@ package io.ebeaninternal.api;
/**
* A hash key for a query including both the query plan and bind values.
*/
public class HashQuery {
public final class HashQuery {
private final CQueryPlanKey planHash;
private final int bindHash;
private final BindValuesKey bindValuesKey;
/**
* Create the HashQuery.
*/
public HashQuery(CQueryPlanKey planHash, int bindHash) {
public HashQuery(CQueryPlanKey planHash, BindValuesKey bindValuesKey) {
this.planHash = planHash;
this.bindHash = bindHash;
this.bindValuesKey = bindValuesKey;
}
@Override
@@ -25,7 +24,7 @@ public class HashQuery {
@Override
public int hashCode() {
int hc = 92821 * planHash.hashCode();
hc = 92821 * hc + bindHash;
hc = 92821 * hc + bindValuesKey.hashCode();
return hc;
}
@@ -37,8 +36,7 @@ public class HashQuery {
if (!(obj instanceof HashQuery)) {
return false;
}
HashQuery e = (HashQuery) obj;
return e.bindHash == bindHash && e.planHash.equals(planHash);
return e.bindValuesKey.equals(bindValuesKey) && e.planHash.equals(planHash);
}
}
@@ -6,7 +6,7 @@ import io.ebean.TxScope;
/**
* Helper object to make AOP generated code simpler.
*/
public class HelpScopeTrans {
public final class HelpScopeTrans {
private static boolean enabled = true;
/**
@@ -13,16 +13,12 @@ import java.util.Set;
/**
* Request for loading ManyToOne and OneToOne relationships.
*/
public class LoadBeanRequest extends LoadRequest {
public final class LoadBeanRequest extends LoadRequest {
private final List<EntityBeanIntercept> batch;
private final LoadBeanBuffer loadBuffer;
private final String lazyLoadProperty;
private final boolean loadCache;
private boolean loadedFromCache;
/**
@@ -92,9 +88,7 @@ public class LoadBeanRequest extends LoadRequest {
* Return the list of Id values for the beans in the lazy load buffer.
*/
public List<Object> getIdList() {
List<Object> idList = new ArrayList<>();
BeanDescriptor<?> desc = loadBuffer.getBeanDescriptor();
for (EntityBeanIntercept ebi : batch) {
idList.add(desc.getId(ebi.getOwner()));
@@ -106,10 +100,8 @@ public class LoadBeanRequest extends LoadRequest {
* Configure the query for lazy loading execution.
*/
public void configureQuery(SpiQuery<?> query, List<Object> idList) {
query.setMode(SpiQuery.Mode.LAZYLOAD_BEAN);
query.setPersistenceContext(loadBuffer.getPersistenceContext());
String mode = isLazy() ? "+lazy" : "+query";
query.setLoadDescription(mode, getDescription());
@@ -117,9 +109,7 @@ public class LoadBeanRequest extends LoadRequest {
// cascade the batch size (if set) for further lazy loading
query.setLazyLoadBatchSize(getBatchSize());
}
loadBuffer.configureQuery(query, lazyLoadProperty);
if (idList.size() == 1) {
query.where().idEq(idList.get(0));
} else {
@@ -131,19 +121,16 @@ public class LoadBeanRequest extends LoadRequest {
* Load the beans into the L2 cache if that is requested and check for load failures due to deletes.
*/
public void postLoad(List<?> list) {
Set<Object> loadedIds = new HashSet<>();
BeanDescriptor<?> desc = loadBuffer.getBeanDescriptor();
// collect Ids and maybe load bean cache
for (Object aList : list) {
EntityBean loadedBean = (EntityBean) aList;
for (Object bean : list) {
EntityBean loadedBean = (EntityBean) bean;
loadedIds.add(desc.getId(loadedBean));
}
if (isLoadCache()) {
desc.cacheBeanPutAll(list);
}
if (lazyLoadProperty != null) {
for (EntityBeanIntercept ebi : batch) {
// check if the underlying row in DB was deleted. Mark the bean as 'failed' if
@@ -15,16 +15,13 @@ import java.util.List;
/**
* Request for loading Associated Many Beans.
*/
public class LoadManyRequest extends LoadRequest {
public final class LoadManyRequest extends LoadRequest {
private static final Logger logger = LoggerFactory.getLogger(LoadManyRequest.class);
private final List<BeanCollection<?>> batch;
private final LoadManyBuffer loadContext;
private final boolean onlyIds;
private final boolean loadCache;
/**
@@ -17,16 +17,13 @@ import java.util.TreeSet;
* Holds the joins needs to support the many where predicates.
* These joins are independent of any 'fetch' joins on the many.
*/
public class ManyWhereJoins implements Serializable {
public final class ManyWhereJoins implements Serializable {
private static final long serialVersionUID = -6490181101871795417L;
private final TreeMap<String, PropertyJoin> joins = new TreeMap<>();
private List<String> formulaJoinProperties;
private boolean aggregation;
/**
* 'Mode' indicating that joins added while this is true are required to be outer joins.
*/
@@ -1,12 +0,0 @@
package io.ebeaninternal.api;
import java.io.Serializable;
/**
* Object used as a synchronization monitor that is serializable.
*/
public class Monitor implements Serializable {
private static final long serialVersionUID = -2741687226680981940L;
}
@@ -11,7 +11,7 @@ import java.util.Map;
/**
* Natural key entry with name value pairs for each of the properties making up the key.
*/
class NaturalKeyEntryBasic implements NaturalKeyEntry {
final class NaturalKeyEntryBasic implements NaturalKeyEntry {
private final Map<String,Object> map = new HashMap<>();
private final String key;
@@ -1,6 +1,6 @@
package io.ebeaninternal.api;
class NaturalKeyEntrySimple implements NaturalKeyEntry {
final class NaturalKeyEntrySimple implements NaturalKeyEntry {
private final String key;
private final Object val;
@@ -3,7 +3,7 @@ package io.ebeaninternal.api;
/**
* A property value pair in a natural key lookup.
*/
public class NaturalKeyEq {
public final class NaturalKeyEq {
final String property;
final Object value;
@@ -11,28 +11,22 @@ import java.util.Set;
/**
* Collects the data for processing the natural key cache processing.
*/
public class NaturalKeyQueryData<T> {
public final class NaturalKeyQueryData<T> {
private final BeanNaturalKey naturalKey;
/**
* Only one of IN or IN PAIRS is allowed.
*/
private boolean hasIn;
// IN Pairs clause - only one allowed
private String inProperty0, inProperty1;
private List<Pairs.Entry> inPairs;
// IN clause - only one allowed
private List<Object> inValues;
private String inProperty;
// normal EQ expressions
private List<NaturalKeyEq> eqList;
private NaturalKeySet set;
private int hitCount;
public NaturalKeyQueryData(BeanNaturalKey naturalKey) {
@@ -4,8 +4,7 @@ import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
public class NaturalKeySet {
public final class NaturalKeySet {
private final Map<Object, NaturalKeyEntry> map = new LinkedHashMap<>();
@@ -2,7 +2,7 @@ package io.ebeaninternal.api;
import io.ebeaninternal.server.type.bindcapture.BindCapture;
class NoopQueryBindCapture implements SpiQueryBindCapture {
final class NoopQueryBindCapture implements SpiQueryBindCapture {
@Override
public boolean collectFor(long timeMicros) {
@@ -6,7 +6,7 @@ import io.ebean.meta.QueryPlanRequest;
import java.util.Collections;
import java.util.List;
class NoopQueryPlanManager implements QueryPlanManager {
final class NoopQueryPlanManager implements QueryPlanManager {
@Override
public void setDefaultThreshold(long thresholdMicros) {
@@ -3,7 +3,7 @@ package io.ebeaninternal.api;
import io.ebean.annotation.Platform;
import io.ebean.util.StringHelper;
public class PlatformMatch {
public final class PlatformMatch {
/**
* Return true if the script platforms is a match/supported for the given platform.
@@ -15,7 +15,6 @@ public class PlatformMatch {
if (platforms == null || platforms.trim().isEmpty()) {
return true;
}
// match on base platform name and platform name
for (String name : StringHelper.splitNames(platforms)) {
if (name.equalsIgnoreCase(platform.base().name()) || name.equalsIgnoreCase(platform.name())) {
@@ -5,16 +5,9 @@ import io.ebeaninternal.server.query.SqlJoinType;
/**
* Represents a join required for a given property and whether than needs to be an outer join.
*/
public class PropertyJoin {
public final class PropertyJoin {
/**
* The property name.
*/
private final String property;
/**
* Set to true if the property needs to be an outer join.
*/
private final SqlJoinType joinType;
public PropertyJoin(String property, SqlJoinType joinType) {
@@ -7,7 +7,7 @@ import java.util.ArrayList;
/**
* Used internally to handle the scoping of transactions for methods.
*/
public class ScopeTrans {
public final class ScopeTrans {
private static final int OPCODE_ATHROW = 191;
@@ -15,43 +15,32 @@ public class ScopeTrans {
* The transaction in scope (can be null).
*/
private final SpiTransaction transaction;
/**
* If true by default rollback on Checked exceptions.
*/
private final boolean rollbackOnChecked;
/**
* True if the transaction was created and hence should be committed
* on finally if it hasn't already been rolled back.
*/
private final boolean created;
/**
* Explicit set of Exceptions that DO NOT cause a rollback to occur.
*/
private final ArrayList<Class<? extends Throwable>> noRollbackFor;
/**
* Explicit set of Exceptions that DO cause a rollback to occur.
*/
private final ArrayList<Class<? extends Throwable>> rollbackFor;
private Boolean restoreBatch;
private Boolean restoreBatchOnCascade;
private int restoreBatchSize;
private Boolean restoreBatchGeneratedKeys;
private boolean restoreBatchFlushOnQuery;
/**
* Flag set when a rollback has occurred.
*/
private boolean rolledBack;
/**
* Flag set when nested commit has occurred.
*/
@@ -10,15 +10,13 @@ import javax.persistence.PersistenceException;
*
* These can be nested and internally they are pushed and popped from a stack.
*/
public class ScopedTransaction extends SpiTransactionProxy {
public final class ScopedTransaction extends SpiTransactionProxy {
private final TransactionScopeManager manager;
/**
* Stack of 'nested' transactions.
*/
private final ArrayStack<ScopeTrans> stack = new ArrayStack<>();
private ScopeTrans current;
/**
@@ -8,6 +8,7 @@ import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.event.readaudit.ReadAuditLogger;
import io.ebean.event.readaudit.ReadAuditPrepare;
import io.ebean.meta.MetricVisitor;
import io.ebeaninternal.api.SpiQuery.Type;
import io.ebeaninternal.server.core.SpiResultSet;
import io.ebeaninternal.server.core.timezone.DataTimeZone;
import io.ebeaninternal.server.deploy.BeanDescriptor;
@@ -149,7 +150,7 @@ public interface SpiEbeanServer extends ExtendedServer, EbeanServer, BeanCollect
/**
* Compile a query.
*/
<T> CQuery<T> compileQuery(Query<T> query, Transaction t);
<T> CQuery<T> compileQuery(Type type, Query<T> query, Transaction t);
/**
* Execute the findId's query but without copying the query.
@@ -54,9 +54,9 @@ public interface SpiExpression extends Expression {
void queryPlanHash(StringBuilder builder);
/**
* Return the hash value for the values that will be bound.
* Build the key for bind values of the query.
*/
int queryBindHash();
void queryBindKey(BindValuesKey key);
/**
* Return true if the expression is the same with respect to bind values.
@@ -8,10 +8,9 @@ import java.util.Set;
/**
* Property expression validation request for a given root bean type.
*/
public class SpiExpressionValidation {
public final class SpiExpressionValidation {
private final BeanType<?> desc;
private final LinkedHashSet<String> unknown = new LinkedHashSet<>();
public SpiExpressionValidation(BeanType<?> desc) {
@@ -84,7 +84,7 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
/**
* Find single attribute.
*/
ATTRIBUTE(FIND_ATTRIBUTE, "findAttribute"),
ATTRIBUTE(FIND_ATTRIBUTE, "findAttribute", false, false),
/**
* Find rowCount.
@@ -92,9 +92,14 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
COUNT(FIND_COUNT, "findCount"),
/**
* A subquery used as part of a where clause.
* A subquery used as part of an exists where clause.
*/
SUBQUERY(FIND_SUBQUERY, "subquery"),
SQ_EXISTS(FIND_SUBQUERY, "sqExists", false, false),
/**
* A subquery used as part of an in where clause.
*/
SQ_IN(FIND_SUBQUERY, "sqIn", false, false),
/**
* Delete query.
@@ -107,17 +112,21 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
UPDATE(FIND_UPDATE, "update", true);
private final boolean update;
private final boolean defaultSelect;
private final String profileEventId;
private final String label;
Type(String profileEventId, String label) {
this(profileEventId, label, false);
this(profileEventId, label, false, true);
}
Type(String profileEventId, String label, boolean update) {
this(profileEventId, label, update, true);
}
Type(String profileEventId, String label, boolean update, boolean defaultSelect) {
this.profileEventId = profileEventId;
this.label = label;
this.update = update;
this.defaultSelect = defaultSelect;
}
/**
@@ -127,6 +136,13 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
return update;
}
/**
* Return true if this allows default select clause.
*/
public boolean defaultSelect() {
return defaultSelect;
}
public String profileEventId() {
return profileEventId;
}
@@ -629,13 +645,11 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
CQueryPlanKey prepare(SpiOrmQueryRequest<T> request);
/**
* Calculate a hash based on the bind values used in the query.
* Build the key for the bind values used in the query (for l2 query cache).
* <p>
* Combined with queryPlanHash() to return getQueryHash (a unique hash for a
* query).
* </p>
* Combined with queryPlanHash() to return queryHash (a unique key for a query).
*/
int queryBindHash();
void queryBindKey(BindValuesKey key);
/**
* Identifies queries that are exactly the same including bind variables.
@@ -18,7 +18,7 @@ public interface SpiQueryPlan {
String getName();
/**
* The hash for the query plan.
* The hash of the sql.
*/
String getHash();
@@ -20,7 +20,7 @@ import java.util.List;
* to the TransactionEventManager.
* </p>
*/
public class TransactionEvent implements Serializable {
public final class TransactionEvent implements Serializable {
private static final long serialVersionUID = 7230903304106097120L;
@@ -29,13 +29,9 @@ public class TransactionEvent implements Serializable {
* the cluster).
*/
private final transient boolean local;
private TransactionEventTable eventTables;
private transient List<PersistRequestBean<?>> listenerNotify;
private transient DeleteByIdMap deleteByIdMap;
private transient CacheChangeSet changeSet;
/**
@@ -110,11 +106,9 @@ public class TransactionEvent implements Serializable {
* Build and return the cache changeSet.
*/
public CacheChangeSet buildCacheChanges(TransactionManager manager) {
if (changeSet == null && deleteByIdMap == null && eventTables == null) {
return null;
}
if (changeSet == null) {
changeSet = new CacheChangeSet();
}
@@ -28,20 +28,17 @@ public final class TransactionEventTable implements Serializable, BinaryWritable
}
public void add(TransactionEventTable table) {
for (TableIUD iud : table.values()) {
add(iud);
}
}
public void add(String table, boolean insert, boolean update, boolean delete) {
table = table.toUpperCase();
add(new TableIUD(table, insert, update, delete));
}
public void add(TableIUD newTableIUD) {
TableIUD existingTableIUD = map.put(newTableIUD.getTableName(), newTableIUD);
if (existingTableIUD != null) {
newTableIUD.add(existingTableIUD);
@@ -56,7 +53,7 @@ public final class TransactionEventTable implements Serializable, BinaryWritable
return map.values();
}
public static class TableIUD implements Serializable, BulkTableEvent, BinaryWritable {
public static final class TableIUD implements Serializable, BulkTableEvent, BinaryWritable {
private static final long serialVersionUID = -1958317571064162089L;
@@ -73,12 +70,10 @@ public final class TransactionEventTable implements Serializable, BinaryWritable
}
public static TableIUD readBinaryMessage(BinaryReadContext dataInput) throws IOException {
String table = dataInput.readUTF();
boolean insert = dataInput.readBoolean();
boolean update = dataInput.readBoolean();
boolean delete = dataInput.readBoolean();
return new TableIUD(table, insert, update, delete);
}
@@ -17,7 +17,7 @@ import java.util.Set;
/**
* Utility that converts between JSON content and simple java Maps/Lists.
*/
public class DJsonService implements SpiJsonService {
public final class DJsonService implements SpiJsonService {
/**
* Write the nested Map/List as json.
@@ -14,7 +14,7 @@ import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
class EJsonReader {
final class EJsonReader {
static final JsonFactory json = new JsonFactory();
@@ -14,7 +14,7 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
class EJsonWriter {
final class EJsonWriter {
/**
* Base jsonFactory implementation used when it is not passed in.
@@ -7,7 +7,7 @@ import java.io.Serializable;
/**
* Detects when content has been modified and as such needs to be persisted (included in an update).
*/
public class ModifyAwareFlag implements ModifyAwareType, Serializable {
public final class ModifyAwareFlag implements ModifyAwareType, Serializable {
private static final long serialVersionUID = 1;
@@ -7,10 +7,9 @@ import java.util.Iterator;
/**
* Wraps an iterator for the purposes of detecting modifications.
*/
public class ModifyAwareIterator<E> implements Iterator<E> {
public final class ModifyAwareIterator<E> implements Iterator<E> {
private final ModifyAwareType owner;
private final Iterator<E> it;
/**
@@ -13,12 +13,11 @@ import java.util.Objects;
/**
* Modify aware wrapper of a list.
*/
public class ModifyAwareList<E> implements List<E>, ModifyAwareType, Serializable {
public final class ModifyAwareList<E> implements List<E>, ModifyAwareType, Serializable {
private static final long serialVersionUID = 1;
final List<E> list;
final ModifyAwareType owner;
public ModifyAwareList(List<E> list) {
@@ -7,10 +7,9 @@ import java.util.ListIterator;
/**
* Modify aware wrapper of a ListIterator.
*/
public class ModifyAwareListIterator<E> implements ListIterator<E> {
public final class ModifyAwareListIterator<E> implements ListIterator<E> {
final ModifyAwareType owner;
final ListIterator<E> iterator;
public ModifyAwareListIterator(ModifyAwareType owner, ListIterator<E> iterator) {
@@ -12,15 +12,11 @@ import java.util.Set;
/**
* Map that is wraps an underlying map for the purpose of detecting changes.
*/
public class ModifyAwareMap<K, V> implements Map<K, V>, ModifyAwareType, Serializable {
public final class ModifyAwareMap<K, V> implements Map<K, V>, ModifyAwareType, Serializable {
private static final long serialVersionUID = 1;
final ModifyAwareType owner;
/**
* The underlying map.
*/
final Map<K, V> map;
public ModifyAwareMap(Map<K, V> underlying) {
@@ -11,13 +11,12 @@ import java.util.Set;
/**
* Wraps a Set for the purposes of detecting modifications.
*/
public class ModifyAwareSet<E> implements Set<E>, ModifyAwareType, Serializable {
public final class ModifyAwareSet<E> implements Set<E>, ModifyAwareType, Serializable {
private static final long serialVersionUID = 1;
protected final ModifyAwareType owner;
protected final Set<E> set;
private final ModifyAwareType owner;
private final Set<E> set;
/**
* Create as top level with it's own ModifyAwareOwner instance wrapping the given Set.
@@ -8,7 +8,7 @@ import io.ebeaninternal.server.core.DefaultContainer;
/**
* Default container factory found via service loader.
*/
public class DContainerFactory implements SpiContainerFactory {
public final class DContainerFactory implements SpiContainerFactory {
@Override
public SpiContainer create(ContainerConfig containerConfig) {
@@ -5,7 +5,7 @@ import io.ebeaninternal.api.SpiQuery;
/**
* Noop service when AutoTuneService is not available.
*/
public class NoAutoTuneService implements AutoTuneService {
public final class NoAutoTuneService implements AutoTuneService {
@Override
public void startup() {
@@ -8,10 +8,9 @@ import java.util.Collection;
/**
* Change to remove bean from L2 cache.
*/
class CacheChangeBeanRemove implements CacheChange {
final class CacheChangeBeanRemove implements CacheChange {
private final BeanDescriptor<?> descriptor;
private final Collection<Object> ids;
CacheChangeBeanRemove(Object id, BeanDescriptor<?> descriptor) {
@@ -7,7 +7,7 @@ import java.util.Map;
/**
* Put a new bean entry into the cache.
*/
class CacheChangeBeanUpdate implements CacheChange {
final class CacheChangeBeanUpdate implements CacheChange {
private final BeanDescriptor<?> desc;
private final String key;
@@ -5,7 +5,7 @@ import io.ebeaninternal.server.deploy.BeanDescriptor;
/**
* Change the natural key mapping for a bean.
*/
class CacheChangeNaturalKeyPut implements CacheChange {
final class CacheChangeNaturalKeyPut implements CacheChange {
private final BeanDescriptor<?> descriptor;
private final String key;
@@ -14,18 +14,13 @@ import java.util.Set;
/**
* List of changes to be applied to L2 cache.
*/
public class CacheChangeSet {
public final class CacheChangeSet {
private final List<CacheChange> entries = new ArrayList<>();
private final Set<String> touchedTables = new HashSet<>();
private final Set<BeanDescriptor<?>> queryCaches = new HashSet<>();
private final Set<BeanDescriptor<?>> beanCaches = new HashSet<>();
private final Map<BeanDescriptor<?>, CacheChangeBeanRemove> beanRemoveMap = new HashMap<>();
private final Map<ManyKey, ManyChange> manyChangeMap = new HashMap<>();
/**
@@ -173,14 +168,11 @@ public class CacheChangeSet {
/**
* Changes for a specific many property.
*/
private static class ManyChange implements CacheChange {
private static final class ManyChange implements CacheChange {
final ManyKey key;
final Set<Object> removes = new HashSet<>();
final Map<Object, CachedManyIds> puts = new LinkedHashMap<>();
boolean clear;
ManyChange(ManyKey key) {
@@ -229,10 +221,9 @@ public class CacheChangeSet {
/**
* Key for changes on a many property.
*/
private static class ManyKey {
private static final class ManyKey {
private final BeanDescriptor<?> desc;
private final String manyProperty;
ManyKey(BeanDescriptor<?> desc, String manyProperty) {
@@ -10,18 +10,13 @@ import io.ebeaninternal.server.cluster.ClusterManager;
/**
* Configuration options when creating the default cache manager.
*/
public class CacheManagerOptions {
public final class CacheManagerOptions {
private final ClusterManager clusterManager;
private final DatabaseConfig databaseConfig;
private final boolean localL2Caching;
private CurrentTenantProvider currentTenantProvider;
private QueryCacheEntryValidate queryCacheEntryValidate;
private ServerCacheFactory cacheFactory = new DefaultServerCacheFactory();
private ServerCacheOptions beanDefault = new ServerCacheOptions();
private ServerCacheOptions queryDefault = new ServerCacheOptions();
@@ -11,13 +11,12 @@ import java.util.Map;
/**
* Data held in the bean cache for cached beans.
*/
public class CachedBeanData implements Externalizable {
public final class CachedBeanData implements Externalizable {
private long whenCreated;
private long version;
private String discValue;
private Map<String, Object> data;
/**
* The sharable bean is effectively transient (near cache only).
*/
@@ -9,10 +9,9 @@ import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
import java.util.LinkedHashMap;
import java.util.Map;
public class CachedBeanDataFromBean {
public final class CachedBeanDataFromBean {
public static CachedBeanData extract(BeanDescriptor<?> desc, EntityBean bean) {
EntityBeanIntercept ebi = bean._ebean_getIntercept();
Map<String, Object> data = new LinkedHashMap<>();
@@ -46,7 +45,6 @@ public class CachedBeanDataFromBean {
}
private static EntityBean createSharableBean(BeanDescriptor<?> desc, EntityBean bean, EntityBeanIntercept beanEbi) {
if (!desc.isCacheSharableBeans() || !beanEbi.isFullyLoadedBean()) {
return null;
}
@@ -7,30 +7,24 @@ import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.BeanProperty;
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
public class CachedBeanDataToBean {
public final class CachedBeanDataToBean {
public static void load(BeanDescriptor<?> desc, EntityBean bean, CachedBeanData cacheBeanData, PersistenceContext context) {
EntityBeanIntercept ebi = bean._ebean_getIntercept();
// any future lazy loading skips L2 bean cache
ebi.setLoadedFromCache(true);
BeanProperty idProperty = desc.getIdProperty();
if (desc.getInheritInfo() != null) {
desc = desc.getInheritInfo().readType(bean.getClass()).desc();
}
if (idProperty != null) {
// load the id property
loadProperty(bean, cacheBeanData, ebi, idProperty, context);
}
// load the non-many properties
for (BeanProperty prop : desc.propertiesNonMany()) {
loadProperty(bean, cacheBeanData, ebi, prop, context);
}
for (BeanPropertyAssocMany<?> prop : desc.propertiesMany()) {
if (prop.isElementCollection()) {
loadProperty(bean, cacheBeanData, ebi, prop, context);
@@ -38,12 +32,10 @@ public class CachedBeanDataToBean {
prop.createReferenceIfNull(bean);
}
}
ebi.setLoadedLazy();
}
private static void loadProperty(EntityBean bean, CachedBeanData cacheBeanData, EntityBeanIntercept ebi, BeanProperty prop, PersistenceContext context) {
if (cacheBeanData.isLoaded(prop.getName())) {
if (!ebi.isLoadedProperty(prop.getPropertyIndex())) {
Object value = cacheBeanData.getData(prop.getName());
@@ -10,7 +10,7 @@ import java.io.ObjectOutput;
* <p>
* Put into L2 cache such that we know the type of a bean with inheritance.
*/
public class CachedBeanId implements Externalizable {
public final class CachedBeanId implements Externalizable {
private String discValue;
private Object id;
@@ -13,7 +13,7 @@ import java.util.List;
* This is effectively just the Id values for each of the beans in the collection.
* </p>
*/
public class CachedManyIds implements Externalizable {
public final class CachedManyIds implements Externalizable {
private List<Object> idList;
@@ -13,7 +13,7 @@ import java.util.List;
* Used to hide the Supplier part of the SpiCacheManager API from public use.
* </p>
*/
public class DefaultCacheAdapter implements ServerCacheManager {
public final class DefaultCacheAdapter implements ServerCacheManager {
private final SpiCacheManager cacheManager;
@@ -23,14 +23,13 @@ import java.util.concurrent.locks.ReentrantLock;
/**
* Manages the construction of caches.
*/
class DefaultCacheHolder {
final class DefaultCacheHolder {
private static final Logger log = LoggerFactory.getLogger("io.ebean.cache.ALL");
private final ReentrantLock lock = new ReentrantLock();
private final ConcurrentHashMap<String, ServerCache> allCaches = new ConcurrentHashMap<>();
private final ConcurrentHashMap<String, Set<String>> collectIdCaches = new ConcurrentHashMap<>();
private final ServerCacheFactory cacheFactory;
private final ServerCacheOptions beanDefault;
private final ServerCacheOptions queryDefault;
@@ -76,7 +75,6 @@ class DefaultCacheHolder {
* Return the cache for a given bean type.
*/
private ServerCache getCacheInternal(Class<?> beanType, ServerCacheType type, String collectionProperty) {
String shortName = key(beanType.getSimpleName(), collectionProperty, type);
String fullKey = key(beanType.getName(), collectionProperty, type);
return allCaches.computeIfAbsent(fullKey, s -> createCache(beanType, type, fullKey, shortName));
@@ -143,10 +141,8 @@ class DefaultCacheHolder {
}
private ServerCacheOptions getBeanOptions(Class<?> cls) {
Cache cache = cls.getAnnotation(Cache.class);
boolean nearCache = (cache != null && cache.nearCache());
CacheBeanTuning tuning = cls.getAnnotation(CacheBeanTuning.class);
if (tuning != null) {
return new ServerCacheOptions(nearCache, tuning).applyDefaults(beanDefault);
@@ -11,6 +11,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
@@ -37,8 +38,7 @@ public class DefaultServerCache implements ServerCache {
/**
* The underlying map (ConcurrentHashMap or similar)
*/
protected final Map<Object, CacheEntry> map;
protected final Map<Object, SoftReference<CacheEntry>> map;
protected final CountMetric hitCount;
protected final CountMetric missCount;
protected final CountMetric putCount;
@@ -48,16 +48,11 @@ public class DefaultServerCache implements ServerCache {
protected final String name;
protected final String shortName;
private int maxSize;
private final int maxSize;
private final int trimFrequency;
private int maxIdleSecs;
private int maxSecsToLive;
private TenantAwareKey tenantAwareKey;
private final int maxIdleSecs;
private final int maxSecsToLive;
private final TenantAwareKey tenantAwareKey;
public DefaultServerCache(DefaultServerCacheConfig config) {
this.name = config.getName();
@@ -70,7 +65,6 @@ public class DefaultServerCache implements ServerCache {
this.trimFrequency = config.determineTrimFrequency();
MetricFactory factory = MetricFactory.get();
String prefix = "l2n.";
this.hitCount = factory.createCountMetric(prefix + shortName + ".hit");
this.missCount = factory.createCountMetric(prefix + shortName + ".miss");
@@ -81,9 +75,7 @@ public class DefaultServerCache implements ServerCache {
}
public void periodicTrim(BackgroundExecutor executor) {
EvictionRunnable trim = new EvictionRunnable();
// default to trimming the cache every 60 seconds
long trimFreqSecs = (trimFrequency == 0) ? 60 : trimFrequency;
executor.scheduleWithFixedDelay(trim, trimFreqSecs, trimFreqSecs, TimeUnit.SECONDS);
@@ -101,11 +93,9 @@ public class DefaultServerCache implements ServerCache {
@Override
public ServerCacheStatistics getStatistics(boolean reset) {
ServerCacheStatistics cacheStats = new ServerCacheStatistics();
cacheStats.setCacheName(name);
cacheStats.setMaxSize(maxSize);
cacheStats.setSize(size());
cacheStats.setHitCount(hitCount.get(reset));
cacheStats.setMissCount(missCount.get(reset));
@@ -113,7 +103,6 @@ public class DefaultServerCache implements ServerCache {
cacheStats.setRemoveCount(removeCount.get(reset));
cacheStats.setClearCount(clearCount.get(reset));
cacheStats.setEvictCount(evictCount.get(reset));
return cacheStats;
}
@@ -133,10 +122,8 @@ public class DefaultServerCache implements ServerCache {
@Override
public int getHitRatio() {
long mc = missCount.get(false);
long hc = hitCount.get(false);
long totalCount = hc + mc;
if (totalCount == 0) {
return 0;
@@ -177,7 +164,6 @@ public class DefaultServerCache implements ServerCache {
*/
@Override
public Object get(Object id) {
CacheEntry entry = getCacheEntry(id);
if (entry == null) {
missCount.increment();
@@ -199,7 +185,8 @@ public class DefaultServerCache implements ServerCache {
* Get the cache entry - override for query cache to validate dependent tables.
*/
protected CacheEntry getCacheEntry(Object id) {
return map.get(key(id));
final SoftReference<CacheEntry> ref = map.get(key(id));
return ref != null ? ref.get() : null;
}
@Override
@@ -213,7 +200,7 @@ public class DefaultServerCache implements ServerCache {
@Override
public void put(Object id, Object value) {
Object key = key(id);
map.put(key, new CacheEntry(key, value));
map.put(key, new SoftReference<>(new CacheEntry(key, value)));
putCount.increment();
}
@@ -222,8 +209,8 @@ public class DefaultServerCache implements ServerCache {
*/
@Override
public void remove(Object id) {
CacheEntry entry = map.remove(key(id));
if (entry != null) {
SoftReference<CacheEntry> entry = map.remove(key(id));
if (entry != null && entry.get() != null) {
removeCount.increment();
}
}
@@ -250,74 +237,69 @@ 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<CacheEntry> it = map.values().iterator();
Iterator<SoftReference<CacheEntry>> it = map.values().iterator();
while (it.hasNext()) {
CacheEntry cacheEntry = it.next();
if (maxIdleSecs > 0 && idleExpireNano > cacheEntry.getLastAccessTime()) {
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);
}
}
if (trimForMaxSize > 0) {
trimmedByLRU = activeList.size() - maxSize;
if (trimmedByLRU > 0) {
// 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
map.remove(activeList.get(i).getKey());
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++;
}
}
}
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[{}]"
, name, exeMicros, trimmedByIdle, trimmedByTTL, trimmedByLRU);
logger.trace("Executed trim of cache {} in [{}]millis idle[{}] timeToLive[{}] accessTime[{}] gc[{}]",
name, exeMicros, trimmedByIdle, trimmedByTTL, trimmedByLRU, trimmedByGC);
}
}
/**
* Runnable that calls the eviction routine.
*/
public class EvictionRunnable implements Runnable {
public final class EvictionRunnable implements Runnable {
@Override
public void run() {
@@ -328,7 +310,7 @@ public class DefaultServerCache implements ServerCache {
/**
* Comparator for sorting by last access time.
*/
public static class CompareByLastAccess implements Comparator<CacheEntry>, Serializable {
public static final class CompareByLastAccess implements Comparator<CacheEntry>, Serializable {
private static final long serialVersionUID = 1L;
@@ -341,7 +323,7 @@ public class DefaultServerCache implements ServerCache {
/**
* Wraps the value to additionally hold createTime and lastAccessTime and hit counter.
*/
public static class CacheEntry {
public static final class CacheEntry {
private final Object key;
private final Object value;
@@ -4,26 +4,26 @@ import io.ebean.cache.QueryCacheEntryValidate;
import io.ebean.cache.ServerCacheConfig;
import io.ebean.cache.ServerCacheOptions;
import io.ebean.config.CurrentTenantProvider;
import io.ebeaninternal.server.cache.DefaultServerCache.CacheEntry;
import java.lang.ref.SoftReference;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class DefaultServerCacheConfig {
public final class DefaultServerCacheConfig {
private final ServerCacheConfig config;
private int maxSize;
private int maxIdleSecs;
private int maxSecsToLive;
private int trimFrequency;
private Map<Object, DefaultServerCache.CacheEntry> map;
private final int maxSize;
private final int maxIdleSecs;
private final int maxSecsToLive;
private final int trimFrequency;
private final Map<Object, SoftReference<CacheEntry>> map;
public DefaultServerCacheConfig(ServerCacheConfig config) {
this(config, new ConcurrentHashMap<>());
}
public DefaultServerCacheConfig(ServerCacheConfig config, Map<Object, DefaultServerCache.CacheEntry> map) {
public DefaultServerCacheConfig(ServerCacheConfig config, Map<Object, SoftReference<CacheEntry>> map) {
this.config = config;
this.map = map;
@@ -50,7 +50,7 @@ public class DefaultServerCacheConfig {
return config.getShortName();
}
public Map<Object, DefaultServerCache.CacheEntry> getMap() {
public Map<Object, SoftReference<CacheEntry>> getMap() {
return map;
}
@@ -11,7 +11,7 @@ import io.ebean.cache.ServerCacheNotify;
/**
* Default implementation of ServerCacheFactory.
*/
class DefaultServerCacheFactory implements ServerCacheFactory {
final class DefaultServerCacheFactory implements ServerCacheFactory {
private final BackgroundExecutor executor;
@@ -31,7 +31,6 @@ class DefaultServerCacheFactory implements ServerCacheFactory {
@Override
public ServerCache createCache(ServerCacheConfig config) {
DefaultServerCache cache;
if (config.isQueryCache()) {
// use a server cache aware of extra validation and QueryCacheEntry
@@ -19,18 +19,14 @@ import java.util.Map;
/**
* Manages the bean and query caches.
*/
public class DefaultServerCacheManager implements SpiCacheManager {
public final class DefaultServerCacheManager implements SpiCacheManager {
private static final Logger log = LoggerFactory.getLogger("io.ebean.cache.REGION");
private final Map<String, SpiCacheRegion> regionMap = new HashMap<>();
private final ClusterManager clusterManager;
private final DefaultCacheHolder cacheHolder;
private final boolean localL2Caching;
private final String serverName;
/**
@@ -8,7 +8,7 @@ import io.ebean.config.DatabaseConfig;
/**
* Default implementation of ServerCachePlugin.
*/
public class DefaultServerCachePlugin implements ServerCachePlugin {
public final class DefaultServerCachePlugin implements ServerCachePlugin {
/**
* Creates the default ServerCacheFactory.
@@ -3,6 +3,8 @@ package io.ebeaninternal.server.cache;
import io.ebean.cache.QueryCacheEntry;
import io.ebean.cache.QueryCacheEntryValidate;
import java.lang.ref.SoftReference;
/**
* Server cache for query caching.
* <p>
@@ -27,7 +29,8 @@ public class DefaultServerQueryCache extends DefaultServerCache {
@Override
protected CacheEntry getCacheEntry(Object id) {
Object key = key(id);
CacheEntry entry = map.get(key);
final SoftReference<CacheEntry> ref = map.get(key);
CacheEntry entry = ref != null ? ref.get() : null;
if (entry == null) {
return null;
}
@@ -12,11 +12,10 @@ import java.util.List;
/**
* Cache events broadcast across the cluster.
*/
public class RemoteCacheEvent implements BinaryWritable {
public final class RemoteCacheEvent implements BinaryWritable {
private boolean clearAll;
private List<String> clearCaches;
private final boolean clearAll;
private final List<String> clearCaches;
/**
* Clear all the caches.
@@ -57,10 +56,8 @@ public class RemoteCacheEvent implements BinaryWritable {
}
public static RemoteCacheEvent readBinaryMessage(BinaryReadContext dataInput) throws IOException {
boolean clearAll = dataInput.readBoolean();
int size = dataInput.readInt();
List<String> clearCache = null;
if (size > 0) {
clearCache = new ArrayList<>(size);
@@ -68,7 +65,6 @@ public class RemoteCacheEvent implements BinaryWritable {
clearCache.add(dataInput.readUTF());
}
}
return new RemoteCacheEvent(clearAll, clearCache);
}
@@ -14,21 +14,14 @@ import java.util.Map;
/**
* Builds JSON document for a bean change.
*/
class ChangeJsonBuilder {
final class ChangeJsonBuilder {
protected final JsonFactory jsonFactory = new JsonFactory();
protected final JsonContext json;
ChangeJsonBuilder(JsonContext json) {
this.json = json;
}
private final JsonFactory jsonFactory = new JsonFactory();
/**
* Write the bean change as JSON.
*/
void writeBeanJson(Writer writer, BeanChange bean, ChangeSet changeSet) throws IOException {
try (JsonGenerator generator = jsonFactory.createGenerator(writer)) {
writeBeanChange(generator, bean, changeSet);
generator.flush();
@@ -39,9 +32,7 @@ class ChangeJsonBuilder {
* Write the bean change as JSON document containing the transaction header details.
*/
private void writeBeanChange(JsonGenerator gen, BeanChange bean, ChangeSet changeSet) throws IOException {
gen.writeStartObject();
gen.writeNumberField("ts", bean.getEventTime());
gen.writeStringField("change", bean.getEvent().getCode());
gen.writeStringField("type", bean.getType());
@@ -49,9 +40,7 @@ class ChangeJsonBuilder {
if (bean.getTenantId() != null) {
gen.writeStringField("tenantId", bean.getTenantId().toString());
}
writeBeanTransactionDetails(gen, changeSet);
writeBeanValues(gen, bean);
gen.writeEndObject();
}
@@ -60,7 +49,6 @@ class ChangeJsonBuilder {
* Denormalise by writing the transaction header details.
*/
private void writeBeanTransactionDetails(JsonGenerator gen, ChangeSet changeSet) throws IOException {
String source = changeSet.getSource();
if (source != null) {
gen.writeStringField("source", source);
@@ -87,12 +75,10 @@ class ChangeJsonBuilder {
* For insert and update write the new/old values.
*/
private void writeBeanValues(JsonGenerator gen, BeanChange bean) throws IOException {
if (bean.getEvent() != ChangeType.DELETE) {
gen.writeFieldName("data");
gen.writeRaw(":");
gen.writeRaw(bean.getData());
String oldData = bean.getOldData();
if (oldData != null) {
gen.writeRaw(",\"oldData\":");
@@ -15,12 +15,12 @@ import java.util.Properties;
/**
* Simply logs the change sets in JSON form to logger named <code>io.ebean.ChangeLog</code>.
*/
public class DefaultChangeLogListener implements ChangeLogListener, Plugin {
public final class DefaultChangeLogListener implements ChangeLogListener, Plugin {
/**
* The usual application specific logger.
*/
protected static final Logger logger = LoggerFactory.getLogger(DefaultChangeLogListener.class);
private static final Logger logger = LoggerFactory.getLogger(DefaultChangeLogListener.class);
/**
* The named logger we send the change set payload to. Can be externally configured as desired.
@@ -45,8 +45,7 @@ public class DefaultChangeLogListener implements ChangeLogListener, Plugin {
*/
@Override
public void configure(SpiServer server) {
jsonBuilder = new ChangeJsonBuilder(server.json());
jsonBuilder = new ChangeJsonBuilder();
Properties properties = server.getServerConfig().getProperties();
if (properties != null) {
String bufferSize = properties.getProperty("ebean.changeLog.bufferSize");
@@ -11,7 +11,7 @@ import io.ebean.event.changelog.ChangeSet;
* on the changeSet.
* </p>
*/
public class DefaultChangeLogPrepare implements ChangeLogPrepare {
public final class DefaultChangeLogPrepare implements ChangeLogPrepare {
/**
* Just return true to send change set through to the logger.
@@ -14,10 +14,9 @@ import java.util.Set;
/**
* Default implementation of ChangeLogRegister.
*/
public class DefaultChangeLogRegister implements ChangeLogRegister {
public final class DefaultChangeLogRegister implements ChangeLogRegister {
private static final BasicFilter INCLUDE_INSERTS = new BasicFilter(true);
private static final BasicFilter EXCLUDE_INSERTS = new BasicFilter(false);
private final boolean defaultInsertsInclude;
@@ -31,20 +30,16 @@ public class DefaultChangeLogRegister implements ChangeLogRegister {
@Override
public ChangeLogFilter getChangeFilter(Class<?> beanType) {
ChangeLog changeLog = getChangeLog(beanType);
if (changeLog == null) {
return null;
}
String[] updatesThatInclude = changeLog.updatesThatInclude();
if (updatesThatInclude.length == 0) {
return insertModeInclude(changeLog.inserts()) ? INCLUDE_INSERTS : EXCLUDE_INSERTS;
}
Set<String> updateProps = new HashSet<>();
Collections.addAll(updateProps, updatesThatInclude);
return new UpdateFilter(insertModeInclude(changeLog.inserts()), updateProps);
}

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