Compare commits

...
Author SHA1 Message Date
Rob Bygrave 47d55a2f29 [maven-release-plugin] prepare release ebean-11.11.1 2018-02-23 12:50:45 +13:00
Rob Bygrave b037be5d3e No Effective change - bump agent in pom (with query bean enhancement of interface default methods) 2018-02-23 12:48:06 +13:00
Rob Bygrave 60a3c24cba No Effective change - Tidy pom removing commented out old sqlserver jdbc driver 2018-02-23 10:31:22 +13:00
Rob Bygrave 4a243a76a7 #1270 - Multi-tenant - partition mode - Delete by id does not include tenantId value in predicate 2018-02-23 10:26:47 +13:00
Rob Bygrave 9aee7c892d Test only - copy/add multi-tenant partition tests 2018-02-23 10:14:27 +13:00
Rob Bygrave 18d944f228 Test only - copy/add multi-tenant partition tests 2018-02-23 10:13:57 +13:00
Rob Bygrave 29bb9d3b48 #1268 - SQL Server fix for "for update" plus Sequences support plus refactor of sequences 2018-02-22 22:46:17 +13:00
Rob Bygrave f8ea5619d0 #1268 - SQL Server fix for "for update" plus Sequences support plus refactor of sequences 2018-02-22 22:45:44 +13:00
Rob Bygrave e3fac7c622 #1269 - Paging queries should not ALWAYS append an order by ID ... but only when the order by is empty 2018-02-22 22:43:14 +13:00
Rob Bygrave 8ee68ac5e1 #1269 - Paging queries should not ALWAYS append an order by ID ... but only when the order by is empty 2018-02-22 22:40:22 +13:00
Rob Bygrave ec7b376612 Test only change - fix test assert for sql server 2018-02-22 22:12:30 +13:00
Rob Bygrave f2d438f21a Test only change - fix test assert for sql server 2018-02-22 22:11:56 +13:00
Rob Bygrave 20bd2241e4 Test only change - fix test assert to support sequence and identity insert 2018-02-22 22:11:36 +13:00
Rob Bygrave dd907cc4bc Test only change - fix keys for testing against Oracle 2018-02-22 22:10:59 +13:00
Rob Bygrave 4d122ea05b #1267 - DDL issue on @OneToMany @JoinTable ... extra unnecessary index created on fk column 2018-02-22 22:09:53 +13:00
Rob Bygrave 83384c6f0e #323 - DDL Generation support for foreign key cascade options
Tidy up, no GLOBAL_DEFAULT.
2018-02-21 11:04:04 +13:00
Rob Bygrave eaa48468cd #1174 - ENH: Support mapping @TenantId to an entity bean via @ManyToOne 2018-02-21 09:44:37 +13:00
Rob Bygrave 0b1c3a4233 Bump version to 11.11.1-SNAPSHOT 2018-02-21 09:44:07 +13:00
Rob Bygrave 3e8b06e38e #994 - @OneToOne cacade does not honor orphanRemoval = true 2018-02-20 16:59:55 +13:00
Rob Bygrave 81d48d67a7 #123 - Mapping - Add support for OneToMany JoinTables 2018-02-20 14:40:21 +13:00
Rob Bygrave 8d0df6541e Merge branch 'issue/1263-transaction-api' 2018-02-19 22:47:42 +13:00
Rob Bygrave 2be3099d55 #1228 - Add support to not generate FK Constraint when @JoinColumn(foreignKey=@ForeignKey(ConstraintMode.NO_CONSTRAINT)) 2018-02-19 22:45:47 +13:00
Rob Bygrave 183d079b58 #323 - DDL Generation support for foreign key cascade options 2018-02-19 22:24:51 +13:00
Rob Bygrave 40634412f5 #323 - DDL Generation support for foreign key cascade options 2018-02-19 22:24:37 +13:00
Roland PramlandRob Bygrave b8aa822a30 [utf8mb4-support] limited the size of all indexed string columns, as max key length on mysql/mariadb is 767 bytes (which are <= 191 chars on utf8mb4) (#1264) 2018-02-19 16:15:28 +13:00
Rob Bygrave a1d0fbb194 [maven-release-plugin] prepare for next development iteration 2018-02-16 14:45:29 +13:00
Rob Bygrave 70ccc6588d [maven-release-plugin] prepare release ebean-11.10.6 2018-02-16 14:45:16 +13:00
Rob Bygrave 3d62e84d59 #1263 - ENH: Make Transaction API Fluid such that we can set multiple thing like batchSize and label in a fluid fashion 2018-02-16 14:40:35 +13:00
Rob Bygrave ac36172cc6 #997 - TypeReflectHelper does not resolve type variables correctly in non-trivial cases
Part 2 - Fix the failing test, swap in use of TypeResolver and remove all the unused features.
2018-02-16 12:47:10 +13:00
Rob Bygrave 1829c74694 #997 - TypeReflectHelper does not resolve type variables correctly in non-trivial cases
Initial failing test ... and TypeResolver prior to cleanup
2018-02-16 12:25:07 +13:00
Rob Bygrave cc7e22014d #997 - TypeReflectHelper does not resolve type variables correctly in non-trivial cases
Initial failing test ... and TypeResolver prior to cleanup
2018-02-16 12:24:57 +13:00
Rob Bygrave a5c6f483b0 #1258 - ENH: Add ServerConfig notifyL2CacheInForeground option ... was ServerCachePlugin BackgroundExecutor problem 2018-02-16 11:18:17 +13:00
Rob Bygrave 5237e8ba66 #1261 - ENH: Support use of getGeneratedKeys with SqlUpdate 2018-02-16 09:45:49 +13:00
Rob Bygrave 9926cad7f1 #1262 - ENH: Support firstRow maxRows with findNative() 2018-02-16 00:11:27 +13:00
Rob Bygrave 6c1b295d41 [maven-release-plugin] prepare for next development iteration 2018-02-15 22:32:56 +13:00
Rob Bygrave 49b568e7d4 [maven-release-plugin] prepare release ebean-11.10.5 2018-02-15 22:32:43 +13:00
Rob Bygrave 628af31ddd #1142 - Mapping - Add support for @OrderColumn (Ebean automatically maintains an order column) 2018-02-15 22:31:41 +13:00
Rob Bygrave 31cac60393 #107 - Mapping - Add support for @PrimaryKeyJoinColumn/@PrimaryKeyJoinColumns
Adds Bi-directional support
2018-02-15 00:49:51 +13:00
Rob Bygrave 6a067c0cf7 #107 - Mapping - Add support for @PrimaryKeyJoinColumn/@PrimaryKeyJoinColumns
Extra test with UUID and optional OneToOne so has left join
2018-02-14 23:09:10 +13:00
Rob Bygrave 842292ef6b #107 - Mapping - Add support for @PrimaryKeyJoinColumn/@PrimaryKeyJoinColumns 2018-02-14 22:59:57 +13:00
Rob Bygrave 6db9a60f4f #107 - Fix existing test - Ah ??? ... this PrimaryKeyJoinColumn was ignored and should never have been in this test. 2018-02-14 17:24:14 +13:00
Rob Bygrave d9125db957 [maven-release-plugin] prepare for next development iteration 2018-02-14 15:29:26 +13:00
Rob Bygrave 4bd9e67703 [maven-release-plugin] prepare release ebean-11.10.4 2018-02-14 15:29:12 +13:00
Rob Bygrave 2a986ab590 #1260 - Mark query.setForUpdate(true) as deprecated - migrate to query.forUpdate() 2018-02-14 15:28:13 +13:00
Rob Bygrave 7c477827fe #1259 - Throw explicit mapping error when an Enum is mapped to both ORDINAL and STRING 2018-02-14 12:39:35 +13:00
Rob Bygrave b2967dec1e #1257 - ServerConfig with register = true, defaultServer = false ... fails as it tries to create the default server 2018-02-13 16:22:52 +13:00
Rob Bygrave a95fd063ae #1256 - Query where many isNotEmpty() ... on ManyToMany with SoftDelete produces incorrect SQL (Part 2) 2018-02-13 14:52:18 +13:00
Rob Bygrave 17a54e3804 No effective change - extra tests for DeployPropertyParser 2018-02-13 14:09:08 +13:00
Rob Bygrave f1b2a09b30 Testing - modify .travis to run mysql as service (bump MySql version to 5.7) 2018-02-10 01:16:40 +13:00
Rob Bygrave e4d9e4f2de Testing - modify .travis to run mysql as service (bump MySql version to 5.7) 2018-02-10 01:04:19 +13:00
Rob Bygrave 6474f306b5 #1255 - Regression on raw LIKE expression with slashes on Postgres
Related update for Sqlite
2018-02-10 00:57:19 +13:00
Rob Bygrave f1c2f134ad #1255 - Regression on raw LIKE expression with slashes on Postgres
Related update for Sqlite
2018-02-10 00:56:05 +13:00
Rob Bygrave 0f7158ea18 Testing - modify .travis to run mysql as service 2018-02-10 00:34:34 +13:00
Rob Bygrave 3fdb76d18f Testing - modify .travis to run mysql as service 2018-02-10 00:31:39 +13:00
Rob Bygrave b1027a2f25 Testing - modify .travis to run mysql as docker container 2018-02-10 00:18:33 +13:00
Rob Bygrave e5a1f9f7cc Testing - modify .travis adding docker service 2018-02-10 00:07:27 +13:00
Rob Bygrave f78f24136a [maven-release-plugin] prepare for next development iteration 2018-02-09 23:42:42 +13:00
Rob Bygrave 5b2aa0c74d [maven-release-plugin] prepare release ebean-11.10.3 2018-02-09 23:42:28 +13:00
Rob Bygrave 175714046a #1254 - SpringJdbcTransactionManager inifinite recursion #1254
Yeah, nah. This is the real fix. Expose:

   SpiTransaction TransctionManager.getInScope();

... and have ebean-spring-txn SpringJdbcTransactionManager call it instead of getActive().
2018-02-09 23:03:07 +13:00
Rob Bygrave 73b2cc55f3 #1254 - SpringJdbcTransactionManager inifinite recursion #1254
Fix. Note tested in ebean-spring-txn.
2018-02-09 22:22:08 +13:00
Rob Bygrave cebe375856 No effective change - initial docker testing setup for oracle and sqlserver 2018-02-09 21:31:40 +13:00
Rob Bygrave 2f47235018 #1255 - Regression on raw LIKE expression with slashes on Postgres 2018-02-09 21:28:39 +13:00
Rob Bygrave 17abd6d977 #1255 - Regression on raw LIKE expression with slashes on Postgres
Tests
2018-02-09 21:25:36 +13:00
Rob Bygrave cc5f3689f3 No effective change - modify tests for SqlServer 2018-02-09 21:10:18 +13:00
Rob Bygrave abcc651e7f #1253 - Query where many isNotEmpty() ... on ManyToMany with SoftDelete produces incorrect SQL
Fix
2018-02-09 15:00:58 +13:00
Rob Bygrave caa36262c1 #1253 - Query where many isNotEmpty() ... on ManyToMany with SoftDelete produces incorrect SQL
Failing test
2018-02-09 15:00:29 +13:00
Rob Bygrave 66b6dba921 [maven-release-plugin] prepare for next development iteration 2018-02-07 16:54:44 +13:00
Rob Bygrave fc01f230f3 [maven-release-plugin] prepare release ebean-11.10.2 2018-02-07 16:54:31 +13:00
Rob Bygrave 7fe3e657d7 No effective change - put default test db back to default to h2 2018-02-07 16:49:49 +13:00
Rob Bygrave 9bade12c9d #1251 - Delete cascade with 11+ and Postgres throws exception
Fix
2018-02-07 16:47:59 +13:00
Rob Bygrave 7a816ae2da #1251 - Delete cascade with 11+ and Postgres throws exception
Failing test
2018-02-07 16:40:12 +13:00
Rob Bygrave b83412281e #1251 - Delete cascade with 11+ and Postgres throws exception
Failing test
2018-02-07 16:39:58 +13:00
Rob Bygrave 478bba292d #1250 - Add explicit coverage for Enum with abstract method - no new issue 2018-02-07 14:01:11 +13:00
Rob Bygrave 77a4e684bb [maven-release-plugin] prepare for next development iteration 2018-02-02 23:39:51 +13:00
Rob Bygrave a8254c4295 [maven-release-plugin] prepare release ebean-11.10.1 2018-02-02 23:39:38 +13:00
Rob Bygrave 2a5d0084ef #1249 - Bump db-migration to 11.3.1 ... with fix for not running empty sql statements (empty strings) 2018-02-02 23:38:11 +13:00
Rob Bygrave f9404639d7 Fix test for H2 select for update - my bad. 2018-02-02 23:36:12 +13:00
Rob Bygrave bbef5a6bbb #1243 - Add IDENTITY support for Oracle platform (since 12c Oracle supports auto generated identity) 2018-02-02 23:18:23 +13:00
Rob Bygrave 4645fd9725 Cleanup tests for Oracle 2018-02-02 23:17:21 +13:00
Rob Bygrave 823cb45221 Cleanup tests for Oracle 2018-02-02 23:17:03 +13:00
Rob Bygrave b2bbb05b83 #1248 - ENH: Additionally read "db" system property to determine default database (to use when testing with docker against different databases) 2018-02-02 20:49:39 +13:00
Rob Bygrave 5ff71324d0 #1247 - Unique index or primary key violation - when jdbc batch cascading to PrivateOwned child with unique constraint 2018-02-02 20:43:55 +13:00
Rob Bygrave 851f1c98b0 #1245 - Refactor internals - move Transaction ProfileStream creation
Stops the profileId parameter pollution, enables to potentially use transaction label
and runtime toggling of collecting transaction profiling detail.
2018-01-31 14:02:50 +13:00
Rob Bygrave a92e620f7e #1245 - Refactor internals - move logic to TransactionManager from DefaultServer 2018-01-31 13:36:23 +13:00
Rob Bygrave f9cd955f7a #1245 - Refactor internals - Add to TransactionManager externalRemoveTransaction() and externalBeginTransaction()
These provide a better/tidier way for external transaction managers (like ebean-spring-txn) to begin and end externally
managed transactions.
2018-01-31 13:28:42 +13:00
Rob Bygrave 71f66005e7 Merge branch 'master' of github.com:ebean-orm/ebean 2018-01-31 11:57:10 +13:00
Rob Bygrave b682293a32 #1245 - Refactor internals - move logic to TransactionManager from DefaultServer 2018-01-31 11:56:38 +13:00
Rob Bygrave 5bd7853ce8 #1245 - Refactor internals - move TransactionMangerScope to be part of TransactionManager 2018-01-31 11:30:11 +13:00
André CamiloandRob Bygrave 276c56161a DiscriminatorColumn length should be 31 (#1244) 2018-01-31 08:32:21 +13:00
Rob Bygrave 6b01821623 #1242 - Bump avaje-classpath-scanner dependency to 3.1.1 2018-01-26 11:51:28 +13:00
Rob Bygrave 8495ccced6 #1241 - ENH: Support using ebean_db system property to control docker container for testing 2018-01-24 19:17:14 +13:00
Rob Bygrave 2d929837c4 No effective change - Update testing for profile location enhancement (#1227) 2018-01-24 19:11:59 +13:00
Rob Bygrave 6754992b1c [maven-release-plugin] prepare for next development iteration 2018-01-22 23:02:52 +13:00
Rob Bygrave 08b7f4a95f [maven-release-plugin] prepare release ebean-11.9.1 2018-01-22 23:02:37 +13:00
Rob Bygrave 07e2605a30 #1240 - ENH: Add support for @Transactional skipCache and label 2018-01-22 22:57:35 +13:00
Rob Bygrave 9a0b742f14 #1240 - ENH: Add support for @Transactional skipCache and label 2018-01-22 15:07:50 +13:00
Rob Bygrave bce745e88d #1240 - ENH: Add support for @Transactional skipCache and label 2018-01-22 15:04:13 +13:00
Rob Bygrave 51d2e4c600 ENH: Add ProfileLocation - Part 2 - performance metrics for transactions with label and profileLocation 2018-01-22 14:54:27 +13:00
Rob Bygrave 4e33027fdf Bump to 11.9.1-SNAPSHOT, add test dependency for logback 2018-01-19 11:10:18 +13:00
Rob Bygrave 0a809b0fb3 #1239 - When Transaction.setSkipCache(true) ... Query with useQueryCache is still use L2 query cache 2018-01-19 10:46:49 +13:00
Rob Bygrave 13ddb915c8 No effective change - add javadoc 2018-01-19 09:38:50 +13:00
Rob Bygrave 07cdf64ece #1238 - Refactor MetaInfoManager - collect query plan stats, fix collection of stats on UpdateQuery 2018-01-19 01:07:37 +13:00
Rob Bygrave b9ae76d465 #1237 - ENH: Add ProfileLocation - support for relating performance metrics for queries and transactions back to source line of code 2018-01-18 18:10:03 +13:00
Rob Bygrave 82f5c21d26 No effective change - Improve exception error message when property is not found on a bean type
Typically using IDE enhancement plugin with incremental compilation where part of an inheritance
hierarchy has been changed but not all related classes recompiled and re-enhanced.
2018-01-12 01:27:24 +13:00
Rob Bygrave 14105eb1eb #1236 - ENH: Add Transaction.current() ... as alternative to obtain the current transaction 2018-01-11 22:34:31 +13:00
Rob Bygrave bab27f25ca [maven-release-plugin] prepare for next development iteration 2018-01-09 23:19:09 +13:00
Rob Bygrave eed8d69715 [maven-release-plugin] prepare release ebean-11.8.1 2018-01-09 23:18:54 +13:00
Rob Bygrave 7b93df2df7 Bump pom version to 11.8.1-SNAPSHOT 2018-01-09 23:17:53 +13:00
Rob Bygrave bb205ced54 #1235 - Thread deadlock on L2 cache load of many property 2018-01-09 23:16:35 +13:00
Rob Bygrave 0d4c50e19c #1234 - Remove deprecated CacheMode.QUERY_ONLY (migrate to CacheMode.GET) 2018-01-09 19:56:55 +13:00
Rob Bygrave 8cff85fdda #1233 - Remove deprecated CacheMode.RECACHE (migrate to CacheMode.PUT) 2018-01-09 19:50:26 +13:00
Rob Bygrave 932986a6b5 #1232 - Performance: Add support for a second read-only DataSource (for implicit query-only transactions) 2018-01-09 16:35:22 +13:00
Rob Bygrave 01539091ef #1231 - Performance: Only use CallStack when using AutoTune (automatic query tuning or profiling) 2018-01-09 13:28:57 +13:00
Rob Bygrave 7e69f71b51 #1230 - Add DB Migration non strict mode - IllegalArgumentException: non-null column has no default value 2018-01-07 15:33:18 +13:00
Rob Bygrave 58d6b2c24e Merge branch 'master' of github.com:ebean-orm/ebean 2018-01-06 12:52:38 +13:00
Rob Bygrave 3c7ef7d46e #1229 - Implement equals and hashCode on ModifyAwareMap, ModifyAwareList and ModifyAwareSet 2018-01-06 12:51:50 +13:00
Rob Bygrave db5db26fca No effective change - rename parameter fix typo 2018-01-06 12:21:14 +13:00
rob bygrave 7110f4a59b No effective change - remove unused HashQueryPlan etc 2017-12-28 16:17:00 +13:00
rob bygrave 9f91d8bcf9 No effective change - modify specific test to run with Postgres specific syntax 2017-12-27 23:23:01 +13:00
Rob Bygrave ac97444ad1 No effective change - add test for @Aggregation with order by clause 2017-12-27 13:49:46 +13:00
Rob Bygrave f6e9afcab6 #1226 - Version range in dependency makes sbt resolve very slow. Change slf4j-api dependency to provided scope.
Part 2, bring in new version of avaje-classpath-scanner which also has slf4j-api as provided scope.
2017-12-27 13:48:22 +13:00
Rob Bygrave a7226079fe [maven-release-plugin] prepare for next development iteration 2017-12-14 00:00:04 +13:00
Rob Bygrave fc915010d9 [maven-release-plugin] prepare release ebean-11.7.1 2017-12-13 23:59:49 +13:00
Rob Bygrave c1818bc309 #1226 - Version range in dependency makes sbt resolve very slow. Change slf4j-api dependency to provided scope. 2017-12-13 22:51:23 +13:00
Rob Bygrave 4a4134ee93 #1227 - NPE when using L2 Query cache with findOne() or findOneOrEmpty() 2017-12-13 22:19:25 +13:00
Rob Bygrave e07bd8f736 #1223 - Support mapping @DbArray to a List or Set of enums 2017-12-13 21:15:19 +13:00
Rob Bygrave 4d0b29624e #1222 - Extend L2 ServerCache API with putAll(), getAll() and removeAll() methods 2017-12-13 19:58:28 +13:00
Rob Bygrave c7f4b56dd1 #1225 - ENH: Extend L2 server cache (near caching) for clearing "near caches" 2017-12-13 02:09:10 +13:00
Rob Bygrave 69c045443c #1218 - ENH: Bump to migration 11.2.1 with support for options patchInsertOn and patchResetChecksumOn 2017-11-23 19:05:35 +13:00
Rob Bygrave fd2d083971 #1217 - L2 query cache not caching empty result set 2017-11-22 22:03:35 +13:00
Rob Bygrave b9380aa5b8 No effective change - add property test for ServerConfig jsonDateTime 2017-11-22 21:21:09 +13:00
Rob Bygrave 3a1368a342 [maven-release-plugin] prepare for next development iteration 2017-11-19 20:34:54 +13:00
Rob Bygrave 0e9fc31531 [maven-release-plugin] prepare release ebean-11.6.1 2017-11-19 20:34:39 +13:00
Rob Bygrave 5132107748 Bump to 11.6.1-SNAPSHOT 2017-11-19 20:33:27 +13:00
Rob Bygrave 7ff3d703f7 #1215 - ENH: Add Query setBeanCacheMode(CacheMode) ... with a view to it replacing the existing setUseCache(boolean) and setLoadBeanCache(boolean) 2017-11-19 20:16:40 +13:00
Rob Bygrave ef91c643ed #1214 - ENH: Add inPairs() expression - support L2 cache hits for complex natural key with findList() and in pairs expression 2017-11-19 16:47:32 +13:00
Rob Bygrave f0ddf6c7e6 #1213 - NPE with TxType SUPPORTS 2017-11-19 01:51:03 +13:00
Rob Bygrave fcff571664 #1212 - ENH: Add query findSingleAttribute() 2017-11-18 22:36:08 +13:00
Rob Bygrave d5555ed9a9 #1211 - ENH: Support L2 cache complex natural keys include findList() queries 2017-11-18 22:20:42 +13:00
Rob Bygrave c5a11aa5a8 No effective change - format and javadoc 2017-11-18 10:48:37 +13:00
Rob Bygrave d1099c8309 Merge branch 'master' of github.com:ebean-orm/ebean 2017-11-15 01:02:35 +13:00
Rob Bygrave 7ff8758797 No effective change - fix javadoc 2017-11-15 01:02:11 +13:00
Koen De GrooteandRob Bygrave f1ebe7929b Internal refactor / tidy - Suggestions from intellij code analysis. (#1209) 2017-11-14 18:19:38 +13:00
Rob Bygrave 0056568bc7 [maven-release-plugin] prepare for next development iteration 2017-11-13 23:18:10 +13:00
Rob Bygrave 4b72924529 [maven-release-plugin] prepare release ebean-11.5.1 2017-11-13 23:17:54 +13:00
Rob Bygrave a75ed676f8 Bump pom version to 11.5.1-SNAPSHOT 2017-11-13 23:16:38 +13:00
Rob Bygrave c3438b888d #995 - @OneToMany with constraints on the many side 2017-11-13 22:43:56 +13:00
Rob Bygrave 56be274acc No effective change - change internal use of ArrayList to List 2017-11-13 22:42:39 +13:00
Rob Bygrave 84bb4ff78c #1207 - Regression added in 11.4.1 with NPE on @transactional(type = TxType.SUPPORTS) 2017-11-13 21:33:39 +13:00
Rob Bygrave 4054eda1f6 #1207 - Regression added in 11.4.1 with NPE on @transactional(type = TxType.SUPPORTS) 2017-11-13 21:32:52 +13:00
Rob Bygrave a4b9354e43 #1206 - NPE when using @Encrypted with Enum property that is null 2017-11-13 19:12:57 +13:00
Rob Bygrave 06e033f23f #1181 - ENH: Add @FetchPreference support - Secondary query generation is based on order of fetch statements 2017-11-08 23:20:08 +13:00
Rob Bygrave 156f505394 #1181 - ENH: Add @FetchPreference support - Secondary query generation is based on order of fetch statements 2017-11-08 23:19:58 +13:00
Rob Bygrave 9b2b2f7787 #1205 - ENH: Add support for raw expression array binding with Postgres - e.g. raw(" foo = any(?) ", collection) 2017-11-08 00:56:13 +13:00
Rob Bygrave e68dae0baa Update ebean-annotation to 3.3 and tests to use 11.5.1 agent 2017-11-07 22:57:04 +13:00
Rob Bygrave 2cf864954f #1204 - Check presence of JAXB and javax @PostConstruct (which may not be present in minimal Java 9) 2017-11-07 20:08:10 +13:00
Rob Bygrave 2b94487573 #1202 - Automatically remove old query plans from Ebean's internal query plan cache 2017-11-06 22:59:42 +13:00
Rob Bygrave fcf730ec39 [maven-release-plugin] prepare for next development iteration 2017-11-06 14:49:08 +13:00
Rob Bygrave 7d343455ac [maven-release-plugin] prepare release ebean-11.4.1 2017-11-06 14:48:55 +13:00
Rob Bygrave 21e0b748a6 #1199 - Remove deprecated findUnique() method - please migrate to findOne() 2017-11-03 03:35:19 +13:00
Rob Bygrave 2fab733e4e Update agent and maven plugin for 11.4.1 enhancement (@Transactional and PropertyChangeListener changes) 2017-11-03 03:30:53 +13:00
Rob Bygrave 7260a1b6eb #1198 - Remove support for PropertyChangeListener from entity beans 2017-11-03 03:08:43 +13:00
Rob Bygrave 434a005366 #1198 - Remove support for PropertyChangeListener from entity beans 2017-11-03 03:05:59 +13:00
Rob Bygrave ff67ef60b0 #1197 - Refactor how @Transactional methods internally managed 2017-11-03 02:13:56 +13:00
Rob Bygrave 0a1747d8e3 #1194 - Change from using Jetbrains @Nullable to ... class retention based javax annotation @Nonnull 2017-11-02 15:56:15 +13:00
Rob Bygrave f36499f71f No effective change - remove use of jetbrains @NotNull in tests 2017-11-02 15:26:35 +13:00
rob bygrave da818f17c2 #1190 - MySql throwing DataIntegrityException when it should throw the more specific DuplicateKeyException
Ah, remove the 23000 SQLState to just use the error codes for MySql.
2017-11-02 01:16:52 +13:00
rob bygrave 10eb2bc21f #1193 - For RawSql ignore the Postgres cast double colon like ::text 2017-11-02 00:03:38 +13:00
rob bygrave 66fe278e3f #1192 - findNative() with @Embedded beans ... the embedded bean isn't loaded properly 2017-11-01 23:03:57 +13:00
rob bygrave 10607385e0 #1191 - Trim logged SQL removing new line chars (for sql from SqlUpdate) 2017-11-01 22:00:55 +13:00
rob bygrave db6562df76 #1190 - MySql throwing DataIntegrityException when it should throw the more specific DuplicateKeyException 2017-11-01 21:54:48 +13:00
rob bygrave c0ec87d4cd #1189 - ExpressionList.isNull and SoftDelete 2017-11-01 21:48:23 +13:00
rob bygrave 0dbba7a211 #1189 - ExpressionList.isNull and SoftDelete 2017-11-01 21:26:15 +13:00
rob bygrave e75670f207 #1188 - When using inheritance getReference() on a leaf type ... should not hit the DB 2017-11-01 20:42:18 +13:00
rob bygrave fb8db14f3a #1186 - Tidy, remove H2MultiValueBind for now 2017-10-31 22:14:01 +13:00
rob bygrave c00b1849ef Merge branch 'feature/1186-MultiValueBind' 2017-10-31 22:11:30 +13:00
rob bygrave 1e1c518641 #1186 - ENH: Support using TableValues / Array for select prop in (?) queries
Use Postgres Array ANY and ALL without select unnest
2017-10-31 22:09:35 +13:00
Rob Bygrave d5b42f9ba1 [maven-release-plugin] prepare for next development iteration 2017-10-31 10:52:44 +13:00
Rob Bygrave bda564d2c8 [maven-release-plugin] prepare release ebean-11.3.1 2017-10-31 10:52:31 +13:00
Rob Bygrave dce124cabd #1187 - Fix connection leak regression introduced in 11.2.3 for findEach() with invalid SQL 2017-10-31 10:50:20 +13:00
Rob Bygrave f5cfcbd56e #1187 - Fix connection leak regression introduced in 11.2.3 for findEach() with invalid SQL 2017-10-31 10:49:35 +13:00
rob bygrave 5bccdccbd6 #1186 - ENH: Support using TableValues / Array for select prop in (?) queries 2017-10-31 02:53:34 +13:00
rob bygrave 6e62b72fb9 #1186 - ENH: Support using TableValues / Array for select prop in (?) queries 2017-10-31 02:53:20 +13:00
rob bygrave 89dac3820b #1182 - Error when applied disjunction to filterMany 2017-10-30 22:06:57 +13:00
rob bygrave ea836a0078 No effective change - rename variable 2017-10-30 21:29:57 +13:00
rob bygrave 1ffd7c7720 git push origin masterMerge branch 'OndrejPacay-feature/1179_bugCollectionL2CacheNotInvalidatedAfterExternalChange' 2017-10-30 21:25:43 +13:00
rob bygrave 387582543c Merge branch 'feature/1179_bugCollectionL2CacheNotInvalidatedAfterExternalChange' of https://github.com/OndrejPacay/ebean into OndrejPacay-feature/1179_bugCollectionL2CacheNotInvalidatedAfterExternalChange 2017-10-30 21:25:30 +13:00
rob bygrave a215878a7c #1183 - ENH: Add support for transaction profiling 2017-10-30 21:21:12 +13:00
rob bygrave dbedb65922 #1183 - ENH: Add support for transaction profiling 2017-10-30 21:19:58 +13:00
Rob Bygrave 1d52b3a818 #1183 - Support transaction profiling, adjust output format 2017-10-27 00:27:21 +13:00
Rob Bygrave 6ce2b91fff #1183 - Support transaction profiling, move away from binary encoding 2017-10-26 23:32:54 +13:00
Rob Bygrave 55d66ae851 #1183 - Support transaction profiling, move away from binary encoding 2017-10-26 23:32:44 +13:00
Rob Bygrave 37d001f754 #1185 - Modify JDBC batch so it does not "auto flush" on non-Id non-generated property 2017-10-26 00:03:58 +13:00
rob bygrave c121618c0c #1183 - ENH: Add support for transaction profiling 2017-10-25 01:31:09 +13:00
rob bygrave 7ebef51859 #1183 - ENH: Add support for transaction profiling 2017-10-25 01:07:00 +13:00
rob bygrave 093f82a87f #1178 - Make the new changeLogAsync property default to true in ServerConfig 2017-10-19 22:26:13 +13:00
Ondrej Pacay b60f1f978f Bug Collection IDs L2 cache not cleared on external sql modification of the table #1179 2017-10-19 01:06:43 +02:00
Roland PramlandRob Bygrave 6ac146cabe Fix beanchange deser (#1178)
Fix / support JSON marshalling of BeanChange + add changeLogAsync option to ServerConfig
2017-10-19 09:40:27 +13:00
Roland PramlandRob Bygrave 2263d31f46 Improved the performance of findAnnotation (#1177) 2017-10-19 09:34:57 +13:00
rob bygrave 4a66d0be6b [maven-release-plugin] prepare for next development iteration 2017-10-19 01:26:28 +13:00
rob bygrave e68e496207 [maven-release-plugin] prepare release ebean-11.2.3 2017-10-19 01:26:12 +13:00
rob bygrave 088110385f Bump ebean-migration dependency to 11.1.1 2017-10-19 01:19:51 +13:00
rob bygrave a355f66561 #1176 - Allow script in extra-ddl.xml ... to not have trailing semi-colon 2017-10-19 01:11:14 +13:00
rob bygrave 00fdb632d7 #1173 - Ebean server should read ebean.mf entity-packages to locate entity beans 2017-10-18 23:58:22 +13:00
rob bygrave a54c4157e6 Refactor as part of - Ensure that Ebean.currentTransaction is available in lifecycle handlers (#1166) #1175 2017-10-18 23:27:59 +13:00
Rob Bygrave a89a9f0202 #1166 - Refactor to use beginServerTransaction() to make Ebean.currentTransaction available in lifecycle handlers 2017-10-17 01:07:48 +13:00
Rob Bygrave 331f49824f #1172 - Refactor - remove internal unused DefaultOrmQuery logSecondaryQuery (as we use LoggedSqlCollector) 2017-10-16 23:49:23 +13:00
Rob Bygrave 94a857d345 #1171 - ENH: Add Finder.update() method ... returning a UpdateQuery<T> 2017-10-16 23:25:56 +13:00
Rob Bygrave 1005f177fd #1170 - ENH: Add isIn() methods as alias to in() on ExpressionList (for use with Kotlin where in is a keyword) 2017-10-16 23:13:49 +13:00
Rob Bygrave 96a4b93c75 #1167 - BUG: query.setId(...).delete() does not work 2017-10-16 22:58:48 +13:00
Rob Bygrave 5869187368 [maven-release-plugin] prepare for next development iteration 2017-10-16 22:26:39 +13:00
Rob Bygrave eac50b8f5b [maven-release-plugin] prepare release ebean-11.2.2 2017-10-16 22:26:21 +13:00
Rob Bygrave 6e2712ea49 #1169 - Memory leak - DefaultTransactionThreadLocal holding reference to transaction 2017-10-16 22:14:48 +13:00
Rob Bygrave f6e5446dab #1169 - Memory leak - DefaultTransactionThreadLocal holding reference to transaction - test case 2017-10-16 22:13:41 +13:00
Koen De GrooteandRob Bygrave 4879d44da4 Bit of cleanup suggestions from intellij. (#1168) 2017-10-16 20:16:30 +13:00
rob bygrave 2c5bf98d0b Merge branch 'master' of github.com:ebean-orm/ebean 2017-10-09 21:13:32 +13:00
rob bygrave 45a571bd97 #1165 - ENH: Add to Finder - currentTransaction() and flush() methods ... (as useful shortcuts) 2017-10-09 21:13:12 +13:00
Roland PramlandRob Bygrave d0ca75c25b FIX: connection leak in query-iterator (#1164) 2017-10-09 20:46:02 +13:00
Roland PramlandRob Bygrave fb1c7667cc FIX: order by must be added in findEach also (#1163) 2017-10-09 20:28:36 +13:00
Roland PramlandRob Bygrave 1909ba1557 Fix like escaping for DB2, Oracle and MySql (#1162)
* Extended test case to show problem

* FIX: Proper escaping of backslash in like/contains queries

* Had to replace "like ?" assertions in tests with "like " as mysql will do a "like binary ? escape'|'" now to be case sensitive
2017-10-06 09:46:56 +13:00
Roland PramlandRob Bygrave e4eca4bbe9 FIX: Oto relations must match datatype (#1161) 2017-10-06 09:44:06 +13:00
Roland PramlandRob Bygrave b2438ecd71 FIX: do not generate unique-constraint for PK as it is useless (and oracle does not accept this) (#1160) 2017-10-06 09:43:30 +13:00
Roland PramlandRob Bygrave ed08567d06 FIX: bundle symbolic name in manifest (#1159) 2017-10-06 09:42:42 +13:00
Roland PramlandRob Bygrave bbe8abcc2e Can handle one to many & many to one relations in docstore only entities (#1158) 2017-10-06 09:42:05 +13:00
Roland PramlandRob Bygrave 1651d5e119 Misc platform fixes (#1157)
* Oracle does not return row count - so we probably cannot detect Optimistic locking

* DB2 wants a varchar null value (other platfroms are happy with this, too)

* FIX Test for DB2 platform
2017-10-05 21:51:09 +13:00
Roland PramlandRob Bygrave 64bf6d6a35 commit transaction only if active (#1156) 2017-10-05 11:04:12 +13:00
Roland PramlandRob Bygrave 47b0a917a2 No effective code change - fix imports and override annotations (#1155) 2017-10-05 10:55:48 +13:00
rob bygrave 2fe1a349c3 [maven-release-plugin] prepare for next development iteration 2017-10-05 01:36:46 +13:00
rob bygrave f168a8fd0d [maven-release-plugin] prepare release ebean-11.2.1 2017-10-05 01:36:30 +13:00
rob bygrave dda98c1dda Bump to 11.2.1-SNAPSHOT 2017-10-05 01:35:30 +13:00
rob bygrave 88a13c5416 #1154 - Remove deprecated TxCallable and TxRunnable - migrate to use Callable and Runnable 2017-10-05 01:24:53 +13:00
rob bygrave 16b8f5da35 Refactor EbeanServerFactory internals - use SpiContainerFactory interface and service loader 2017-10-05 01:12:07 +13:00
rob bygrave 3471f6d206 Refactor EbeanServerFactory internals - use SpiContainerShutdown interface for container shutdown mechanism 2017-10-05 00:57:40 +13:00
rob bygrave 0bf4c84bc8 #1153 - Refactor move SplitName into io.ebean.util 2017-10-05 00:41:32 +13:00
rob bygrave d366336ee5 #1153 - Refactor move ExtraTypeFactory out of io.ebean.plugin into io.ebeaninternal 2017-10-05 00:38:42 +13:00
rob bygrave bf3f8ecff5 Refactor plugin.BeanType addInheritanceWhere() to just take Query and not SpiQuery 2017-10-05 00:35:12 +13:00
rob bygrave 7524903aea #1152 - Refactor EJson internals extracting io.ebean.service.SpiJsonService 2017-10-05 00:29:43 +13:00
rob bygrave 90cf3fddc9 #1151 - Refactor add util AnnotationUtil ... moving common annotation searching methods there 2017-10-05 00:00:44 +13:00
rob bygrave 8e0f9f7591 Refactor - remove unused methods from StringHelper 2017-10-04 23:35:57 +13:00
rob bygrave 24936c0a41 Refactor - remove unused class ClassUtil 2017-10-04 23:34:13 +13:00
rob bygrave f02a552cdf #1150 - Refactor convert RawSql and RawSqlBuilder into interfaces and push the parsers into io.ebeaninternal 2017-10-04 23:03:12 +13:00
rob bygrave 5a5cb7ffbd #1149 - Refactor move PersistenceContextUtil into ... io.ebeaninternal 2017-10-04 21:12:39 +13:00
rob bygrave f85fa772bf #1147 - Refactor move DbMigration internals into io.ebeaninternal - change to use DbMigration.create() - move DbMigrationFactory.create() method 2017-10-04 21:06:55 +13:00
rob bygrave 9f9ec8ef9f #1147 - Refactor move DbMigration internals into io.ebeaninternal - change to use DbMigration.create() - move IdentityType handling into internal from DbIdentity 2017-10-04 20:49:04 +13:00
rob bygrave 62707caf64 #1147 - Refactor move DbMigration internals into io.ebeaninternal - change to use DbMigration.create() - move PlatformDdl into internal 2017-10-04 20:30:57 +13:00
rob bygrave c6fc7a032d #1147 - Refactor move DbMigration internals into io.ebeaninternal - change to use DbMigration.create() - DbOffline & ServerConfig 2017-10-04 19:44:29 +13:00
rob bygrave 10faa1fae6 #1147 - Refactor move DbMigration internals into io.ebeaninternal - change to use DbMigration.create() - initial move 2017-10-04 19:36:27 +13:00
Rob Bygrave 764f5ce4d4 [maven-release-plugin] prepare for next development iteration 2017-10-03 23:20:50 +13:00
Rob Bygrave 65ba231fc0 [maven-release-plugin] prepare release ebean-11.1.1 2017-10-03 23:20:35 +13:00
Rob Bygrave 1da2382e45 No effective change - javadoc only 2017-10-03 15:38:17 +13:00
Rob Bygrave a86af94a8c Reduce logging level only - no functional change 2017-10-03 15:35:21 +13:00
Rob Bygrave 8301cb634e #1027 - ENH: Add a Slow query event listener ... to log or listen to queries that exceed some defined execution time 2017-10-03 15:04:30 +13:00
Rob Bygrave 721654d033 #1140 - Error loading embedded instance
The issue was due to the loaded status not being recursively set on embedded
beans after inserts. The test case invoked lazy loading due to that which
lead to the issue.
2017-10-03 12:47:29 +13:00
Rob Bygrave fe1817ef02 No effective change - update test 2017-10-03 12:34:56 +13:00
Rob Bygrave fc996659f2 #1139 - NoSuchMethodError: javax.persistence.Embedded.prefix()Ljava/lang/String; 2017-10-03 11:02:38 +13:00
rob bygrave 368d22baa6 #1145 - Refactor @ChangeLog based on JSON documents for 'new values' and 'old values' 2017-10-03 01:31:37 +13:00
rob bygrave daf3d97266 #1144 - Refactor internals - move generated property setting into PersistRequestBean 2017-10-03 00:30:34 +13:00
rob bygrave f2179fca2d #1123 - 11.1.1 API change - moved PersistBatch, Platform, TxIsolation and TxType to io.ebean.annotation package 2017-09-15 21:48:53 +12:00
rob bygrave 2c436c3af5 #1123 - 11.1.1 API change - moved PersistBatch, Platform, TxIsolation and TxType to io.ebean.annotation package 2017-09-15 21:48:37 +12:00
Roland PramlandRob Bygrave 8d334ff2e8 Feature/contitional test runner (#1132)
* FIX: warnings (add generics, overrides, fix imports) - should be no effecive code change

* replaced deprecated methods by default methods

* FIX: more compiler warnings

* FIX more warnings - no code changes

* FIX: deprecated call to JsonParseException

* Remove unused code, check unused variables

* ADD: ContitonaltestRunner to skip tests for certain platforms

* Use annotations to control on which platforms a test shoud run

* FIX: compile errors
2017-09-15 21:03:03 +12:00
rob bygrave f3e4696498 [maven-release-plugin] prepare for next development iteration 2017-09-14 01:03:21 +12:00
rob bygrave 221260fa44 [maven-release-plugin] prepare release ebean-10.4.7 2017-09-14 01:03:07 +12:00
rob bygrave f8e7a79e9a #1131 - Migration broken in 10.4.6 due different classpath-scanner version 2017-09-14 00:56:37 +12:00
Roland PramlandRob Bygrave b66f18bfd6 Fix warnings 2 (#1130)
* FIX: warnings (add generics, overrides, fix imports) - should be no effecive code change

* replaced deprecated methods by default methods

* FIX: more compiler warnings

* FIX more warnings - no code changes

* FIX: deprecated call to JsonParseException

* Remove unused code, check unused variables
2017-09-14 00:32:48 +12:00
Roland PramlandRob Bygrave ac6708e0d0 Fix warnings (#1129)
* FIX: warnings (add generics, overrides, fix imports) - should be no effecive code change

* replaced deprecated methods by default methods

* FIX: more compiler warnings

* FIX more warnings - no code changes
2017-09-14 00:29:01 +12:00
rob bygrave a5f46c095d [maven-release-plugin] prepare for next development iteration 2017-09-13 23:02:39 +12:00
rob bygrave 3ac7ea6e60 [maven-release-plugin] prepare release ebean-10.4.6 2017-09-13 23:02:25 +12:00
rob bygrave b2e0271ce7 #1128 - Allow "2 word SQL" like TRUNCATE t, ANALYSE t etc 2017-09-13 21:40:17 +12:00
rob bygrave c7a7651602 #1127 - Remove the ebean.query.globallimit of 1 million "backstop" 2017-09-13 21:22:03 +12:00
rob bygrave 1e6678cbb4 #1126 - Regression bug in 10.4.5 with new line character use with SqlQuery, SqlUpdate and CallableSql 2017-09-13 21:14:19 +12:00
Roland PramlandRob Bygrave a6e4e181bf Feature/cache improvements 2 (#1067)
* New Mode to control queryCache behavior

* Collections form the cache have to be read only

* findCount not queried in query cache

* return modifiable collections from the cache

* FIX: Compile errors

* No effective code change: reformat code / javadoc
2017-09-12 23:40:18 +12:00
Roland PramlandRob Bygrave b8e1dffca2 replaced findUnique by "default" method in interfaces. (#1124) 2017-09-12 23:20:04 +12:00
rob bygrave 7e8ed72b7b #1125 - ENH: Add a SpiContainerBootup API ... to enable automatic startup of docker containers (for testing usually) 2017-09-12 22:44:37 +12:00
rob bygrave ec8dd30a04 [maven-release-plugin] prepare for next development iteration 2017-09-11 23:12:43 +12:00
rob bygrave f81d5c9f3a [maven-release-plugin] prepare release ebean-10.4.5 2017-09-11 23:12:29 +12:00
rob bygrave 74b24b1db1 #1120 - Bump classpath scanner dependency to 2.2.4 (fix for NPE on empty directory) 2017-09-11 23:09:28 +12:00
rob bygrave 179ef8c8a0 No effective change - javadoc update on Ebean 2017-09-10 21:23:37 +12:00
rob bygrave f77f3c3d6e #1119 - Deprecate TxRunnable and TxCallable - migrate to plan JDK Runnable and Callable. Add explicit executeCall() method 2017-09-10 20:47:26 +12:00
Roland PramlandRob Bygrave 9a7646195c Featur/dbmigration 3 (#1118)
* ADD: more test classes for Softdelete and History

* update reference models after adding test classes

* DbMigration:Improved History generation for sqlserver

* FIX: When DB supports Sql2011 platform, we must not alter the history-table (as this is handled by DB itself)

* DbMigration: When dropping a table, drop the sequence also.

* DbMigration: dropColumn is handled by platformDdl now, as SqlServerDdl needs to delete dependent objects (default constraints...) first

* FIX: DbMigration is not executed on history table

* DbMigration: can drop comment now.

* No effective code change: completed ObjectFactory / fixed imports

* FIX: drop table comment

* Committed the reference models
2017-09-10 15:26:01 +12:00
rob bygrave 84d3578e33 No effective change - add a test for saveAll() with existing batch mode on
Assert that it does not flush the batch.  We want the batch to continue and flush normally.
2017-09-09 14:14:57 +12:00
rob bygrave ef05b81014 #1117 - Refactor - moved DbDefault and DbMigration annotations to ebean-annotation 2017-09-09 13:27:09 +12:00
rob bygrave 726c682984 #1116 - Remove references to annotation EbeanDDL which is no longer needed 2017-09-09 13:18:39 +12:00
rob bygrave 0c22a99fdf #1116 - Remove references to annotation EbeanDDL which is no longer needed 2017-09-09 13:12:40 +12:00
rob bygrave c062c8e001 #1054 Java 9 - adding "Automatic-Module-Name" to MANIFEST.MF initial step
Update dependency to ebean-migration 10.2.1, avaje-classpath-scanner and avaje-datasource to avoid package name clash
2017-09-09 01:53:47 +12:00
rob bygrave 06f3c000f5 #1115 - Trim SQL for SqlUpdate, SqlQuery and CallableSql - also replace \n with space 2017-09-08 23:45:28 +12:00
rob bygrave 8c0232fdb8 #1114 - Deprecate findUnique() - please migrate to findOne() - update tests 2017-09-08 22:48:46 +12:00
rob bygrave 2470486f20 #1114 - Deprecate findUnique() - please migrate to findOne() 2017-09-08 22:37:50 +12:00
rob bygrave 8fbf0374dd No effective change - tidy around Db migration changes 2017-09-08 22:02:56 +12:00
Roland PramlandRob Bygrave dd8fff0277 Feature/ddl migration (#1111)
* REFACTOR: use functions from ddl-help

* NEW: Default values are written to DDL

* fix testcase for sqlserver as default constraints will get names in future

* Reading DbMigration

* ADD: DbmIgrationGenerateTest

* Tables must be created first

* Sanity checks and some getters

* DdlMigration gets applied now

* ADD: Testcase and reference migration scripts

* no effective code changes: add comments
2017-09-08 21:47:33 +12:00
Rob Bygrave 73b3d1d977 [maven-release-plugin] prepare for next development iteration 2017-09-07 00:41:49 +12:00
Rob Bygrave 2a76ae2192 [maven-release-plugin] prepare release ebean-10.4.4 2017-09-07 00:41:36 +12:00
Rob Bygrave 39931a3a2c No effective change - add test example of markUnset on version property (to avoid occ check) 2017-09-07 00:40:19 +12:00
Rob Bygrave 58eb49617b #1113 - SqlUpdate with leading spaces leads to Invalid event detection (which table was update for L2 cache invalidation etc) 2017-09-07 00:36:52 +12:00
Rob Bygrave 9b621d2ec7 #1112 - Enhance JDBC batch behavior when cascade persist is turned off (manual master/detail batch persisting) 2017-09-06 23:57:54 +12:00
Roland PramlandRob Bygrave f2e8b652fa FIX: DDL process comment change correctly & drop references when index is dropped (#1109) 2017-09-01 20:45:06 +12:00
Roland PramlandRob Bygrave f342d9d561 API-CHANGE: DbMigration returns which version was generated (#1108) 2017-09-01 20:42:02 +12:00
Roland PramlandRob Bygrave 8009bdf099 REFACTOR: Created a "splitNames" in StringHelper and use it in various places. Also wrote some tests for StringHelper. (#1107) 2017-09-01 20:40:39 +12:00
Roland PramlandRob Bygrave 7336ce81bd FIX: Do not add AssocOne-generatedProperties if they should not. (#1106) 2017-09-01 20:38:13 +12:00
Roland PramlandRob Bygrave f805bec8f2 FIX: Using correct datatype for null value when json is serialized to varchar column (#1105) 2017-09-01 20:36:41 +12:00
Roland PramlandRob Bygrave 46cdc84e6b Refactor/findannotation (#1104)
* refactor: renamed findAnnotation method that searches recursive to findAnnotationRecursive

* CHG: searching namedQueries & indices also recursive in superclasses

* FIX: Using the AnnotationBase methods on several places and documented them
2017-09-01 20:25:10 +12:00
Roland PramlandRob Bygrave e908d16ba8 Pr/add tests (#1103)
* ADD: Testcase for Sqlserver-6.2.0 driver

* CHG: Removed Row-limit - so we need no special handling when sqlserver-platform generates a "select top 100" statement

* ADD: additional asserts to TestQueryCache

* CHG: Ignore test for sqlserver
2017-09-01 20:17:56 +12:00
rob bygrave 96e3f4138f #1064 - Query table alias not used in update() or delete() queries 2017-08-31 21:29:08 +12:00
rob bygrave 977dd52890 No effective change - code reformat only 2017-08-31 21:10:13 +12:00
Roland PramlandRob Bygrave a9b7bb2175 FIX: Passing MDC through background-executor (#1102) 2017-08-31 21:09:04 +12:00
rob bygrave f83c7fdac8 #1100 - Refactor OrmQueryPlanKey to use string expression for where 2017-08-31 02:11:49 +12:00
rob bygrave a695fb59b2 [maven-release-plugin] prepare for next development iteration 2017-08-31 01:50:20 +12:00
rob bygrave e197bb2900 [maven-release-plugin] prepare release ebean-10.4.3 2017-08-31 01:50:06 +12:00
rob bygrave b54b8815d9 Merge branch 'master' of github.com:ebean-orm/ebean 2017-08-30 21:59:08 +12:00
rob bygrave 1d1fde61be #1101 - findNative() on a bean with an associated @OneToOne (with the PK being derived from the parent) maps incorrectly 2017-08-30 21:58:33 +12:00
rob bygrave 683186cbe9 No effective change - pom whitespace only 2017-08-30 21:14:20 +12:00
Roy de BokxandRob Bygrave 5e6be40454 Only throwing warning for autocommit when server is not set to use autocommit-friendly TransactionManager. (#1085) 2017-08-30 20:57:49 +12:00
Roland PramlandRob Bygrave c00febd95b ENH: Abort all tests if connection to db could not be esablished (#1099) 2017-08-30 20:04:50 +12:00
Roland PramlandRob Bygrave 4c8e1113bf FIX: deadlock in TestCommitAndContiune for sqlserver & hsqldb (#1098) 2017-08-30 20:03:41 +12:00
Roland PramlandRob Bygrave 6f854da70b Fix/corrected error codes (#1097)
* FIX: db2plaform error codes and dbtypes

* FIX: H2: Add error code for locking

* FIX: Mysql: Add DataIntegrity-error code
2017-08-30 20:02:34 +12:00
Roland PramlandRob Bygrave 3f5a162a4e Fix/connection to different platforms (#1096)
* ADD: Profile for oracle and db2 to pom file. Downgraded mysql driver

* FIX: connection string for several platforms

* ADD: Documentation
2017-08-30 20:00:58 +12:00
Roland PramlandRob Bygrave d14529b602 FIX: optimized unique constraint handling for platforms that does support them on nullable columns (#1095) 2017-08-30 19:54:53 +12:00
Roland PramlandRob Bygrave f471961f06 FIX: extra-ddl modified to be compatible with different platfoms (#1094) 2017-08-30 17:51:41 +12:00
Roland PramlandRob Bygrave 457c1356a4 Fix/shortened tablenames (#1093)
* FIX: Shortened tablename (will fail on oracle)

* FIX: renamed table, otherwise, in db2 he_link_doc & hi_link_ are both generating the same index ix_h_lnk_dc_h_dc
2017-08-30 17:50:40 +12:00
Roland PramlandRob Bygrave 419ac2bf50 FIX: Possible NPE in StringHelper (#1092) 2017-08-30 17:49:34 +12:00
Roland PramlandRob Bygrave 727d088577 FIX: add MAX-DATE as default value for ROW END (#1091) 2017-08-30 17:48:36 +12:00
Roland PramlandRob Bygrave 972d2dcc6b FIX: nvarchar(max) length specified differently, otherwise this leads to a ddl like this "nvarchar(max)(700)" (#1090) 2017-08-30 17:47:21 +12:00
Roland PramlandRob Bygrave a5bcd49ecb FIX: Clean up before running tests - otherwise tests will fail if a previous test did not clean up well. (This fixes test failures in Eclipse where tests are executed in different order than in maven) (#1089) 2017-08-30 17:44:30 +12:00
Roland PramlandRob Bygrave ff496ad2d3 FIX: EnumToDbIntegerMap did not set 'integerType' - this leads to an incompatible quoting. Constraints like "check in ('1','2','3')" were not accepted by hsqldb on integer columns. (#1088) 2017-08-30 17:42:25 +12:00
Roland PramlandRob Bygrave 24d438ba23 FIX: H2HistoryTrigger honors schema (#1087) 2017-08-30 17:38:52 +12:00
Roland PramlandRob Bygrave 591067e39e FIX: Typo in classname (#1086) 2017-08-30 17:37:45 +12:00
rob bygrave 38a95dc5c4 No effective change - Reformat code - ScalarTypeEnumStandard 2017-08-24 22:37:41 +12:00
icodeandRob Bygrave 53426d8493 use jackson configuration [SD]eserialization enum (#1079)
* use jackson configuration [SD]eserialization enum

https://github.com/FasterXML/jackson-databind/wiki/Serialization-features 
https://github.com/FasterXML/jackson-databind/wiki/Deserialization-Features

keep jackson and ebean [SD]eserialization same
`objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_INDEX);`

* Update ScalarTypeEnumStandard.java

* Update ScalarTypeEnumStandard.java

* Update ScalarTypeEnumStandard.java

* Update ScalarTypeEnumStandard.java
2017-08-24 22:35:36 +12:00
rob bygrave a06238558e No effective change - Jackson WRITE_ENUMS_USING_INDEX test 2017-08-24 22:34:57 +12:00
Yuan XueguiandRob Bygrave b3a3b19d5d Fix: query table entity or sql entity has no id (#1082)
When query table entity or sql entity,include NamedQuery which modified via code and RawSqlQuery which modified via code.
2017-08-24 22:18:46 +12:00
rob bygrave 57231c80a8 #1084 - NPE When DB Migration generation run with @WhoCreated mapping 2017-08-24 22:15:01 +12:00
rob bygrave dc96fb9ad5 No effective change - update test, better asserts 2017-08-15 21:47:21 +12:00
rob bygrave 567847b47a #1081 - Update jackson-core dependency to 2.9.0 2017-08-05 00:11:53 +12:00
rob bygrave b74fed7073 Bump to 10.4.1 agent (@Transient properties included in mapped superclass enhancement detection) 2017-08-04 22:59:53 +12:00
rob bygrave cdaf8ee6d5 [maven-release-plugin] prepare for next development iteration 2017-08-04 21:33:33 +12:00
rob bygrave c6c5073e47 [maven-release-plugin] prepare release ebean-10.4.2 2017-08-04 21:33:19 +12:00
rob bygrave 2a58b954e9 #1062 - Multi-tenant - Update statements should include tenantId in where clause 2017-08-04 21:16:14 +12:00
Koen De GrooteandRob Bygrave 9772623880 Added the Serializable interface to classes that extend/implement a Comparator with an anonymous/typed class. (#1078) 2017-08-03 23:29:56 +12:00
rob bygrave 27b6183aad Merge branch 'master' of github.com:ebean-orm/ebean 2017-08-03 23:28:35 +12:00
David HofmannandRob Bygrave 55e19618f8 fix connection leak in JTA managed transactions (#1077) 2017-08-03 23:28:21 +12:00
rob bygrave 5c60ba4d7f Update test for WriteJson to just use PathProperties 2017-08-03 23:01:22 +12:00
rob bygrave b9cc584086 #1080 - NOT IN expression using entity beans / reference beans uses "in" 2017-08-03 20:31:18 +12:00
Koen De GrooteandRob Bygrave bf5a8c2fad Changed some boolean checks to use the recommended method of comparing floating point values in Java. (#1075) 2017-07-22 13:00:24 +12:00
rob bygrave 66138e5ea2 #1070 Fix for - Create test for bean cache not being cleared with delete or update queries 2017-07-21 23:31:23 +12:00
Rien Nentjes 75fb89ef76 Create test for bean cache not being cleared with delete or update queries 2017-07-14 11:04:43 +02:00
rob bygrave a2cb468222 No effective change - add test resource ebean.mf to hint to enhancement agent packages to enhance 2017-07-11 21:11:54 +12:00
rob bygrave 166bcd7c45 #1061 - findCount query is not cached in L2 query cache 2017-07-06 21:51:52 +12:00
rob bygrave 95aed6af54 #1060 - findSingleAttributeList doesn't store result in L2 query cache 2017-07-06 21:35:20 +12:00
rob bygrave 7a697c12af No effective change - moved mssql-jdbc down with other test scope dependencies 2017-07-06 21:11:40 +12:00
rob bygrave 23278ce30b #1058 - Refactor - PlatformPrefix isn't actually used in PlatformDddlWriter, removing. 2017-07-06 20:30:20 +12:00
Koen De GrooteandRob Bygrave 36a5610e25 Using Regular expression objects for splitting and replacing in strings. (#1059)
* Where possible, replace .split() and .replace() methods with compiled Regex patterns.
This prevents a regular expression from being compiled multiple times during runtime.

* Forgot making one instance `private static final`.
2017-07-06 20:14:51 +12:00
rob bygrave 08263c4588 [maven-release-plugin] prepare for next development iteration 2017-07-05 21:41:12 +12:00
rob bygrave 1e88a52208 [maven-release-plugin] prepare release ebean-10.4.1 2017-07-05 21:40:58 +12:00
rob bygrave e770a42175 Bump to 10.4.1-SNAPSHOT (due to ServerConfig h2ProductionMode removal) 2017-07-05 21:39:12 +12:00
Thibault MeyerandRob Bygrave 35b467c04f JSON simple implementation for MSSQL (#1057)
- Use JSON_VALUE
  - Use NVARCHAR type

Signed-off-by: Thibault Meyer <meyer.thibault@gmail.com>
2017-07-03 20:45:48 +12:00
Roland PramlandRob Bygrave 2001539755 Sqlserver support (#1053)
* made some tests sqlserver ready (No effective code change in src/main)

* FIX enhance packages and let all testcases inherit from BaseTestCase, so that they can be launched directly from eclipse

* ADD sqldriver in pom and datasource

* FIX: DDL-generation for sqlserver - not yet all sqlserver tests passing
mvn verify -Ddatasource.default=mssql => Tests run: 1980, Failures: 22, Errors: 44, Skipped: 16

* BaseDdlHandlerTest checks against correct sqlserver-ddl now
2017-07-03 20:27:37 +12:00
rob bygrave e49c4bfe5a #867 - ENH: Add ability to globally use quoted identifiers on all tables and columns 2017-07-02 21:07:58 +12:00
rob bygrave 15be31fd5f #1051 - Remove ServerConfig h2ProductionMode ... means for testing with h2 explicitly set ddlGenerate and ddlRun 2017-07-02 11:42:56 +12:00
rob bygrave 4777ec46be #1050 - Bump db-migration to 10.1.10 2017-07-02 11:12:03 +12:00
rob bygrave 80ab731aec Use older postgres jdbc driver 2017-06-25 22:56:21 +12:00
rob bygrave 080bafe18f #1048 - Fix connection leak on failed findIterate() 2017-06-25 22:39:04 +12:00
rob bygrave e913f88f52 Fix test - TestCommitAndContinue ... close extra transactions used in asserts 2017-06-25 21:43:37 +12:00
rob bygrave e94c5484a0 #1047 - Fix connection leak on failed beginTransaction() 2017-06-25 21:42:51 +12:00
rob bygrave 4af00c51d3 travis - dist: trusty ... to get PG 9.6 2017-06-25 19:57:31 +12:00
rob bygrave 23d1256dbf Update to postgres 9.6 for travis test runs 2017-06-25 19:43:05 +12:00
rob bygrave ed0ef46d2e No effective change - update postgresql jdbc driver 2017-06-25 19:03:07 +12:00
rob bygrave 1860ded735 [maven-release-plugin] prepare for next development iteration 2017-06-25 16:01:50 +12:00
rob bygrave d432854b82 [maven-release-plugin] prepare release ebean-10.3.2 2017-06-25 16:01:37 +12:00
rob bygrave 93582c8ea3 Downgrade postgres jdbc driver for commit and continue test 2017-06-25 15:54:14 +12:00
rob bygrave 520d35b1d6 #963 - NullPointerException on no version provided (when setVersion(null) is used) 2017-06-25 14:44:13 +12:00
rob bygrave 8ca3599cbf #1046 Bump DB migration to 10.1.9 - fix for Checksum mismatch does not stop migration 2017-06-25 14:29:46 +12:00
rob bygrave 283ae74219 Update javadoc on ScalarTypeConverter. Should look to officially deprecate this in favor of AttributeConverter. 2017-06-24 11:35:58 +12:00
rob bygrave cebd3f92a4 #1045 - MySql - DbMigration generate wrong comment syntax - should be alter table comment = syntax 2017-06-24 11:23:21 +12:00
rob bygrave 4b2481d3ea #1039 Fix for - reset of dirty flag on L2 cached entities after lazy load 2017-06-23 23:20:17 +12:00
rob bygrave f1f2a416d3 No effective change - reformat only 2017-06-23 23:19:22 +12:00
rob bygrave 74dd97a55f No effective change 2017-06-23 23:18:57 +12:00
rob bygrave 3f04f7f363 Merge branch 'master' of https://github.com/SamhammerAG/ebean into SamhammerAG-master 2017-06-23 19:52:55 +12:00
rob bygrave 800f854a12 #1043 Additional test for RawSql with upper case SQL 2017-06-23 19:46:47 +12:00
rob bygrave bef9e6d54f Merge branch 'master' of github.com:ebean-orm/ebean 2017-06-23 19:43:45 +12:00
Tigran_DadaiantsandRob Bygrave 0e4c0ae6c3 #1043 RawSql should automatically map upper-case column alias to lower-case bean property (#1044) 2017-06-23 19:43:15 +12:00
rob bygrave a0ea9887df No effective change - remove unused imports 2017-06-23 19:37:24 +12:00
Roland PramlandRob Bygrave 0413c22e6e no effective code change - fixed warnings about serialization, override, raw-types (#1032) 2017-06-23 19:33:03 +12:00
rob bygrave 989ae44a6d Merge branch 'pr/id-in-as-collection' of https://github.com/FOCONIS/ebean into FOCONIS-pr/id-in-as-collection 2017-06-23 19:28:25 +12:00
rob bygrave 100d314e63 #1035 Update for - FIX: deleting and adding same bean in beanCollection leads to deletion in DB
If use Modify mode we need to listen for both adds and removes to support sorting (can't rely on undoDelete() due to ordering)
2017-06-19 23:34:44 +12:00
rob bygrave dbf4e99187 #1035 tests for - FIX: deleting and adding same bean in beanCollection leads to deletion in DB 2017-06-19 23:32:58 +12:00
Roland PramlandRob Bygrave 7b8a85106c FIX: deleting and adding same bean in beanCollection leads to deletion in DB (#1035) 2017-06-19 22:50:20 +12:00
rob bygrave 58c5f01e2b #1042 - JtaTransaction is TenantMode.DB aware 2017-06-19 22:28:15 +12:00
Roland PramlandRob Bygrave bc74d35651 FIX: correct behavior of "startsWith, "contains" etc (#1031)
* FIX: correct behavior of "startsWith" if string contains "like"-wildcards

* Removed likeClasues with disabled escaping in database platforms as bind values are properly escaped now.
2017-06-19 22:21:26 +12:00
Roland PramlandRob Bygrave a1f95bf25e Pr/id in as collection2 (#1034)
* ENH: Changed  idIn(List) to idIn(Collection)

* ADD: sanity checks in IdBinder & special case if ID-list is empty
2017-06-19 22:05:56 +12:00
rob bygrave c454e1f8a7 No effective change - add test 2017-06-19 21:53:35 +12:00
Koen De GrooteandRob Bygrave 5a3669e1db Noticed that this boolean parameter was ignored. (#1041)
After some quick analysis, implemented that way it probably should be used.

Of course, this could have been on purpose, please advise.
2017-06-19 21:39:58 +12:00
rob bygrave 7a2e0b3695 Bump to the later agent 2017-06-19 21:34:18 +12:00
AWoelfel ce6d6269cd Step to reproduce reset of dirty flag on L2 cached entities after lazy load 2017-06-08 15:07:32 +02:00
Roland Praml 7d800b7080 ENH: Changed idIn(List) to idIn(Collection) 2017-05-29 15:22:48 +02:00
rob bygrave 136154e247 [maven-release-plugin] prepare for next development iteration 2017-05-21 21:56:29 +12:00
rob bygrave 0a5ce1bee8 [maven-release-plugin] prepare release ebean-10.3.1 2017-05-21 21:56:16 +12:00
Koen De GrooteandRob Bygrave b4e2c89e2d Moved a few variables closer to the point where they are actually used, but only in cases where this means moving them past a (potential) return/throw statement. (#1029) 2017-05-21 21:51:58 +12:00
Koen De GrooteandRob Bygrave 9e2923f571 For debug and trace levels, either added isEnabled check or made arguments parameterized. (#1028) 2017-05-21 21:50:13 +12:00
rob bygrave d0c1ae76f4 #955 - Migration "add column" DDL with check constraint is missing constraint name 2017-05-21 01:23:55 +12:00
rob bygrave fe9500e6d0 #1011 - Create valid migration scripts for non-Postgres databases and @DbArray columns.
Merge branch 'test/dbarray-create-migration' of https://github.com/FOCONIS/ebean into FOCONIS-test/dbarray-create-migration

commit 3a8f32b173
Author: Michael Benz <michael.benz@foconis.de>
Date:   Wed Apr 19 18:16:51 2017 +0200

    adding dbmigration ddlgeneration test for Ebean @DbArray extension.
2017-05-20 23:40:02 +12:00
rob bygrave 79f7c73983 #999 - Refactor tidy for ... @DiscriminatorColumn columnDefinition is ignored for DDL generation 2017-05-20 15:22:06 +12:00
rob bygrave d04954e46f #999 - @DiscriminatorColumn columnDefinition is ignored for DDL generation 2017-05-20 15:03:21 +12:00
rob bygrave 88c6ec358c #981 Additional refactor to 981 - use composed key in multi tenant environment - Expose TenantAwareKey handling for plugins 2017-05-20 13:53:46 +12:00
Roland PramlandRob Bygrave d3ea01b76e use composed key in multi tenant environment instead a cache per tenant (#981) 2017-05-20 12:35:34 +12:00
rob bygrave 0c1a9786a3 #996 Add findOne() and findOneOrEmpty() - SqlQuery 2017-05-19 23:48:41 +12:00
rob bygrave db298a349e #996 Add findOne() and findOneOrEmpty() 2017-05-19 23:38:40 +12:00
rob bygrave c1bed9f578 #996 Add findOne() and findOneOrEmpty() 2017-05-19 23:38:24 +12:00
rob bygrave c7cbe4ead8 Read the new @Length annotation 2017-05-19 23:00:10 +12:00
rob bygrave 4064aaf714 #1004 - Ebean migrations can not be executed if they contain ';' into a string 2017-05-15 22:18:24 +12:00
rob bygrave 6ad808003a Refactor - remove unused ebeandeploy.dtd 2017-05-14 21:11:00 +12:00
rob bygrave 70de6101db Refactor, remove unused SqlReservedWords 2017-05-14 21:10:24 +12:00
Roland PramlandRob Bygrave 933595ceea ADD: Testcases for "fetchDistinct" (#1024)
* ADD: Testcases for "fetchDistinct"

* Updated the tests for #1024
2017-05-14 17:39:07 +12:00
rob bygrave 461c2aef60 #946 - Treat primitive numbers (long, int, short, float, double) as NOT NULL wrt DDL generation 2017-05-14 01:31:28 +12:00
Rob Bygrave 0c49b6514c [maven-release-plugin] prepare for next development iteration 2017-05-11 23:54:47 +12:00
Rob Bygrave 0ec425928b [maven-release-plugin] prepare release ebean-10.2.3 2017-05-11 23:54:33 +12:00
rob bygrave 711701932a #1023 - Bug with findSingleAttributeList() when used against @ManyToOne / foreign key 2017-05-11 23:20:19 +12:00
Koen De GrooteandRob Bygrave 951e517caf Replaced Tail Recursion while while/true loops. (#1019) 2017-05-11 22:07:10 +12:00
rob bygrave 8cef603d1c #1021 Fix for query plan clash with single inheritance and cached query 2017-05-11 21:57:24 +12:00
Rien Nentjes 2a64a02211 Discriminator query cache error 2017-05-04 14:16:38 +02:00
Rob Bygrave 67ef0cd5d9 Refactor - repackage / move test code only 2017-05-01 20:39:49 +12:00
Rob Bygrave 9f2334362a [maven-release-plugin] prepare for next development iteration 2017-04-30 23:15:34 +12:00
Rob Bygrave 44ff304423 [maven-release-plugin] prepare release ebean-10.2.2 2017-04-30 23:15:20 +12:00
Roland PramlandRob Bygrave f9c70d2a2b Fix/select distinct cascaded fetch (#1015)
Fix/select distinct cascaded fetch with findSingleAttributeList() on associated property path
2017-04-30 23:07:35 +12:00
Rob Bygrave e51f7f11f1 Fix tests for #1016 2017-04-30 22:56:07 +12:00
Yuan XueguiandRob Bygrave 54ef0e7465 FIX BUG:and blank space after 1=1 (#1016)
FIX BUG:and blank space after 1=1 (Noop expression for equals null with @SoftDelete)
2017-04-30 22:50:03 +12:00
OndrejPacayandRob Bygrave 63def00626 #1012 - Filtering on embedded values in a joined table does not produce a sql join (#1013) 2017-04-30 22:33:02 +12:00
Koen De GrooteandRob Bygrave 335c4de109 Static code analysis. (#1017) 2017-04-30 14:47:02 +12:00
Rob Bygrave a120c2aaee #947 - Treat primitive boolean as NOT NULL - DDL as not null 2017-04-25 13:17:58 +12:00
Koen De GrooteandRob Bygrave 43408fcb87 Java language level updates concerning Maps. (#1008)
* Java language level updates concerning Maps.

* Reverts when comments indicated no sync can happen.
2017-04-22 15:48:46 +12:00
Koen De GrooteandRob Bygrave 8432f7b0d5 Some changes that are possible in Java language level 7 and 8. (#1007) 2017-04-22 15:43:56 +12:00
Koen De GrooteandRob Bygrave bdd7884f42 Changes for ArrayStack. (#1006)
Removed old inspection suppression.
2017-04-22 15:42:25 +12:00
Alexander WinklerandRob Bygrave 485e62b5d6 Added multi tenant catalog support. (#987) 2017-04-01 00:41:08 +13:00
Roland PramlandRob Bygrave 0557e6cd08 Wrong alter table / alter column DDL was generated (#988)
* FIX: alter column type uses correct DB-type now.

* FIX: Oracle test case
2017-04-01 00:38:23 +13:00
Koen De GrooteandRob Bygrave b821702b8d Moving defaultservercache implementation to use nanoseconds to determine whether or not something needs to be evicted from the cache. (#998)
The old implementation used System.currentTimeMillis(), which might be unreliable, for instance during a jump in DST.
Thanks @rPraml for noticing and suggesting the fix.
2017-04-01 00:30:01 +13:00
Rob Bygrave c5b23c321e #1002 - Bump ebean-dbmigration to 10.1.6 (better support for schema & sql server) 2017-04-01 00:28:46 +13:00
Rob Bygrave 964d2d00a2 #1001 - Add @Length and @NotNull, (plus move @Transactional to ebean-annotation) 2017-03-31 21:56:30 +13:00
Rob Bygrave 1778afa17d [maven-release-plugin] prepare for next development iteration 2017-03-13 23:15:12 +13:00
Rob Bygrave 0d9f9982b7 [maven-release-plugin] prepare release ebean-10.2.1 2017-03-13 23:15:00 +13:00
Rob Bygrave 7178085680 #993 - ENH: Add flush() to EbeanServer and Model to make it more accessible than the current transaction.flushBatch() - Add Ebean.flush() 2017-03-13 23:13:41 +13:00
Rob Bygrave 4d82b86f81 #993 - ENH: Add flush() to EbeanServer and Model to make it more accessible than the current transaction.flushBatch() 2017-03-13 23:07:17 +13:00
Rob Bygrave 1d99a5c5a4 #992 - API Change - Change Transaction.close() to throw PersistenceException rather than IOException 2017-03-13 22:10:08 +13:00
Rob Bygrave 41a7f2c97e Bump to 10.2.1-SNAPSHOT 2017-03-13 21:11:34 +13:00
Rob Bygrave c8d01828b3 #991 ENH: Add forUpdateNoWait() and forUpdateSkipLocked() options ... #528 ENH: Improve exception handling 2017-03-13 20:50:22 +13:00
Péter CsubákandRob Bygrave a3dbd4538f Wrong cast to query and childid propblem fix (#990) 2017-03-11 12:21:34 +13:00
Rob Bygrave 3051412d90 #989 - ENH: Support @DbArray with Set ... (addition to the existing List support) 2017-03-10 20:50:07 +13:00
Rob Bygrave a22eb555d0 [maven-release-plugin] prepare for next development iteration 2017-03-05 22:44:48 +13:00
Rob Bygrave cb89300027 [maven-release-plugin] prepare release ebean-10.1.7 2017-03-05 22:44:37 +13:00
Rob Bygrave 27cb0d062d Bump ebean-dbmigration to 10.1.4 2017-03-05 22:42:00 +13:00
Rob Bygrave 140c1dd965 #985 - IllegalArgumentException when using @DbArray of type List<String> with @ChangeLog 2017-03-05 11:40:17 +13:00
Rob Bygrave 75b9e748f4 #985 - IllegalArgumentException when using @DbArray of type List<String> with @ChangeLog 2017-03-05 11:40:08 +13:00
Koen De GrooteandRob Bygrave 289c0253b1 Warning suppressions. (#986)
* Went over compilation warnings with Xlint. Only imports for DateMidnight are left, as they cannot receive a suppression annotation.

Not doing this one.

* Doing inline fully qualified path of the deprecated path.
2017-03-05 11:08:45 +13:00
Rob Bygrave 07ce758302 #984 - ENH: DocumentStore API - add RawDoc with findEach() and findEachWhile() 2017-03-02 01:12:02 +13:00
Rob Bygrave d91729f65d #983 - Add credentials configuration support for document store (like basic auth for ElasticSearch) 2017-03-01 22:15:28 +13:00
Rob Bygrave 9e64d09e07 Update maven plugin (with separate testEnhance goal and enhance goal) 2017-03-01 22:07:47 +13:00
Roland PramlandRob Bygrave 5f63d5c35f Fix multi tenant bean change (#982)
* FIX: beanChange has tenant-id

* FIX: NPE in DefaultServer.currentTenantId()
2017-02-26 13:12:26 +13:00
Rob Bygrave 23e1ab4bfd No effective change - imports 2017-02-26 13:10:42 +13:00
Rob Bygrave 0e2900d796 #980 - fix several bugs in findSingleAttibute - Refactor moving logic into DefaultOrmQuery setDefaultSelectClause() from findSingleAttributeList() (to support alternate calling via EbeanServer) 2017-02-26 13:08:10 +13:00
Roland PramlandRob Bygrave a46e086dc4 fix several bugs in findSingleAttibute (#980)
* add test case for distinct on id property

* suggested fix for "select distinct id"

* add test case for distinct with fetch

* FIX: .setDistinct(true) can be used in conjunction with fetch() now

* add test case for distinct with beans that have a disriminator column

* FIX: discriminator column is only read if also Id is read.

* fine tuned the test case

* added test cases for findSingleAttributeList without distinct

* improved fix to support also findSingleAttribute without distinct

* ADD: Bonus test case - assertion not yet verified
2017-02-26 12:37:36 +13:00
Roland PramlandRob Bygrave 40ca179509 FIX: do not hit database if inherited entity has no children (#974)
* FIX: do not hit database if inherited entity has no children

* ADD: Testcase for creating references of inherited beans
2017-02-26 12:25:55 +13:00
Roland PramlandRob Bygrave 7632910027 FIX: potential NPE - manager can be null - eg when creted with new ExternalJdbcTransaction(conn) (#979) 2017-02-24 12:53:35 +13:00
Roland PramlandRob Bygrave ca777d7967 no effective code change: add some try-with resources (#978)
* no effective code change: add some try-with resources

* moved return statement outside try-with-resources, because otherwise the order changes
2017-02-24 12:52:22 +13:00
Roland PramlandRob Bygrave a315c7c11e More small fixes (#977)
* no effecitve code change: add @FunctionalInterface to designated interfaces

* no effective code change: removed obsolete imports

* no effective code change: removed obsolete @SuppressWarnings

* no effective code change: add @SuppressWarnings to UUID_PLACEHOLDER
2017-02-24 08:42:27 +13:00
Rob Bygrave 35f3f53443 No effective change - format and imports only 2017-02-24 00:06:13 +13:00
Roland PramlandRob Bygrave 40f5596837 add missing @override (#975)
* no effective code change: add missing @override in "io.ebean.*" package
* no effective code change: add missing @override in "io.ebeaninternal.api.*" package
* no effective code change: add missing @override in "io.ebeaninternal.server.*" package
* no effective code change: add missing @override in "io.ebeaninternal.util.*" package
* no effective code change: add missing @override in "io.ebeanservice.*" package
* no effective code change: add missing @override in "src/test/java/"
2017-02-24 00:01:25 +13:00
maksym-kitandRob Bygrave 43c978e41a Pass dataType to DataBind for Types.OTHER (#923) 2017-02-23 23:50:43 +13:00
Koen De GrooteandRob Bygrave 6120a465e1 Simple fixes (#976)
* Should be only the really simple stuff.
* Final cleanups.
2017-02-23 23:46:51 +13:00
Rob Bygrave 8bb884374b #970 - FOR UPDATE queries are not honored when beans are already cached 2017-02-21 22:53:14 +13:00
Rob Bygrave 3d8db775f7 #966 - ENH: Add serverConfig.setDbOffline(true) ... for creating new EbeanServer without a DataSource (for DbMigration typically) 2017-02-21 22:04:28 +13:00
Rob Bygrave b3b8f6b154 #973 - Refactor - Tidy internals of DefaultBeanLoader 2017-02-21 21:57:11 +13:00
Rob Bygrave e4c80582a5 [maven-release-plugin] prepare for next development iteration 2017-02-13 22:18:56 +13:00
Rob Bygrave 1846427859 [maven-release-plugin] prepare release ebean-10.1.6 2017-02-13 22:18:44 +13:00
Rob Bygrave 82102340b8 #960 - Incorrect query when using '.betweenProperties' with '@SoftDelete' 2017-02-09 23:43:45 +13:00
Rob Bygrave d9e884b8bd #969 - ENH: Add Finder.query(String ormQuery) ... helper method 2017-02-09 23:27:13 +13:00
Rob Bygrave 6744c7886a #968 - Refactor - Update ANTLR 4 generated code to 4.6 2017-02-09 23:20:33 +13:00
Rob Bygrave 271b4ee095 Modify pom - bump java8-parent to 1.3 2017-02-09 23:12:11 +13:00
Rob Bygrave 7cfdd331ca Merge branch 'master' of github.com:ebean-orm/ebean 2017-02-09 22:37:58 +13:00
Rob Bygrave 7e15faa9a8 #967 - ENH: Add DocStoreConfig.setAllowAllCertificates(true) ... 2017-02-09 22:37:25 +13:00
Roland PramlandRob Bygrave 1292c86b76 removed duplicate StringHelper (#958) 2017-01-31 22:10:45 +13:00
Rob Bygrave 0260a73cb6 #957 - Javadoc update only 2017-01-27 00:36:25 +13:00
Rob Bygrave 085fdaf177 #956 - Bump dependencies - avaje-datasource and ebean-dbmigration 2017-01-26 23:30:58 +13:00
Rob Bygrave a4b49dfa27 No effective change - Fix javadoc issues in Finder 2017-01-12 18:53:34 +13:00
Rob Bygrave d056151852 [maven-release-plugin] prepare for next development iteration 2017-01-12 00:46:22 +13:00
Rob Bygrave f9ba6f9a3a [maven-release-plugin] prepare release ebean-10.1.5 2017-01-12 00:46:11 +13:00
Rob Bygrave 2fa4345742 #945 - Invalid SQL when using @Aggregation with a fetch() to a ManyToOne - missing columns in GROUP BY 2017-01-12 00:42:27 +13:00
Rob Bygrave d9147327c1 #944 - Incorrect join (should be outer join) when predicate only path traverses an optional relationship to a mandatory relationship 2017-01-11 23:21:50 +13:00
Rob Bygrave 5ad9a611f9 #941 - @Transactional( type = TxType.MANDATORY ) creates a new transaction even if there is one available 2017-01-11 22:41:22 +13:00
Rob Bygrave 3fb497b651 No effective change - style, merge ifs 2017-01-11 22:17:29 +13:00
Rob Bygrave fbfe5d1ff8 #943 - Refactor internals - Performance tweak / tidy for WhoCreated, WhoModified on OneToMany connections. #942 2017-01-11 21:42:23 +13:00
Rob Bygrave b6f21f8649 No effective change - refactor merge AnnotationFields initWhoModified() and initWhoCreated() methods 2017-01-11 20:59:11 +13:00
Nagy VilmosandRob Bygrave 8fd04807c7 WhoCreated, WhoModified on OneToMany connections. (#942)
* WhoCreated, WhoModified on OneToMany connections.

* PostgreSQL table name fix in tests.
2017-01-11 20:54:20 +13:00
Rob Bygrave e49c42302a [maven-release-plugin] prepare for next development iteration 2017-01-09 22:39:47 +13:00
Rob Bygrave d96abece75 [maven-release-plugin] prepare release ebean-10.1.4 2017-01-09 22:39:36 +13:00
Rob Bygrave c953da637e Bump ebean-annotation to 2.2 for meta-annotation support on @Formula 2017-01-09 22:37:10 +13:00
Rob Bygrave 8d39b0a996 #940 - Allow findNative to use @Formula properties (add test for MySql := use with RawSql and findNative) 2017-01-09 22:29:15 +13:00
Rob Bygrave 0efcf1eeb3 Merge branch 'master' of github.com:ebean-orm/ebean 2017-01-09 19:40:23 +13:00
Rob Bygrave 335cef870f #939 - Make ModifyAwareSet serializable ... (for serializable entity beans with @DbJson etc) 2017-01-09 19:39:54 +13:00
Michael BenzandRob Bygrave 4c40962f04 MigrationXmlWriter adds DOCTYPE xml to avoid warning of missing external DTD in eclipse IDE. (#937) 2017-01-05 09:16:39 +13:00
Thibault MeyerandRob Bygrave 9be0d22cfb Upgrade provided dependencies (#936)
- javax.validation from 1.0.0.GA to 1.1.0.Final
- servlet-api from 2.4 to javax.servlet-api 3.1.0
- joda-time from 1.6 to 2.9.7
- postgresql from 9.4.1202-jdbc41 to 9.4.1212.jre7
- h2 from 1.4.192 to 1.4.193

Signed-off-by: Thibault Meyer <meyer.thibault@gmail.com>
2017-01-01 19:57:02 +13:00
Thibault MeyerandRob Bygrave 2893d73fad Upgrade test dependencies (#935)
- avaje-agentloader from 2.1.1 to 2.1.2
- avaje-moduuid from 1.2 to 2.1
- commons-io from 2.4 to 2.5
- hsqldb from 2.0.0 to 2.3.4
- mysql-connector-java from 5.1.36 to 6.0.5
- sqlite-jdbc from 3.8.11.2 to 3.15.1

Signed-off-by: Thibault Meyer <meyer.thibault@gmail.com>
2017-01-01 19:55:56 +13:00
Thibault MeyerandRob Bygrave 33d66ea9d1 Upgrade antlr4-runtime to prior version 4.6 (#934)
Signed-off-by: Thibault Meyer <meyer.thibault@gmail.com>
2017-01-01 19:54:25 +13:00
Nagy VilmosandRob Bygrave 073ea9c550 SQL Server boolean mapping fix (#932) 2017-01-01 19:52:57 +13:00
Rob Bygrave 8467934021 [maven-release-plugin] prepare for next development iteration 2016-12-23 16:14:19 +13:00
Rob Bygrave 96ba63407f [maven-release-plugin] prepare release ebean-10.1.3 2016-12-23 16:14:10 +13:00
Rob Bygrave 88df6ffc6e #931 - Refactor internals - DefaultTypeManager ... 2016-12-23 13:33:11 +13:00
Rob Bygrave 3efcfec300 #930 - Refactor (renames etc) for SQL Server History support 2016-12-23 13:18:15 +13:00
Rob BygraveandGitHub e51eb00889 Merge pull request #929 from vilmosnagy/feature/sqlServer2016History
SqlServer 2016 history support.
2016-12-23 13:00:23 +13:00
vilmos.nagy 9ae27ddcdd SqlServer 2016 history support. 2016-12-22 19:22:44 +01:00
Rob Bygrave b9516e64a3 #928 - Pom - change over to io.ebean persistence-api from org.avaje.ebean one. 2016-12-22 23:45:35 +13:00
Rob Bygrave f7f5552bf0 #927 - Pom - bump ebean-dbmigration to 10.1.2 2016-12-22 23:38:18 +13:00
Rob Bygrave adec2ab1b8 #926 - Pom - bump avaje-datasource to 1.1.4 2016-12-22 22:42:24 +13:00
Rob Bygrave da6d7284f8 No effective change - update Readme to maven groupId io.ebean 2016-12-22 00:00:35 +13:00
Rob Bygrave 1c160fea5a No functional change - update enhancement agent to 10.1.2 2016-12-21 23:38:32 +13:00
Rob Bygrave cc87de76d7 [maven-release-plugin] prepare for next development iteration 2016-12-21 00:09:30 +13:00
Rob Bygrave 70b380e6e7 [maven-release-plugin] prepare release ebean-10.1.2 2016-12-21 00:09:19 +13:00
Rob Bygrave 3e419d3e3a No effective change - test ebean.properties back to H2 for default 2016-12-20 21:31:02 +13:00
Rob Bygrave 7e2be20b6e #925 - Change generated SQL for H2, Postgres and MySql to not use column alias' 2016-12-20 21:30:00 +13:00
Rob Bygrave ab2d5fb4c8 No effective change - update test to use trimmed sql (trim out sql column alias to allow it to be optional) 2016-12-20 21:14:12 +13:00
Rob Bygrave 809901ff13 No effective change - update H2 specific test 2016-12-20 21:02:36 +13:00
Rob Bygrave fcc58d77e8 No effective change - update tests using Platform enum rather than name 2016-12-20 20:41:55 +13:00
Rob Bygrave bc93a82b1a #900 - Error - Can't fetch JsonDB field - org.postgresql.util.PSQLException: ERROR: could not identify an equality operator for type json 2016-12-20 03:00:08 +13:00
Rob Bygrave 84e1e12b66 #900 - Error - Can't fetch JsonDB field - org.postgresql.util.PSQLException: ERROR: could not identify an equality operator for type json 2016-12-20 02:59:47 +13:00
Rob Bygrave 2eb0c12213 #924 - Bump ebean-dbmigration dependency to 10.1.1 (sql server fix) 2016-12-19 22:19:53 +13:00
Rob Bygrave 4941134ce1 #922 - NPE Issue with ebean-elastic and multi-tenant Ebean ... NPE at DLoadContext line 96 2016-12-14 00:53:30 +13:00
Rob Bygrave cf37fda3f4 #921 - Refactor internals - Change internal use of "findRowCount" to "findCount" 2016-12-13 19:51:11 +13:00
Rob Bygrave f429811f79 [maven-release-plugin] prepare for next development iteration 2016-12-12 02:10:10 +13:00
Rob Bygrave 70fd988d8c [maven-release-plugin] prepare release ebean-10.1.1 2016-12-12 02:09:55 +13:00
Rob Bygrave fe4167ed60 #920 - Update DBMigration to io.ebean 2016-12-12 02:07:52 +13:00
Rob Bygrave 0eef69a277 #920 - Change logger package to io.ebean (e.g. for logging SQL instead of org.avaje.ebean.SQL use io.ebean.SQL) 2016-12-11 23:42:38 +13:00
Rob Bygrave 76bfd805c0 #919 - io.ebean package, use ebean-annotation 2016-12-11 23:34:29 +13:00
Rob Bygrave 971e2dc91b #919 - io.ebean package initial 2016-12-11 23:23:22 +13:00
Rob Bygrave 5821dc96b9 [maven-release-plugin] prepare for next development iteration 2016-12-10 00:08:52 +13:00
Rob Bygrave e027110006 [maven-release-plugin] prepare release ebean-9.5.1 2016-12-10 00:08:42 +13:00
Rob Bygrave b5e6e9a66c Bump pom to 9.5.1-SNAPSHOT 2016-12-10 00:06:09 +13:00
Rob Bygrave 514047e680 #918 - Remove DbMigrationConfig.generateOnStart() ... migrate to offline generation 2016-12-10 00:04:41 +13:00
Rob Bygrave a727a98a21 #917 - ENH: Add findNative() ... ala automatic mapping of native SQL into object graphs / paths. 2016-12-09 23:45:57 +13:00
Rob Bygrave e75b5e8b30 #916 - Refactor internals - bump use of 31 in hashes to 92821 2016-12-08 23:28:58 +13:00
Rob Bygrave ad0e085ff5 #915 - Refactor internals - Change update plan to string key 2016-12-08 23:23:19 +13:00
Rob Bygrave 322a2f500d No effective change - move method - BeanDescriptor.merge() 2016-12-08 23:01:05 +13:00
Rob Bygrave 1c7454d249 [maven-release-plugin] prepare for next development iteration 2016-12-08 22:26:13 +13:00
Rob Bygrave e1efca6736 [maven-release-plugin] prepare release ebean-9.4.2 2016-12-08 22:26:04 +13:00
Rob Bygrave 8ae61074ad #914 - Fix multi-tenancy support such that it automatically propagates the tenantId for lazy loading 2016-12-08 22:04:18 +13:00
Rob Bygrave c3bc0c4975 #913 - IllegalArgumentException: No enum constant com.avaje.ebean.config.Platform.HSQLDB 2016-12-07 21:58:07 +13:00
Rob Bygrave 611bba272a Modify testAggregationCount to make MySql happy - avoid count(u1.*) 2016-12-07 21:39:26 +13:00
Rob Bygrave 4c9ec38c88 [maven-release-plugin] prepare for next development iteration 2016-12-06 23:44:35 +13:00
Rob Bygrave e2731a99be [maven-release-plugin] prepare release ebean-9.4.1 2016-12-06 23:44:26 +13:00
Rob Bygrave 7d56df3b23 Bump pom to 9.4.1-SNAPSHOT 2016-12-06 23:43:37 +13:00
Rob Bygrave bebef48332 Update test ebean.properties 2016-12-03 22:03:55 +13:00
Rob Bygrave f66ea12fbf #912 - Refactor - move platform specfic code into subpackages 2016-12-03 15:39:24 +13:00
Rob Bygrave b08f1580f9 #910 - SQL Server update - Add ANSI based row limiter (2012+) and make as default platform 2016-12-03 15:10:11 +13:00
Rob Bygrave 707912f7ad No effective change - add some wait into history test (TestHistoryInsert) 2016-12-03 13:55:45 +13:00
Rob Bygrave 5ce31b16d4 #910 - SQL Server update - refactor rename platform to SqlServerPlatform 2016-12-03 13:30:17 +13:00
Rob Bygrave a5945b1d5d #911 - SQL Server - remove old MsSqlServer2000Platform (expecting users migrated to SQL Server 2005+) 2016-12-03 13:24:52 +13:00
Rob Bygrave b8577ae6d0 #910 - SQL Server update - tidy whitespace for MsSqlServer2005SqlLimiter 2016-12-03 13:19:15 +13:00
Rob Bygrave 14dedb7b9a #910 - SQL Server update 2016-12-03 13:18:33 +13:00
Rob Bygrave 2dbd543127 #909 - @Lob with @Size ... produces incorrect DDL for Postgres 2016-12-03 08:42:46 +13:00
Rob Bygrave cc989af1c6 #908 - Remove support for Immutable Compound Values 2016-12-02 22:49:00 +13:00
Rob Bygrave 0aad285f35 #907 - Remove Model.Finder ... migrate to Finder 2016-12-02 21:47:30 +13:00
Rob Bygrave a3754e31f2 #906 - Add NamingConvention Support for JoinColumn (OneToMany, ManyToOne) - was PR #887 2016-12-02 21:21:19 +13:00
Rob Bygrave 1dd0f3f609 [maven-release-plugin] prepare for next development iteration 2016-12-01 21:04:18 +13:00
2561 changed files with 50505 additions and 26922 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ ebean-profiling*.xml
/db
/mydb.db
!src/test/ddl-review/*.sql
profiling/
# Intellij project files
*.iml
+13 -1
View File
@@ -1,3 +1,4 @@
dist: trusty
sudo: required
language: java
jdk:
@@ -7,17 +8,28 @@ git:
depth: 3
addons:
postgresql: "9.4"
postgresql: "9.6"
# apt:
# packages:
# - mysql-server-5.7
# - mysql-client-core-5.7
# - mysql-client-5.7
services:
- docker
- postgresql
- mysql
before_script:
- ./.travis/setup_database
- mysql -u root -e 'CREATE DATABASE test_ebean;'
- mysql -u root -e "CREATE USER 'test_ebean'@'localhost' IDENTIFIED BY 'test';"
- mysql -u root -e "GRANT ALL ON test_ebean.* TO 'test_ebean'@'localhost';"
env:
- EBEAN_DB=h2
- EBEAN_DB=pg
# - EBEAN_DB=mysql
install: true
+4 -4
View File
@@ -6,12 +6,12 @@ Goto [https://ebean-orm.github.io/](http://ebean-orm.github.io/ "Ebean ORM's Web
## Maven cental links:
[Maven central - ebean](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.avaje.ebean%22%20AND%20a%3A%22ebean%22 "maven central ebean")
[Maven central - ebean](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22io.ebean%22%20AND%20a%3A%22ebean%22 "maven central ebean")
[Maven central - all related projects](http://search.maven.org/#search%7Cga%7C1%7Cebean "maven central all related projects")
## Current versions
* [![Maven Central : ebean](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebean/ebean/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebean/ebean) - ebean
* [![Maven Central : ebean-agent](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebean/ebean-agent/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebean/ebean-agent) - ebean-agent
* [![Maven Central : ebean-maven-plugin](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebean/ebean-maven-plugin/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebean/ebean-maven-plugin) - ebean-maven-plugin
* [![Maven Central : ebean](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebean/ebean) - ebean
* [![Maven Central : ebean-agent](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean-agent/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebean/ebean-agent) - ebean-agent
* [![Maven Central : ebean-maven-plugin](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean-maven-plugin/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebean/ebean-maven-plugin) - ebean-maven-plugin
+152
View File
@@ -0,0 +1,152 @@
This is a short description how to run tests
============================================
Run tests from maven
--------------------
Just type `mvn test` - it will run the whole test suite with the settings
from `src/test/resources/ebean.properties`.
Run tests from eclipse
----------------------
Running tests requires, that the classes are enhanced. By default, the
`BaseTestCase` tries to load the enhancer-agent in a very early stage. This
also works for most test cases, but it does not work if you try to run a
complete test-suite, as classes that are loaded before the enhancer-agent
kicks in will not get enhanced. To solve this problem, you need either the
[Eclipse-Enhancer-Plugin](https://github.com/ebean-orm-tools/ebean-eclipse-enhancer)
or add the agent to your JVM arguments (Preferences->Installed JREs) or to
your run configuration:
`-javaagent:<USER_HOME>/.m2/repository/io/ebean/ebean-agent/<VERSION>/ebean-agent-<VERSION>.jar=debug=0`
Platform Tests
==============
By default, the `h2` platform is used. To test a different platform, add
`-Ddatasource.default=xxx` to your maven command or JVM arguments.
'h2' platform
-------------
Reqires no setup
run: `mvn clean test`
Current status: PASS
Tests run: 1986, Failures: 0, Errors: 0, Skipped: 16
'pg' platform
-------------
Reqirements
- a locally installed PostgreSQL server with PostGis.
- Create a user "unit" with password "unit" and a database "unit"
- Give the user all permissions to that db
run: `mvn clean test -Ddatasource.default=pg`
Current status: PASS
Tests run: 1986, Failures: 0, Errors: 0, Skipped: 16
'mysql' platform
-------------
Reqirements
- a locally installed MySQL server.
- Create a user "unit" with password "unit" and a database "unit"
- Give the user all permissions to that db
run: `mvn clean test -Ddatasource.default=mysql`
Current status: FAIL
Tests run: 1986, Failures: 2, Errors: 4, Skipped: 16
'sqlserver' platform
--------------------
Reqires an installed sqlserver - e.g. https://hub.docker.com/r/microsoft/mssql-server-linux/
- Create a user "ebean" with password "ebean" and a database "ebean_unittest"
- Adjust the connection string and/or username in ebean.properties
run: `mvn clean test -Ddatasource.default=mssql`
Current status: FAIL
Tests run: 1986, Failures: 19, Errors: 43, Skipped: 16
'oracle' platform
-----------------
Reqires a locally installed Oracle server.
- Create a user "unit" with password "unit" with all permissions
- The test wirtes directly to the "xe" SID - so do not use a productive server!
- As the Oracle JDBC driver is only available on an oracle repository,
you need a special maven setup as described [here](http://docs.oracle.com/middleware/1213/core/MAVEN/config_maven_repo.htm#MAVEN9010)
run: `mvn clean test -Ddatasource.default=ora -Poracle`
Current status: FAIL
Tests run: 1986, Failures: 17, Errors: 34, Skipped: 16
'db2' platform
--------------
Reqires a locally installed DB2 Express-C server.
- Create a user "unit" with password "unit" with all permissions
- Install the db2jcc4 driver (see pom.xml)
run: `mvn clean test -Ddatasource.default=db2 -Pdb2`
Current status: FAIL
Tests run: 1986, Failures: 33, Errors: 26, Skipped: 16
'sqlite' platform
-----------------
Reqires no setup
run: `mvn clean test -Ddatasource.default=sqlite`
Current status: FAIL
Tests run: 1986, Failures: 24, Errors: 86, Skipped: 16
After some time, the db locks up, every test takes 3 seconds and fails with
"the database file is locked"
'hsqldb' platform
-----------------
Reqires no setup
run: `mvn clean test -Ddatasource.default=hsqldb`
Current status: FAIL
Tests run: 1980, Failures: 3, Errors: 657, Skipped: 16
@Rob FYI
The problem is https://sourceforge.net/p/hsqldb/bugs/1364/
In `InsertHandler.getPstmt` the `meta.getIdentityDbColumns()` contains
'id' in lowercase. Changing that to uppercase gives me this result:
`Tests run: 1986, Failures: 2, Errors: 18, Skipped: 16`
(as quick hack I added temporary a toUpperCase to BindableIdScalar.getIdentityColumn)
'sqlanywhere' platform
----------------------
TODO: not yet tested
+133 -75
View File
@@ -4,100 +4,144 @@
<parent>
<groupId>org.avaje</groupId>
<artifactId>java8-parent</artifactId>
<version>1.1</version>
<version>1.3</version>
</parent>
<groupId>org.avaje.ebean</groupId>
<groupId>io.ebean</groupId>
<artifactId>ebean</artifactId>
<version>9.3.1</version>
<version>11.11.1</version>
<packaging>jar</packaging>
<name>ebean</name>
<url>http://ebean-orm.github.io/</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<scm>
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
<tag>ebean-9.3.1</tag>
<tag>ebean-11.11.1</tag>
</scm>
<profiles>
<profile>
<!-- Note: to use this profile, you need credentials for the oracle repository in your
settings.xml as described here:
http://docs.oracle.com/middleware/1213/core/MAVEN/config_maven_repo.htm#MAVEN9010 -->
<id>oracle</id>
<dependencies>
<dependency>
<groupId>com.oracle.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>12.2.0.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>maven.oracle.com</id>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
<url>https://maven.oracle.com</url>
<layout>default</layout>
</repository>
</repositories>
</profile>
<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>
<dependency>
<groupId>com.ibm.jdbc</groupId>
<artifactId>db2jcc4</artifactId>
<version>4.23.42</version>
<scope>test</scope>
</dependency>
</dependencies>
</profile>
</profiles>
<dependencies>
<!--
Projects are expected to explicit depend on version
of slf4j that they want to use
-->
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>13.0</version>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
<scope>provided</scope>
</dependency>
<!--
Class retention Nonnull and Nullable annotations
to assist with IDE auto-completion with Ebean API
-->
<dependency>
<groupId>org.avaje.ebean</groupId>
<artifactId>persistence-api</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>org.avaje.ebean</groupId>
<artifactId>ebean-annotation</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.avaje</groupId>
<artifactId>avaje-datasource-api</artifactId>
<groupId>io.ebean</groupId>
<artifactId>ebean-jsr305</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>persistence-api</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-annotation</artifactId>
<version>3.8</version>
</dependency>
<dependency>
<groupId>org.avaje</groupId>
<artifactId>avaje-datasource</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>org.avaje</groupId>
<artifactId>avaje-classpath-scanner-api</artifactId>
<version>2.2</version>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.avaje</groupId>
<artifactId>avaje-classpath-scanner</artifactId>
<version>2.2.1</version>
<version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.avaje</groupId>
<artifactId>avaje-dbmigration</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>[1.7.1,1.7.99)</version>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>11.3.1</version>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>4.5.3</version>
<version>4.6</version>
</dependency>
<!-- Jackson core used internally by Ebean -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.6.5</version>
<version>2.9.0</version>
</dependency>
<!-- provided scope for JsonNode support -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.6.5</version>
<version>2.9.0</version>
<scope>provided</scope>
</dependency>
@@ -112,21 +156,21 @@
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.0.0.GA</version>
<version>1.1.0.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>1.6</version>
<version>2.9.7</version>
<scope>provided</scope>
</dependency>
@@ -134,7 +178,7 @@
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4-1202-jdbc41</version>
<version>9.4.1212</version>
<scope>provided</scope>
</dependency>
@@ -147,24 +191,31 @@
<!--<scope>test</scope>-->
<!--</dependency>-->
<!--<dependency>-->
<!--<groupId>microsoft</groupId>-->
<!--<artifactId>sqlserver-jdbc</artifactId>-->
<!--<version>4.2</version>-->
<!--<scope>test</scope>-->
<!--</dependency>-->
<dependency>
<groupId>org.avaje</groupId>
<artifactId>avaje-agentloader</artifactId>
<version>1.1.1</version>
<groupId>io.ebean</groupId>
<artifactId>ebean-docker-run</artifactId>
<version>1.5.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.avaje.ebean</groupId>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.avaje</groupId>
<artifactId>avaje-agentloader</artifactId>
<version>2.1.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-agent</artifactId>
<version>8.1.1</version>
<version>11.10.1</version>
<scope>test</scope>
</dependency>
@@ -173,28 +224,36 @@
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.192</version>
<version>1.4.196</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.8.11.2</version>
<version>3.15.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.0.0</version>
<version>2.3.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>6.1.3.jre8-preview</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.36</version>
<!-- Do not upgrade to 6.0.6: https://bugs.mysql.com/bug.php?id=82896 -->
<version>5.1.43</version>
<scope>test</scope>
</dependency>
@@ -209,14 +268,14 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
<version>2.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.avaje.moduuid</groupId>
<artifactId>avaje-moduuid</artifactId>
<version>1.2</version>
<version>2.1</version>
<scope>test</scope>
</dependency>
@@ -227,19 +286,18 @@
<plugins>
<plugin>
<groupId>org.avaje.ebean</groupId>
<groupId>io.ebean</groupId>
<artifactId>ebean-maven-plugin</artifactId>
<version>8.1.1</version>
<version>11.10.1</version>
<executions>
<execution>
<id>test</id>
<phase>process-test-classes</phase>
<configuration>
<classSource>target/test-classes</classSource>
<transformArgs>debug=1</transformArgs>
</configuration>
<goals>
<goal>enhance</goal>
<goal>testEnhance</goal>
</goals>
</execution>
</executions>
@@ -283,11 +341,11 @@
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<configuration>
<doctitle>Ebean 9</doctitle>
<overview>src/main/java/com/avaje/ebean/overview.html</overview>
<doctitle>Ebean 10</doctitle>
<overview>src/main/java/io/ebean/overview.html</overview>
<source>1.8</source>
<doclet>org.avaje.doclet.PygmentsDoclet</doclet>
<excludePackageNames>com.avaje.ebeaninternal.*:com.avaje.ebean.util:com.avaje.ebean.dbmigration.ddlgeneration:com.avaje.ebean.dbmigration.migration:com.avaje.ebean.dbmigration.migrationreader:com.avaje.ebean.dbmigration.model</excludePackageNames>
<excludePackageNames>io.ebeaninternal.*:com.avaje.ebean.util</excludePackageNames>
<docletArtifact>
<groupId>org.avaje</groupId>
<artifactId>pygments-doclet</artifactId>
-888
View File
@@ -1,888 +0,0 @@
package com.avaje.ebean;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebean.util.ClassUtil;
import org.jetbrains.annotations.Nullable;
import javax.persistence.MappedSuperclass;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
* A MappedSuperclass base class that provides convenience methods for inserting, updating and
* deleting beans.
* <p>
* By having your entity beans extend this it provides a 'Active Record' style programming model for
* Ebean users.
* <p>
* Note that there is a avaje-ebeanorm-mocker project that enables you to use Mockito or similar
* tools to still mock out the underlying 'default EbeanServer' for testing purposes.
* <p>
* You may choose not use this Model mapped superclass if you don't like the 'Active Record' style
* or if you believe it 'pollutes' your entity beans.
* <p>
* You can use Dependency Injection like Guice or Spring to construct and wire a EbeanServer instance
* and have that same instance used with this Model and Finder. The way that works is that when the
* DI container creates the EbeanServer instance it can be registered with the Ebean singleton. In this
* way the EbeanServer instance can be injected as per normal Guice / Spring dependency injection and
* that same instance also used to support the Model and Finder active record style.
* <p>
* If you choose to use the Model mapped superclass you will probably also chose to additionally add
* a {@link Find} as a public static field to complete the active record pattern and provide a
* relatively nice clean way to write queries.
* <p>
* <h3>Typical common @MappedSuperclass</h3>
* <pre>{@code
*
* // Typically there is a common base model that has some
* // common properties like the ones below
*
* @MappedSuperclass
* public class BaseModel extends Model {
*
* @Id Long id;
*
* @Version Long version;
*
* @CreatedTimestamp Timestamp whenCreated;
*
* @UpdatedTimestamp Timestamp whenUpdated;
*
* ...
*
* }</pre>
* <p>
* <h3>Extend the Model</h3>
* <pre>{@code
*
* // Extend the mappedSuperclass
*
* @Entity @Table(name="oto_account")
* public class Customer extends BaseModel {
*
* // Add a static Find
* // ... with Long being the type of our @Id property.
* // ... Note the {} at the end as Find is an abstract class.
*
* public static final Find<Long,Account> find = new Find<Long,Account>(){};
*
* String name;
* ...
* }
*
* }</pre>
* <p>
* <h3>Modal: save()</h3>
* <pre>{@code
*
* // Active record style ... save(), delete() etc
* Customer customer = new Customer();
* customer.setName("AC234");
*
* // save() method inherited from Model
* customer.save();
*
* }</pre>
* <p>
* <h3>Find byId</h3>
* <pre>{@code
*
* // find byId
* Customer customer = Customer.find.byId(42);
*
* }</pre>
* <p>
* <h3>Find where</h3>
* <pre>{@code
*
* // find where ...
* List<Customer> customers =
* Customer.find
* .where().gt("startDate", lastMonth)
* .findList();
*
* }</pre>
*/
@MappedSuperclass
public abstract class Model {
/**
* Return the underlying 'default' EbeanServer.
* <p>
* This provides full access to the API such as explicit transaction demarcation etc.
* <p>
* Example:
* <pre>{@code
*
* Transaction transaction = Customer.db().beginTransaction();
* try {
*
* // turn off cascade persist for this transaction
* transaction.setPersistCascade(false);
*
* // extra control over jdbc batching for this transaction
* transaction.setBatchGetGeneratedKeys(false);
* transaction.setBatchMode(true);
* transaction.setBatchSize(20);
*
* Customer customer = new Customer();
* customer.setName(&quot;Roberto&quot;);
* customer.save();
*
* Customer otherCustomer = new Customer();
* otherCustomer.setName("Franko");
* otherCustomer.save();
*
* transaction.commit();
*
* } finally {
* transaction.end();
* }
*
* }</pre>
*/
public static EbeanServer db() {
return Ebean.getDefaultServer();
}
/**
* Return a named EbeanServer that is typically different to the default server.
* <p>
* If you are using multiple databases then each database has a name and maps to a single
* EbeanServer. You can use this method to get an EbeanServer for another database.
*
* @param server The name of the EbeanServer. If this is null then the default EbeanServer is returned.
*/
public static EbeanServer db(String server) {
return Ebean.getServer(server);
}
/**
* Marks the entity bean as dirty.
* <p>
* This is used so that when a bean that is otherwise unmodified is updated the version
* property is updated.
* <p>
* An unmodified bean that is saved or updated is normally skipped and this marks the bean as
* dirty so that it is not skipped.
* <p>
* <pre>{@code
*
* Customer customer = Customer.find.byId(id);
*
* // mark the bean as dirty so that a save() or update() will
* // increment the version property
* customer.markAsDirty();
* customer.save();
*
* }</pre>
*
* @see EbeanServer#markAsDirty(Object)
*/
public void markAsDirty() {
db().markAsDirty(this);
}
/**
* Mark the property as unset or 'not loaded'.
* <p>
* This would be used to specify a property that we did not wish to include in a stateless update.
* </p>
* <pre>{@code
*
* // populate an entity bean from JSON or whatever
* User user = ...;
*
* // mark the email property as 'unset' so that it is not
* // included in a 'stateless update'
* user.markPropertyUnset("email");
*
* user.update();
*
* }</pre>
*
* @param propertyName the name of the property on the bean to be marked as 'unset'
*/
public void markPropertyUnset(String propertyName) {
((EntityBean) this)._ebean_getIntercept().setPropertyLoaded(propertyName, false);
}
/**
* Insert or update this entity depending on its state.
* <p>
* Ebean will detect if this is a new bean or a previously fetched bean and perform either an
* insert or an update based on that.
*
* @see EbeanServer#save(Object)
*/
public void save() {
db().save(this);
}
/**
* Update this entity.
*
* @see EbeanServer#update(Object)
*/
public void update() {
db().update(this);
}
/**
* Insert this entity.
*
* @see EbeanServer#insert(Object)
*/
public void insert() {
db().insert(this);
}
/**
* Delete this bean.
* <p>
* This will return true if the bean was deleted successfully or JDBC batch is being used.
* </p>
* <p>
* If there is no current transaction one will be created and committed for
* you automatically.
* </p>
* <p>
* If the Bean does not have a version property (or loaded version property) and
* the bean does not exist then this returns false indicating that nothing was
* deleted. Note that, if JDBC batch mode is used then this always returns true.
* </p>
*
* @see EbeanServer#delete(Object)
*/
public boolean delete() {
return db().delete(this);
}
/**
* Delete a bean permanently without soft delete.
* <p>
* This is used when the bean contains a <code>@SoftDelete</code> property and we
* want to perform a hard/permanent delete.
* </p>
*
* @see EbeanServer#deletePermanent(Object)
*/
public boolean deletePermanent() {
return db().deletePermanent(this);
}
/**
* Perform an update using this entity against the specified server.
*/
public void update(String server) {
db(server).update(this);
}
/**
* Perform an insert using this entity against the specified server.
*/
public void insert(String server) {
db(server).insert(this);
}
/**
* Perform a delete using this entity against the specified server.
*/
public boolean delete(String server) {
return db(server).delete(this);
}
/**
* Refreshes this entity from the database.
*
* @see EbeanServer#refresh(Object)
*/
public void refresh() {
db().refresh(this);
}
/**
* A concrete implementation of Find.
* <p>
* It should be preferred to use {@link Find} instead of Finder as that can use reflection to determine the class
* literal type of the entity bean.
* </p>
*
* @param <I> type of the Id property
* @param <T> type of the entity bean
*/
public static class Finder<I, T> extends Find<I, T> {
/**
* Create with the type of the entity bean.
* <p>
* <pre>{@code
*
* @Entity
* public class Customer extends BaseModel {
*
* public static final Finder<Long,Customer> find = new Finder<Long,Customer>(Customer.class);
* ...
*
* }</pre>
* <p>
* <p/>
* The preferred approach is to instead use <code>Find</code> as below. This approach is more DRY in that it does
* not require the class literal Customer.class to be passed into the constructor.
* <p>
* <pre>{@code
*
* @Entity
* public class Customer extends BaseModel {
*
* public static final Find<Long,Customer> find = new Find<Long,Customer>(){};
* ...
*
* }</pre>
*/
public Finder(Class<T> type) {
super(null, type);
}
/**
* Create with the type of the entity bean and specific server name.
*/
public Finder(String serverName, Class<T> type) {
super(serverName, type);
}
}
/**
* Helper object for performing queries.
* <p>
* <p>
* Typically a Find instance is defined as a public static field on an entity bean class to provide a
* nice way to write queries.
* <p>
* <h3>Example use:</h3>
* <p>
* <pre>{@code
*
* @Entity
* public class Customer extends BaseModel {
*
* public static final Find<Long,Customer> find = new Find<Long,Customer>(){};
*
* ...
*
* }</pre>
* <p/>
* This enables you to write code like:
* <pre>{@code
*
* Customer customer = Customer.find.byId(42L);
*
* List<Customer> customers =
* Customer.find
* .select("name, dateOfBirth")
* .findList();
*
* }</pre>
* <p>
* <h3>Kotlin</h3>
* In Kotlin you would typically create Find as a companion object.
* <pre>{@code
*
* // kotlin
* companion object : Model.Find<Long, Product>() {}
*
* }</pre>
*
* @param <I> The Id type. This is most often a {@link Long} but is also often a {@link UUID} or
* {@link String}.
* @param <T> The entity bean type
*/
public static abstract class Find<I, T> {
/**
* The entity bean type.
*/
private final Class<T> type;
/**
* The name of the EbeanServer, null for the default server.
*/
private final String serverName;
/**
* Creates a finder for entity of type <code>T</code> with ID of type <code>I</code>.
* <p/>
* Typically you create Find as a public static field on each entity bean as the example below.
* <p>
* <p/>
* Note that Find is an abstract class and hence <code>{}</code> is required. This is done so
* that the type (class literal) of the entity bean can be derived from the generics parameter.
* <p>
* <pre>{@code
*
* @Entity
* public class Customer extends BaseModel {
*
* // Note the trailing {} as Find is an abstract class.
* // We do this so that we can derive the type literal Customer.class
* // via reflection
* public static final Find<Long,Customer> find = new Find<Long,Customer>(){};
* ...
*
* }</pre>
* <p/>
* This enables you to write code like:
* <pre>{@code
*
* Customer customer = Customer.find.byId(42L);
*
* List<Customer> customers =
* Customer.find
* .select("name, email, dateOfBirth")
* .findList();
*
* }</pre>
* <p>
* <h3>Kotlin</h3>
* In Kotlin you would typically create it as a companion object.
* <p>
* <pre>{@code
*
* // kotlin
* companion object : Model.Find<Long, Product>() {}
*
* }</pre>
*/
@SuppressWarnings("unchecked")
public Find() {
this.serverName = null;
this.type = (Class<T>) ClassUtil.getSecondArgumentType(getClass());
}
/**
* Construct passing the class literal type of the entity type.
*/
protected Find(String serverName, Class<T> type) {
this.serverName = serverName;
this.type = type;
}
/**
* Return the underlying 'default' EbeanServer.
* <p>
* <p>
* This provides full access to the API such as explicit transaction demarcation etc.
*/
public EbeanServer db() {
return Ebean.getServer(serverName);
}
/**
* Return typically a different EbeanServer to the default.
* <p>
* This is equivalent to {@link Ebean#getServer(String)}
*
* @param server The name of the EbeanServer. If this is null then the default EbeanServer is
* returned.
*/
public EbeanServer db(String server) {
return Ebean.getServer(server);
}
/**
* Creates a Finder for the named EbeanServer.
* <p>
* <p>
* Create and return a new Finder for a different server.
*/
public Finder<I, T> on(String server) {
return new Finder<>(server, type);
}
/**
* Delete a bean by Id.
* <p>
* Equivalent to {@link EbeanServer#delete(Class, Object)}
*/
public void deleteById(I id) {
db().delete(type, id);
}
/**
* Retrieves all entities of the given type.
* <p>
* <p>
* This is the same as (synonym for) {@link #findList()}
*/
public List<T> all() {
return findList();
}
/**
* Retrieves an entity by ID.
* <p>
* <p>
* Equivalent to {@link EbeanServer#find(Class, Object)}
*/
@Nullable
public T byId(I id) {
return db().find(type, id);
}
/**
* Creates an entity reference for this ID.
* <p>
* <p>
* Equivalent to {@link EbeanServer#getReference(Class, Object)}
*/
public T ref(I id) {
return db().getReference(type, id);
}
/**
* Creates a filter for sorting and filtering lists of entities locally without going back to
* the database.
* <p>
* Equivalent to {@link EbeanServer#filter(Class)}
*/
public Filter<T> filter() {
return db().filter(type);
}
/**
* Creates a query.
* <p>
* Equivalent to {@link EbeanServer#find(Class)}
*/
public Query<T> query() {
return db().find(type);
}
/**
* Creates a query applying the path properties to set the select and fetch clauses.
* <p>
* Equivalent to {@link Query#apply(FetchPath)}
*/
public Query<T> apply(FetchPath fetchPath) {
return db().find(type).apply(fetchPath);
}
/**
* Returns the next identity value.
*
* @see EbeanServer#nextId(Class)
*/
@SuppressWarnings("unchecked")
public I nextId() {
return (I) db().nextId(type);
}
/**
* Executes a query and returns the results as a list of IDs.
* <p>
* Equivalent to {@link Query#findIds()}
*/
public <A> List<A> findIds() {
return query().findIds();
}
/**
* Execute the query consuming each bean one at a time.
* <p>
* This is generally used to process large queries where unlike findList
* you do not want to hold all the results in memory at once but instead
* process them one at a time (requiring far less memory).
* </p>
* Equivalent to {@link Query#findEach(Consumer)}
*/
public void findEach(Consumer<T> consumer) {
query().findEach(consumer);
}
/**
* Execute the query consuming each bean one at a time.
* <p>
* Equivalent to {@link Query#findEachWhile(Predicate)}
* <p>
* This is similar to #findEach except that you return boolean
* true to continue processing beans and return false to stop
* processing early.
* </p>
* <p>
* This is generally used to process large queries where unlike findList
* you do not want to hold all the results in memory at once but instead
* process them one at a time (requiring far less memory).
* </p>
* Equivalent to {@link Query#findEachWhile(Predicate)}
*/
public void findEachWhile(Predicate<T> consumer) {
query().findEachWhile(consumer);
}
/**
* Retrieves all entities of the given type.
* <p>
* The same as {@link #all()}
* <p>
* Equivalent to {@link Query#findList()}
*/
public List<T> findList() {
return query().findList();
}
/**
* Returns all the entities of the given type as a set.
* <p>
* Equivalent to {@link Query#findSet()}
*/
public Set<T> findSet() {
return query().findSet();
}
/**
* Retrieves all entities of the given type as a map of objects.
* <p>
* Equivalent to {@link Query#findMap()}
*/
public <K> Map<K, T> findMap() {
return query().findMap();
}
/**
* Executes a find row count query in a background thread.
* <p>
* Equivalent to {@link Query#findFutureCount()}
*/
public FutureRowCount<T> findFutureCount() {
return query().findFutureCount();
}
/**
* Deprecated in favor of findFutureCount().
* <p>
* Equivalent to {@link Query#findFutureCount()}
*/
public FutureRowCount<T> findFutureRowCount() {
return query().findFutureCount();
}
/**
* Returns the total number of entities for this type. *
* <p>
* Equivalent to {@link Query#findCount()}
*/
public int findCount() {
return query().findCount();
}
/**
* Deprecated in favor of findCount().
*
* @deprecated
*/
public int findRowCount() {
return query().findCount();
}
/**
* Returns the <code>ExpressionFactory</code> used by this query.
*/
public ExpressionFactory getExpressionFactory() {
return query().getExpressionFactory();
}
/**
* Explicitly sets a comma delimited list of the properties to fetch on the 'main' entity bean,
* to load a partial object.
* <p>
* Equivalent to {@link Query#select(String)}
*/
public Query<T> select(String fetchProperties) {
return query().select(fetchProperties);
}
/**
* Specifies a path to load including all its properties.
* <p>
* Equivalent to {@link Query#fetch(String)}
*/
public Query<T> fetch(String path) {
return query().fetch(path);
}
/**
* Additionally specifies a <code>FetchConfig</code> to specify a 'query join' and/or define the
* lazy loading query.
* <p>
* Equivalent to {@link Query#fetch(String, FetchConfig)}
*/
public Query<T> fetch(String path, FetchConfig joinConfig) {
return query().fetch(path, joinConfig);
}
/**
* Specifies a path to fetch with a specific list properties to include, to load a partial
* object.
* <p>
* Equivalent to {@link Query#fetch(String, String)}
*/
public Query<T> fetch(String path, String fetchProperties) {
return query().fetch(path, fetchProperties);
}
/**
* Additionally specifies a <code>FetchConfig</code> to use a separate query or lazy loading to
* load this path.
* <p>
* Equivalent to {@link Query#fetch(String, String, FetchConfig)}
*/
public Query<T> fetch(String assocProperty, String fetchProperties, FetchConfig fetchConfig) {
return query().fetch(assocProperty, fetchProperties, fetchConfig);
}
/**
* Adds expressions to the <code>where</code> clause with the ability to chain on the
* <code>ExpressionList</code>.
* <p>
* Equivalent to {@link Query#where()}
*/
public ExpressionList<T> where() {
return query().where();
}
/**
* Returns the <code>order by</code> clause so that you can append an ascending or descending
* property to the <code>order by</code> clause.
* <p>
* This is exactly the same as {@link #orderBy}.
* <p>
* Equivalent to {@link Query#order()}
*/
public OrderBy<T> order() {
return query().order();
}
/**
* Sets the <code>order by</code> clause, replacing the existing <code>order by</code> clause if
* there is one.
* <p>
* This is exactly the same as {@link #orderBy(String)}.
*/
public Query<T> order(String orderByClause) {
return query().order(orderByClause);
}
/**
* Returns the <code>order by</code> clause so that you can append an ascending or descending
* property to the <code>order by</code> clause.
* <p>
* This is exactly the same as {@link #order}.
* <p>
* Equivalent to {@link Query#orderBy()}
*/
public OrderBy<T> orderBy() {
return query().orderBy();
}
/**
* Set the <code>order by</code> clause replacing the existing <code>order by</code> clause if
* there is one.
* <p>
* This is exactly the same as {@link #order(String)}.
*/
public Query<T> orderBy(String orderByClause) {
return query().orderBy(orderByClause);
}
/**
* Sets the first row to return for this query.
* <p>
* Equivalent to {@link Query#setFirstRow(int)}
*/
public Query<T> setFirstRow(int firstRow) {
return query().setFirstRow(firstRow);
}
/**
* Sets the maximum number of rows to return in the query.
* <p>
* Equivalent to {@link Query#setMaxRows(int)}
*/
public Query<T> setMaxRows(int maxRows) {
return query().setMaxRows(maxRows);
}
/**
* Sets the ID value to query.
* <p>
* <p>
* Use this to perform a find byId query but with additional control over the query such as
* using select and fetch to control what parts of the object graph are returned.
* <p>
* Equivalent to {@link Query#setId(Object)}
*/
public Query<T> setId(Object id) {
return query().setId(id);
}
/**
* Create and return a new query based on the <code>RawSql</code>.
* <p>
* Equivalent to {@link Query#setRawSql(RawSql)}
*/
public Query<T> setRawSql(RawSql rawSql) {
return query().setRawSql(rawSql);
}
/**
* Create a query with explicit 'AutoTune' use.
*/
public Query<T> setAutoTune(boolean autoTune) {
return query().setAutoTune(autoTune);
}
/**
* Create a query with the select with "for update" specified.
* <p>
* <p>
* This will typically create row level database locks on the selected rows.
*/
public Query<T> setForUpdate(boolean forUpdate) {
return query().setForUpdate(forUpdate);
}
/**
* Create a query specifying whether the returned beans will be read-only.
*/
public Query<T> setReadOnly(boolean readOnly) {
return query().setReadOnly(readOnly);
}
/**
* Create a query specifying if the beans should be loaded into the L2 cache.
*/
public Query<T> setLoadBeanCache(boolean loadBeanCache) {
return query().setLoadBeanCache(loadBeanCache);
}
/**
* Create a query specifying if the L2 bean cache should be used.
*/
public Query<T> setUseCache(boolean useBeanCache) {
return query().setUseCache(useBeanCache);
}
/**
* Create a query specifying if the L2 query cache should be used.
*/
public Query<T> setUseQueryCache(boolean useQueryCache) {
return query().setUseQueryCache(useQueryCache);
}
}
}
@@ -1,47 +0,0 @@
package com.avaje.ebean;
/**
* Execute a TxCallable in a Transaction scope.
* <p>
* Use this with the {@link Ebean#execute(TxCallable)} method.
* </p>
* <p>
* Note that this is basically the same as TxRunnable except that it returns an
* Object (and you specify the return type via generics).
* </p>
* <p>
* See also {@link TxRunnable}.
* </p>
* <p>
* <pre>{@code
*
* Ebean.execute(new TxCallable<String>() {
* public String call() {
* User u1 = Ebean.find(User.class, 1);
* User u2 = Ebean.find(User.class, 2);
*
* u1.setName("u1 mod");
* u2.setName("u2 mod");
*
* Ebean.save(u1);
* Ebean.save(u2);
*
* return u1.getEmail();
* }
* });
*
* }</pre>
*
* @see TxRunnable
*/
public interface TxCallable<T> {
/**
* Execute the method within a transaction scope returning the result.
* <p>
* If you do not want to return a result you should look to use TxRunnable
* instead.
* </p>
*/
T call();
}
@@ -1,40 +0,0 @@
package com.avaje.ebean;
/**
* Execute a TxRunnable in a Transaction scope.
* <p>
* Use this with the {@link Ebean#execute(TxRunnable)} method.
* </p>
* <p>
* See also {@link TxCallable}.
* </p>
* <p>
* <pre>{@code
*
* // this run method runs in a transaction scope
* // which by default is TxScope.REQUIRED
*
* Ebean.execute(new TxRunnable() {
* public void run() {
* User u1 = Ebean.find(User.class, 1);
* User u2 = Ebean.find(User.class, 2);
*
* u1.setName("u1 mod");
* u2.setName("u2 mod");
*
* Ebean.save(u1);
* Ebean.save(u2);
* }
* });
*
* }</pre>
*
* @see TxCallable
*/
public interface TxRunnable {
/**
* Run the method in a transaction sope.
*/
void run();
}
@@ -1,119 +0,0 @@
package com.avaje.ebean.annotation;
import com.avaje.ebean.Query;
import com.avaje.ebean.config.Platform;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Assign to a property to be based on a SQL formula.
* <p>
* This is typically a SQL Literal value, SQL case statement, SQL function or
* similar.
* </p>
* <p>
* Any property based on a formula becomes a read only property.
* </p>
* <p>
* You may also put use the Transient annotation with the Formula annotation.
* The effect of the Transient annotation in this case is that the formula will
* <b>NOT</b> be included in queries by default - you have to explicitly include
* it via {@link Query#select(String)} or {@link Query#fetch(String, String, com.avaje.ebean.FetchConfig)}.
* You may want to do this if the Formula is relatively expensive and only want
* it included in the query when you explicitly state it.
* </p>
* <p>
* <pre>{@code
* // On the Order "master" bean
* // ... a formula using the Order details
* // ... sum(order_qty*unit_price)
* @Transient
* @Formula(select = "_b${ta}.total_amount", join = "join (select order_id, sum(order_qty*unit_price) as total_amount from o_order_detail group by order_id) as _b${ta} on _b${ta}.order_id = ${ta}.id")
* Double totalAmount;
*
* }</pre>
* <p>
* As the totalAmount formula is also Transient it is not included by default in
* queries - it needs to be explicitly included.
* </p>
* <pre>{@code
*
* // find by Id
* Order o1 = Ebean.find(Order.class)
* .select("id, totalAmount")
* .setId(1).findUnique();
*
* // find list ... using totalAmount in the where clause
* List<Order> list = Ebean.find(Order.class)
* .select("id, totalAmount")
* .where()
* .eq("status", Order.Status.NEW)
* .gt("totalAmount", 10)
* .findList();
*
* // as a join from customer
* List<Customer> l0 = Ebean.find(Customer.class)
* .select("id, name")
* .fetch("orders", "status, totalAmount")
* .where()
* .gt("id", 0)
* .gt("orders.totalAmount", 10)
* .findList();
*
* }</pre>
*/
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Formula.List.class)
public @interface Formula {
/**
* The SQL to be used in the SELECT part of the SQL to populate a property.
*/
String select();
/**
* OPTIONAL - the SQL to be used in the JOIN part of the SQL to support the
* formula.
* <p>
* This is commonly used to join a 'dynamic view' to support aggregation such
* as count, sum etc.
* </p>
* <p>
* The join string should start with either "left join" or "join".
* </p>
* <p>
* You will almost certainly use the "${ta}" as a place holder for the table
* alias of the table you are joining back to (the "base table" of the entity
* bean).
* </p>
* <p>
* The example below is used to support a total count of topics created by a
* user.
* </p>
* <p>
* <pre>{@code
*
* join (select user_id, count(*) as topic_count from f_topic group by user_id) as _tc on _tc.user_id = ${ta}.id
*
* }</pre>
*/
String join() default "";
Platform[] platforms() default {};
/**
* Repeatable support for {@link Formula}.
*/
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@interface List {
Formula[] value() default {};
}
}
@@ -1,138 +0,0 @@
package com.avaje.ebean.annotation;
import com.avaje.ebean.TxIsolation;
import com.avaje.ebean.TxType;
import com.avaje.ebean.config.PersistBatch;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Specify transaction scoping for a method.
* <p>
* <b><i> This is only supported if "Enhancement" is used via javaagent, ANT
* task or IDE enhancement plugin etc. </i></b>
* </p>
* <p>
* Note: Currently there are 3 known annotations that perform this role.
* <ul>
* <li>EJB's javax.ejb.TransactionAttribute</li>
* <li>Spring's org.springframework.transaction.annotation.Transactional</li>
* <li>and this one, Ebean's own com.avaje.ebean.annotation.Transactional</li>
* </ul>
* Spring created their one because the EJB annotation does not support features
* such as isolation level and specifying rollbackOn, noRollbackOn exceptions.
* This one exists for Ebean because I agree that the standard one is
* insufficient and don't want to include a dependency on Spring.
* </p>
* <p>
* The default behaviour of EJB (and hence Spring) is to NOT ROLLBACK on checked
* exceptions. I find this very counter-intuitive. Ebean will provide a property
* to set the default behaviour to rollback on any exception and optionally
* change the setting to be consistent with EJB/Spring if people wish to do so.
* </p>
* <p>
* <pre>{@code
*
* // a normal class
* public class MySimpleUserService {
*
* // this method is transactional automatically handling
* // transaction begin, commit and rollback etc
* @Transactional
* public void runInTrans() throws IOException {
*
* // tasks performed within the transaction
* ...
* // find some objects
* Customer cust = ebeanServer.find(Customer.class, 42);
*
* Order order = ...;
* ...
* // save some objects
* ebeanServer.save(customer);
* ebeanServer.save(order);
* }
*
* }</pre>
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Transactional {
/**
* The type of transaction scoping. Defaults to REQUIRED.
*/
TxType type() default TxType.REQUIRED;
/**
* Persist batch mode for the transaction.
*/
PersistBatch batch() default PersistBatch.INHERIT;
/**
* Persist batch mode for the request if not set on the transaction.
* <p>
* If batch is set to NONE then batchOnCascade can be set to INSERT or ALL
* and then each save(), delete(), insert(), update() request that cascades
* to child beans can use JDBC batch.
* </p>
*/
PersistBatch batchOnCascade() default PersistBatch.INHERIT;
/**
* The batch size to use when using JDBC batch mode.
* <p>
* If unset this defaults to the value set in ServerConfig.
* </p>
*/
int batchSize() default 0;
/**
* Set to false when we want to skip getting generatedKeys.
* <p>
* This is typically used in the case of large batch inserts where we get a
* performance benefit from not calling getGeneratedKeys (as we are going to
* insert a lot of rows and have no need for the Id values after the insert).
* </p>
*/
boolean getGeneratedKeys() default true;
/**
* The transaction isolation level this transaction should have.
* <p>
* This will only be used if this scope creates the transaction. If the
* transaction has already started then this will currently be ignored (you
* could argue that it should throw an exception).
* </p>
*/
TxIsolation isolation() default TxIsolation.DEFAULT;
/**
* Set this to true if the transaction should be only contain queries.
*/
boolean readOnly() default false;
/**
* The name of the server that you want the transaction to be created from.
* <p>
* If left blank the 'default' server is used.
* </p>
*/
String serverName() default "";
// int timeout() default 0;
/**
* The Throwable's that will explicitly cause a rollback to occur.
*/
Class<? extends Throwable>[] rollbackFor() default {};
/**
* The Throwable's that will explicitly NOT cause a rollback to occur.
*/
Class<? extends Throwable>[] noRollbackFor() default {};
}
@@ -1,68 +0,0 @@
package com.avaje.ebean.annotation;
import com.avaje.ebean.config.Platform;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Add an Literal to add to the where clause when a many property (List, Set or
* Map) is loaded or refreshed.
* <pre>{@code
*
* // on a OneToMany property...
*
* @OneToMany
* @Where(clause = "deleted='y'")
* List<Topic> topics;
*
* }</pre>
* <p>
* Note that you can include "${ta}" as a place holder for the table alias if
* you need to include the table alias in the clause.
* </p>
* <pre>{@code
* // ... including the ${ta} table alias placeholder...
*
* @OneToMany
* @Where(clause = "${ta}.deleted='y'")
* List<Topic> topics;
*
* }</pre>
* <p>
* This will be added to the where clause when lazy loading the OneToMany
* property or when there is a join to that OneToMany property.
* </p>
*/
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Where.List.class)
public @interface Where {
/**
* The clause added to the lazy load query.
* <p>
* Note that you can include "${ta}" as a place holder for the table alias if
* you need to include the table alias in the clause.
* </p>
*/
String clause();
/**
* The platform where this annotation is active. Default: any platform
*/
Platform[] platforms() default {};
/**
* Repeatable support for {@link Where}.
*/
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@interface List {
Where[] value() default {};
}
}
@@ -1,42 +0,0 @@
package com.avaje.ebean.config;
/**
* API from creating and getting property values from an Immutable Compound
* Value Object.
* <p>
* A Compound Value object should contain multiple properties that are stored
* separately. If you only have a single scalar value you should instead look to
* use {@link ScalarTypeConverter}.
* </p>
* <p>
* For each property in the compound type you need to implement the
* {@link CompoundTypeProperty} interface. These must be returned from
* {@link #getProperties()} in the same order that the properties appear in the
* constructor.
* </p>
* <p>
* If your compound type is mutable then you should look to use the JPA Embedded
* annotation instead of implementing this interface.
* </p>
* <p>
* When using classpath search Ebean will detect and automatically register any
* implementations of this interface (along with detecting the entity classes
* etc).
* </p>
*
* @param <V> The type of the Value Object
* @author rbygrave
* @see ScalarTypeConverter
*/
public interface CompoundType<V> {
/**
* Create an instance of the compound type given its property values.
*/
V create(Object[] propertyValues);
/**
* Return the properties in the order they appear in the constructor.
*/
CompoundTypeProperty<V, ?>[] getProperties();
}
@@ -1,45 +0,0 @@
package com.avaje.ebean.config;
/**
* Represents a Property of a Compound Value Object.
* <p>
* For each property in a {@link CompoundType} you need an implementation of
* this CompoundTypeProperty interface.
* </p>
*
* @param <V> The type of the Compound value object
* @param <P> The type of the property
* @author rbygrave
* @see CompoundType
* @see ScalarTypeConverter
*/
public interface CompoundTypeProperty<V, P> {
/**
* The name of this property.
*/
String getName();
/**
* Return the property value from the containing compound value object.
*
* @param valueObject the compound value object
* @return the property value.
*/
P getValue(V valueObject);
/**
* This should <b>ONLY</b> be used when the persistence type is different from
* the logical type returned. It most cases just return 0 and Ebean will
* persist the logical type.
* <p>
* Typically this should be used when the logical type is long but the
* persistence type is java.sql.Timestamp. In this case return
* java.sql.Types.TIMESTAMP (rather than 0).
* </p>
*
* @return Return the java.sql.Type that you want to use to persist this
* property or 0 and Ebean will use the logical type.
*/
int getDbType();
}
@@ -1,60 +0,0 @@
package com.avaje.ebean.config;
import java.util.Properties;
/**
* Configuration for the container that holds the EbeanServer instances.
* <p>
* Provides configuration for cluster communication (if clustering is used). The cluster communication is
* used to invalidate appropriate parts of the L2 cache across the cluster.
*/
public class ContainerConfig {
protected boolean clusterActive;
protected Properties properties;
/**
* Return true if clustering is active.
*/
public boolean isClusterActive() {
return clusterActive;
}
/**
* Set to true for clustering to be active.
*/
public void setClusterActive(boolean clusterActive) {
this.clusterActive = clusterActive;
}
/**
* Return the deployment properties.
*/
public Properties getProperties() {
return properties;
}
/**
* Set the deployment properties.
*/
public void setProperties(Properties properties) {
this.properties = properties;
}
/**
* Load the settings from properties.
*/
public void loadFromProperties(Properties properties) {
this.properties = properties;
this.clusterActive = getProperty(properties, "ebean.cluster.active", clusterActive);
}
/**
* Return the boolean property setting.
*/
protected boolean getProperty(Properties properties, String key, boolean defaultValue) {
return "true".equalsIgnoreCase(properties.getProperty(key, Boolean.toString(defaultValue)));
}
}
@@ -1,42 +0,0 @@
package com.avaje.ebean.config.dbplatform;
import com.avaje.ebean.BackgroundExecutor;
import com.avaje.ebean.dbmigration.ddlgeneration.platform.DB2Ddl;
import javax.sql.DataSource;
import java.sql.Types;
/**
* DB2 specific platform.
*/
public class DB2Platform extends DatabasePlatform {
public DB2Platform() {
super();
this.name = "db2";
this.maxTableNameLength = 18;
this.maxConstraintNameLength = 18;
this.sqlLimiter = new Db2SqlLimiter();
this.platformDdl = new DB2Ddl(this);
this.dbIdentity.setSupportsGetGeneratedKeys(true);
this.dbIdentity.setSupportsSequence(true);
booleanDbType = Types.BOOLEAN;
dbTypeMap.put(DbType.REAL, new DbPlatformType("real"));
dbTypeMap.put(DbType.TINYINT, new DbPlatformType("smallint"));
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("decimal", 15));
}
/**
* Return a DB2 specific sequence IdGenerator that supports batch fetching
* sequence values.
*/
@Override
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be,
DataSource ds, String seqName, int batchSize) {
return new DB2SequenceIdGenerator(be, ds, seqName, batchSize);
}
}
@@ -1,70 +0,0 @@
package com.avaje.ebean.config.dbplatform;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* DB Column default values mapping to database platform specific literals.
*/
public class DbDefaultValue {
/**
* The key for FALSE.
*/
public static final String FALSE = "false";
/**
* The key for TRUE.
*/
public static final String TRUE = "true";
/**
* The key for the NOW / current timestamp.
*/
public static final String NOW = "now";
protected Map<String, String> map = new LinkedHashMap<>();
/**
* Set the DB now function.
*/
public void setNow(String dbFunction) {
put(NOW, dbFunction);
}
/**
* Set the DB false literal.
*/
public void setFalse(String dbFalseLiteral) {
put(FALSE, dbFalseLiteral);
}
/**
* Set the DB true literal.
*/
public void setTrue(String dbTrueLiteral) {
put(TRUE, dbTrueLiteral);
}
/**
* Add an translation entry.
*/
public void put(String dbLiteral, String dbTranslated) {
map.put(dbLiteral, dbTranslated);
}
/**
* Convert the DB default literal to platform specific type or function.
* <p>
* This is intended for the DB column default clause in DDL.
* </p>
*/
public String convert(String dbDefaultLiteral) {
if (dbDefaultLiteral == null) {
return null;
}
String val = map.get(dbDefaultLiteral);
return val != null ? val : dbDefaultLiteral;
}
}
@@ -1,49 +0,0 @@
package com.avaje.ebean.config.dbplatform;
import com.avaje.ebean.BackgroundExecutor;
import com.avaje.ebean.dbmigration.ddlgeneration.platform.H2Ddl;
import javax.sql.DataSource;
/**
* H2 specific platform.
*/
public class H2Platform extends DatabasePlatform {
public H2Platform() {
super();
this.name = "h2";
this.dbEncrypt = new H2DbEncrypt();
this.platformDdl = new H2Ddl(this);
this.historySupport = new H2HistorySupport();
this.nativeUuidType = true;
this.dbDefaultValue.setNow("now()");
this.dbIdentity.setIdType(IdType.IDENTITY);
this.dbIdentity.setSupportsGetGeneratedKeys(true);
this.dbIdentity.setSupportsSequence(true);
this.dbIdentity.setSupportsIdentity(true);
// like ? escape'' not working in the latest version H2 so just using no
// escape clause for now noting that backslash is an escape char for like in H2
this.likeClause = "like ?";
dbTypeMap.put(DbType.UUID, new DbPlatformType("uuid", false));
}
/**
* Return a H2 specific sequence IdGenerator that supports batch fetching
* sequence values.
*/
@Override
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds,
String seqName, int batchSize) {
return new H2SequenceIdGenerator(be, ds, seqName, batchSize);
}
@Override
protected String withForUpdate(String sql) {
return sql + " for update";
}
}
@@ -1,33 +0,0 @@
package com.avaje.ebean.config.dbplatform;
import com.avaje.ebean.BackgroundExecutor;
import com.avaje.ebean.dbmigration.ddlgeneration.platform.HsqldbDdl;
import javax.sql.DataSource;
/**
* H2 specific platform.
*/
public class HsqldbPlatform extends DatabasePlatform {
public HsqldbPlatform() {
super();
this.name = "hsqldb";
this.dbEncrypt = new H2DbEncrypt();
this.platformDdl = new HsqldbDdl(this);
this.dbIdentity.setIdType(IdType.IDENTITY);
this.dbIdentity.setSupportsGetGeneratedKeys(true);
this.dbIdentity.setSupportsSequence(true);
this.dbIdentity.setSupportsIdentity(true);
dbTypeMap.put(DbType.INTEGER, new DbPlatformType("integer", false));
}
@Override
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
return new H2SequenceIdGenerator(be, ds, seqName, batchSize);
}
}
@@ -1,49 +0,0 @@
package com.avaje.ebean.config.dbplatform;
import com.avaje.ebean.config.PersistBatch;
/**
* Microsoft SQL Server 2000 specific platform.
* <p>
* <ul>
* <li>supportsGetGeneratedKeys = false</li>
* <li>Use select @@IDENTITY to return the generated Id instead</li>
* <li>Uses LIMIT OFFSET clause</li>
* <li>Uses [ & ] for quoted identifiers</li>
* </ul>
* </p>
*/
public class MsSqlServer2000Platform extends DatabasePlatform {
public MsSqlServer2000Platform() {
super();
this.name = "mssqlserver2000";
this.persistBatchOnCascade = PersistBatch.NONE;
this.dbIdentity.setIdType(IdType.IDENTITY);
this.dbIdentity.setSupportsGetGeneratedKeys(false);
this.dbIdentity.setSelectLastInsertedIdTemplate("select @@IDENTITY as X");
this.dbIdentity.setSupportsIdentity(true);
this.openQuote = "[";
this.closeQuote = "]";
dbTypeMap.put(DbType.BOOLEAN, new DbPlatformType("bit default 0"));
dbTypeMap.put(DbType.BIGINT, new DbPlatformType("numeric", 19));
dbTypeMap.put(DbType.REAL, new DbPlatformType("float(16)"));
dbTypeMap.put(DbType.DOUBLE, new DbPlatformType("float(32)"));
dbTypeMap.put(DbType.TINYINT, new DbPlatformType("smallint"));
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("numeric", 28));
dbTypeMap.put(DbType.BLOB, new DbPlatformType("image"));
dbTypeMap.put(DbType.CLOB, new DbPlatformType("text"));
dbTypeMap.put(DbType.LONGVARBINARY, new DbPlatformType("image"));
dbTypeMap.put(DbType.LONGVARCHAR, new DbPlatformType("text"));
dbTypeMap.put(DbType.DATE, new DbPlatformType("datetime"));
dbTypeMap.put(DbType.TIME, new DbPlatformType("datetime"));
dbTypeMap.put(DbType.TIMESTAMP, new DbPlatformType("datetime"));
}
}
@@ -1,55 +0,0 @@
package com.avaje.ebean.config.dbplatform;
import com.avaje.ebean.config.PersistBatch;
import com.avaje.ebean.dbmigration.ddlgeneration.platform.MsSqlServerDdl;
/**
* Microsoft SQL Server 2005 specific platform.
* <p>
* <ul>
* <li>supportsGetGeneratedKeys = true</li>
* <li>Uses LIMIT OFFSET clause</li>
* <li>Uses [ & ] for quoted identifiers</li>
* </ul>
* </p>
*/
public class MsSqlServer2005Platform extends DatabasePlatform {
public MsSqlServer2005Platform() {
super();
this.name = "mssqlserver2005";
// effectively disable persistBatchOnCascade mode for SQL Server
// due to lack of support for getGeneratedKeys in batch mode
this.persistBatchOnCascade = PersistBatch.NONE;
this.idInExpandedForm = true;
this.selectCountWithAlias = true;
this.sqlLimiter = new MsSqlServer2005SqlLimiter();
this.platformDdl = new MsSqlServerDdl(this);
this.dbIdentity.setIdType(IdType.IDENTITY);
this.dbIdentity.setSupportsGetGeneratedKeys(true);
this.dbIdentity.setSupportsIdentity(true);
this.openQuote = "[";
this.closeQuote = "]";
dbTypeMap.put(DbType.BOOLEAN, new DbPlatformType("bit default 0"));
dbTypeMap.put(DbType.INTEGER, new DbPlatformType("integer", false));
dbTypeMap.put(DbType.BIGINT, new DbPlatformType("numeric", 19));
dbTypeMap.put(DbType.REAL, new DbPlatformType("float(16)"));
dbTypeMap.put(DbType.DOUBLE, new DbPlatformType("float(32)"));
dbTypeMap.put(DbType.TINYINT, new DbPlatformType("smallint"));
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("numeric", 28));
dbTypeMap.put(DbType.BLOB, new DbPlatformType("image"));
dbTypeMap.put(DbType.CLOB, new DbPlatformType("text"));
dbTypeMap.put(DbType.LONGVARBINARY, new DbPlatformType("image"));
dbTypeMap.put(DbType.LONGVARCHAR, new DbPlatformType("text"));
dbTypeMap.put(DbType.DATE, new DbPlatformType("date"));
dbTypeMap.put(DbType.TIME, new DbPlatformType("time"));
dbTypeMap.put(DbType.TIMESTAMP, new DbPlatformType("datetime2"));
}
}
@@ -1,240 +0,0 @@
package com.avaje.ebean.config.dbplatform;
import com.avaje.ebean.BackgroundExecutor;
import com.avaje.ebean.Transaction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.persistence.PersistenceException;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
/**
* Database sequence based IdGenerator.
*/
public abstract class SequenceIdGenerator implements PlatformIdGenerator {
private static final Logger logger = LoggerFactory.getLogger(SequenceIdGenerator.class);
/**
* Used to synchronise the idList access.
*/
protected final Object monitor = new Object();
/**
* Used to synchronise background loading (loadBatchInBackground).
*/
protected final Object backgroundLoadMonitor = new Object();
/**
* The actual sequence name.
*/
protected final String seqName;
protected final DataSource dataSource;
protected final BackgroundExecutor backgroundExecutor;
protected final ArrayList<Long> idList = new ArrayList<>(50);
protected final int batchSize;
protected int currentlyBackgroundLoading;
/**
* Construct given a dataSource and sql to return the next sequence value.
*/
public SequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
this.backgroundExecutor = be;
this.dataSource = ds;
this.seqName = seqName;
this.batchSize = batchSize;
}
public abstract String getSql(int batchSize);
/**
* Returns the sequence name.
*/
public String getName() {
return seqName;
}
/**
* Returns true.
*/
public boolean isDbSequence() {
return true;
}
/**
* If allocateSize is large load some sequences in a background thread.
* <p>
* For example, when inserting a bean with a cascade on a OneToMany with many
* beans Ebean can call this to ensure .
* </p>
*/
public void preAllocateIds(int allocateSize) {
if (batchSize > 1 && allocateSize > batchSize) {
// only bother if allocateSize is bigger than
// the normal loading batchSize
if (allocateSize > 100) {
// max out at 100 for now
allocateSize = 100;
}
loadLargeAllocation(allocateSize);
}
}
/**
* Called by preAllocateIds when we know that a large number of Id's is going
* to be needed shortly.
*/
protected void loadLargeAllocation(final int allocateSize) {
// preAllocateIds was called with a relatively large batchSize
// so we will just go ahead and load those anyway in background
backgroundExecutor.execute(() -> loadMoreIds(allocateSize, null));
}
/**
* Return the next Id.
* <p>
* If a Transaction has been passed in use the Connection from it.
* </p>
*/
public Object nextId(Transaction t) {
synchronized (monitor) {
if (idList.isEmpty()) {
loadMoreIds(batchSize, t);
}
Long nextId = idList.remove(0);
if (batchSize > 1) {
if (idList.size() <= batchSize / 2) {
loadBatchInBackground();
}
}
return nextId;
}
}
/**
* Load another batch of Id's using a background thread.
*/
protected void loadBatchInBackground() {
// single threaded processing...
synchronized (backgroundLoadMonitor) {
if (currentlyBackgroundLoading > 0) {
// skip as already background loading
logger.debug("... skip background sequence load (another load in progress)");
return;
}
currentlyBackgroundLoading = batchSize;
backgroundExecutor.execute(() -> {
loadMoreIds(batchSize, null);
synchronized (backgroundLoadMonitor) {
currentlyBackgroundLoading = 0;
}
});
}
}
protected void loadMoreIds(final int numberToLoad, Transaction t) {
ArrayList<Long> newIds = getMoreIds(numberToLoad, t);
if (logger.isDebugEnabled()) {
logger.debug("... seq:" + seqName + " loaded:" + numberToLoad + " ids:" + newIds);
}
synchronized (monitor) {
for (Long newId : newIds) {
idList.add(newId);
}
}
}
/**
* Get more Id's by executing a query and reading the Id's returned.
*/
protected ArrayList<Long> getMoreIds(int loadSize, Transaction t) {
String sql = getSql(loadSize);
ArrayList<Long> newIds = new ArrayList<>(loadSize);
boolean useTxnConnection = t != null;
Connection c = null;
PreparedStatement pstmt = null;
ResultSet rset = null;
try {
c = useTxnConnection ? t.getConnection() : dataSource.getConnection();
pstmt = c.prepareStatement(sql);
rset = pstmt.executeQuery();
while (rset.next()) {
newIds.add(rset.getLong(1));
}
if (newIds.isEmpty()) {
throw new PersistenceException("Always expecting more than 1 row from " + sql);
}
return newIds;
} catch (SQLException e) {
if (e.getMessage().contains("Database is already closed")) {
String msg = "Error getting SEQ when DB shutting down " + e.getMessage();
logger.info(msg);
System.out.println(msg);
return newIds;
} else {
throw new PersistenceException("Error getting sequence nextval", e);
}
} finally {
if (useTxnConnection) {
closeResources(null, pstmt, rset);
} else {
closeResources(c, pstmt, rset);
}
}
}
/**
* Close the JDBC resources.
*/
protected void closeResources(Connection c, PreparedStatement pstmt, ResultSet rset) {
try {
if (rset != null) {
rset.close();
}
} catch (SQLException e) {
logger.error("Error closing ResultSet", e);
}
try {
if (pstmt != null) {
pstmt.close();
}
} catch (SQLException e) {
logger.error("Error closing PreparedStatement", e);
}
try {
if (c != null) {
c.close();
}
} catch (SQLException e) {
logger.error("Error closing Connection", e);
}
}
}
@@ -1,15 +0,0 @@
package com.avaje.ebean.dbmigration.ddlgeneration.platform;
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
/**
* DB2 platform specific DDL.
*/
public class DB2Ddl extends PlatformDdl {
public DB2Ddl(DatabasePlatform platform) {
super(platform);
this.identitySuffix = " generated by default as identity";
}
}
@@ -1,15 +0,0 @@
package com.avaje.ebean.dbmigration.ddlgeneration.platform;
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
/**
* H2 platform specific DDL.
*/
public class H2Ddl extends PlatformDdl {
public H2Ddl(DatabasePlatform platform) {
super(platform);
this.historyDdl = new H2HistoryDdl();
}
}
@@ -1,105 +0,0 @@
package com.avaje.ebean.dbmigration.ddlgeneration.platform;
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
import com.avaje.ebean.dbmigration.ddlgeneration.DdlBuffer;
import com.avaje.ebean.dbmigration.migration.AlterColumn;
import java.io.IOException;
/**
* MS SQL Server platform specific DDL.
*/
public class MsSqlServerDdl extends PlatformDdl {
public MsSqlServerDdl(DatabasePlatform platform) {
super(platform);
this.identitySuffix = " identity(1,1)";
this.foreignKeyRestrict = "";
this.inlineUniqueOneToOne = false;
this.columnSetDefault = "add default";
this.dropConstraintIfExists = "drop constraint";
}
@Override
public String dropTable(String tableName) {
return "IF OBJECT_ID('" + tableName + "', 'U') IS NOT NULL drop table " + tableName;
}
@Override
public String alterTableDropForeignKey(String tableName, String fkName) {
return "IF OBJECT_ID('" + fkName + "', 'F') IS NOT NULL " + super.alterTableDropForeignKey(tableName, fkName);
}
/**
* MsSqlServer specific null handling on unique constraints.
*/
@Override
public String alterTableAddUniqueConstraint(String tableName, String uqName, String[] columns) {
// issues#233
String start = "create unique nonclustered index " + uqName + " on " + tableName + "(";
StringBuilder sb = new StringBuilder(start);
for (int i = 0; i < columns.length; i++) {
if (i > 0) {
sb.append(",");
}
sb.append(columns[i]);
}
sb.append(") where");
for (String column : columns) {
sb.append(" ").append(column).append(" is not null");
}
return sb.toString();
}
@Override
public String alterColumnDefaultValue(String tableName, String columnName, String defaultValue) {
if (isDropDefault(defaultValue)) {
return "-- alter table " + tableName + " drop constraint <unknown> -- find the appropriate constraint for default value on column " + columnName;
} else {
return "alter table " + tableName + " add default " + defaultValue + " for " + columnName;
}
}
public String alterColumnBaseAttributes(AlterColumn alter) {
String tableName = alter.getTableName();
String columnName = alter.getColumnName();
String type = alter.getType() != null ? alter.getType() : alter.getCurrentType();
boolean notnull = (alter.isNotnull() != null) ? alter.isNotnull() : Boolean.TRUE.equals(alter.isCurrentNotnull());
String notnullClause = notnull ? " not null" : "";
return "alter table " + tableName + " alter column " + columnName + " " + type + notnullClause;
}
@Override
public String alterColumnType(String tableName, String columnName, String type) {
// can't alter itself - done in alterColumnBaseAttributes()
return null;
}
public String alterColumnNotnull(String tableName, String columnName, boolean notnull) {
// can't alter itself - done in alterColumnBaseAttributes()
return null;
}
/**
* Add table comment as a separate statement (from the create table statement).
*/
public void addTableComment(DdlBuffer apply, String tableName, String tableComment) throws IOException {
// do nothing for MS SQL Server (cause it requires stored procedures etc)
}
/**
* Add column comment as a separate statement.
*/
public void addColumnComment(DdlBuffer apply, String table, String column, String comment) throws IOException {
// do nothing for MS SQL Server (cause it requires stored procedures etc)
}
}
@@ -1,24 +0,0 @@
package com.avaje.ebean.dbmigration.ddlgeneration.platform;
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
/**
* Oracle platform specific DDL.
*/
public class Oracle10Ddl extends PlatformDdl {
public Oracle10Ddl(DatabasePlatform platform) {
super(platform);
this.dropTableIfExists = "drop table ";
this.dropSequenceIfExists = "drop sequence ";
this.dropConstraintIfExists = "drop constraint";
this.dropIndexIfExists = "drop index ";
this.dropTableCascade = " cascade constraints purge";
this.foreignKeyRestrict = "";
this.alterColumn = "modify";
this.columnSetNotnull = "not null";
this.columnSetNull = "null";
this.columnSetDefault = "default";
}
}
@@ -1,27 +0,0 @@
package com.avaje.ebean.event;
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.Query;
import com.avaje.ebean.Transaction;
/**
* Holds the information available for a bean query.
*/
public interface BeanQueryRequest<T> {
/**
* Return the server processing the request.
*/
EbeanServer getEbeanServer();
/**
* Return the Transaction associated with this request.
*/
Transaction getTransaction();
/**
* Returns the query.
*/
Query<T> getQuery();
}
@@ -1,127 +0,0 @@
package com.avaje.ebean.event.changelog;
import com.avaje.ebean.ValuePair;
import java.util.Map;
/**
* A bean insert, update or delete change sent as part of a ChangeSet.
*/
public class BeanChange {
/**
* The underling base table name.
*/
String table;
/**
* The id value.
*/
Object id;
/**
* The INSERT, UPDATE or DELETE change type.
*/
ChangeType type;
/**
* The time the bean change was created.
*/
long eventTime;
/**
* The values for insert or update. Note that null values are not included for insert.
*/
Map<String, ValuePair> values;
/**
* Construct with all the details.
*/
public BeanChange(String table, Object id, ChangeType type, Map<String, ValuePair> values) {
this.table = table;
this.id = id;
this.type = type;
this.eventTime = System.currentTimeMillis();
this.values = values;
}
/**
* Default constructor for JSON tools.
*/
public BeanChange() {
}
public String toString() {
return "table:" + table + " id:" + id + " values:" + values;
}
/**
* Return the object type (typically table name).
*/
public String getTable() {
return table;
}
/**
* Set the object type (for JSON tools).
*/
public void setTable(String table) {
this.table = table;
}
/**
* Return the object id.
*/
public Object getId() {
return id;
}
/**
* Set the bean id (for JSON tools).
*/
public void setId(Object id) {
this.id = id;
}
/**
* Return the change type (INSERT, UPDATE or DELETE).
*/
public ChangeType getType() {
return type;
}
/**
* Set the type (for JSON tools).
*/
public void setType(ChangeType type) {
this.type = type;
}
/**
* Return the event time in epoch millis.
*/
public long getEventTime() {
return eventTime;
}
/**
* Set the event time in epoch millis.
*/
public void setEventTime(long eventTime) {
this.eventTime = eventTime;
}
/**
* Return the value pairs. For inserts the ValuePair oldValue is always null.
*/
public Map<String, ValuePair> getValues() {
return values;
}
/**
* Set the value pairs (for JSON tools).
*/
public void setValues(Map<String, ValuePair> values) {
this.values = values;
}
}
@@ -1,17 +0,0 @@
package com.avaje.ebean.meta;
import java.util.List;
public interface MetaBeanInfo {
/**
* Collect the current query plan statistics return the non-empty statistics.
*/
List<MetaQueryPlanStatistic> collectQueryPlanStatistics(boolean reset);
/**
* Collect the current query plan statistics return all the statistics (include query plans that haven't had query executions).
*/
List<MetaQueryPlanStatistic> collectAllQueryPlanStatistics(boolean reset);
}
@@ -1,47 +0,0 @@
package com.avaje.ebean.util;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
/**
* Helper to find classes taking into account the context class loader.
*/
public class ClassUtil {
/**
* Returns the raw type for the 2nd generic parameter for a subclass.
*/
public static Class<?> getSecondArgumentType(Class<?> subclass) {
Type[] typeArguments = getSuperclassTypeParameter(subclass);
if (typeArguments.length != 2) {
throw new IllegalArgumentException("Expected type with 2 generic argument types but got "
+ typeArguments.length + " - " + Arrays.toString(typeArguments));
}
return getRawType(typeArguments[1]);
}
static Type[] getSuperclassTypeParameter(Class<?> subclass) {
Type superclass = subclass.getGenericSuperclass();
if (superclass instanceof Class) {
throw new RuntimeException("Missing generics type parameters on subclass " + subclass);
}
return ((ParameterizedType) superclass).getActualTypeArguments();
}
private static Class<?> getRawType(Type type) {
if (type instanceof Class<?>) {
return (Class<?>) type;
} else if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
Type rawType = parameterizedType.getRawType();
if (rawType instanceof Class<?>) {
return (Class<?>) rawType;
}
}
throw new RuntimeException("Unable to obtain raw class type from " + type);
}
}
@@ -1,54 +0,0 @@
package com.avaje.ebeaninternal.api;
/**
* A hash for a query plan.
*/
public class HashQueryPlan {
private final String rawSql;
private final int planHash;
private final int bindCount;
public HashQueryPlan(String rawSql, int planHash, int bindCount) {
this.rawSql = rawSql;
this.planHash = planHash;
this.bindCount = bindCount;
}
public String toString() {
return planHash + ":" + bindCount + (rawSql != null ? ":r" : "");
}
/**
* Return as a partial key. For rawSql hash the sql is part of the key and as such
* needs to be included in order to have a complete key. Typically the MD5 of the sql
* can be used as a shot form proxy for the actual sql.
*/
public String getPartialKey() {
return planHash + "_" + bindCount;
}
public int hashCode() {
int hc = planHash;
hc = hc * 31 + bindCount;
hc = hc * 31 + (rawSql == null ? 0 : rawSql.hashCode());
return hc;
}
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof HashQueryPlan)) {
return false;
}
HashQueryPlan e = (HashQueryPlan) obj;
//noinspection StringEquality
return e.planHash == planHash
&& e.bindCount == bindCount
&& ((e.rawSql == rawSql) || (e.rawSql != null && e.rawSql.equals(rawSql)));
}
}
@@ -1,96 +0,0 @@
package com.avaje.ebeaninternal.api;
import java.util.Set;
/**
* Used to build HashQueryPlan instances.
*/
public class HashQueryPlanBuilder {
private int planHash;
private int bindCount;
public HashQueryPlanBuilder() {
this.planHash = 92821;
}
public String toString() {
return planHash + ":" + bindCount;
}
/**
* Add a class to the hash calculation.
*/
public HashQueryPlanBuilder add(Class<?> cls) {
planHash = planHash * 92821 + cls.getName().hashCode();
return this;
}
/**
* Add an object to the hash calculation.
*/
public HashQueryPlanBuilder add(Object object) {
planHash = planHash * 92821 + (object == null ? 0 : object.hashCode());
return this;
}
/**
* Add the set with order being important.
*/
public HashQueryPlanBuilder addOrdered(Set<?> set) {
if (set == null) {
add(false);
} else {
add(true);
for (Object o : set) {
add(o);
}
}
return this;
}
/**
* Add an integer to the hash calculation.
*/
public HashQueryPlanBuilder add(int hashValue) {
planHash = planHash * 92821 + (hashValue);
return this;
}
/**
* Add a boolean to the hash calculation.
*/
public HashQueryPlanBuilder add(boolean booleanValue) {
planHash = planHash * 92821 + (booleanValue ? 92821 : 0);
return this;
}
/**
* Add a number to the bind count for the hash.
*/
public void bind(int extraBindCount) {
bindCount += extraBindCount;
}
public void bindIfNotNull(Object someValue) {
if (someValue != null) {
bindCount++;
}
}
/**
* Build and return the calculated HashQueryPlan.
*/
public String build() {
return planHash + "_" + bindCount;
}
public int getPlanHash() {
return planHash;
}
public int getBindCount() {
return bindCount;
}
}
@@ -1,37 +0,0 @@
package com.avaje.ebeaninternal.api;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.TxScope;
/**
* Helper object to make AOP generated code simpler.
*/
public class HelpScopeTrans {
/**
* Create a ScopeTrans for a given methods TxScope.
*/
public static ScopeTrans createScopeTrans(TxScope txScope) {
EbeanServer server = Ebean.getServer(txScope.getServerName());
SpiEbeanServer iserver = (SpiEbeanServer) server;
return iserver.createScopeTrans(txScope);
}
/**
* Exiting the method in an expected fashion.
* <p>
* That is returning successfully or via a caught exception.
* Unexpected exceptions are caught via the Thread uncaughtExceptionHandler.
* </p>
*
* @param returnOrThrowable the return or throwable object
* @param opCode the opcode for ATHROW or ARETURN etc
* @param scopeTrans the scoped transaction the method was run with.
*/
public static void onExitScopeTrans(Object returnOrThrowable, int opCode, ScopeTrans scopeTrans) {
scopeTrans.onExit(returnOrThrowable, opCode);
}
}
@@ -1,10 +0,0 @@
package com.avaje.ebeaninternal.api;
import com.avaje.ebean.SqlUpdate;
public interface SpiSqlUpdate extends SqlUpdate {
BindParams getBindParams();
void setGeneratedSql(String sql);
}
@@ -1 +0,0 @@
package com.avaje.ebeaninternal.api;
@@ -1,14 +0,0 @@
package com.avaje.ebeaninternal.server.autotune.service;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.server.autotune.AutoTuneService;
public class AutoTuneServiceFactory {
public static AutoTuneService create(SpiEbeanServer server, ServerConfig serverConfig) {
return new DefaultAutoTuneService(server, serverConfig);
}
}
@@ -1,74 +0,0 @@
package com.avaje.ebeaninternal.server.cache;
import com.avaje.ebean.cache.ServerCache;
import com.avaje.ebean.cache.ServerCacheFactory;
import com.avaje.ebean.cache.ServerCacheOptions;
import com.avaje.ebean.cache.ServerCacheType;
import com.avaje.ebean.config.CurrentTenantProvider;
import java.util.function.Supplier;
/**
* Manages the bean and query caches.
*/
public class DefaultServerCacheManager implements SpiCacheManager {
private final DefaultCacheHolder cacheHolder;
private final boolean localL2Caching;
/**
* Create with a cache factory and default cache options.
*/
public DefaultServerCacheManager(boolean localL2Caching, CurrentTenantProvider tenantProvider, ServerCacheFactory cacheFactory,
ServerCacheOptions beanDefault, ServerCacheOptions queryDefault) {
this.localL2Caching = localL2Caching;
this.cacheHolder = new DefaultCacheHolder(cacheFactory, beanDefault, queryDefault, tenantProvider);
}
/**
* Construct when l2 cache is disabled.
*/
public DefaultServerCacheManager() {
this(true, null, new DefaultServerCacheFactory(), new ServerCacheOptions(), new ServerCacheOptions());
}
public boolean isLocalL2Caching() {
return localL2Caching;
}
/**
* Clear all caches.
*/
public void clearAll() {
cacheHolder.clearAll();
}
public Supplier<ServerCache> getCollectionIdsCache(Class<?> beanType, String propertyName) {
return cacheHolder.getCache(beanType, name(beanType) + "." + propertyName, ServerCacheType.COLLECTION_IDS);
}
public Supplier<ServerCache> getNaturalKeyCache(Class<?> beanType) {
return cacheHolder.getCache(beanType, name(beanType), ServerCacheType.NATURAL_KEY);
}
/**
* Return the query cache for a given bean type.
*/
public Supplier<ServerCache> getQueryCache(Class<?> beanType) {
return cacheHolder.getCache(beanType, name(beanType), ServerCacheType.QUERY);
}
/**
* Return the bean cache for a given bean type.
*/
public Supplier<ServerCache> getBeanCache(Class<?> beanType) {
return cacheHolder.getCache(beanType, name(beanType), ServerCacheType.BEAN);
}
private String name(Class<?> beanType) {
return beanType.getName();
}
}
@@ -1,46 +0,0 @@
package com.avaje.ebeaninternal.server.cache;
import com.avaje.ebean.cache.ServerCache;
import java.util.function.Supplier;
/**
* The cache service for server side caching of beans and query results.
*/
public interface SpiCacheManager {
/**
* Return true if the L2 caching is local.
* <p>
* Local L2 caching means that the cache updates should occur in foreground
* rather than background processing.
* </p>
*/
boolean isLocalL2Caching();
/**
* Return the cache for mapping natural keys to id values.
*/
Supplier<ServerCache> getNaturalKeyCache(Class<?> beanType);
/**
* Return the cache for beans of a particular type.
*/
Supplier<ServerCache> getBeanCache(Class<?> beanType);
/**
* Return the cache for associated many properties of a bean type.
*/
Supplier<ServerCache> getCollectionIdsCache(Class<?> beanType, String propertyName);
/**
* Return the cache for query results of a particular type of bean.
*/
Supplier<ServerCache> getQueryCache(Class<?> beanType);
/**
* Clear all the caches.
*/
void clearAll();
}
@@ -1 +0,0 @@
package com.avaje.ebeaninternal.server.cache;
@@ -1,130 +0,0 @@
package com.avaje.ebeaninternal.server.changelog;
import com.avaje.ebean.ValuePair;
import com.avaje.ebean.event.changelog.BeanChange;
import com.avaje.ebean.event.changelog.ChangeSet;
import com.avaje.ebean.event.changelog.ChangeType;
import com.avaje.ebean.text.json.JsonContext;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import java.io.IOException;
import java.io.Writer;
import java.util.Map;
/**
* Builds JSON document for a bean change.
*/
public class ChangeJsonBuilder {
protected final JsonFactory jsonFactory = new JsonFactory();
protected final JsonContext json;
protected ChangeJsonBuilder(JsonContext json) {
this.json = json;
}
/**
* Write the bean change as JSON.
*/
public void writeBeanJson(Writer writer, BeanChange bean, ChangeSet changeSet, int position) throws IOException {
JsonGenerator generator = jsonFactory.createGenerator(writer);
writeBeanChange(generator, bean, changeSet, position);
generator.flush();
generator.close();
}
/**
* Write the bean change as JSON document containing the transaction header details.
*/
protected void writeBeanChange(JsonGenerator gen, BeanChange bean, ChangeSet changeSet, int position) throws IOException {
gen.writeStartObject();
writeBeanTransactionDetails(gen, changeSet, position);
gen.writeStringField("object", bean.getTable());
gen.writeStringField("objectId", bean.getId().toString());
gen.writeStringField("change", bean.getType().getCode());
gen.writeNumberField("eventTime", bean.getEventTime());
writeBeanValues(gen, bean);
gen.writeEndObject();
}
/**
* Denormalise by writing the transaction header details.
*/
protected void writeBeanTransactionDetails(JsonGenerator gen, ChangeSet changeSet, int position) throws IOException {
gen.writeStringField("txnId", changeSet.getTxnId());
gen.writeStringField("txnState", changeSet.getTxnState().getCode());
gen.writeNumberField("txnBatch", changeSet.getTxnBatch());
gen.writeNumberField("txnPosition", position);
String source = changeSet.getSource();
if (source != null) {
gen.writeStringField("source", source);
}
String userId = changeSet.getUserId();
if (userId != null) {
gen.writeStringField("userId", userId);
}
String userIpAddress = changeSet.getUserIpAddress();
if (userIpAddress != null) {
gen.writeStringField("userIpAddress", userIpAddress);
}
Map<String, String> userContext = changeSet.getUserContext();
if (userContext != null && !userContext.isEmpty()) {
gen.writeObjectFieldStart("userContext");
for (Map.Entry<String, String> entry : userContext.entrySet()) {
gen.writeStringField(entry.getKey(), entry.getValue());
}
gen.writeEndObject();
}
}
/**
* For insert and update write the new/old values.
*/
protected void writeBeanValues(JsonGenerator gen, BeanChange bean) throws IOException {
if (bean.getType() != ChangeType.DELETE) {
gen.writeFieldName("values");
gen.writeStartObject();
writeValuePairs(bean, gen);
gen.writeEndObject();
}
}
/**
* Write all the value pairs suppressing null values.
* <p>
* We are intentionally keeping the same new/old structure for both inserts and updates.
* </p>
*/
protected void writeValuePairs(BeanChange bean, JsonGenerator gen) throws IOException {
for (Map.Entry<String, ValuePair> entry : bean.getValues().entrySet()) {
gen.writeFieldName(entry.getKey());
gen.writeStartObject();
ValuePair value = entry.getValue();
Object newValue = value.getNewValue();
if (newValue != null) {
gen.writeFieldName("new");
json.writeScalar(gen, newValue);
}
Object oldValue = value.getOldValue();
if (oldValue != null) {
gen.writeFieldName("old");
json.writeScalar(gen, oldValue);
}
gen.writeEndObject();
}
}
}
@@ -1,42 +0,0 @@
package com.avaje.ebeaninternal.server.core;
import com.avaje.ebeaninternal.api.SpiBackgroundExecutor;
import com.avaje.ebeaninternal.server.lib.DaemonExecutorService;
import com.avaje.ebeaninternal.server.lib.DaemonScheduleThreadPool;
import java.util.concurrent.TimeUnit;
/**
* The default implementation of the BackgroundExecutor.
*/
public class DefaultBackgroundExecutor implements SpiBackgroundExecutor {
private final DaemonScheduleThreadPool schedulePool;
private final DaemonExecutorService pool;
/**
* Construct the default implementation of BackgroundExecutor.
*/
public DefaultBackgroundExecutor(int schedulePoolSize, int shutdownWaitSeconds, String namePrefix) {
this.pool = new DaemonExecutorService(shutdownWaitSeconds, namePrefix);
this.schedulePool = new DaemonScheduleThreadPool(schedulePoolSize, shutdownWaitSeconds, namePrefix + "-periodic-");
}
/**
* Execute a Runnable using a background thread.
*/
public void execute(Runnable r) {
pool.execute(r);
}
public void executePeriodically(Runnable r, long delay, TimeUnit unit) {
schedulePool.scheduleWithFixedDelay(r, delay, delay, unit);
}
public void shutdown() {
pool.shutdown();
schedulePool.shutdown();
}
}
@@ -1,27 +0,0 @@
package com.avaje.ebeaninternal.server.core;
import com.avaje.ebean.bean.CallStack;
/**
* Default CallStackFactory where the Hash function for StackTraceElement includes the line number.
*/
public class DefaultCallStackFactory implements CallStackFactory {
@Override
public CallStack createCallStack(StackTraceElement[] finalTrace) {
return new CallStack(finalTrace, finalTrace[0].hashCode(), pathHash(finalTrace));
}
/**
* Return the hash code for the path excluding the first element.
*/
private int pathHash(StackTraceElement[] callStack) {
int hc = 0;
for (int i = 1; i < callStack.length; i++) {
hc = 92821 * hc + callStack[i].hashCode();
}
return hc;
}
}
@@ -1,57 +0,0 @@
package com.avaje.ebeaninternal.server.core;
import com.avaje.ebean.meta.MetaBeanInfo;
import com.avaje.ebean.meta.MetaInfoManager;
import com.avaje.ebean.meta.MetaObjectGraphNodeStats;
import com.avaje.ebean.meta.MetaQueryPlanStatistic;
import java.util.ArrayList;
import java.util.List;
/**
* DefaultServer based implementation of MetaInfoManager.
*/
public class DefaultMetaInfoManager implements MetaInfoManager {
private final DefaultServer server;
public DefaultMetaInfoManager(DefaultServer server) {
this.server = server;
}
@Override
public MetaBeanInfo getMetaBeanInfo(Class<?> beanClass) {
return server.getBeanDescriptor(beanClass);
}
@Override
public List<MetaBeanInfo> getMetaBeanInfoList() {
return new ArrayList<>(server.getBeanDescriptors());
}
@Override
public List<MetaQueryPlanStatistic> collectQueryPlanStatistics(boolean reset) {
List<MetaQueryPlanStatistic> list = new ArrayList<>();
for (MetaBeanInfo metaBeanInfo : getMetaBeanInfoList()) {
list.addAll(metaBeanInfo.collectQueryPlanStatistics(reset));
}
return list;
}
public List<MetaObjectGraphNodeStats> collectNodeStatistics(boolean reset) {
List<MetaObjectGraphNodeStats> list = new ArrayList<>();
for (CObjectGraphNodeStatistics nodeStatistics : server.objectGraphStats.values()) {
MetaObjectGraphNodeStats nodeStats = nodeStatistics.get(reset);
if (nodeStats.getCount() > 0) {
// Only collection non-empty statistics
list.add(nodeStats);
}
}
return list;
}
}
@@ -1,104 +0,0 @@
package com.avaje.ebeaninternal.server.core;
import com.avaje.ebean.ValuePair;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Helper to perform a diff given two beans of the same type.
* <p>
* This intentionally does not include any OneToMany or ManyToMany properties.
* </p>
*/
public class DiffHelp {
private DiffHelp() {
}
/**
* Return a map of the differences between a and b.
* <p>
* A and B must be of the same type. B can be null, in which case the 'dirty
* values' of a is returned.
* </p>
* <p>
* This intentionally does not include as OneToMany or ManyToMany properties.
* </p>
*/
public static Map<String, ValuePair> diff(Object newBean, Object oldBean, BeanDescriptor<?> desc) {
if (!(newBean instanceof EntityBean)) {
throw new IllegalArgumentException("First bean expected to be an enhanced EntityBean? bean:" + newBean);
}
if (oldBean != null) {
if (!(oldBean instanceof EntityBean)) {
throw new IllegalArgumentException("Second bean expected to be an enhanced EntityBean? bean:" + oldBean);
}
if (!newBean.getClass().isAssignableFrom(oldBean.getClass())) {
throw new IllegalArgumentException("Second bean not assignable to the first bean?");
}
}
if (oldBean == null) {
return ((EntityBean) newBean)._ebean_getIntercept().getDirtyValues();
}
return desc.diff((EntityBean) newBean, (EntityBean) oldBean);
}
/**
* Flattens an existing diff map converting assoc one beans into the associated id changes.
*/
public static Map<String, ValuePair> flatten(Map<String, ValuePair> values, BeanDescriptor<?> desc) {
Map<String, ValuePair> flattened = null;
Iterator<Map.Entry<String, ValuePair>> iterator = values.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, ValuePair> entry = iterator.next();
BeanProperty beanProperty = desc.getBeanProperty(entry.getKey());
if (beanProperty instanceof BeanPropertyAssocMany) {
// filter out assoc many bean properties
iterator.remove();
} else if (beanProperty instanceof BeanPropertyAssocOne) {
BeanPropertyAssocOne<?> assoc = (BeanPropertyAssocOne<?>) beanProperty;
if (!assoc.isEmbedded()) {
// flatten for assoc one beans
if (flattened == null) {
flattened = new LinkedHashMap<>();
}
flattenToId(flattened, entry, beanProperty, assoc);
iterator.remove();
}
}
}
if (flattened != null) {
values.putAll(flattened);
}
return values;
}
private static void flattenToId(Map<String, ValuePair> flattened, Map.Entry<String, ValuePair> entry, BeanProperty beanProperty, BeanPropertyAssocOne<?> assoc) {
BeanDescriptor<?> oneDesc = assoc.getTargetDescriptor();
ValuePair value = entry.getValue();
Object newId = value.getNewValue() == null ? null : oneDesc.getId((EntityBean) value.getNewValue());
Object oldId = value.getOldValue() == null ? null : oneDesc.getId((EntityBean) value.getOldValue());
String propName = beanProperty.getName() + "." + oneDesc.getIdProperty().getName();
flattened.put(propName, new ValuePair(newId, oldId));
}
}
@@ -1,104 +0,0 @@
package com.avaje.ebeaninternal.server.core;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.api.SpiTransaction;
import com.avaje.ebeaninternal.server.persist.BatchControl;
import com.avaje.ebeaninternal.server.persist.BatchPostExecute;
import com.avaje.ebeaninternal.server.persist.PersistExecute;
/**
* Wraps all the objects used to persist a bean.
*/
public abstract class PersistRequest extends BeanRequest implements BatchPostExecute {
public enum Type {
INSERT, UPDATE, DELETE, SOFT_DELETE, DELETE_PERMANENT, UPDATESQL, CALLABLESQL
}
protected boolean persistCascade;
/**
* One of INSERT, UPDATE, DELETE, UPDATESQL or CALLABLESQL.
*/
protected Type type;
protected final PersistExecute persistExecute;
/**
* Used by CallableSqlRequest and UpdateSqlRequest.
*/
public PersistRequest(SpiEbeanServer server, SpiTransaction t, PersistExecute persistExecute) {
super(server, t);
this.persistExecute = persistExecute;
}
/**
* Execute a the request or queue/batch it for later execution.
*/
public abstract int executeOrQueue();
/**
* Execute the request right now.
*/
public abstract int executeNow();
public boolean isLogSql() {
return transaction.isLogSql();
}
public boolean isLogSummary() {
return transaction.isLogSummary();
}
/**
* Return true if this persist request should use JDBC batch.
*/
public boolean isBatchThisRequest() {
return transaction.isBatchThisRequest(type);
}
/**
* Execute the statement.
*/
public int executeStatement() {
boolean batch = isBatchThisRequest();
int rows;
BatchControl control = transaction.getBatchControl();
if (control != null) {
rows = control.executeStatementOrBatch(this, batch);
} else if (batch) {
// need to create the BatchControl
control = persistExecute.createBatchControl(transaction);
rows = control.executeStatementOrBatch(this, true);
} else {
rows = executeNow();
}
return rows;
}
public void initTransIfRequired() {
createImplicitTransIfRequired();
persistCascade = transaction.isPersistCascade();
}
/**
* Return the type of this request. One of INSERT, UPDATE, DELETE, UPDATESQL
* or CALLABLESQL.
*/
public Type getType() {
return type;
}
/**
* Return true if save and delete should cascade.
*/
public boolean isPersistCascade() {
return persistCascade;
}
}
@@ -1,30 +0,0 @@
package com.avaje.ebeaninternal.server.core;
import com.avaje.ebeaninternal.server.transaction.DataSourceSupplier;
import org.avaje.datasource.DataSourcePool;
import javax.sql.DataSource;
/**
* Simple DataSource supplier when no multi-tenancy used.
*/
class SimpleDataSourceProvider implements DataSourceSupplier {
private final DataSource dataSource;
SimpleDataSourceProvider(DataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public DataSource getDataSource() {
return dataSource;
}
@Override
public void shutdown(boolean deregisterDriver) {
if (dataSource instanceof DataSourcePool){
((DataSourcePool) dataSource).shutdown(deregisterDriver);
}
}
}
@@ -1,56 +0,0 @@
package com.avaje.ebeaninternal.server.core;
import com.avaje.ebeaninternal.api.SpiTransaction;
/**
* Used to temporarily wrap a thread local based transaction.
* <p>
* Additionally notes if the transaction was created by the request in which
* case it needs to be commited after the request has been processed.
* </p>
*/
final class TransWrapper {
final SpiTransaction transaction;
private final boolean wasCreated;
/**
* Wrap the transaction indicating if it was just created.
*/
TransWrapper(SpiTransaction t, boolean created) {
transaction = t;
wasCreated = created;
}
void batchEscalateOnCollection() {
transaction.checkBatchEscalationOnCollection();
}
void flushBatchOnCollection() {
if (!wasCreated) {
transaction.flushBatchOnCollection();
}
}
void commitIfCreated() {
if (wasCreated) {
transaction.commit();
}
}
void rollbackIfCreated() {
if (wasCreated) {
transaction.rollbackIfActive();
}
}
/**
* Return true if the transaction was just created. If true it should be
* committed after the request has been processed.
*/
boolean wasCreated() {
return wasCreated;
}
}
@@ -1,175 +0,0 @@
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebean.text.json.EJson;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyCompound;
import com.avaje.ebeaninternal.server.el.ElPropertyChainBuilder;
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
import com.avaje.ebeaninternal.server.query.SqlBeanLoad;
import com.avaje.ebeaninternal.server.text.json.ReadJson;
import com.avaje.ebeaninternal.server.text.json.WriteJson;
import com.avaje.ebeaninternal.server.type.CtCompoundProperty;
import com.avaje.ebeaninternal.server.type.CtCompoundPropertyElAdapter;
import com.avaje.ebeaninternal.server.type.CtCompoundType;
import java.io.IOException;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Property mapped to an Immutable Compound Value Object.
* <p>
* An Immutable Compound Value Object is similar to an Embedded bean but it
* doesn't require enhancement and MUST be treated as an Immutable type.
* </p>
*/
public class BeanPropertyCompound extends BeanProperty {
private final CtCompoundType<?> compoundType;
private final BeanProperty[] scalarProperties;
private final LinkedHashMap<String, BeanProperty> propertyMap = new LinkedHashMap<>();
private final LinkedHashMap<String, CtCompoundPropertyElAdapter> nonScalarMap = new LinkedHashMap<>();
/**
* Create the property.
*/
public BeanPropertyCompound(BeanDescriptor<?> descriptor, DeployBeanPropertyCompound deploy) {
super(descriptor, deploy);
this.compoundType = deploy.getCompoundType();
BeanPropertyCompoundRoot root = deploy.getFlatProperties();
this.scalarProperties = root.getScalarProperties();
for (BeanProperty scalarProperty : scalarProperties) {
propertyMap.put(scalarProperty.getName(), scalarProperty);
}
List<CtCompoundProperty> nonScalarPropsList = root.getNonScalarProperties();
for (CtCompoundProperty ctProp : nonScalarPropsList) {
CtCompoundPropertyElAdapter adapter = new CtCompoundPropertyElAdapter(ctProp);
nonScalarMap.put(ctProp.getRelativeName(), adapter);
}
}
@Override
public void initialise() {
// do nothing for normal BeanProperty
if (!isTransient && compoundType == null) {
String msg = "No cvoInternalType assigned to " + descriptor.getFullName() + "." + getName();
throw new RuntimeException(msg);
}
}
@Override
public void setDeployOrder(int deployOrder) {
this.deployOrder = deployOrder;
for (CtCompoundPropertyElAdapter adapter : nonScalarMap.values()) {
adapter.setDeployOrder(deployOrder);
}
}
public ElPropertyValue buildElPropertyValue(String propName, String remainder, ElPropertyChainBuilder chain, boolean propertyDeploy) {
if (chain == null) {
chain = new ElPropertyChainBuilder(true, propName);
}
// first add this property
chain.add(this);
// handle all the rest of the chain handled by the
// BeanProperty (all depth for nested compound type)
BeanProperty p = propertyMap.get(remainder);
if (p != null) {
return chain.add(p).build();
}
CtCompoundPropertyElAdapter elAdapter = nonScalarMap.get(remainder);
if (elAdapter == null) {
throw new RuntimeException("property [" + remainder + "] not found in " + getFullBeanName());
}
return chain.add(elAdapter).build();
}
@Override
public void appendSelect(DbSqlContext ctx, boolean subQuery) {
if (!isTransient) {
for (BeanProperty scalarProperty : scalarProperties) {
scalarProperty.appendSelect(ctx, subQuery);
}
}
}
public BeanProperty[] getScalarProperties() {
return scalarProperties;
}
@Override
public Object readSet(DbReadContext ctx, EntityBean bean) throws SQLException {
Object v = compoundType.read(ctx.getDataReader());
setValue(bean, v);
return v;
}
/**
* Read the data from the resultSet effectively ignoring it and returning
* null.
*/
@Override
public Object read(DbReadContext ctx) throws SQLException {
return compoundType.read(ctx.getDataReader());
}
@Override
public void loadIgnore(DbReadContext ctx) {
compoundType.loadIgnore(ctx.getDataReader());
}
@Override
public void load(SqlBeanLoad sqlBeanLoad) {
sqlBeanLoad.load(this);
}
@Override
public Object pathGetNested(Object bean) {
return bean;
}
public void jsonWrite(WriteJson ctx, EntityBean bean) throws IOException {
if (!jsonSerialize) {
return;
}
Object value = getValueIntercept(bean);
if (value == null) {
ctx.writeNullField(name);
} else {
ctx.writeFieldName(name);
compoundType.jsonWrite(ctx, value, name);
}
}
@Override
public void jsonRead(ReadJson readJson, EntityBean bean) throws IOException {
if (!jsonDeserialize) {
return;
}
Map<String, Object> map = EJson.parseObject(readJson.getParser());
if (map == null) {
setValue(bean, null);
} else {
Object objValue = compoundType.jsonConvert(map);
setValue(bean, objValue);
}
}
}
@@ -1,80 +0,0 @@
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.properties.BeanPropertySetter;
import com.avaje.ebeaninternal.server.type.CtCompoundProperty;
import java.util.ArrayList;
import java.util.List;
/**
* Represents the root BeanProperty for properties of a compound type.
* <p>
* Holds all the scalar and non-scalar properties of the compound type. The
* scalar properties match to DB columns and the non-scalar ones are here solely
* to support EL expression language for nested compound types.
* </p>
*/
public class BeanPropertyCompoundRoot {
private final BeanPropertySetter setter;
private final String name;
private final String fullBeanName;
private final ArrayList<BeanPropertyCompoundScalar> propList;
private List<CtCompoundProperty> nonScalarProperties;
public BeanPropertyCompoundRoot(DeployBeanProperty deploy) {
this.fullBeanName = deploy.getFullBeanName();
this.name = deploy.getName();
this.setter = deploy.getSetter();
this.propList = new ArrayList<>();
}
public BeanProperty[] getScalarProperties() {
return propList.toArray(new BeanProperty[propList.size()]);
}
public void register(BeanPropertyCompoundScalar prop) {
propList.add(prop);
}
public List<CtCompoundProperty> getNonScalarProperties() {
return nonScalarProperties;
}
public void setNonScalarProperties(List<CtCompoundProperty> nonScalarProperties) {
this.nonScalarProperties = nonScalarProperties;
}
/**
* Set the value of the property without interception or
* PropertyChangeSupport.
*/
public void setRootValue(EntityBean bean, Object value) {
try {
setter.set(bean, value);
} catch (Exception ex) {
String beanType = bean == null ? "null" : bean.getClass().getName();
String msg = "set " + name + " with arg[" + value + "] on [" + fullBeanName + "] with type[" + beanType + "] threw error";
throw new RuntimeException(msg, ex);
}
}
/**
* Set the value of the property.
*/
public void setRootValueIntercept(EntityBean bean, Object value) {
try {
setter.setIntercept(bean, value);
} catch (Exception ex) {
String beanType = bean == null ? "null" : bean.getClass().getName();
String msg = "setIntercept " + name + " arg[" + value + "] on [" + fullBeanName + "] with type[" + beanType + "] threw error";
throw new RuntimeException(msg, ex);
}
}
}
@@ -1,81 +0,0 @@
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.type.CtCompoundProperty;
/**
* A BeanProperty owned by a Compound value object that maps to
* a real scalar type.
*/
public class BeanPropertyCompoundScalar extends BeanProperty {
private final BeanPropertyCompoundRoot rootProperty;
private final CtCompoundProperty ctProperty;
public BeanPropertyCompoundScalar(BeanPropertyCompoundRoot rootProperty, DeployBeanProperty scalarDeploy, CtCompoundProperty ctProperty) {
super(scalarDeploy);
this.rootProperty = rootProperty;
this.ctProperty = ctProperty;
}
/**
* Return one of the scalar values from a compound type.
*/
public Object getValueObject(Object compoundValue) {
return ctProperty.getValue(compoundValue);
}
@Override
public Object getValue(EntityBean valueObject) {
return ctProperty.getValue(valueObject);
}
@Override
public void setValue(EntityBean bean, Object value) {
setValueInCompound(bean, value, false);
}
public void setValueInCompound(EntityBean bean, Object value, boolean intercept) {
Object compoundValue = ctProperty.setValue(bean, value);
if (compoundValue != null) {
// we are at the top level and we have a compound value
// that we can set using the root property
if (intercept) {
rootProperty.setRootValueIntercept(bean, compoundValue);
} else {
rootProperty.setRootValue(bean, compoundValue);
}
}
}
/**
* No interception on embedded scalar values inside a CVO.
*/
@Override
public void setValueIntercept(EntityBean bean, Object value) {
setValueInCompound(bean, value, true);
}
/**
* No interception on embedded scalar values inside a CVO.
*/
@Override
public Object getValueIntercept(EntityBean bean) {
return getValue(bean);
}
@Override
public Object pathGetNested(Object bean) {
return pathGet(bean);
}
@Override
public Object pathGet(Object bean) {
return ctProperty.getValue(bean);
}
}
@@ -1,121 +0,0 @@
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebeaninternal.server.core.InternString;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanTable;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoinColumn;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Used for associated beans in place of a BeanDescriptor. This is done to avoid
* recursion issues due to the potentially bi-directional and circular
* relationships between beans.
* <p>
* It holds the main deployment information and not all the detail that is held
* in a BeanDescriptor.
* </p>
*/
public class BeanTable {
private static final Logger logger = LoggerFactory.getLogger(BeanTable.class);
private final Class<?> beanType;
/**
* The base table.
*/
private final String baseTable;
private final BeanProperty[] idProperties;
/**
* Create the BeanTable.
*/
public BeanTable(DeployBeanTable mutable, BeanDescriptorMap owner) {
this.beanType = mutable.getBeanType();
this.baseTable = InternString.intern(mutable.getBaseTable());
this.idProperties = mutable.createIdProperties(owner);
}
public String toString(){
return baseTable;
}
/**
* Return the base table for this BeanTable.
* This is used to determine the join information
* for associations.
*/
public String getBaseTable() {
return baseTable;
}
/**
* Gets the unqualified base table.
*
* @return the unqualified base table
*/
public String getUnqualifiedBaseTable(){
final String[] chunks = baseTable.split("\\.");
return chunks.length == 2 ? chunks[1] :chunks[0];
}
/**
* Return the Id properties.
*/
public BeanProperty[] getIdProperties() {
return idProperties;
}
/**
* Return the class for this beanTable.
*/
public Class<?> getBeanType() {
return beanType;
}
public void createJoinColumn(String foreignKeyPrefix, DeployTableJoin join, boolean reverse, String sqlFormulaSelect) {
boolean complexKey = false;
BeanProperty[] props = idProperties;
if (idProperties.length == 1){
if (idProperties[0] instanceof BeanPropertyAssocOne<?>) {
BeanPropertyAssocOne<?> assocOne = (BeanPropertyAssocOne<?>)idProperties[0];
props = assocOne.getProperties();
complexKey = true;
}
}
for (BeanProperty prop : props) {
String lc = prop.getDbColumn();
String fk = lc;
if (foreignKeyPrefix != null) {
fk = foreignKeyPrefix + "_" + fk;
}
if (complexKey) {
// just to copy the column name rather than prefix with the foreignKeyPrefix.
// I think that with complex keys this is the more common approach.
String msg = "On table[" + baseTable + "] foreign key column [" + lc + "]";
logger.debug(msg);
fk = lc;
}
if (sqlFormulaSelect != null) {
fk = sqlFormulaSelect;
}
DeployTableJoinColumn joinCol = new DeployTableJoinColumn(lc, fk);
joinCol.setForeignSqlFormula(sqlFormulaSelect);
if (reverse) {
joinCol = joinCol.reverse();
}
join.addJoinColumn(joinCol);
}
}
}
@@ -1,185 +0,0 @@
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.event.BeanPersistController;
import com.avaje.ebean.event.BeanPersistRequest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
/**
* Chains multiple BeanPersistController's together.
*
* Used when multiple BeanPersistController register for the same bean type.
*/
public class ChainedBeanPersistController implements BeanPersistController {
private static final Sorter SORTER = new Sorter();
private final List<BeanPersistController> list;
private final BeanPersistController[] chain;
/**
* Construct adding 2 BeanPersistController's.
*/
public ChainedBeanPersistController(BeanPersistController c1, BeanPersistController c2) {
this(addList(c1, c2));
}
/**
* Helper method used to create a list from 2 BeanPersistController's.
*/
private static List<BeanPersistController> addList(BeanPersistController c1, BeanPersistController c2) {
ArrayList<BeanPersistController> addList = new ArrayList<>(2);
addList.add(c1);
addList.add(c2);
return addList;
}
/**
* Construct given the list of BeanPersistController's.
*/
public ChainedBeanPersistController(List<BeanPersistController> list) {
this.list = list;
BeanPersistController[] c = list.toArray(new BeanPersistController[list.size()]);
Arrays.sort(c, SORTER);
this.chain = c;
}
/**
* Return the size of the chain.
*/
protected int size() {
return chain.length;
}
/**
* Register a new BeanPersistController and return the resulting chain.
*/
public ChainedBeanPersistController register(BeanPersistController c) {
if (list.contains(c)){
return this;
} else {
ArrayList<BeanPersistController> newList = new ArrayList<>();
newList.addAll(list);
newList.add(c);
return new ChainedBeanPersistController(newList);
}
}
/**
* De-register a BeanPersistController and return the resulting chain.
*/
public ChainedBeanPersistController deregister(BeanPersistController c) {
if (!list.contains(c)){
return this;
} else {
ArrayList<BeanPersistController> newList = new ArrayList<>();
newList.addAll(list);
newList.remove(c);
return new ChainedBeanPersistController(newList);
}
}
/**
* Always returns 0 (not used for this object).
*/
@Override
public int getExecutionOrder() {
return 0;
}
/**
* Always returns false (not used for this object).
*/
@Override
public boolean isRegisterFor(Class<?> cls) {
return false;
}
@Override
public void postDelete(BeanPersistRequest<?> request) {
for (BeanPersistController aChain : chain) {
aChain.postDelete(request);
}
}
@Override
public void postInsert(BeanPersistRequest<?> request) {
for (BeanPersistController aChain : chain) {
aChain.postInsert(request);
}
}
@Override
public void postUpdate(BeanPersistRequest<?> request) {
for (BeanPersistController aChain : chain) {
aChain.postUpdate(request);
}
}
@Override
public void postSoftDelete(BeanPersistRequest<?> request) {
for (BeanPersistController aChain : chain) {
aChain.postSoftDelete(request);
}
}
@Override
public boolean preDelete(BeanPersistRequest<?> request) {
for (BeanPersistController aChain : chain) {
if (!aChain.preDelete(request)) {
return false;
}
}
return true;
}
@Override
public boolean preSoftDelete(BeanPersistRequest<?> request) {
for (BeanPersistController aChain : chain) {
if (!aChain.preSoftDelete(request)) {
return false;
}
}
return true;
}
@Override
public boolean preInsert(BeanPersistRequest<?> request) {
for (BeanPersistController aChain : chain) {
if (!aChain.preInsert(request)) {
return false;
}
}
return true;
}
@Override
public boolean preUpdate(BeanPersistRequest<?> request) {
for (BeanPersistController aChain : chain) {
if (!aChain.preUpdate(request)) {
return false;
}
}
return true;
}
/**
* Helper to order the BeanPersistController's in a chain.
*/
private static class Sorter implements Comparator<BeanPersistController> {
public int compare(BeanPersistController o1, BeanPersistController o2) {
int i1 = o1.getExecutionOrder() ;
int i2 = o2.getExecutionOrder() ;
return (i1<i2 ? -1 : (i1==i2 ? 0 : 1));
}
}
}
@@ -1,109 +0,0 @@
package com.avaje.ebeaninternal.server.deploy;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import com.avaje.ebean.event.BeanPersistListener;
/**
* Handles multiple BeanPersistListener's for a given entity type.
*/
public class ChainedBeanPersistListener implements BeanPersistListener {
private final List<BeanPersistListener> list;
private final BeanPersistListener[] chain;
/**
* Construct adding 2 BeanPersistListener's.
*/
ChainedBeanPersistListener(BeanPersistListener c1, BeanPersistListener c2) {
this(addList(c1, c2));
}
/**
* Return the size of the chain.
*/
protected int size() {
return chain.length;
}
@Override
public boolean isRegisterFor(Class<?> cls) {
// never called
return false;
}
/**
* Helper method used to create a list from 2 BeanPersistListener.
*/
private static List<BeanPersistListener> addList(BeanPersistListener c1, BeanPersistListener c2) {
ArrayList<BeanPersistListener> addList = new ArrayList<>(2);
addList.add(c1);
addList.add(c2);
return addList;
}
/**
* Construct given the list of BeanPersistListener's.
*/
public ChainedBeanPersistListener(List<BeanPersistListener> list) {
this.list = list;
this.chain = list.toArray(new BeanPersistListener[list.size()]);
}
/**
* Register a new BeanPersistListener and return the resulting chain.
*/
public ChainedBeanPersistListener register(BeanPersistListener c) {
if (list.contains(c)){
return this;
} else {
List<BeanPersistListener> newList = new ArrayList<>();
newList.addAll(list);
newList.add(c);
return new ChainedBeanPersistListener(newList);
}
}
/**
* De-register a BeanPersistListener and return the resulting chain.
*/
public ChainedBeanPersistListener deregister(BeanPersistListener c) {
if (!list.contains(c)){
return this;
} else {
ArrayList<BeanPersistListener> newList = new ArrayList<>();
newList.addAll(list);
newList.remove(c);
return new ChainedBeanPersistListener(newList);
}
}
public void deleted(Object bean) {
for (BeanPersistListener aChain : chain) {
aChain.deleted(bean);
}
}
public void softDeleted(Object bean) {
for (BeanPersistListener aChain : chain) {
aChain.softDeleted(bean);
}
}
public void inserted(Object bean) {
for (BeanPersistListener aChain : chain) {
aChain.inserted(bean);
}
}
public void updated(Object bean, Set<String> updatedProperties) {
for (BeanPersistListener aChain : chain) {
aChain.updated(bean, updatedProperties);
}
}
}
@@ -1,77 +0,0 @@
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.event.BeanPostLoad;
import java.util.ArrayList;
import java.util.List;
/**
* Handles multiple BeanPostLoad's for a given entity type.
*/
public class ChainedBeanPostLoad implements BeanPostLoad {
private final List<BeanPostLoad> list;
private final BeanPostLoad[] chain;
/**
* Construct given the list of BeanPostLoad's.
*/
public ChainedBeanPostLoad(List<BeanPostLoad> list) {
this.list = list;
this.chain = list.toArray(new BeanPostLoad[list.size()]);
}
/**
* Register a new BeanPostLoad and return the resulting chain.
*/
public ChainedBeanPostLoad register(BeanPostLoad c) {
if (list.contains(c)){
return this;
} else {
List<BeanPostLoad> newList = new ArrayList<>();
newList.addAll(list);
newList.add(c);
return new ChainedBeanPostLoad(newList);
}
}
/**
* De-register a BeanPostLoad and return the resulting chain.
*/
public ChainedBeanPostLoad deregister(BeanPostLoad c) {
if (!list.contains(c)){
return this;
} else {
ArrayList<BeanPostLoad> newList = new ArrayList<>();
newList.addAll(list);
newList.remove(c);
return new ChainedBeanPostLoad(newList);
}
}
/**
* Return the size of the chain.
*/
protected int size() {
return chain.length;
}
@Override
public boolean isRegisterFor(Class<?> cls) {
// never called
return false;
}
/**
* Fire postLoad on all registered BeanPostLoad implementations.
*/
@Override
public void postLoad(Object bean) {
for (BeanPostLoad aChain : chain) {
aChain.postLoad(bean);
}
}
}
@@ -1,96 +0,0 @@
package com.avaje.ebeaninternal.server.deploy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import com.avaje.ebean.event.BeanQueryAdapter;
import com.avaje.ebean.event.BeanQueryRequest;
/**
* Handles multiple BeanQueryAdapter for a given entity type.
*/
public class ChainedBeanQueryAdapter implements BeanQueryAdapter {
private static final Sorter SORTER = new Sorter();
private final List<BeanQueryAdapter> list;
private final BeanQueryAdapter[] chain;
/**
* Construct given the list of BeanQueryAdapter's.
*/
public ChainedBeanQueryAdapter(List<BeanQueryAdapter> list) {
this.list = list;
BeanQueryAdapter[] c = list.toArray(new BeanQueryAdapter[list.size()]);
Arrays.sort(c, SORTER);
this.chain = c;
}
/**
* Register a new BeanQueryAdapter and return the resulting chain.
*/
public ChainedBeanQueryAdapter register(BeanQueryAdapter c) {
if (list.contains(c)){
return this;
} else {
List<BeanQueryAdapter> newList = new ArrayList<>();
newList.addAll(list);
newList.add(c);
return new ChainedBeanQueryAdapter(newList);
}
}
/**
* De-register a BeanQueryAdapter and return the resulting chain.
*/
public ChainedBeanQueryAdapter deregister(BeanQueryAdapter c) {
if (!list.contains(c)){
return this;
} else {
ArrayList<BeanQueryAdapter> newList = new ArrayList<>();
newList.addAll(list);
newList.remove(c);
return new ChainedBeanQueryAdapter(newList);
}
}
/**
* Return 0 as not used by this Chained adapter.
*/
public int getExecutionOrder() {
return 0;
}
/**
* Return false as only individual adapters are registered.
*/
public boolean isRegisterFor(Class<?> cls) {
return false;
}
public void preQuery(BeanQueryRequest<?> request) {
for (BeanQueryAdapter aChain : chain) {
aChain.preQuery(request);
}
}
/**
* Helper to order the BeanQueryAdapter's in a chain.
*/
private static class Sorter implements Comparator<BeanQueryAdapter> {
public int compare(BeanQueryAdapter o1, BeanQueryAdapter o2) {
int i1 = o1.getExecutionOrder() ;
int i2 = o2.getExecutionOrder() ;
return (i1<i2 ? -1 : (i1==i2 ? 0 : 1));
}
}
}
@@ -1,170 +0,0 @@
package com.avaje.ebeaninternal.server.deploy;
import java.util.Set;
/**
* Converts logical property names to database columns.
*/
public abstract class DeployParser {
/**
* used to identify sql literal.
*/
protected static final char SINGLE_QUOTE = '\'';
/**
* used to identify query named parameters.
*/
protected static final char COLON = ':';
/**
* Used to determine when a column name terminates.
*/
protected static final char UNDERSCORE = '_';
/**
* Used to determine when a column name terminates.
*/
protected static final char PERIOD = '.';
protected boolean encrypted;
protected String source;
protected StringBuilder sb;
protected int sourceLength;
protected int pos;
protected String word;
protected char wordTerminator;
protected abstract String convertWord();
public abstract String getDeployWord(String expression);
/**
* Return the join includes.
*/
public abstract Set<String> getIncludes();
public void setEncrypted(boolean encrypted) {
this.encrypted = encrypted;
}
public String parse(String source) {
if (source == null) {
return null;
}
pos = -1;
this.source = source;
this.sourceLength = source.length();
this.sb = new StringBuilder(source.length() + 20);
while (nextWord()) {
String deployWord = convertWord();
sb.append(deployWord);
if (pos < sourceLength) {
sb.append(wordTerminator);
if (wordTerminator == SINGLE_QUOTE) {
readLiteral();
}
}
}
return sb.toString();
}
private boolean nextWord() {
if (!findWordStart()) {
return false;
}
StringBuilder wordBuffer = new StringBuilder();
wordBuffer.append(source.charAt(pos));
while (++pos < sourceLength) {
char ch = source.charAt(pos);
if (isWordPart(ch)) {
wordBuffer.append(ch);
} else {
wordTerminator = ch;
break;
}
}
word = wordBuffer.toString();
return true;
}
private boolean findWordStart() {
while (++pos < sourceLength) {
char ch = source.charAt(pos);
if (ch == SINGLE_QUOTE) {
// read a literal value and just
// append to string builder
sb.append(ch);
readLiteral();
} else if (ch == COLON) {
// read a named parameter
// just append to string builder
sb.append(ch);
readNamedParameter();
} else if (isWordStart(ch)) {
// its the start of a word that could
// be translated
return true;
} else {
sb.append(ch);
}
}
return false;
}
/**
* Read the rest of a literal value. These do not get translated so are just
* read and appended to the string builder.
*/
private void readLiteral() {
while (++pos < sourceLength) {
char ch = source.charAt(pos);
sb.append(ch);
if (ch == SINGLE_QUOTE) {
break;
}
}
}
/**
* Read a named parameter. These are not translated. They will be replaced
* by positioned parameters later.
*/
private void readNamedParameter() {
while (++pos < sourceLength) {
char ch = source.charAt(pos);
sb.append(ch);
if (Character.isWhitespace(ch)) {
break;
} else if (ch == ',') {
break;
}
}
}
/**
* return true if the char is a letter, digit or underscore.
*/
private boolean isWordPart(char ch) {
return Character.isLetterOrDigit(ch) || ch == UNDERSCORE || ch == PERIOD;
}
private boolean isWordStart(char ch) {
return Character.isLetter(ch);
}
}
@@ -1,52 +0,0 @@
package com.avaje.ebeaninternal.server.deploy;
import java.util.HashSet;
import java.util.Set;
import com.avaje.ebeaninternal.server.el.ElPropertyDeploy;
/**
* Converts logical property names to database columns with table alias.
* <p>
* In doing so it builds an 'includes' set which becomes the joins required to
* support the properties parsed.
* </p>
*/
public final class DeployPropertyParser extends DeployParser {
private final BeanDescriptor<?> beanDescriptor;
private final Set<String> includes = new HashSet<>();
public DeployPropertyParser(BeanDescriptor<?> beanDescriptor) {
this.beanDescriptor = beanDescriptor;
}
public Set<String> getIncludes() {
return includes;
}
@Override
public String getDeployWord(String expression) {
ElPropertyDeploy elProp = beanDescriptor.getElPropertyDeploy(expression);
if (elProp == null){
return null;
} else {
addIncludes(elProp.getElPrefix());
return elProp.getElPlaceholder(encrypted);
}
}
@Override
public String convertWord() {
String r = getDeployWord(word);
return r == null ? word : r;
}
private void addIncludes(String prefix) {
if (prefix != null){
includes.add(prefix);
}
}
}
@@ -1,90 +0,0 @@
package com.avaje.ebeaninternal.server.deploy;
import java.util.Set;
import com.avaje.ebeaninternal.server.el.ElPropertyDeploy;
/**
* For updates converts logical property names to database columns and bean type to base table.
*/
public final class DeployUpdateParser extends DeployParser {
private final BeanDescriptor<?> beanDescriptor;
public DeployUpdateParser(BeanDescriptor<?> beanDescriptor) {
this.beanDescriptor = beanDescriptor;
}
/**
* Return null as not used for updates.
*/
@Override
public Set<String> getIncludes() {
return null;
}
public String convertWord() {
String dbWord = getDeployWord(word);
if (dbWord != null) {
return dbWord;
}
// maybe tableAlias.propertyName
return convertSubword(0, word, null);
}
private String convertSubword(int start, String currentWord, StringBuilder localBuffer) {
int dotPos = currentWord.indexOf('.', start);
if (start == 0 && dotPos == -1){
return currentWord;
}
if (start == 0){
localBuffer = new StringBuilder();
}
if (dotPos == -1){
// no match...
localBuffer.append(currentWord.substring(start));
return localBuffer.toString();
}
// append up to the dot
localBuffer.append(currentWord.substring(start, dotPos+1));
if (dotPos == currentWord.length()-1){
// ends with a "." ???
return localBuffer.toString();
}
// get the remainder after the dot
start = dotPos+1;
String remainder = currentWord.substring(start, currentWord.length());
//String dbWord = deployMap.get(remainder.toLowerCase());
String dbWord = getDeployWord(remainder);
if (dbWord != null){
// we have found a match for the remainder
localBuffer.append(dbWord);
return localBuffer.toString();
} else {
//
return convertSubword(start, currentWord, localBuffer);
}
}
public String getDeployWord(String expression) {
if (expression.equalsIgnoreCase(beanDescriptor.getName())){
return beanDescriptor.getBaseTable();
}
ElPropertyDeploy elProp = beanDescriptor.getElPropertyDeploy(expression);
if (elProp != null){
return elProp.getDbColumn();
} else {
return null;
}
}
}
@@ -1,13 +0,0 @@
package com.avaje.ebeaninternal.server.deploy;
/**
* Used to visit all the InheritInfo in a single inheritance hierarchy.
*/
public interface InheritInfoVisitor {
/**
* visit the InheritInfo for this node.
*/
void visit(InheritInfo inheritInfo);
}
@@ -1,78 +0,0 @@
package com.avaje.ebeaninternal.server.deploy;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* Helper object to find generic parameter types for a given class.
*/
public class ParamTypeUtil {
/**
* Find and return the parameter type given a generic interface or class.
* <p>
* This assumes there is only one generic parameter.
* </p>
* <p>
* Returns null if no match was found.
* </p>
* @param cls the class to search for the parameter type
* @param matchType the type which has the generic parameter
*/
public static Class<?> findParamType(Class<?> cls, Class<?> matchType) {
// search for: implementing a generic interface
Type paramType = matchByInterfaces(cls, matchType);
if (paramType == null){
// search for: extending a generic class
Type genericSuperclass = cls.getGenericSuperclass();
if (genericSuperclass != null){
paramType = matchParamType(genericSuperclass, matchType);
}
}
if (paramType instanceof Class<?>){
// only interested in classes
return (Class<?>)paramType;
} else {
return null;
}
}
/**
* Check if the type is a generic one with parameters and of the correct type we are
* searching for. Return the parameter type if this matches otherwise return null.
*/
private static Type matchParamType(Type type, Class<?> matchType) {
if (type instanceof ParameterizedType){
ParameterizedType pt = (ParameterizedType)type;
Type rawType = pt.getRawType();
boolean isAssignable = matchType.isAssignableFrom((Class<?>) rawType);
if (isAssignable) {
// assume there is only one parameter type
Type[] typeArguments = pt.getActualTypeArguments();
if (typeArguments.length != 1){
String m = "Expecting only 1 generic paramater but got "+typeArguments.length+" for "+type;
throw new RuntimeException(m);
}
return typeArguments[0];
}
}
return null;
}
/**
* Search the interfaces this class implements.
*/
private static Type matchByInterfaces(Class<?> cls, Class<?> matchType) {
Type[] gis = cls.getGenericInterfaces();
for (Type gi : gis) {
Type match = matchParamType(gi, matchType);
if (match != null) {
return match;
}
}
return null;
}
}
@@ -1,42 +0,0 @@
package com.avaje.ebeaninternal.server.deploy;
import com.avaje.ebean.event.BeanPersistListener;
import com.avaje.ebeaninternal.server.core.bootup.BootupClasses;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
/**
* Manages the assignment/registration of BeanPersistListener with their
* respective DeployBeanDescriptor's.
*/
public class PersistListenerManager {
private static final Logger logger = LoggerFactory.getLogger(PersistListenerManager.class);
private final List<BeanPersistListener> list;
public PersistListenerManager(BootupClasses bootupClasses) {
list = bootupClasses.getBeanPersistListeners();
}
public int getRegisterCount() {
return list.size();
}
/**
* Return the BeanPersistController for a given entity type.
*/
public <T> void addPersistListeners(DeployBeanDescriptor<T> deployDesc) {
for (BeanPersistListener listener : list) {
if (listener.isRegisterFor(deployDesc.getBeanType())) {
logger.debug("BeanPersistListener on[{}] {}", deployDesc.getFullName(), listener.getClass().getName());
deployDesc.addPersistListener(listener);
}
}
}
}
@@ -1,10 +0,0 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
<TITLE>Helpers for Id property conversion</TITLE>
</HEAD>
<Body BGCOLOR="#ffffff">
Helpers for Id property conversion
</Body>
</HTML>
@@ -1,150 +0,0 @@
package com.avaje.ebeaninternal.server.deploy.meta;
import com.avaje.ebeaninternal.server.deploy.BeanCascadeInfo;
import com.avaje.ebeaninternal.server.deploy.BeanTable;
/**
* Abstract base for properties mapped to an associated bean, list, set or map.
*/
public abstract class DeployBeanPropertyAssoc<T> extends DeployBeanProperty {
/**
* The type of the joined bean.
*/
protected Class<T> targetType;
/**
* Persist settings.
*/
private final BeanCascadeInfo cascadeInfo = new BeanCascadeInfo();
/**
* The join table information.
*/
private BeanTable beanTable;
/**
* Join between the beans.
*/
protected final DeployTableJoin tableJoin = new DeployTableJoin();
/**
* Literal added to where clause of lazy loading query.
*/
private String extraWhere;
/**
* From the deployment mappedBy attribute.
*/
private String mappedBy;
private String docStoreDoc;
/**
* Construct the property.
*/
DeployBeanPropertyAssoc(DeployBeanDescriptor<?> desc, Class<T> targetType) {
super(desc, targetType, null, null);
this.targetType = targetType;
}
/**
* Return the target DeployBeanDescriptor for this associated bean property.
*/
public DeployBeanDescriptor<?> getTargetDeploy() {
return desc.getDeploy(targetType).getDescriptor();
}
/**
* Return the type of the target.
* <p>
* This is the class of the associated bean, or beans contained in a list,
* set or map.
* </p>
*/
public Class<T> getTargetType() {
return targetType;
}
/**
* Return a literal expression that is added to the query that lazy loads
* the collection.
*/
public String getExtraWhere() {
return extraWhere;
}
/**
* Set a literal expression to add to the query that lazy loads the
* collection.
*/
public void setExtraWhere(String extraWhere) {
this.extraWhere = extraWhere;
}
/**
* return the join to use for the bean.
*/
public DeployTableJoin getTableJoin() {
return tableJoin;
}
/**
* Return the BeanTable for this association.
* <p>
* This has the table name which is used to determine the relationship for
* this association.
* </p>
*/
public BeanTable getBeanTable() {
return beanTable;
}
/**
* Set the bean table.
*/
public void setBeanTable(BeanTable beanTable) {
this.beanTable = beanTable;
getTableJoin().setTable(beanTable.getBaseTable());
}
/**
* Get the persist info.
*/
public BeanCascadeInfo getCascadeInfo() {
return cascadeInfo;
}
/**
* Return the mappedBy deployment attribute.
* <p>
* This is the name of the property in the 'detail' bean that maps back to
* this 'master' bean.
* </p>
*/
public String getMappedBy() {
return mappedBy;
}
/**
* Set mappedBy deployment attribute.
*/
public void setMappedBy(String mappedBy) {
if (!"".equals(mappedBy)) {
this.mappedBy = mappedBy;
}
}
/**
* Set DocStoreEmbedded deployment information.
*/
public void setDocStoreEmbedded(String embeddedDoc) {
this.docStoreDoc = embeddedDoc;
}
public String getDocStoreDoc() {
return docStoreDoc;
}
}
@@ -1,209 +0,0 @@
package com.avaje.ebeaninternal.server.deploy.meta;
import com.avaje.ebean.bean.BeanCollection.ModifyListenMode;
import com.avaje.ebeaninternal.server.deploy.ManyType;
import com.avaje.ebeaninternal.server.deploy.TableJoin;
/**
* Property mapped to a List Set or Map.
*/
public class DeployBeanPropertyAssocMany<T> extends DeployBeanPropertyAssoc<T> {
/**
* The type of the many, set, list or map.
*/
final ManyType manyType;
ModifyListenMode modifyListenMode = ModifyListenMode.NONE;
/**
* Flag to indicate manyToMany relationship.
*/
boolean manyToMany;
/**
* Flag to indicate this is a unidirectional relationship.
*/
boolean unidirectional;
/**
* Join for manyToMany intersection table.
*/
DeployTableJoin intersectionJoin;
/**
* For ManyToMany this is the Inverse join used to build reference queries.
*/
DeployTableJoin inverseJoin;
String fetchOrderBy;
String mapKey;
String intersectionDraftTable;
/**
* Create this property.
*/
public DeployBeanPropertyAssocMany(DeployBeanDescriptor<?> desc, Class<T> targetType, ManyType manyType) {
super(desc, targetType);
this.manyType = manyType;
}
/**
* When generics is not used for manyType you can specify via annotations.
* <p>
* Really only expect this for Scala due to a Scala compiler bug at the moment.
* Otherwise I'd probably not bother support this.
* </p>
*/
@SuppressWarnings("unchecked")
public void setTargetType(Class<?> cls){
this.targetType = (Class<T>)cls;
}
/**
* Return the many type.
*/
public ManyType getManyType() {
return manyType;
}
/**
* Return true if this is many to many.
*/
public boolean isManyToMany() {
return manyToMany;
}
/**
* Set to true if this is a many to many.
*/
public void setManyToMany() {
this.manyToMany = true;
}
/**
* Return the mode for listening to changes to the List Set or Map.
*/
public ModifyListenMode getModifyListenMode() {
return modifyListenMode;
}
/**
* Set the mode for listening to changes to the List Set or Map.
*/
public void setModifyListenMode(ModifyListenMode modifyListenMode) {
this.modifyListenMode = modifyListenMode;
}
/**
* Return true if this is a unidirectional relationship.
*/
public boolean isUnidirectional() {
return unidirectional;
}
/**
* Set to true if this is a unidirectional relationship.
*/
public void setUnidirectional() {
this.unidirectional = true;
}
/**
* Create the immutable version of the intersection join.
*/
public TableJoin createIntersectionTableJoin() {
if (intersectionJoin != null){
return new TableJoin(intersectionJoin);
} else {
return null;
}
}
/**
* Create the immutable version of the inverse join.
*/
public TableJoin createInverseTableJoin() {
if (inverseJoin != null){
return new TableJoin(inverseJoin);
} else {
return null;
}
}
/**
* ManyToMany only, join from local table to intersection table.
*/
public DeployTableJoin getIntersectionJoin() {
return intersectionJoin;
}
public DeployTableJoin getInverseJoin() {
return inverseJoin;
}
/**
* ManyToMany only, join from local table to intersection table.
*/
public void setIntersectionJoin(DeployTableJoin intersectionJoin) {
this.intersectionJoin = intersectionJoin;
}
/**
* ManyToMany only, join from foreign table to intersection table.
*/
public void setInverseJoin(DeployTableJoin inverseJoin) {
this.inverseJoin = inverseJoin;
}
/**
* Return the order by clause used to order the fetching of the data for
* this list, set or map.
*/
public String getFetchOrderBy() {
return fetchOrderBy;
}
/**
* Return the default mapKey when returning a Map.
*/
public String getMapKey() {
return mapKey;
}
/**
* Set the default mapKey to use when returning a Map.
*/
public void setMapKey(String mapKey) {
if (mapKey != null && !mapKey.isEmpty()) {
this.mapKey = mapKey;
}
}
/**
* Set the order by clause used to order the fetching or the data for this
* list, set or map.
*/
public void setFetchOrderBy(String orderBy) {
if (orderBy != null && !orderBy.isEmpty()) {
fetchOrderBy = orderBy;
}
}
/**
* Return a draft table for intersection between 2 @Draftable entities.
*/
public String getIntersectionDraftTable() {
return (intersectionDraftTable != null) ? intersectionDraftTable : intersectionJoin.getTable();
}
/**
* ManyToMany between 2 @Draftable entities to also need draft intersection table.
*/
public void setIntersectionDraftTable() {
this.intersectionDraftTable = intersectionJoin.getTable()+"_draft";
}
}
@@ -1,100 +0,0 @@
package com.avaje.ebeaninternal.server.deploy.meta;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompoundRoot;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompoundScalar;
import com.avaje.ebeaninternal.server.type.CtCompoundProperty;
import com.avaje.ebeaninternal.server.type.CtCompoundType;
import com.avaje.ebeaninternal.server.type.CtCompoundTypeScalarList;
import com.avaje.ebeaninternal.server.type.ScalarType;
import java.util.Map.Entry;
/**
* Property mapped to a joined bean.
*/
public class DeployBeanPropertyCompound extends DeployBeanProperty {
private final CtCompoundType<?> compoundType;
private DeployBeanEmbedded deployEmbedded;
/**
* Create the property.
*/
public DeployBeanPropertyCompound(DeployBeanDescriptor<?> desc, Class<?> targetType, CtCompoundType<?> compoundType) {
super(desc, targetType, null, null);
this.compoundType = compoundType;
}
public BeanPropertyCompoundRoot getFlatProperties() {
// get a 'flat' list of all the scalar types, their relative property names
// and also set their matching dbColumn
// represents the root property
BeanPropertyCompoundRoot rootProperty = new BeanPropertyCompoundRoot(this);
// Walk the tree of a compound type collecting the
// scalar types and non-scalar properties
CtCompoundTypeScalarList ctMeta = new CtCompoundTypeScalarList();
compoundType.accumulateScalarTypes(null, ctMeta);
// for each of the scalar types inside a compound value object
// build a BeanPropertyCompoundScalar with appropriate deployment
// information.
for (Entry<String, ScalarType<?>> entry : ctMeta.entries()) {
String relativePropertyName = entry.getKey();
ScalarType<?> scalarType = entry.getValue();
CtCompoundProperty ctProp = ctMeta.getCompoundType(relativePropertyName);
String dbColumn = (getName() + "." + relativePropertyName).replace(".", "_");
dbColumn = getDbColumn(relativePropertyName, dbColumn);
DeployBeanProperty deploy = new DeployBeanProperty(null, scalarType.getType(), scalarType, null);
deploy.setScalarType(scalarType);
deploy.setDbColumn(dbColumn);
deploy.setName(relativePropertyName);
deploy.setDbInsertable(true);
deploy.setDbUpdateable(true);
deploy.setDbRead(true);
rootProperty.register(new BeanPropertyCompoundScalar(rootProperty, deploy, ctProp));
}
rootProperty.setNonScalarProperties(ctMeta.getNonScalarProperties());
return rootProperty;
}
private String getDbColumn(String propName, String defaultDbColumn) {
if (deployEmbedded == null) {
return defaultDbColumn;
}
String dbColumn = deployEmbedded.getPropertyColumnMap().get(propName);
return dbColumn == null ? defaultDbColumn : dbColumn;
}
/**
* Return the deploy information specifically for the deployment
* of Embedded beans.
*/
public DeployBeanEmbedded getDeployEmbedded() {
// deployment should be single threaded
if (deployEmbedded == null) {
deployEmbedded = new DeployBeanEmbedded();
}
return deployEmbedded;
}
public CtCompoundType<?> getCompoundType() {
return compoundType;
}
}
@@ -1,90 +0,0 @@
package com.avaje.ebeaninternal.server.deploy.meta;
import java.util.List;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorMap;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
/**
* Used for associated beans in place of a BeanDescriptor. This is done to avoid
* recursion issues due to the potentially bi-directional and circular
* relationships between beans.
* <p>
* It holds the main deployment information and not all the detail that is held
* in a BeanDescriptor.
* </p>
*/
public class DeployBeanTable {
private final Class<?> beanType;
/**
* The base table.
*/
private String baseTable;
private List<DeployBeanProperty> idProperties;
/**
* Create the BeanTable.
*/
public DeployBeanTable(Class<?> beanType) {
this.beanType = beanType;
}
/**
* Return the base table for this BeanTable.
* This is used to determine the join information
* for associations.
*/
public String getBaseTable() {
return baseTable;
}
/**
* Set the base table for this BeanTable.
*/
public void setBaseTable(String baseTable) {
this.baseTable = baseTable;
}
/**
* Return the id properties.
*/
public BeanProperty[] createIdProperties(BeanDescriptorMap owner) {
BeanProperty[] props = new BeanProperty[idProperties.size()];
for (int i = 0; i < idProperties.size(); i++) {
props[i] = createProperty(owner, idProperties.get(i));
}
return props;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private BeanProperty createProperty(BeanDescriptorMap owner, DeployBeanProperty prop){
if (prop instanceof DeployBeanPropertyAssocOne<?>){
return new BeanPropertyAssocOne(owner, (DeployBeanPropertyAssocOne<?>)prop);
} else {
return new BeanProperty(prop);
}
}
/**
* Set the Id properties.
*/
public void setIdProperties(List<DeployBeanProperty> idProperties) {
this.idProperties = idProperties;
}
/**
* Return the class for this beanTable.
*/
public Class<?> getBeanType() {
return beanType;
}
}
@@ -1,185 +0,0 @@
package com.avaje.ebeaninternal.server.deploy.meta;
import javax.persistence.JoinColumn;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.BeanTable;
/**
* A join pair of local and foreign properties.
*/
public class DeployTableJoinColumn {
/**
* The local database column name.
*/
String localDbColumn;
/**
* SQL formula used for local column
*/
String localSqlFormula;
/**
* The foreign database column name.
*/
String foreignDbColumn;
/**
* SQL formula used for foreign column
*/
String foreignSqlFormula;
boolean insertable;
boolean updateable;
/**
* Construct when automatically determining the join.
* <p>
* Assume that we want the foreign key to be insertable and updateable.
* </p>
*/
public DeployTableJoinColumn(String localDbColumn, String foreignDbColumn) {
this(localDbColumn, foreignDbColumn, true, true);
}
/**
* Construct with explicit insertable and updateable flags.
*/
public DeployTableJoinColumn(String localDbColumn, String foreignDbColumn, boolean insertable, boolean updateable) {
this.localDbColumn = nullEmptyString(localDbColumn);
this.foreignDbColumn = nullEmptyString(foreignDbColumn);
this.insertable = insertable;
this.updateable = updateable;
}
public void setLocalSqlFormula(String localSqlFormula) {
if (localSqlFormula != null) {
this.localSqlFormula = localSqlFormula;
this.localDbColumn = null;
this.insertable = false;
this.updateable = false;
}
}
public String getLocalSqlFormula() {
return localSqlFormula;
}
public void setForeignSqlFormula(String foreignSqlFormula) {
if (foreignSqlFormula != null) {
this.foreignSqlFormula = foreignSqlFormula;
this.foreignDbColumn = null;
this.insertable = false;
this.updateable = false;
}
}
public String getForeignSqlFormula() {
return foreignSqlFormula;
}
public DeployTableJoinColumn(boolean order, JoinColumn jc, BeanTable beanTable) {
this(jc.referencedColumnName(), jc.name(), jc.insertable(), jc.updatable());
setReferencedColumn(beanTable);
if (!order){
reverse();
}
}
private void setReferencedColumn(BeanTable beanTable){
if (localDbColumn == null){
BeanProperty[] idProperties = beanTable.getIdProperties();
if (idProperties.length == 1){
localDbColumn = idProperties[0].getDbColumn();
}
}
}
/**
* Reverse the direction of the join.
*/
public DeployTableJoinColumn reverse() {
String temp = localDbColumn;
localDbColumn = foreignDbColumn;
foreignDbColumn = temp;
temp = localSqlFormula;
localSqlFormula = foreignSqlFormula;
foreignSqlFormula = temp;
return this;
}
/**
* Helper method to null out empty strings.
*/
private String nullEmptyString(String s){
if ("".equals(s)){
return null;
}
return s;
}
public DeployTableJoinColumn copy(boolean reverse) {
// Note that the insertable and updateable are just copied
// which may not always be the correct thing to do
// but will leave it like this for now
DeployTableJoinColumn ret;
if (reverse){
ret = new DeployTableJoinColumn(foreignDbColumn, localDbColumn, insertable, updateable);
ret.setLocalSqlFormula(foreignSqlFormula);
ret.setForeignSqlFormula(localSqlFormula);
} else {
ret = new DeployTableJoinColumn(localDbColumn, foreignDbColumn, insertable, updateable);
ret.setLocalSqlFormula(localSqlFormula);
ret.setForeignSqlFormula(foreignSqlFormula);
}
return ret;
}
public String toString() {
return localDbColumn + " = " + foreignDbColumn;
}
/**
* Return true if this column should be insertable.
*/
public boolean isInsertable() {
return insertable;
}
/**
* Return true if this column should be updateable.
*/
public boolean isUpdateable() {
return updateable;
}
/**
* Return the foreign database column name.
*/
public String getForeignDbColumn() {
return foreignDbColumn;
}
/**
* Return the local database column name.
*/
public String getLocalDbColumn() {
return localDbColumn;
}
/**
* Set the local database column name.
*/
public void setLocalDbColumn(String localDbColumn) {
this.localDbColumn = localDbColumn;
}
}
@@ -1,10 +0,0 @@
<html>
<head>
<meta HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
<title>Temporary objects used to collect deployment information</title>
</head>
<body BGCOLOR="#ffffff">
Temporary objects used to collect deployment information
</body>
</html>
@@ -1,14 +0,0 @@
<html>
<head>
<meta HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
<title>Bean description</title>
</head>
<body BGCOLOR="#ffffff">
Bean description
<p>
Describes beans with their properties and configuration.
</p>
</body>
</html>
@@ -1,92 +0,0 @@
package com.avaje.ebeaninternal.server.deploy.parse;
import com.avaje.ebean.RawSql;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
import com.avaje.ebeaninternal.server.deploy.meta.DeployTableJoin;
import com.avaje.ebeaninternal.server.query.SqlJoinType;
import java.util.HashMap;
/**
* Wraps information about a bean during deployment parsing.
*/
public class DeployBeanInfo<T> {
/**
* Holds TableJoins for secondary table properties.
*/
private final HashMap<String,DeployTableJoin> tableJoinMap = new HashMap<>();
private final DeployUtil util;
private final DeployBeanDescriptor<T> descriptor;
/**
* Create with a DeployUtil and BeanDescriptor.
*/
public DeployBeanInfo(DeployUtil util, DeployBeanDescriptor<T> descriptor) {
this.util = util;
this.descriptor = descriptor;
}
public String toString() {
return ""+descriptor;
}
/**
* Return the BeanDescriptor currently being processed.
*/
public DeployBeanDescriptor<T> getDescriptor() {
return descriptor;
}
/**
* Return the DeployUtil we are using.
*/
public DeployUtil getUtil() {
return util;
}
/**
* Appropriate TableJoin for a property mapped to a secondary table.
*/
public DeployTableJoin getTableJoin(String tableName) {
String key = tableName.toLowerCase();
DeployTableJoin tableJoin = tableJoinMap.get(key);
if (tableJoin == null) {
tableJoin = new DeployTableJoin();
tableJoin.setTable(tableName);
tableJoin.setType(SqlJoinType.INNER);
descriptor.addTableJoin(tableJoin);
tableJoinMap.put(key, tableJoin);
}
return tableJoin;
}
/**
* Set a the join alias for a assoc one property.
*/
public void setBeanJoinType(DeployBeanPropertyAssocOne<?> beanProp, boolean outerJoin) {
DeployTableJoin tableJoin = beanProp.getTableJoin();
tableJoin.setType(outerJoin ? SqlJoinType.OUTER : SqlJoinType.INNER);
}
/**
* Add named RawSql from ebean.xml.
*/
public void addRawSql(String name, RawSql rawSql) {
descriptor.addRawSql(name, rawSql);
}
/**
* Add the named query.
*/
public void addNamedQuery(String name, String query) {
descriptor.addNamedQuery(name, query);
}
}
@@ -1,78 +0,0 @@
package com.avaje.ebeaninternal.server.deploy.parse;
import java.util.HashSet;
/**
* Keywords deemed inappropriate for use as table alias' column or table name.
* <p>
* That is, they might cause sql syntax errors if used.
* </p>
*/
public class SqlReservedWords {
private static final String baseKeyWords =
"ALIAS,ALTER,ADD,ALL,ARE,AND,ANY,ARRAY"
+",AS,ASC,AT"
+",AVG,BEGIN,BETWEEN,BIGINT,BINARY,BIT,BIT_LENGTH,BLOB,BOOLEAN"
+",BOTH,BY,CALL,CALLED,CASCADE,CASCADED,CASE,CAST,CATALOG,CHAR"
+",CHARACTER,CHECK,CLOB,CLOSE,COALESCE,COLLATE"
+",COLLATION,COLUMN,COMMIT,CONDITION,CONNECT,CONNECTION,CONSTRAINT"
+",CONSTRAINTS,CONSTRUCTOR,CONTAINS,CONTINUE,CONVERT"
+",COUNT,CREATE,CROSS,CURRENT_DATE"
+",CURRENT_PATH,CURRENT_ROLE,CURRENT_TIME,CURRENT_TIMESTAMP"
+",CURRENT_USER,CURSOR,DATE"
+",DAY,DEC,DECIMAL,DECLARE,DEFAULT,DELETE"
+",DESC"
+",DISTINCT,DO,DOUBLE,DROP,ELSE,ELSEIF,END,EQUALS"
+",EXEC,EXIT,EXISTS,EXTRACT"
+",FLOAT,FROM,FOR,FREE"
+",GET,GLOBAL,GO,GOTO,GRANT,GROUP,HAVING,HOUR"
+",IF,IN,INNER,INOUT,INSERT"
+",INT,INTEGER,INTO,IS,JOIN"
+",LAST,LIKE,LIMIT"
+",MAX,MIN"
+",NCHAR,NCLOB,NOT"
+",NULL,NULLIF,NUMERIC,"
+",OR,ORDER,OUTER"
+",REAL,REF,REFERENCES"
+",RETURN,RETURNS"
+",SELECT,SSL"
+",SMALLINT,"
+",SYSTEM,SYSTEM_USER,TABLE"
+",TO"
+",TRIGGER,UNION,UNIQUE"
+",UPDATE,USER,VARCHAR,VIEW,WHEN"
+",WHERE,WITH";
private static final HashSet<String> keywords = new HashSet<>();
static {
String[] initialKeywords = baseKeyWords.split(",");
for (String initialKeyword : initialKeywords) {
keywords.add(initialKeyword.trim());
}
}
/**
* Return true if the tableAlias is a keyword.
*/
public static synchronized boolean isKeyword(String keyword){
String s = keyword.trim().toUpperCase();
return keywords.contains(s);
}
/**
* Add a sql keyword to the known set.
*/
public static synchronized void addKeyword(String keyword){
if (keyword != null){
keyword = keyword.trim().toUpperCase();
if (!keyword.isEmpty()){
keywords.add(keyword);
}
}
}
}
@@ -1,48 +0,0 @@
package com.avaje.ebeaninternal.server.deploy.parse;
import java.util.List;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocMany;
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
/**
* Mark transient properties.
*/
public class TransientProperties {
public TransientProperties() {
}
/**
* Mark any additional properties as transient.
*/
public void process(DeployBeanDescriptor<?> desc) {
List<DeployBeanProperty> props = desc.propertiesBase();
for (DeployBeanProperty prop : props) {
if (!prop.isDbRead() && !prop.isDbInsertable() && !prop.isDbUpdateable()) {
// non-transient...
prop.setTransient();
}
}
List<DeployBeanPropertyAssocOne<?>> ones = desc.propertiesAssocOne();
for (DeployBeanPropertyAssocOne<?> prop : ones) {
if (prop.getBeanTable() == null) {
if (!prop.isEmbedded()) {
prop.setTransient();
}
}
}
List<DeployBeanPropertyAssocMany<?>> manys = desc.propertiesAssocMany();
for (DeployBeanPropertyAssocMany<?> prop : manys) {
if (prop.getBeanTable() == null) {
prop.setTransient();
}
}
}
}
@@ -1,16 +0,0 @@
<!ELEMENT ebean (table | iudextender | findextender | datasource | primarykeys | property)* >
<!ELEMENT table EMPTY >
<!ATTLIST table name CDATA #REQUIRED>
<!ELEMENT iudextender EMPTY >
<!ATTLIST iudextender classname CDATA #REQUIRED>
<!ELEMENT findextender EMPTY >
<!ATTLIST findextender classname CDATA #REQUIRED>
<!ELEMENT datasource EMPTY >
<!ATTLIST datasource name CDATA #REQUIRED>
<!ELEMENT primarykeys EMPTY >
<!ATTLIST primarykeys keys CDATA #REQUIRED>
<!ELEMENT property EMPTY >
<!ATTLIST property name CDATA #REQUIRED
datatype CDATA #REQUIRED
deploydatatype CDATA #IMPLIED
deployname CDATA #IMPLIED >
@@ -1,11 +0,0 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
<TITLE>Deployment information parsing</TITLE>
</HEAD>
<Body BGCOLOR="#ffffff">
Deployment information parsing
</Body>
</HTML>
@@ -1 +0,0 @@
package com.avaje.ebeaninternal.server.el;
@@ -1,121 +0,0 @@
package com.avaje.ebeaninternal.server.expression;
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
import com.avaje.ebeaninternal.api.ManyWhereJoins;
import com.avaje.ebeaninternal.api.SpiExpression;
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
import com.avaje.ebeaninternal.api.SpiExpressionValidation;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.id.IdBinder;
import java.io.IOException;
import java.util.List;
/**
* Slightly redundant as Query.setId() ultimately also does the same job.
*/
public class IdInExpression extends NonPrepareExpression {
private final List<?> idList;
public IdInExpression(List<?> idList) {
this.idList = idList;
}
@Override
public String nestedPath(BeanDescriptor<?> desc) {
return null;
}
@Override
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
}
@Override
public void writeDocQuery(DocQueryContext context) throws IOException {
context.writeIds(idList);
}
@Override
public void validate(SpiExpressionValidation validation) {
// always valid
}
@Override
public void addBindValues(SpiExpressionRequest request) {
// Bind the Id values including EmbeddedId and multiple Id
DefaultExpressionRequest r = (DefaultExpressionRequest) request;
BeanDescriptor<?> descriptor = r.getBeanDescriptor();
IdBinder idBinder = descriptor.getIdBinder();
for (Object anIdList : idList) {
idBinder.addIdInBindValue(request, anIdList);
}
}
/**
* For use with deleting non attached detail beans during stateless update.
*/
public void addSqlNoAlias(SpiExpressionRequest request) {
DefaultExpressionRequest r = (DefaultExpressionRequest) request;
BeanDescriptor<?> descriptor = r.getBeanDescriptor();
IdBinder idBinder = descriptor.getIdBinder();
request.append(descriptor.getIdBinder().getBindIdInSql(null));
String inClause = idBinder.getIdInValueExpr(idList.size());
request.append(inClause);
}
@Override
public void addSql(SpiExpressionRequest request) {
DefaultExpressionRequest r = (DefaultExpressionRequest) request;
BeanDescriptor<?> descriptor = r.getBeanDescriptor();
IdBinder idBinder = descriptor.getIdBinder();
request.append(descriptor.getIdBinderInLHSSql());
String inClause = idBinder.getIdInValueExpr(idList.size());
request.append(inClause);
}
/**
* Incorporates the number of Id values to bind.
*/
@Override
public void queryPlanHash(HashQueryPlanBuilder builder) {
builder.add(IdInExpression.class).add(idList.size());
builder.bind(idList.size());
}
@Override
public int queryBindHash() {
return idList.hashCode();
}
@Override
public boolean isSameByPlan(SpiExpression other) {
if (!(other instanceof IdInExpression)) {
return false;
}
IdInExpression that = (IdInExpression) other;
return this.idList.size() == that.idList.size();
}
@Override
public boolean isSameByBind(SpiExpression other) {
IdInExpression that = (IdInExpression) other;
if (this.idList.size() != that.idList.size()) {
return false;
}
for (int i = 0; i < idList.size(); i++) {
if (!idList.get(i).equals(that.idList.get(i))) {
return false;
}
}
return true;
}
}
@@ -1,292 +0,0 @@
package com.avaje.ebeaninternal.server.lib.util;
import java.util.HashMap;
import java.util.Map;
/**
* Utility String class that supports String manipulation functions.
*/
public class StringHelper {
/**
* Parses out a list of Name Value pairs that are delimited together. Will
* always return a StringMap. If allNameValuePairs is null, or no name
* values can be parsed out an empty StringMap is returned.
*
* @param allNameValuePairs the entire string to be parsed.
* @param listDelimiter (typically ';') the delimited between the list
* @param nameValueSeparator (typically '=') the separator between the name and value
*/
public static Map<String, String> delimitedToMap(String allNameValuePairs,
String listDelimiter, String nameValueSeparator) {
HashMap<String, String> params = new HashMap<>();
if ((allNameValuePairs == null) || (allNameValuePairs.isEmpty())) {
return params;
}
// trim off any leading listDelimiter...
allNameValuePairs = trimFront(allNameValuePairs, listDelimiter);
return getKeyValue(params, 0, allNameValuePairs, listDelimiter, nameValueSeparator);
}
/**
* Trims off recurring strings from the front of a string.
*
* @param source the source string
* @param trim the string to trim off the front
*/
public static String trimFront(String source, String trim) {
if (source == null) {
return null;
}
if (source.indexOf(trim) == 0) {
// dp("trim ...");
return trimFront(source.substring(trim.length()), trim);
} else {
return source;
}
}
/**
* Return true if the value is null or an empty string.
*/
public static boolean isNull(String value) {
return value == null || value.trim().isEmpty();
}
/**
* Recursively pulls out the key value pairs from a raw string.
*/
private static HashMap<String, String> getKeyValue(HashMap<String, String> map, int pos,
String allNameValuePairs, String listDelimiter, String nameValueSeparator) {
if (pos >= allNameValuePairs.length()) {
// dp("end as "+pos+" >= "+allNameValuePairs.length() );
return map;
}
int equalsPos = allNameValuePairs.indexOf(nameValueSeparator, pos);
int delimPos = allNameValuePairs.indexOf(listDelimiter, pos);
if (delimPos == -1) {
delimPos = allNameValuePairs.length();
}
if (equalsPos == -1) {
// dp("no more equals...");
return map;
}
if (delimPos == (equalsPos + 1)) {
// dp("Ignoring as nothing between delim and equals...
// delim:"+delimPos+" eq:"+equalsPos);
return getKeyValue(map, delimPos + 1, allNameValuePairs, listDelimiter,
nameValueSeparator);
}
if (equalsPos > delimPos) {
// there is a key without a value?
String key = allNameValuePairs.substring(pos, delimPos);
key = key.trim();
if (!key.isEmpty()) {
map.put(key, null);
}
return getKeyValue(map, delimPos + 1, allNameValuePairs, listDelimiter,
nameValueSeparator);
}
String key = allNameValuePairs.substring(pos, equalsPos);
if (delimPos > -1) {
String value = allNameValuePairs.substring(equalsPos + 1, delimPos);
// dp("cont "+key+","+value+" pos:"+pos+"
// len:"+allNameValuePairs.length());
key = key.trim();
map.put(key, value);
pos = delimPos + 1;
// recurse the rest of the values...
return getKeyValue(map, pos, allNameValuePairs, listDelimiter, nameValueSeparator);
} else {
// dp("ERROR: delimPos < 0 ???");
return map;
}
}
/**
* This method takes a String and will replace all occurrences of the match
* String with that of the replace String.
*
* @param source the source string
* @param match the string used to find a match
* @param replace the string used to replace match with
* @return the source string after the search and replace
*/
public static String replaceString(String source, String match, String replace) {
if (source == null) {
return null;
}
if (replace == null) {
return source;
}
if (match == null) {
throw new NullPointerException("match is null?");
}
if (match.equals(replace)) {
return source;
}
return replaceString(source, match, replace, 30, 0, source.length());
}
/**
* Additionally specify the additionalSize to add to the buffer. This will
* make the buffer bigger so that it doesn't have to grow when replacement
* occurs.
*/
public static String replaceString(String source, String match, String replace,
int additionalSize, int startPos, int endPos) {
if (source == null) {
return null;
}
char match0 = match.charAt(0);
int matchLength = match.length();
if (matchLength == 1 && replace.length() == 1) {
char replace0 = replace.charAt(0);
return source.replace(match0, replace0);
}
if (matchLength >= replace.length()) {
additionalSize = 0;
}
int sourceLength = source.length();
int lastMatch = endPos - matchLength;
StringBuilder sb = new StringBuilder(sourceLength + additionalSize);
if (startPos > 0) {
sb.append(source.substring(0, startPos));
}
char sourceChar;
boolean isMatch;
int sourceMatchPos;
for (int i = startPos; i < sourceLength; i++) {
sourceChar = source.charAt(i);
if (i > lastMatch || sourceChar != match0) {
sb.append(sourceChar);
} else {
// check to see if this is a match
isMatch = true;
sourceMatchPos = i;
// check each following character...
for (int j = 1; j < matchLength; j++) {
sourceMatchPos++;
if (source.charAt(sourceMatchPos) != match.charAt(j)) {
isMatch = false;
break;
}
}
if (isMatch) {
i = i + matchLength - 1;
sb.append(replace);
} else {
// was not a match
sb.append(sourceChar);
}
}
}
return sb.toString();
}
/**
* A search and replace with multiple matching strings.
* <p>
* Useful when converting CRNL CR and NL all to a BR tag for example.
* </p>
* <p>
* <pre><code>
* String[] multi = { &quot;\r\n&quot;, &quot;\r&quot;, &quot;\n&quot; };
* content = StringHelper.replaceStringMulti(content, multi, &quot;&lt;br/&gt;&quot;);
* </code></pre>
*/
public static String replaceStringMulti(String source, String[] match, String replace) {
return replaceStringMulti(source, match, replace, 30, 0, source.length());
}
/**
* Additionally specify an additional size estimate for the buffer plus
* start and end positions.
* <p>
* The start and end positions can limit the search and replace. Otherwise
* these default to startPos = 0 and endPos = source.length().
* </p>
*/
public static String replaceStringMulti(String source, String[] match, String replace,
int additionalSize, int startPos, int endPos) {
int shortestMatch = match[0].length();
char[] match0 = new char[match.length];
for (int i = 0; i < match0.length; i++) {
match0[i] = match[i].charAt(0);
if (match[i].length() < shortestMatch) {
shortestMatch = match[i].length();
}
}
StringBuilder sb = new StringBuilder(source.length() + additionalSize);
char sourceChar;
int len = source.length();
int lastMatch = endPos - shortestMatch;
if (startPos > 0) {
sb.append(source.substring(0, startPos));
}
int matchCount;
for (int i = startPos; i < len; i++) {
sourceChar = source.charAt(i);
if (i > lastMatch) {
sb.append(sourceChar);
} else {
matchCount = 0;
for (int k = 0; k < match0.length; k++) {
if (matchCount == 0 && sourceChar == match0[k]) {
if (match[k].length() + i <= len) {
++matchCount;
int j = 1;
for (; j < match[k].length(); j++) {
if (source.charAt(i + j) != match[k].charAt(j)) {
--matchCount;
break;
}
}
if (matchCount > 0) {
i = i + j - 1;
sb.append(replace);
break;
}
}
}
}
if (matchCount == 0) {
sb.append(sourceChar);
}
}
}
return sb.toString();
}
}
@@ -1 +0,0 @@
package com.avaje.ebeaninternal.server.loadcontext;
@@ -1,59 +0,0 @@
package com.avaje.ebeaninternal.server.persist.dmlbind;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.server.core.PersistRequestBean;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompound;
import com.avaje.ebeaninternal.server.persist.dml.GenerateDmlRequest;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
/**
* Bindable for a Immutable Compound value object.
*/
public class BindableCompound implements Bindable {
private final BindableProperty[] items;
private final BeanPropertyCompound compound;
public BindableCompound(BeanPropertyCompound embProp, List<BindableProperty> list) {
this.compound = embProp;
this.items = list.toArray(new BindableProperty[list.size()]);
}
public String toString() {
return "BindableCompound " + compound + " items:" + Arrays.toString(items);
}
@Override
public boolean isDraftOnly() {
return false;
}
public void dmlAppend(GenerateDmlRequest request) {
for (BindableProperty item : items) {
item.dmlAppend(request);
}
}
public void addToUpdate(PersistRequestBean<?> request, List<Bindable> list) {
if (request.isAddToUpdate(compound)) {
list.add(this);
}
}
public void dmlBind(BindableRequest bindRequest, EntityBean bean) throws SQLException {
// get the compound type value
Object valueObject = compound.getValue(bean);
// bind each of the underlying scalar values for this compound type
for (BindableProperty item : items) {
item.dmlBindObject(bindRequest, valueObject);
}
}
}
@@ -1,46 +0,0 @@
package com.avaje.ebeaninternal.server.persist.dmlbind;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.generatedproperty.GeneratedProperty;
import com.avaje.ebeaninternal.server.persist.dml.GenerateDmlRequest;
import java.sql.SQLException;
/**
* Bindable for insert on a property with a GeneratedProperty.
* <p>
* This is typically a 'insert timestamp', 'update timestamp' or 'counter'.
* </p>
*/
public class BindablePropertyInsertGenerated extends BindableProperty {
private final GeneratedProperty gen;
public BindablePropertyInsertGenerated(BeanProperty prop, GeneratedProperty gen) {
super(prop);
this.gen = gen;
}
public void dmlBind(BindableRequest request, EntityBean bean) throws SQLException {
Object value = gen.getInsertValue(prop, bean, request.now());
// generated value should be the correct type
if (bean != null) {
// support PropertyChangeSupport
//prop.setValueIntercept(bean, value);
prop.setValue(bean, value);
}
request.bind(value, prop);
}
/**
* Always bind on Insert SET.
*/
@Override
public void dmlAppend(GenerateDmlRequest request) {
request.appendColumn(prop.getDbColumn());
}
}
@@ -1,64 +0,0 @@
package com.avaje.ebeaninternal.server.persist.dmlbind;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebeaninternal.server.core.PersistRequestBean;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.generatedproperty.GeneratedProperty;
import com.avaje.ebeaninternal.server.persist.dml.GenerateDmlRequest;
import java.sql.SQLException;
import java.util.List;
/**
* Bindable for update on a property with a GeneratedProperty.
* <p>
* This is typically a 'update timestamp' or 'counter'.
* </p>
*/
public class BindablePropertyUpdateGenerated extends BindableProperty {
private final GeneratedProperty gen;
public BindablePropertyUpdateGenerated(BeanProperty prop, GeneratedProperty gen) {
super(prop);
this.gen = gen;
}
/**
* Add BindablePropertyUpdateGenerated if the property is loaded.
*/
public void addToUpdate(PersistRequestBean<?> request, List<Bindable> list) {
if (gen.includeInAllUpdates()) {
list.add(this);
} else if (request.isLoadedProperty(prop)) {
list.add(this);
}
}
public void dmlBind(BindableRequest request, EntityBean bean) throws SQLException {
Object value = gen.getUpdateValue(prop, bean, request.now());
// generated value should be the correct type
request.bind(value, prop);
if (prop.isVersion()) {
if (request.getPersistRequest().isLoadedProperty(prop)) {
// set to the bean after the where clause has been generated
request.registerGeneratedVersion(value);
}
} else {
// @WhenModified set without invoking interception
prop.setValueChanged(bean, value);
}
}
/**
* Always bind on Insert SET.
*/
@Override
public void dmlAppend(GenerateDmlRequest request) {
request.appendColumn(prop.getDbColumn());
}
}
@@ -1,67 +0,0 @@
package com.avaje.ebeaninternal.server.persist.dmlbind;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompound;
import com.avaje.ebeaninternal.server.persist.dml.DmlMode;
import java.util.ArrayList;
import java.util.List;
/**
* Add base properties to the BindableList for a bean type.
* <p>
* This excludes unique embedded and associated properties.
* </p>
*/
public class FactoryBaseProperties {
private final FactoryProperty factoryProperty;
public FactoryBaseProperties(boolean bindEncryptDataFirst) {
factoryProperty = new FactoryProperty(bindEncryptDataFirst);
}
/**
* Add Bindable for the base properties to the list.
*/
public void create(List<Bindable> list, BeanDescriptor<?> desc, DmlMode mode, boolean withLobs) {
add(desc.propertiesBaseScalar(), list, mode, withLobs);
BeanPropertyCompound[] compoundProps = desc.propertiesBaseCompound();
for (BeanPropertyCompound compoundProp : compoundProps) {
BeanProperty[] props = compoundProp.getScalarProperties();
List<BindableProperty> newList = new ArrayList<>(props.length);
addCompound(props, newList, mode, withLobs);
BindableCompound compoundBindable = new BindableCompound(compoundProp, newList);
list.add(compoundBindable);
}
}
private void add(BeanProperty[] props, List<Bindable> list, DmlMode mode, boolean withLobs) {
for (BeanProperty prop : props) {
Bindable item = factoryProperty.create(prop, mode, withLobs);
if (item != null) {
list.add(item);
}
}
}
private void addCompound(BeanProperty[] props, List<BindableProperty> list, DmlMode mode, boolean withLobs) {
for (BeanProperty prop : props) {
BindableProperty item = (BindableProperty) factoryProperty.create(prop, mode, withLobs);
if (item != null) {
list.add(item);
}
}
}
}
@@ -1,27 +0,0 @@
package com.avaje.ebeaninternal.server.persist.dmlbind;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
/**
* Creates a Bindable to support version concurrency where clauses.
*/
public class FactoryVersion {
public FactoryVersion() {
}
/**
* Create a Bindable for the version property(s) for a bean type.
*/
public Bindable create(BeanDescriptor<?> desc) {
BeanProperty versionProperty = desc.getVersionProperty();
if (versionProperty == null) {
return null;
}
return new BindableProperty(versionProperty);
}
}
@@ -1 +0,0 @@
package com.avaje.ebeaninternal.server.query;
@@ -1,133 +0,0 @@
package com.avaje.ebeaninternal.server.querydefn;
import com.avaje.ebean.OrderBy;
import com.avaje.ebean.RawSql;
import com.avaje.ebeaninternal.api.BindParams;
import com.avaje.ebeaninternal.api.CQueryPlanKey;
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
import com.avaje.ebeaninternal.api.SpiExpression;
import com.avaje.ebeaninternal.api.SpiQuery;
import com.avaje.ebeaninternal.server.deploy.TableJoin;
/**
* Query plan key for ORM queries.
*/
class OrmQueryPlanKey implements CQueryPlanKey {
private final String m2mIncludeTable;
private final String orderByAsSting;
private final SpiExpression where;
private final SpiExpression having;
private final RawSql.Key rawSqlKey;
private final boolean hasIdValue;
private final SpiQuery.Type type;
private final int maxRows;
private final int firstRow;
private final boolean disableLazyLoading;
private final boolean distinct;
private final boolean sqlDistinct;
private final String mapKey;
private final SpiQuery.TemporalMode temporalMode;
private final boolean forUpdate;
private final String rootTableAlias;
private final OrmUpdateProperties updateProperties;
private final int planHash;
private final int bindCount;
OrmQueryPlanKey(TableJoin m2mIncludeTable, SpiQuery.Type type, OrmQueryDetail detail, int maxRows, int firstRow, boolean disableLazyLoading, OrderBy<?> orderBy, boolean distinct, boolean sqlDistinct, String mapKey, Object id, BindParams bindParams, SpiExpression whereExpressions, SpiExpression havingExpressions, SpiQuery.TemporalMode temporalMode, boolean forUpdate, String rootTableAlias, RawSql rawSql, OrmUpdateProperties updateProperties) {
this.m2mIncludeTable = m2mIncludeTable == null ? null : m2mIncludeTable.getTable();
this.type = type;
this.maxRows = maxRows;
this.firstRow = firstRow;
this.disableLazyLoading = disableLazyLoading;
this.orderByAsSting = (orderBy == null) ? null : orderBy.toStringFormat();
this.distinct = distinct;
this.sqlDistinct = sqlDistinct;
this.mapKey = mapKey;
this.hasIdValue = (id != null);
this.where = (whereExpressions == null) ? null : whereExpressions.copyForPlanKey();
this.having = (havingExpressions == null) ? null : havingExpressions.copyForPlanKey();
this.temporalMode = temporalMode;
this.forUpdate = forUpdate;
this.rootTableAlias = rootTableAlias;
this.updateProperties = updateProperties;
this.rawSqlKey = (rawSql == null) ? null : rawSql.getKey();
// exclude bind values and things unrelated to the sql being generated
HashQueryPlanBuilder builder = new HashQueryPlanBuilder();
builder.add((type == null ? 0 : type.ordinal() + 1));
builder.add(distinct).add(sqlDistinct);
builder.add(firstRow).add(maxRows);
builder.add(orderBy).add(forUpdate);
builder.add(mapKey);
builder.add(disableLazyLoading);
builder.add(hasIdValue);
builder.add(temporalMode);
builder.add(rawSqlKey == null ? 0 : rawSqlKey.hashCode());
builder.add(this.m2mIncludeTable);
builder.add(rootTableAlias);
if (detail != null) {
detail.queryPlanHash(builder);
}
if (bindParams != null) {
bindParams.buildQueryPlanHash(builder);
}
if (where != null) {
where.queryPlanHash(builder);
}
if (having != null) {
having.queryPlanHash(builder);
}
if (updateProperties != null) {
updateProperties.buildQueryPlanHash(builder);
}
this.planHash = builder.getPlanHash();
this.bindCount = builder.getBindCount();
}
@Override
public String getPartialKey() {
return planHash + "_" + bindCount;
}
@Override
public int hashCode() {
return planHash;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
OrmQueryPlanKey that = (OrmQueryPlanKey) o;
if (planHash != that.planHash) return false;
if (bindCount != that.bindCount) return false;
if (maxRows != that.maxRows) return false;
if (firstRow != that.firstRow) return false;
if (disableLazyLoading != that.disableLazyLoading) return false;
if (distinct != that.distinct) return false;
if (sqlDistinct != that.sqlDistinct) return false;
if (forUpdate != that.forUpdate) return false;
if (hasIdValue != that.hasIdValue) return false;
if (type != that.type) return false;
if (temporalMode != that.temporalMode) return false;
if (m2mIncludeTable != null ? !m2mIncludeTable.equals(that.m2mIncludeTable) : that.m2mIncludeTable != null)
return false;
if (orderByAsSting != null ? !orderByAsSting.equals(that.orderByAsSting) : that.orderByAsSting != null)
return false;
if (where != null ? !where.isSameByPlan(that.where) : that.where != null) return false;
if (having != null ? !having.isSameByPlan(that.having) : that.having != null) return false;
if (updateProperties != null ? !updateProperties.isSameByPlan(that.updateProperties) : that.updateProperties != null)
return false;
if (rawSqlKey != null ? !rawSqlKey.equals(that.rawSqlKey) : that.rawSqlKey != null) return false;
if (mapKey != null ? !mapKey.equals(that.mapKey) : that.mapKey != null) return false;
return rootTableAlias != null ? rootTableAlias.equals(that.rootTableAlias) : that.rootTableAlias == null;
}
}
@@ -1 +0,0 @@
package com.avaje.ebeaninternal.server.querydefn;
@@ -1 +0,0 @@
package com.avaje.ebeaninternal.server.text.csv;
@@ -1,25 +0,0 @@
package com.avaje.ebeaninternal.server.transaction;
import javax.sql.DataSource;
/**
* Supply the DataSource to the transaction manager.
* <p>
* Implementations can support multi-tenancy via DB or SCHEMA.
* </p>
*/
public interface DataSourceSupplier {
/**
* Return the DataSource to use for the current request.
* <p>
* This should take into account multi-tenancy and the current tenantId.
* </p>
*/
DataSource getDataSource();
/**
* Shutdown the datasource de-registering the JDBC driver if requested.
*/
void shutdown(boolean deregisterDriver);
}
@@ -1,48 +0,0 @@
package com.avaje.ebeaninternal.server.transaction;
import com.avaje.ebean.config.ExternalTransactionManager;
import com.avaje.ebeaninternal.api.SpiTransaction;
/**
* A TransactionScopeManager aware of external transaction managers.
*/
public class ExternalTransactionScopeManager extends TransactionScopeManager {
final ExternalTransactionManager externalManager;
/**
* Instantiates transaction scope manager.
*
* @param transactionManager the transaction manager
*/
public ExternalTransactionScopeManager(TransactionManager transactionManager, ExternalTransactionManager externalManager) {
super(transactionManager);
this.externalManager = externalManager;
}
public void commit() {
DefaultTransactionThreadLocal.commit(serverName);
}
public void end() {
DefaultTransactionThreadLocal.end(serverName);
}
public SpiTransaction get() {
return (SpiTransaction) externalManager.getCurrentTransaction();
}
public void replace(SpiTransaction trans) {
DefaultTransactionThreadLocal.replace(serverName, trans);
}
public void rollback() {
DefaultTransactionThreadLocal.rollback(serverName);
}
public void set(SpiTransaction trans) {
DefaultTransactionThreadLocal.set(serverName, trans);
}
}
@@ -1,36 +0,0 @@
package com.avaje.ebeaninternal.server.transaction;
import com.avaje.ebean.BackgroundExecutor;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebeaninternal.server.cluster.ClusterManager;
import com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager;
import com.avaje.ebeanservice.docstore.api.DocStoreUpdateProcessor;
/**
* Objects supplied for constructing the TransactionManager.
*/
public class TransactionManagerOptions {
final boolean localL2Caching;
final ServerConfig config;
final ClusterManager clusterManager;
final BackgroundExecutor backgroundExecutor;
final DocStoreUpdateProcessor docStoreUpdateProcessor;
final BeanDescriptorManager descMgr;
final DataSourceSupplier dataSourceSupplier;
public TransactionManagerOptions(boolean localL2Caching, ServerConfig config, ClusterManager clusterManager, BackgroundExecutor backgroundExecutor,
DocStoreUpdateProcessor docStoreUpdateProcessor, BeanDescriptorManager descMgr, DataSourceSupplier dataSourceSupplier) {
this.localL2Caching = localL2Caching;
this.config = config;
this.clusterManager = clusterManager;
this.backgroundExecutor = backgroundExecutor;
this.docStoreUpdateProcessor = docStoreUpdateProcessor;
this.descMgr = descMgr;
this.dataSourceSupplier = dataSourceSupplier;
}
}
@@ -1,82 +0,0 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebean.config.CompoundType;
import com.avaje.ebean.config.CompoundTypeProperty;
import java.time.Period;
/**
* Compound type for Period value type.
* <p>
* Persists the Period into 3 separate integer columns for years, months and days.
* </p>
*/
public class CompoundTypePeriod implements CompoundType<Period> {
final CompoundTypeProperty[] properties = new CompoundTypeProperty[3];
public CompoundTypePeriod() {
properties[0] = new CTPeriodYear();
properties[1] = new CTPeriodMonth();
properties[2] = new CTPeriodDay();
}
@Override
public Period create(Object[] propertyValues) {
return Period.of((Integer) propertyValues[0], (Integer) propertyValues[1], (Integer) propertyValues[2]);
}
@Override
@SuppressWarnings("unchecked")
public CompoundTypeProperty<Period, ?>[] getProperties() {
return properties;
}
static class CTPeriodYear implements CompoundTypeProperty<Period, Integer> {
public String getName() {
return "years";
}
public Integer getValue(Period valueObject) {
return valueObject.getYears();
}
public int getDbType() {
return 0;
}
}
static class CTPeriodMonth implements CompoundTypeProperty<Period, Integer> {
public String getName() {
return "months";
}
public Integer getValue(Period valueObject) {
return valueObject.getMonths();
}
public int getDbType() {
return 0;
}
}
static class CTPeriodDay implements CompoundTypeProperty<Period, Integer> {
public String getName() {
return "days";
}
public Integer getValue(Period valueObject) {
return valueObject.getDays();
}
public int getDbType() {
return 0;
}
}
}
@@ -1,80 +0,0 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebean.config.CompoundTypeProperty;
/**
* Wraps a CompoundTypeProperty with it's type and parent for nested compound
* types.
*/
public class CtCompoundProperty {
private final String relativeName;
private final CtCompoundProperty parent;
private final CtCompoundType<?> compoundType;
@SuppressWarnings({"rawtypes"})
private final CompoundTypeProperty property;
public CtCompoundProperty(String relativeName, CtCompoundProperty parent, CtCompoundType<?> ctType,
CompoundTypeProperty<?, ?> property) {
this.relativeName = relativeName;
this.parent = parent;
this.compoundType = ctType;
this.property = property;
}
/**
* The property name relative to the root of the compound type.
*/
public String getRelativeName() {
return relativeName;
}
/**
* The property name local to its type.
*/
public String getPropertyName() {
return property.getName();
}
public String toString() {
return relativeName;
}
@SuppressWarnings("unchecked")
public Object getValue(Object valueObject) {
if (valueObject == null) {
return null;
}
if (parent != null) {
valueObject = parent.getValue(valueObject);
}
return property.getValue(valueObject);
}
/**
* Set a scalar value that is used to build the immutable compound value
* object.
* <p>
* When all the scalar values have been collected then the compound value
* object is built and this can be recursive for nested compound types.
* </p>
*/
public Object setValue(Object bean, Object value) {
// compoundType and propertyName should be correct depth
Object compoundValue = ImmutableCompoundTypeBuilder.set(compoundType, property.getName(), value);
if (compoundValue != null && parent != null) {
// Continue up the tree
return parent.setValue(bean, compoundValue);
} else {
return compoundValue;
}
}
}
@@ -1,153 +0,0 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebean.text.StringParser;
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
/**
* Adapter for CtCompoundProperty to ElPropertyValue.
* <p>
* This is used for non-scalar properties of a Compound Value Object. These only
* occur in nested compound types.
* </p>
*
* @author rbygrave
*/
public class CtCompoundPropertyElAdapter implements ElPropertyValue {
private final CtCompoundProperty prop;
private int deployOrder;
public CtCompoundPropertyElAdapter(CtCompoundProperty prop) {
this.prop = prop;
}
public void setDeployOrder(int deployOrder) {
this.deployOrder = deployOrder;
}
@Override
public boolean isAggregation() {
return false;
}
@Override
public Object convert(Object value) {
return value;
}
@Override
public Object pathGetNested(Object bean) {
return bean;
}
@Override
public Object pathGet(Object bean) {
return prop.getValue(bean);
}
@Override
public void pathSet(Object bean, Object value) {
prop.setValue(bean, value);
}
public String getAssocIdExpression(String prefix, String operator) {
throw new RuntimeException("Not Supported or Expected");
}
@Override
public String getAssocIsEmpty(SpiExpressionRequest request, String path) {
throw new RuntimeException("Not Supported or Expected");
}
public Object[] getAssocIdValues(EntityBean bean) {
throw new RuntimeException("Not Supported or Expected");
}
public String getAssocIdInExpr(String prefix) {
throw new RuntimeException("Not Supported or Expected");
}
public String getAssocIdInValueExpr(int size) {
throw new RuntimeException("Not Supported or Expected");
}
public BeanProperty getBeanProperty() {
return null;
}
public StringParser getStringParser() {
return null;
}
public boolean isDbEncrypted() {
return false;
}
public boolean isLocalEncrypted() {
return false;
}
@Override
public boolean isAssocMany() {
return false;
}
@Override
public boolean isAssocId() {
return false;
}
public boolean isAssocProperty() {
return false;
}
public boolean isDateTimeCapable() {
return false;
}
public int getJdbcType() {
return 0;
}
public Object parseDateTime(long systemTimeMillis) {
throw new RuntimeException("Not Supported or Expected");
}
@Override
public boolean containsFormulaWithJoin() {
return false;
}
public boolean containsMany() {
return false;
}
public boolean containsManySince(String sinceProperty) {
return containsMany();
}
public String getDbColumn() {
return null;
}
public String getElPlaceholder(boolean encrypted) {
return null;
}
public String getElPrefix() {
return null;
}
public String getName() {
return prop.getPropertyName();
}
public String getElName() {
return prop.getPropertyName();
}
}
@@ -1,201 +0,0 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebean.config.CompoundType;
import com.avaje.ebean.config.CompoundTypeProperty;
import com.avaje.ebeaninternal.server.text.json.WriteJson;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Map;
/**
* The internal representation of a Compound Type (Immutable Compound Value Object).
*
* @param <V> The Type of the "Immutable Compound Value Object".
*/
public final class CtCompoundType<V> implements ScalarDataReader<V> {
private final Class<V> cvoClass;
private final CompoundType<V> cvoType;
private final ScalarDataReader<Object>[] propReaders;
private final CompoundTypeProperty<V, ?>[] properties;
public CtCompoundType(Class<V> cvoClass, CompoundType<V> cvoType, ScalarDataReader<Object>[] propReaders) {
this.cvoClass = cvoClass;
this.cvoType = cvoType;
this.properties = cvoType.getProperties();
this.propReaders = propReaders;
}
public String toString() {
return cvoClass.toString();
}
public Class<V> getCompoundTypeClass() {
return cvoClass;
}
public V create(Object[] propertyValues) {
return cvoType.create(propertyValues);
}
public V create(Map<String, Object> valueMap) {
if (valueMap.size() != properties.length) {
// not enough elements in the map
return null;
}
// we expect the map to contain a value for
// each property and that the values are the
// correct type
Object[] propertyValues = new Object[properties.length];
for (int i = 0; i < properties.length; i++) {
propertyValues[i] = valueMap.get(properties[i].getName());
if (propertyValues[i] == null) {
String m = "Null value for " + properties[i].getName() + " in map " + valueMap;
throw new RuntimeException(m);
}
}
return create(propertyValues);
}
public V read(DataReader source) throws SQLException {
boolean nullValue = false;
Object[] values = new Object[propReaders.length];
for (int i = 0; i < propReaders.length; i++) {
Object o = propReaders[i].read(source);
values[i] = o;
if (o == null) {
nullValue = true;
}
}
if (nullValue) {
return null;
}
return create(values);
}
public void loadIgnore(DataReader dataReader) {
for (ScalarDataReader<Object> propReader : propReaders) {
propReader.loadIgnore(dataReader);
}
}
public void bind(DataBind b, V value) throws SQLException {
CompoundTypeProperty<V, ?>[] props = cvoType.getProperties();
for (int i = 0; i < props.length; i++) {
Object o = props[i].getValue(value);
propReaders[i].bind(b, o);
}
}
/**
* Recursively accumulate all the scalar types (in depth first order).
* <p>
* This creates a flat list of scalars even when compound types are embedded
* inside compound types.
* </p>
*/
public void accumulateScalarTypes(String parent, CtCompoundTypeScalarList list) {
CompoundTypeProperty<V, ?>[] props = cvoType.getProperties();
for (int i = 0; i < propReaders.length; i++) {
String propName = getFullPropName(parent, props[i].getName());
list.addCompoundProperty(propName, this, props[i]);
propReaders[i].accumulateScalarTypes(propName, list);
}
}
/**
* Return the full property name (for compound types embedded in other
* compound types).
*
* @param parent the parent property name
* @param propName the local property name
*/
private String getFullPropName(String parent, String propName) {
if (parent == null) {
return propName;
} else {
return parent + "." + propName;
}
}
public Object jsonConvert(Map<String, Object> map) {
return readJsonElementObject(map);
}
@SuppressWarnings("unchecked")
private Object readJsonElementObject(Map<String, Object> jsonObject) {
boolean nullValue = false;
Object[] values = new Object[propReaders.length];
for (int i = 0; i < propReaders.length; i++) {
String propName = properties[i].getName();
Object jsonElement = jsonObject.get(propName);
if (propReaders[i] instanceof CtCompoundType<?>) {
values[i] = ((CtCompoundType<?>) propReaders[i]).readJsonElementObject((Map<String, Object>) jsonElement);
} else {
values[i] = ((ScalarType<?>) propReaders[i]).parse(jsonElement.toString());
}
if (values[i] == null) {
nullValue = true;
}
}
if (nullValue) {
return null;
}
return create(values);
}
public void jsonWrite(WriteJson ctx, Object valueObject, String propertyName) throws IOException {
ctx.beginAssocOne(propertyName, valueObject);
jsonWriteProps(ctx, valueObject);
ctx.endAssocOne();
}
@SuppressWarnings({"unchecked", "rawtypes"})
private void jsonWriteProps(WriteJson ctx, Object valueObject) throws IOException {
ctx.gen().writeStartObject();
for (int i = 0; i < properties.length; i++) {
String propName = properties[i].getName();
Object value = properties[i].getValue((V) valueObject);
if (propReaders[i] instanceof CtCompoundType<?>) {
ctx.writeFieldName(propName);
((CtCompoundType) propReaders[i]).jsonWrite(ctx, value, propName);
} else {
ctx.writeFieldName(propName);
((ScalarType) propReaders[i]).jsonWrite(ctx.gen(), value);
}
}
ctx.gen().writeEndObject();
}
}
@@ -1,67 +0,0 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebean.config.CompoundTypeProperty;
import com.avaje.ebeaninternal.server.query.SplitName;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
/**
* Used to build a flat list of all the scalar types nested in a compound type.
*/
public final class CtCompoundTypeScalarList {
private final LinkedHashMap<String, ScalarType<?>> scalarProps = new LinkedHashMap<>();
private final LinkedHashMap<String, CtCompoundProperty> compoundProperties = new LinkedHashMap<>();
/**
* Return the list of non-scalar properties. These occur when compound types are nested.
*/
public List<CtCompoundProperty> getNonScalarProperties() {
List<CtCompoundProperty> nonScalarProps = new ArrayList<>();
for (String propKey : compoundProperties.keySet()) {
if (!scalarProps.containsKey(propKey)) {
nonScalarProps.add(compoundProperties.get(propKey));
}
}
return nonScalarProps;
}
/**
* Register a property with it's associated compound type and relative name.
*/
public void addCompoundProperty(String propName, CtCompoundType<?> t, CompoundTypeProperty<?, ?> prop) {
CtCompoundProperty parent = null;
String[] split = SplitName.split(propName);
if (split[0] != null) {
parent = compoundProperties.get(split[0]);
}
CtCompoundProperty p = new CtCompoundProperty(propName, parent, t, prop);
compoundProperties.put(propName, p);
}
/**
* Register a scalarType used in the compound type with its given property name.
*/
public void addScalarType(String propName, ScalarType<?> scalar) {
scalarProps.put(propName, scalar);
}
public CtCompoundProperty getCompoundType(String propName) {
return compoundProperties.get(propName);
}
public Set<Entry<String, ScalarType<?>>> entries() {
return scalarProps.entrySet();
}
}
@@ -1,95 +0,0 @@
package com.avaje.ebeaninternal.server.type;
import java.util.HashMap;
import java.util.Map;
/**
* Used to build Immutable Compound Value objects.
* <p>
* The individual values are collected for a given type and when they have all
* been collected then the immutable compound value object is created and
* returned.
* </p>
*/
public final class ImmutableCompoundTypeBuilder {
private static final ThreadLocal<ImmutableCompoundTypeBuilder> local = new ThreadLocal<ImmutableCompoundTypeBuilder>() {
protected synchronized ImmutableCompoundTypeBuilder initialValue() {
return new ImmutableCompoundTypeBuilder();
}
};
private final Map<Class<?>, Entry> entryMap = new HashMap<>();
/**
* Clear the cache of partial compound objects.
*/
public static void clear() {
local.get().entryMap.clear();
}
/**
* Set the value for the property of a compound type.
* <p>
* If this is the last value required for the compound type then the
* compound type is created and returned, otherwise null is returned (and we
* need more values set).
* </p>
*/
public static Object set(CtCompoundType<?> ct, String propName, Object value) {
return local.get().setValue(ct, propName, value);
}
private Object setValue(CtCompoundType<?> ct, String propName, Object value) {
Entry e = getEntry(ct);
Object compoundValue = e.set(propName, value);
if (compoundValue != null) {
removeEntry(ct);
}
return compoundValue;
}
/**
* Once we have built a compound value we remove the entry.
*/
private void removeEntry(CtCompoundType<?> ct) {
entryMap.remove(ct.getCompoundTypeClass());
}
/**
* Get the Entry which contains the values collected so far for this type.
*/
private Entry getEntry(CtCompoundType<?> ct) {
Entry e = entryMap.get(ct.getCompoundTypeClass());
if (e == null) {
e = new Entry(ct);
entryMap.put(ct.getCompoundTypeClass(), e);
}
return e;
}
/**
* Holds the values collected so far for a given compound type.
*/
private static class Entry {
private final CtCompoundType<?> ct;
private final Map<String, Object> valueMap;
private Entry(CtCompoundType<?> ct) {
this.ct = ct;
this.valueMap = new HashMap<>();
}
private Object set(String propName, Object value) {
// collect the values...
valueMap.put(propName, value);
// when got all the values this returns the
// compound value, otherwise null
return ct.create(valueMap);
}
}
}
@@ -1,118 +0,0 @@
package com.avaje.ebeaninternal.server.type;
import java.util.Collection;
import java.util.Iterator;
/**
* Wraps a collection for the purposes of detecting modifications.
*/
public class ModifyAwareCollection<E> implements Collection<E> {
protected final ModifyAwareOwner owner;
protected final Collection<E> c;
/**
* Create with an Owner and the underlying collection this wraps.
* <p>
* The owner is notified of the additions and removals.
* </p>
*/
public ModifyAwareCollection(ModifyAwareOwner owner, Collection<E> c) {
this.owner = owner;
this.c = c;
}
public String toString() {
return c.toString();
}
public boolean add(E o) {
if (c.add(o)) {
owner.markAsModified();
return true;
}
return false;
}
public boolean addAll(Collection<? extends E> collection) {
boolean changed = false;
for (E o : collection) {
if (c.add(o)) {
owner.markAsModified();
changed = true;
}
}
return changed;
}
public void clear() {
if (!c.isEmpty()) {
owner.markAsModified();
}
c.clear();
}
public boolean contains(Object o) {
return c.contains(o);
}
public boolean containsAll(Collection<?> collection) {
return c.containsAll(collection);
}
public boolean isEmpty() {
return c.isEmpty();
}
public Iterator<E> iterator() {
return new ModifyAwareIterator<>(owner, c.iterator());
}
public boolean remove(Object o) {
if (c.remove(o)) {
owner.markAsModified();
return true;
}
return false;
}
public boolean removeAll(Collection<?> collection) {
boolean changed = false;
for (Object element : collection) {
if (c.remove(element)) {
owner.markAsModified();
changed = true;
}
}
return changed;
}
public boolean retainAll(Collection<?> collection) {
boolean changed = false;
Iterator<?> it = c.iterator();
while (it.hasNext()) {
Object o = it.next();
if (!collection.contains(o)) {
it.remove();
owner.markAsModified();
changed = true;
}
}
return changed;
}
public int size() {
return c.size();
}
public Object[] toArray() {
return c.toArray();
}
public <T> T[] toArray(T[] a) {
//noinspection SuspiciousToArrayCall
return c.toArray(a);
}
}
@@ -1,38 +0,0 @@
package com.avaje.ebeaninternal.server.type;
import java.util.Set;
/**
* Wraps a Set for the purposes of detecting modifications.
*/
public class ModifyAwareSet<E> extends ModifyAwareCollection<E> implements Set<E>, ModifyAwareOwner {
/**
* Create with an Owner that is notified of modifications.
*/
public ModifyAwareSet(ModifyAwareOwner owner, Set<E> s) {
super(owner, s);
}
/**
* Create as top level with it's own ModifyAwareOwner instance wrapping the given Set.
*/
public ModifyAwareSet(Set<E> s) {
super(new ModifyAwareFlag(), s);
}
@Override
public boolean isMarkedDirty() {
return owner.isMarkedDirty();
}
@Override
public void markAsModified() {
owner.markAsModified();
}
@Override
public void resetMarkedDirty() {
owner.resetMarkedDirty();
}
}
@@ -1,15 +0,0 @@
package com.avaje.ebeaninternal.server.type;
import java.util.Set;
/**
* Marker interface for the Enum scalar types.
*/
public interface ScalarTypeEnum {
/**
* Return the IN values for DB constraint construction.
*/
Set<String> getDbCheckConstraintValues();
}
@@ -1,51 +0,0 @@
package com.avaje.ebeaninternal.server.type;
import com.avaje.ebeaninternal.server.core.BasicTypeConverter;
import org.joda.time.DateMidnight;
import java.sql.Date;
import java.sql.Types;
/**
* ScalarType for Joda DateMidnight. This maps to a JDBC Date.
*/
public class ScalarTypeJodaDateMidnight extends ScalarTypeBaseDate<DateMidnight> {
/**
* Instantiates a new scalar type joda date midnight.
*/
public ScalarTypeJodaDateMidnight() {
super(DateMidnight.class, false, Types.DATE);
}
@Override
public long convertToMillis(DateMidnight value) {
return value.getMillis();
}
@Override
public DateMidnight convertFromDate(Date ts) {
return new DateMidnight(ts.getTime());
}
@Override
public Date convertToDate(DateMidnight t) {
return new Date(t.getMillis());
}
@Override
public Object toJdbcType(Object value) {
if (value instanceof DateMidnight) {
return new Date(((DateMidnight) value).getMillis());
}
return BasicTypeConverter.toDate(value);
}
@Override
public DateMidnight toBeanType(Object value) {
if (value instanceof java.util.Date) {
return new DateMidnight(((java.util.Date) value).getTime());
}
return (DateMidnight) value;
}
}
@@ -1,42 +0,0 @@
package com.avaje.ebeaninternal.server.type;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class TypeReflectHelper {
public static Class<?>[] getParams(Class<?> cls, Class<?> matchRawType) {
Type[] types = getParamType(cls, matchRawType);
Class<?>[] result = new Class<?>[types.length];
for (int i = 0; i < result.length; i++) {
result[i] = getClass(types[i]);
}
return result;
}
public static Class<?> getClass(Type type) {
if (type instanceof ParameterizedType) {
return getClass(((ParameterizedType) type).getRawType());
}
return (Class<?>) type;
}
private static Type[] getParamType(Class<?> cls, Class<?> matchRawType) {
Type[] gis = cls.getGenericInterfaces();
for (Type type : gis) {
if (type instanceof ParameterizedType) {
ParameterizedType paramType = (ParameterizedType) type;
Type rawType = paramType.getRawType();
if (rawType.equals(matchRawType)) {
return paramType.getActualTypeArguments();
}
}
}
return null;
}
}

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