Compare commits

...
Author SHA1 Message Date
Robin Bygrave 7984553d96 [maven-release-plugin] prepare release avaje-ebeanorm-6.4.1 2015-08-26 10:48:35 +12:00
Robin Bygrave d592e7d35f No effective change - format only 2015-08-26 10:47:22 +12:00
Robin Bygrave 5a0b65b4f2 Bump pom to 6.4.1-SNAPSHOT 2015-08-26 10:45:06 +12:00
Robin Bygrave aaefaa5dcd #390 - ChangeLog - Add inheritance hierarchy check for @ChangeLog 2015-08-26 10:42:12 +12:00
Robin Bygrave f3e66c459a #390 - ChangeLog - Add ServerConfig.isChangeLogIncludeInserts() and ChangeLogInsertMode enum with associated changes 2015-08-25 13:54:34 +12:00
Robin Bygrave 16d5e04809 #390 - ChangeLog - Change userContext to be Map<String,String> 2015-08-25 13:22:09 +12:00
Robin Bygrave b01df515bd #390 - ChangeLog - Refactor DefaultChangeLogListener (simplify to use standard logger) 2015-08-25 13:05:58 +12:00
Robin Bygrave 7fda911931 #394 - ENH: SpiServer - Add getServerConfig() to the api 2015-08-25 13:04:36 +12:00
Robin Bygrave e332aace16 No effective change - format test logback-test.xml 2015-08-25 11:54:11 +12:00
Robin Bygrave c79231c846 #394 - ENH: Add plugin API SpiServer - add shutdown() method to SpiServerPlugin. 2015-08-25 11:52:58 +12:00
Robin Bygrave efad23d482 #390 - ENH: Add Change log mechanism - javadoc update - no effective change 2015-08-25 08:12:22 +12:00
Robin Bygrave fe8a32ea18 #390 - ENH: Add Change log mechanism for easy fine grained logging of insert, update, delete activity.
This adds default implementations for register,filter, prepare and log of the change sets.
2015-08-22 12:10:30 +12:00
Robin Bygrave 31099f6dda #397 - Internal logger name change - Rename DefaultContainer logger to be com.avaje.ebean.internal.DefaultContainer ... so that the offline debugging messages come out without a extra logback name logger entry 2015-08-22 12:02:21 +12:00
Robin Bygrave 58f4f791f6 Opps - remove Oracle jdbc and MS SQL Server jdbc drivers ... (put those in here by mistake during @History testing). 2015-08-22 10:18:46 +12:00
Robin Bygrave b27989f541 #396 - Rename migration method to DbMigration.generateMigration() ... update javadoc 2015-08-21 21:37:36 +12:00
Robin Bygrave 7bc1a902ed No effective change - code format only 2015-08-21 21:10:22 +12:00
Robin Bygrave 358720776e No effective change - code format only 2015-08-21 21:08:29 +12:00
Robin Bygrave 417ee4061e #395 - No functional change - cleanup unused BeanDelta 2015-08-21 21:06:33 +12:00
Robin Bygrave 394cb3854a No effective change - format and organise imports 2015-08-21 18:31:55 +12:00
Robin Bygrave 547fa342c4 Internal change only - just reuse class name as bean descriptor key 2015-08-21 18:28:10 +12:00
Robin Bygrave f8b8a41bce #394 - ENH: Add plugin API SpiServer, SpiBeanType ... migrate plugins towards using this API, migrate away from direct use of BeanDescriptor etc. 2015-08-21 17:33:43 +12:00
Robin Bygrave ba39897b18 ChangeSet - add size() method 2015-08-21 16:05:30 +12:00
Robin Bygrave 1437843f08 #393 - ENH: Add ServerConfig.getProperties() ... serverConfig remembers the properties that were used in configuration in order to make these available to plugins 2015-08-21 16:05:09 +12:00
Robin Bygrave 7c705e2baa #377 - Add back support for JsonWriteBeanVisitor 2015-08-21 08:20:47 +12:00
Robin Bygrave 2caeb4fff1 #392 - Fix for AutoCommit mode ... fixing change from #204 ... such that AutoCommitJdbcTransaction works as expected 2015-08-20 22:38:53 +12:00
Robin Bygrave 84190f3c2a #390 - ENH: Add Change log mechanism for easy fine grained logging of insert, update, delete activity 2015-08-20 20:46:28 +12:00
Robin Bygrave 46b158a0a0 #391 - Minor internals - Ebean catch Throwable on instantiation rather than RuntimeException 2015-08-20 10:08:54 +12:00
Robin Bygrave b172a32710 No effective change - remove commented out test 2015-08-19 15:58:13 +12:00
Robin Bygrave f8ef87f7a8 #389 - ENH: Allow Postgres8 platform also support identity (stills defaults to use sequences but can also use identity if defined explicitly) 2015-08-19 13:24:58 +12:00
Robin Bygrave ea54d1b794 #388 - Postgres DbType.HSTORE ... not registered as logical type for DbMigration 2015-08-19 13:16:22 +12:00
Robin Bygrave b1780948a8 #387 - Change ebeanServer.diff() to default to 'flat' mode 2015-08-19 12:47:31 +12:00
Robin Bygrave 1a0f3a6614 #386 - ENH: Add setDistinct() onto ExpressionList ... so you don't need to get back to the query(and #385 javadoc) 2015-08-19 12:37:53 +12:00
Robin Bygrave 580b51381e #384 - ENH: Add findVersionsBetween(start, end) ... including implementation support for Oracle total recall 2015-08-18 23:57:11 +12:00
Robin Bygrave 75e9770d5e #383 - Refactor - Rename Oracle10Platform to OraclePlatform, remove Oracle9Platform (as not different) 2015-08-18 22:26:44 +12:00
Robin Bygrave 10937de24b #382 - ENH: Add support for @History using Oracle Total Recall ... for 'as of' queries 2015-08-18 22:19:55 +12:00
Robin Bygrave 18aeedc153 #381 - Change DbMigration to use default server platform when no platform specified 2015-08-18 22:15:11 +12:00
Robin Bygrave 9ca1a87f8b No effective change - add missing javadoc 2015-08-18 22:13:12 +12:00
Robin Bygrave 111354f391 [maven-release-plugin] prepare for next development iteration 2015-08-18 08:21:32 +12:00
Robin Bygrave 79879fb326 [maven-release-plugin] prepare release avaje-ebeanorm-6.3.1 2015-08-18 08:21:11 +12:00
Robin Bygrave 9f6ccdee66 #369 - Add test .sql resources 2015-08-18 08:16:19 +12:00
Robin Bygrave bbf469bd54 #369 - Rollback of base column attributes 2015-08-18 08:02:37 +12:00
Robin Bygrave ad97ac2be9 #369 - Rollback of create index - drop index 2015-08-18 07:00:34 +12:00
Robin Bygrave 9d83017374 #379 - Add MySql support for @History 2015-08-18 06:13:59 +12:00
Robin Bygrave 98ec00a2d6 #374 - Add @History support with MySql - refactor extracting DbTriggerBasedHistoryDdl 2015-08-17 22:12:06 +12:00
Robin Bygrave 24971bcc86 #374 - Refactor to support generating multiple platform DDL for a single migration 2015-08-17 16:03:51 +12:00
Robin Bygrave c1c45139a0 #374 - Cleanup - remove 'all' migration xml 2015-08-17 14:48:29 +12:00
Robin Bygrave 116425b460 #374 - Add support for rollback on history function 2015-08-17 14:43:44 +12:00
Robin Bygrave 48acb6294b #374 - Add DropIndex and CreateIndex migration 2015-08-17 13:06:05 +12:00
Robin Bygrave 61f5057528 #374 - Add DropIndex and CreateIndex migration 2015-08-17 13:05:54 +12:00
Robin Bygrave b91ef46243 #374 - Cleanup - remove unused migration objects 2015-08-17 11:42:12 +12:00
Robin Bygrave 0eddcc30bb #374 - Cleanup - remove unused migration objects 2015-08-17 11:42:06 +12:00
Robin Bygrave 24ec0fefba #374 - DbConstrainNaming - add index naming 2015-08-17 11:41:49 +12:00
Robin Bygrave 5ac28cb3fb #374 - BaseTableDdl change to protected visibility 2015-08-17 11:41:31 +12:00
Robin Bygrave d4635fb615 #374 - Add PlatformDdl.configure() and move add fk and create index onto PlatformDdl 2015-08-17 08:35:43 +12:00
Robin Bygrave b9774e64e9 #374 - Add comments for when a history table trigger/function is regenerated 2015-08-17 07:44:59 +12:00
Robin Bygrave f29ba8383e #374 - Find whenCreatedColumn and use as default effective start when adding history 2015-08-16 20:19:52 +12:00
Robin Bygrave a15dd33380 #374 - Add GeneratedWhenCreated and GeneratedWhenModified marker interfaces etc - used to find bean properties with those behaviours 2015-08-16 20:08:56 +12:00
Robin Bygrave f22563b36a #374 - ms sql server ... alter column default values 2015-08-15 16:53:02 +12:00
Robin Bygrave fe17ec5dbb #374 - Update tests 2015-08-15 16:09:27 +12:00
Robin Bygrave 85fdf8646d #374 - Update migration generation 2015-08-15 01:58:35 +12:00
Robin Bygrave bd9acab335 #374 - Update ModelDiff and migration generation 2015-08-15 00:06:24 +12:00
Robin Bygrave 0a6941bda5 #374 - Update ModelDiff and migration generation 2015-08-15 00:06:14 +12:00
Robin Bygrave 215417a43c #374 - Move db constraint max length to database platform 2015-08-14 17:06:08 +12:00
Robin Bygrave 60c1a5b111 #374 - Add DbOffline check into TransactionManager isReadCommittedIsolation() 2015-08-14 17:02:58 +12:00
Robin Bygrave 5166fbed96 #374 - Merge BaseColumnDdl into BaseTableDdl 2015-08-14 12:14:18 +12:00
Robin Bygrave 851f40e7b0 DbMigration update - constraints up front 2015-08-11 08:25:29 +12:00
Robin Bygrave 845faf74ff WIP: Db migration alterColumn ... 2015-08-10 14:26:47 +12:00
Robin Bygrave c0d4dac2b3 #374 - Update example/sample xml for xml schema changes 2015-08-07 13:26:35 +12:00
Robin Bygrave f6c3279e86 #374 - Table remarks -> comment 2015-08-07 13:25:22 +12:00
Robin Bygrave 48f0da9343 No effective change - update test to give slf4j a little time in multithreaded case to catch logged sql 2015-08-07 13:24:26 +12:00
Robin Bygrave ce0d73cf23 #374 - updated migration xml generated 2015-08-07 13:23:25 +12:00
Robin Bygrave 1585bd7cd0 #374 - ChangeSetType ... baseline, CreateHistoryTable whenCreatedColumn 2015-08-07 12:46:17 +12:00
Robin Bygrave 1603c69156 #374 - IdentityType lowered 2015-08-07 12:45:45 +12:00
Robin Bygrave 7cd9dc0c8d Quiet down the logging of enhancement via AgentLoader 2015-08-07 12:45:03 +12:00
Robin Bygrave e4304494e1 #374 - ChangeSetType ... baseline, CreateHistoryTable whenCreatedColumn 2015-08-07 12:44:13 +12:00
Robin Bygrave 0612d89e9a #376 - Refactor - Remove PstmtDelegate ... that was used to access the underlying oracle specific PreparedStatement 2015-08-06 23:03:25 +12:00
Robin Bygrave e6f779268a Update .gitignore to include ddl-review directory 2015-08-06 22:26:23 +12:00
Robin Bygrave 815d846695 Add ddl-review with sql/ddl for the various databases, can review/diff over time 2015-08-06 22:25:35 +12:00
Robin Bygrave 4b74062d80 #374 - uniqueOneToOne reflected in migration.xml 2015-08-06 22:03:18 +12:00
Robin Bygrave 1dd0841f00 #374 - MsSqlServer - adjust tests (due to jdbc batch support etc) add in support for unique index handling 2015-08-06 21:49:04 +12:00
Robin Bygrave 3a9668fe6c #375 - javax.persistence.PersistenceException: Query threw SQLException:Incorrect syntax near the keyword distinct 2015-08-06 19:30:57 +12:00
Robin Bygrave 93f802f7fe #374 - Drop foreign keys before indexes 2015-08-06 13:37:51 +12:00
Robin Bygrave 8cde0da419 #374 - Update tests for cross db (order by and too fast) 2015-08-06 13:36:55 +12:00
Robin Bygrave 14f984ea3e #374 - Remove old DbDdlSyntax - move to PlatformDdl 2015-08-06 13:09:41 +12:00
Robin Bygrave 253bebb9bb No effective change - camel case variable names 2015-08-06 12:27:03 +12:00
Robin Bygrave 483538bbc1 #374 -Move DdlGenerator 2015-08-06 12:16:06 +12:00
Robin Bygrave c0ef6d8b34 #374 - removed old ddl generation mechanism 2015-08-06 12:04:41 +12:00
Robin Bygrave 7f06863b19 #374 - SpiEbeanPlugin API change : DatabasePlatform dbPlatform parameter removed 2015-08-06 12:03:32 +12:00
Robin Bygrave 8be7ee1b7d identityType="EXTERNAL" - Internal changes for DB Migration / DDL generation #369 2015-08-06 11:51:00 +12:00
Robin Bygrave 15e2fde864 Postgres updated migration xml - Internal changes for DB Migration / DDL generation #369 2015-08-06 11:46:29 +12:00
Robin Bygrave 4e5140c877 Postgres dropTableCascade - Internal changes for DB Migration / DDL generation #369 2015-08-06 11:46:12 +12:00
Robin Bygrave 13ed298ee8 MySql update - Internal changes for DB Migration / DDL generation #369 2015-08-06 11:15:31 +12:00
Robin Bygrave e83a6f05bc Oracle specific changes - Internal changes for DB Migration / DDL generation #369 2015-08-06 08:09:20 +12:00
Robin Bygrave a0c312e5a4 #373 - Internals for Oracle - Remove the oracle proprietary jdbc batch handling in favour of standard jdbc batch api 2015-08-06 08:06:46 +12:00
Robin Bygrave 1eabb7fdb4 #373 - Internals for Oracle - Remove the oracle proprietary jdbc batch handling in favour of standard jdbc batch api 2015-08-06 08:02:44 +12:00
Robin Bygrave 9e170b40f6 Support duplicate index detection, max constraint names - Internal changes for DB Migration / DDL generation #369 2015-08-06 07:39:50 +12:00
Robin Bygrave efd5e16511 Update tests for better cross database execution (ordering of results etc) 2015-08-06 07:27:04 +12:00
Robin Bygrave c4e0d7aedc Internal - BeanRequest.rollbackTransIfRequired() ... change catch from PersistenceException -> Exception #371 2015-08-06 05:31:55 +12:00
Robin Bygrave d1584bed40 Change tests for better portability - Internal changes for DB Migration / DDL generation #369 2015-08-06 05:28:25 +12:00
Robin Bygrave 689d201b04 Update for pg - Internal changes for DB Migration / DDL generation #369 2015-08-05 20:59:09 +12:00
Robin Bygrave 22407506ff DB migration initial 2015-08-04 23:23:32 +12:00
Robin Bygrave 009f91b949 WIP Db Migration compound keys 2015-08-04 19:48:47 +12:00
Robin Bygrave 3bd281bea0 DB migration initial 2015-08-04 17:37:16 +12:00
Robin Bygrave 30c3a435d6 Internal changes for DB Migration / DDL generation #369 2015-08-03 17:29:57 +12:00
Robin Bygrave 0fe321b0ef Bump pom to 6.3.1-SNAPSHOT 2015-08-03 17:23:40 +12:00
Robin Bygrave 8f12442ac7 #363 - API CHANGE - BeanPersistController postLoad() ... moved to new/separate BeanPostLoad interface 2015-08-02 21:56:56 +12:00
Robin Bygrave 40ab3c81dc #364 - CallableStatement with a parameter that is both IN and OUT (so an INOUT parameter) 2015-08-02 15:24:01 +12:00
Robin Bygrave d5a8bf38ad No effective change - @SuppressWarnings("unchecked") 2015-08-02 13:48:15 +12:00
Robin Bygrave 0e793036fb No effective change - remove unused ScalarTypeConverter from BeanPropertyCompound (ala wrapper type like Option) 2015-08-02 13:27:32 +12:00
Robin Bygrave 19b7637d46 No effective change - param always true 2015-08-02 13:18:40 +12:00
Robin Bygrave 5609bc6d02 No effective change - add extra tests 2015-08-02 13:07:48 +12:00
Robin Bygrave fceeeacf88 #367 - ENH: Add EbeanServer deleteAll() with an explicit transaction 2015-08-02 12:43:19 +12:00
Robin Bygrave 4327108ddf No effective change - param always null, removed 2015-08-02 11:27:49 +12:00
Robin Bygrave cb77f33fc8 No effective change - param always null, removed 2015-08-02 11:22:46 +12:00
Robin Bygrave b687305be2 No effective change - param always true, removed 2015-08-02 11:15:43 +12:00
Robin Bygrave 192305c61f No effective change - suppress code inspection warnings 2015-08-02 11:06:38 +12:00
Robin Bygrave 03faf29bcf #366 - ServerConfigStart when registered via instance rather than class not fired 2015-08-02 11:02:02 +12:00
Robin Bygrave d389f8b5ac No effective change - remove unread variable 2015-08-02 09:52:56 +12:00
Robin Bygrave 56348938fb No effective change - remove unread variable (include props) 2015-08-02 09:48:00 +12:00
Robin Bygrave 9b0aafbfa8 No effective change - remove unused fields 2015-08-02 09:37:17 +12:00
Robin Bygrave 9239d61c74 No effective change - simplify ManyType to be an enum 2015-08-02 09:34:11 +12:00
Robin Bygrave 58a110e109 No effective change - remove unused 2015-08-02 09:33:46 +12:00
Robin Bygrave b255102780 No effective change - remove unused 2015-08-02 09:18:49 +12:00
Robin Bygrave 3a14b4c87f No effective change - remove unused methods 2015-08-02 09:17:10 +12:00
Robin Bygrave e1d6bf5961 No effective change - BeanPropertyAssocOne - importedPrimaryKey never set 2015-08-02 09:04:46 +12:00
Robin Bygrave 8e546bde0b No effective change - remove unused methods 2015-08-02 09:04:07 +12:00
Robin Bygrave 29a97d84a1 No effective change - format only 2015-08-02 08:55:36 +12:00
Robin Bygrave c526b3ef57 DataSourcePool - use IllegalArgumentException - remove need for DataSourceException 2015-08-02 08:54:00 +12:00
Robin Bygrave 032721d246 No effective change - remove unused 2015-08-02 08:51:40 +12:00
Robin Bygrave 0731084ec0 No effective change - remove unused 2015-08-02 08:47:37 +12:00
Robin Bygrave 11a3e49daa No effective change - remove unused 2015-08-02 08:41:10 +12:00
Robin Bygrave 68481844ee No effective change - param always true 2015-08-02 08:24:44 +12:00
Robin Bygrave 96a9def513 No effective change - LoadBeanRequest / LoadManyRequest cleanup of constructors 2015-08-01 22:35:35 +12:00
Robin Bygrave 98a4f046ee No effective change - format only 2015-08-01 22:21:08 +12:00
Robin Bygrave 9db8c941dc No effective change - SplitName - extract constant 2015-08-01 22:20:24 +12:00
Robin Bygrave fd4a6906bd No effective change - SqlTreeNodeBean cleanup - always same value params 2015-08-01 22:17:50 +12:00
Robin Bygrave da65256208 No effective change - ArrayStack cleanup 2015-08-01 22:00:00 +12:00
Robin Bygrave 0d2615522f No effective change - suppress warnings, simplify if 2015-08-01 21:16:03 +12:00
Robin Bygrave 6e5e5fb666 No effective change - remove unused assignment 2015-08-01 21:07:57 +12:00
Robin Bygrave 8005ef8432 No effective change - simplify if 2015-08-01 21:07:09 +12:00
Robin Bygrave 49fe97bbe4 No effective change - simplify if 2015-08-01 21:06:36 +12:00
Robin Bygrave 95ab97df73 No effective change - add code inspection suppression comments 2015-08-01 21:01:53 +12:00
Robin Bygrave 3be9833ee0 No effective change - DeployBeanPropertyLists cleanup - Assoc One / Many types when collected 2015-08-01 20:58:43 +12:00
Robin Bygrave b82223dc1d No effective change - add code inspection suppression comments 2015-08-01 20:41:50 +12:00
Robin Bygrave 17d97623d5 No effective change - add test HashQueryPlanTest 2015-08-01 20:41:07 +12:00
Robin Bygrave 1fca5ba008 BeanMap - code cleanup - while loop to foreach 2015-08-01 20:17:57 +12:00
Robin Bygrave 5bb97ee42f No effective change - code cleanup - remove unnecessary boxing 2015-08-01 20:12:09 +12:00
Robin Bygrave ae9a03e58c No effective change - code cleanup - remove unused 2015-08-01 20:11:21 +12:00
Robin Bygrave ca12761fb2 No effective change - code cleanup - remove unused 2015-08-01 20:06:13 +12:00
Robin Bygrave 18a61416fd No effective change - code cleanup - unused imports 2015-08-01 20:03:31 +12:00
Robin Bygrave 37ff2c7227 No effective change - code cleanup - removed unused param 2015-08-01 20:02:19 +12:00
Robin Bygrave af4018403b No effective change - code cleanup - removed unused param 2015-08-01 19:59:54 +12:00
Robin Bygrave d3b9bde5c2 No effective change - code cleanup - removed unused param 2015-08-01 19:59:01 +12:00
Robin Bygrave d704fef294 No effective change - code cleanup - removed unused param 2015-08-01 19:57:53 +12:00
Robin Bygrave bb4bb64795 No effective change - code cleanup - removed unused param 2015-08-01 19:55:52 +12:00
Robin Bygrave 402ab092d8 No effective change - code cleanup - removed unused param 2015-08-01 19:53:07 +12:00
Robin Bygrave 9769e4b574 No effective change - code cleanup - removed unused param 2015-08-01 19:47:05 +12:00
Robin Bygrave e19fe5ccd3 No effective change - code cleanup - removed unused param 2015-08-01 19:42:39 +12:00
Robin Bygrave 11963e1ff7 No effective change - code cleanup - removed unused param 2015-08-01 19:41:07 +12:00
Robin Bygrave ec0d4fbd07 No effective change - code cleanup - removed unused param 2015-08-01 19:38:40 +12:00
Robin Bygrave 4e66e348fc No effective change - code cleanup - removed unused param 2015-08-01 19:36:52 +12:00
Robin Bygrave eb6fce5a72 No effective change - code cleanup - removed unused param - TypeManager 2015-08-01 19:33:48 +12:00
Robin Bygrave 21b33bb9cd No effective change - code cleanup - removed unused BeanCollectionParams 2015-08-01 19:30:06 +12:00
Robin Bygrave 430b3cff96 No effective change - code cleanup - removed not required throws 2015-08-01 19:29:09 +12:00
Robin Bygrave 334a8b66bd No effective change - code cleanup - removed not required throws 2015-08-01 19:20:51 +12:00
Robin Bygrave 204b9ca6e5 No effective change - code cleanup - return void (unused return values), remove unused methods 2015-08-01 17:54:06 +12:00
Robin Bygrave 93f13113e6 No effective change - code cleanup - return void (unused return values) 2015-08-01 17:51:04 +12:00
Robin Bygrave ca1f95df7a No effective change - code cleanup - remove unused 2015-08-01 17:40:40 +12:00
Robin Bygrave 0c9bcca584 No effective change - code cleanup - BeanPropertyOverride - unused override of sql formula 2015-08-01 17:21:09 +12:00
Robin Bygrave a27433dc11 No effective change - code cleanup - unused params 2015-08-01 17:16:33 +12:00
Robin Bygrave dbd789f4be No effective change - suppress warnings in test 2015-08-01 16:56:12 +12:00
Robin Bygrave 7efbffb46d No effective change - format only 2015-08-01 09:11:04 +12:00
Robin Bygrave 559383a810 No effective change - format only 2015-08-01 09:02:34 +12:00
Robin Bygrave 1897ac67a0 No effective change - OrmQueryDetail - remove unnecessary if, simplify if 2015-08-01 09:01:43 +12:00
Robin Bygrave 4f2d669897 No effective change - format only 2015-08-01 08:54:49 +12:00
Robin Bygrave f50b18556e No effective change - SqlTreeBuilder , remove unnecessary null check 2015-08-01 08:51:40 +12:00
Robin Bygrave 1dc8a7f314 Add int getPageSize() to PagedList 2015-08-01 08:42:37 +12:00
Robin Bygrave b526d07eed No effective change - remove unused methods and parameters, simplify if 2015-08-01 08:42:09 +12:00
Robin Bygrave 97cd0909e8 No effective change - format only 2015-07-31 23:10:26 +12:00
Robin Bygrave 39cb85fda6 No effective change - remove unused BindValue comment 2015-07-31 23:09:31 +12:00
Robin Bygrave 498f567e37 No effective change - format only 2015-07-31 23:03:17 +12:00
Robin Bygrave 99cecd6756 No effective change - simplify if, remove unused 2015-07-31 23:02:17 +12:00
Robin Bygrave 7ab374b4ee No effective change - format only 2015-07-31 22:59:02 +12:00
Robin Bygrave 22d36bd1c4 No effective change - remove unused 2015-07-31 22:55:58 +12:00
Robin Bygrave ebc4d9fdc5 No effective change - format only 2015-07-31 22:52:59 +12:00
Robin Bygrave b1c41a58f2 No effective change - remove unused 2015-07-31 22:51:45 +12:00
Robin Bygrave 40710f788d No effective change - remove unused 2015-07-31 22:49:13 +12:00
Robin Bygrave 5513c46f78 No effective change - format only 2015-07-31 22:47:37 +12:00
Robin Bygrave 8879bd2be8 No effective change - format only 2015-07-31 22:46:20 +12:00
Robin Bygrave 4ab8ced4a3 No effective change - remove unused 2015-07-31 22:45:40 +12:00
Robin Bygrave 5bb9e1b188 No effective change - format only 2015-07-31 22:45:32 +12:00
Robin Bygrave db97d4576f No effective change - code cleanup - remove unused for GenerateDmlRequest 2015-07-31 22:42:28 +12:00
Robin Bygrave c581fa27ab No effective change - code cleanup - remove unused 2015-07-31 22:29:32 +12:00
Robin Bygrave bef4e476d7 No effective change - code cleanup - remove unused 2015-07-31 22:26:44 +12:00
Robin Bygrave e30e35bf4f No effective change - code cleanup - remove unused 2015-07-31 22:25:09 +12:00
Robin Bygrave 2e1f02163c No effective change - code cleanup - remove unused - TableJoin properties 2015-07-31 22:22:57 +12:00
Robin Bygrave 1ce84ec343 No effective change - code cleanup - remove unused - methods 2015-07-31 22:06:34 +12:00
Robin Bygrave 6dc21ce69b No effective change - code cleanup - remove unused - methods 2015-07-31 22:03:45 +12:00
Robin Bygrave 8d5621248f No effective change - code cleanup - remove unused - objects 2015-07-31 22:00:52 +12:00
Robin Bygrave b73cc378b5 No effective change - code cleanup - remove unused - methods 2015-07-31 21:57:26 +12:00
Robin Bygrave 564c7b8317 No effective change - code cleanup - remove unused - methods 2015-07-31 21:55:35 +12:00
Robin Bygrave f4a61cddaf No effective change - code cleanup - remove unused - methods 2015-07-31 21:51:48 +12:00
Robin Bygrave 456f5c1d6a No effective change - code cleanup - remove unused - BeanSqlSelect 2015-07-31 21:48:34 +12:00
Robin Bygrave ae0404b1a7 No effective change - code cleanup - BeanRequest remove unused 2015-07-31 21:46:17 +12:00
Robin Bygrave 31f91e571d No effective change - code cleanup - format only 2015-07-31 21:44:08 +12:00
Robin Bygrave 20acd56bb9 No effective change - code cleanup - format only 2015-07-31 21:43:38 +12:00
Robin Bygrave a764006523 No effective change - code cleanup - remove unused propMap 2015-07-31 21:43:23 +12:00
Robin Bygrave 84b8777c2b No effective change - code cleanup - BeanPropertyAssoc cleanup 2015-07-31 21:41:28 +12:00
Robin Bygrave c0fc7d69a6 No effective change - code cleanup - remove unused validateCascade property 2015-07-31 21:38:05 +12:00
Robin Bygrave 4807ca32be No effective change - code cleanup - remove unused methods 2015-07-31 21:33:05 +12:00
Robin Bygrave 4c841a8f9f No effective change - code cleanup - remove unused BeanPathUpdate 2015-07-31 21:32:36 +12:00
Robin Bygrave 6babebfec5 No effective change - code cleanup - simplify if 2015-07-31 21:28:36 +12:00
Robin Bygrave 660666a28b No effective change - code cleanup - removed unused logger 2015-07-31 21:25:41 +12:00
Robin Bygrave 34550dd778 No effective change - code cleanup - BeanIdList - removed unused methods 2015-07-31 21:24:05 +12:00
Robin Bygrave 64bc0636d7 No effective change - code cleanup - empty method 2015-07-31 21:09:35 +12:00
Robin Bygrave aa199da57d No effective change - code cleanup - SocketCluster 2015-07-31 21:07:22 +12:00
Robin Bygrave b265ffd7d6 No effective change - code cleanup - ResourceSource 2015-07-31 21:02:31 +12:00
Robin Bygrave 00f4aee80a No effective change - code cleanup - remove unused throws exception 2015-07-31 20:58:18 +12:00
Robin Bygrave d6973ed88d No effective change - code cleanup - remove unused throws exception 2015-07-31 20:56:26 +12:00
Robin Bygrave 2ada43f6ba No effective change - code cleanup - remove unused throws exception 2015-07-31 20:53:31 +12:00
Robin Bygrave e800a18b31 No effective change - code cleanup - remove unused methods 2015-07-31 20:49:21 +12:00
Robin Bygrave ea5ceb61ca No effective change - code cleanup - BeanProperty - remove unused extraAttributeMap 2015-07-31 20:45:58 +12:00
Robin Bygrave 972609281f No effective change - code cleanup - BeanProperty - remove unused defaultValue 2015-07-31 20:43:30 +12:00
Robin Bygrave 4ea68ebce4 No effective change - code cleanup - IdBinder - remove unused method 2015-07-31 20:36:18 +12:00
Robin Bygrave d01c6262b6 No effective change - format only 2015-07-31 20:34:17 +12:00
Robin Bygrave 19e3d82d98 No effective change - code cleanup - BeanFkeyProperty 2015-07-31 20:32:27 +12:00
Robin Bygrave f06c1b83a9 No effective change - code cleanup - change return to void 2015-07-31 20:28:41 +12:00
Robin Bygrave ea504a93cf No effective change - code cleanup - remove redundant casts 2015-07-31 20:11:31 +12:00
Robin Bygrave 9fe47194ff No effective change - code cleanup - remove unnecessary boxing 2015-07-31 20:08:30 +12:00
Robin Bygrave ba3b1fea6f No effective change - code cleanup - suppress some warnings 2015-07-31 19:48:59 +12:00
Robin Bygrave 58088b2090 No effective change - code cleanup - remove unnecessary colon 2015-07-31 19:43:12 +12:00
Robin Bygrave cca7a505a3 No effective change - code cleanup - while to foreach on BeanList etc 2015-07-31 19:39:18 +12:00
Robin Bygrave ece7466117 No effective change - code cleanup - while to foreach 2015-07-31 16:51:43 +12:00
Robin Bygrave 3451280679 No effective change - code cleanup - while to foreach 2015-07-31 16:51:12 +12:00
Robin Bygrave bef2894949 No effective change - code cleanup - StringBuffer to StringBuilder 2015-07-31 15:02:46 +12:00
Robin Bygrave 06b6638926 No effective change - code cleanup - string indexOf to contains 2015-07-31 15:00:02 +12:00
Robin Bygrave 53cf6c162c No effective change - code cleanup - simplify if 2015-07-31 14:51:34 +12:00
Robin Bygrave 069b83b78d No effective change - code cleanup - unused imports 2015-07-31 14:37:13 +12:00
Robin Bygrave c0c56c0040 No effective change - code cleanup - remove redundant overrides 2015-07-31 14:14:25 +12:00
Robin Bygrave 92c298b848 No effective change - code cleanup - duplicate throws 2015-07-31 14:08:12 +12:00
Robin Bygrave 831d2a6179 No effective change - add final modifier 2015-07-31 14:07:09 +12:00
Robin Bygrave 90886193c0 No effective change - add final modifier 2015-07-31 14:02:38 +12:00
Robin Bygrave deed0bb01d No effective change - add final modifier 2015-07-31 13:53:10 +12:00
Robin Bygrave 7f2c705b94 No effective change - remove unused 2015-07-31 13:42:09 +12:00
Robin Bygrave 6c0401b191 No effective change - remove unused 2015-07-31 13:34:32 +12:00
Robin Bygrave 331d28b512 No effective change - Code cleanup, remove unused param 2015-07-31 13:33:35 +12:00
Robin Bygrave 9fd936c521 No effective change - Code cleanup, remove redundant variables 2015-07-31 13:29:42 +12:00
Robin Bygrave 4a13fc307b No effective change - Code cleanup, remove unnecessary return 2015-07-31 13:25:54 +12:00
Robin Bygrave adef15ce2b No effective change - Code cleanup, simplified if 2015-07-31 13:23:49 +12:00
Robin Bygrave 88340618af No effective change - Code cleanup, simplified if 2015-07-31 13:20:23 +12:00
Robin Bygrave 49b97887b0 No effective change - Code cleanup,remove unnecessary comma 2015-07-31 13:18:26 +12:00
Robin Bygrave 6843c72149 No effective change - Code cleanup,remove unnecessary public modifier on interfaces 2015-07-31 13:16:36 +12:00
Robin Bygrave f78c217d83 No effective change - Code cleanup,remove unnecessary public modifier on interfaces 2015-07-31 13:11:08 +12:00
Robin Bygrave ede91ecf78 No effective change - Code cleanup,remove unnecessary public modifier on interfaces 2015-07-31 13:08:07 +12:00
Robin Bygrave efe4e69ed1 No effective change - Code cleanup,remove unnecessary public modifier on interfaces 2015-07-31 13:05:22 +12:00
Robin Bygrave 8a3d9edd34 No effective change - Code cleanup, convert unnecessary fields to local vars 2015-07-31 13:00:53 +12:00
Robin Bygrave b9aa76c367 [maven-release-plugin] prepare for next development iteration 2015-07-30 06:45:59 +12:00
Robin Bygrave a49b99156b [maven-release-plugin] prepare release avaje-ebeanorm-6.2.2 2015-07-30 06:45:36 +12:00
Robin Bygrave 54f3dbf35a #361 - ENH: Add ServerConfig expressionEqualsWithNullAsNoop - Can eq ne gt ... methods in ExpressionList treat null value as 1=1 ? 2015-07-30 06:41:51 +12:00
Rob Bygrave 27847424b3 Merge pull request #362 from kdeng/master
Introduce a ClassPathSearchService to support multiple ClassPath search processes with customise search methods
2015-07-30 05:12:47 +12:00
Robin Bygrave a5e94f6ae2 #357 - batch insertAll has no effect when tx commited 2015-07-30 04:23:02 +12:00
Kefeng Deng 9f8b3799eb Merge branch 'master' of github.com:kdeng/avaje-ebeanorm 2015-07-29 21:11:17 +12:00
Kefeng Deng 7734919010 Merge branch 'master' of github.com:kdeng/avaje-ebeanorm 2015-07-29 21:10:45 +12:00
Robin Bygrave 19f40cb2e5 No effective change - format 2015-07-29 20:56:58 +12:00
Robin Bygrave 3d4bd15dac #360 ENH: Add query setDisableLazyLoading(true) ... for use when graph serialised via external library (and you don't want lazy loading to fire) 2015-07-29 20:31:25 +12:00
Kefeng Deng a3c81c3a31 Merge branch 'master' of github.com:kdeng/avaje-ebeanorm
# Conflicts:
#	src/main/java/com/avaje/ebeaninternal/server/core/BootupClassPathSearch.java
#	src/main/java/com/avaje/ebeaninternal/server/util/ClassPathSearch.java
2015-07-29 20:19:43 +12:00
Kefeng Deng 3549f88232 Introduced a service interface to allow multiple ClassPathSearchs with its own customized search way 2015-07-29 20:14:44 +12:00
Robin Bygrave 59d009bc94 No effective change - change to assertJ from hamcrest matchers 2015-07-29 15:54:31 +12:00
Robin Bygrave a6edafbf2d No effective change - add generics type on variable 2015-07-29 15:40:21 +12:00
Robin Bygrave 5fab66204c #359 - ENH: add BeanState.setDisableLazyLoad(boolean) 2015-07-29 15:36:11 +12:00
Kefeng Deng 2fa7c57357 Introduced a service interface to allow multiple ClassPathSearchs with its own customized search way 2015-07-28 21:31:49 +12:00
Robin Bygrave 890e924eb0 [maven-release-plugin] prepare for next development iteration 2015-07-27 23:03:50 +12:00
Robin Bygrave 1c6592a6ec [maven-release-plugin] prepare release avaje-ebeanorm-6.2.1 2015-07-27 23:03:27 +12:00
Robin Bygrave 554c5a7bfc No effective change - format 2015-07-27 23:02:33 +12:00
Robin Bygrave 7a32c50894 Bump pom to 6.2.1-SNAPSHOT 2015-07-27 23:00:12 +12:00
Robin Bygrave 3fa8f04a4c #358 - ENH: Add ServerConfig updateAllPropertiesInBatch with a default of true 2015-07-27 22:59:18 +12:00
Robin Bygrave 962d7f601d #356 - ENH: Change to Binder logging such that the value in the bind log is the converted/bound value 2015-07-27 20:59:40 +12:00
Robin Bygrave f2aa2b5b8b No effective change - format and tidy 2015-07-27 20:47:23 +12:00
Robin Bygrave 87b485cfa4 #355 - ENH: Add notIn(...) expressions. Just to make life easier in those cases 2015-07-27 20:39:34 +12:00
Robin Bygrave 5a55b5235d No effective change - tidy 2015-07-27 15:56:06 +12:00
Robin Bygrave 97adb76eac No effective change - remove unused methods 2015-07-27 15:54:20 +12:00
Robin Bygrave d0d5ab474d No effective change - remove unused import 2015-07-27 15:42:57 +12:00
Robin Bygrave d396f09b3a #296 - ENH: Add to transaction setUpdateAllLoadedProperties() - force update all properties api 2015-07-24 21:56:11 +12:00
Robin Bygrave 3baa5bca46 #352 - Remove deprecated API - ValuePair getValue1() getValue2() ... use getNewValue() getOldValue() 2015-07-24 20:15:13 +12:00
Robin Bygrave c00484026c #351 - ENH: Add diff to Version beans returned from findVersions() 2015-07-24 20:12:26 +12:00
Robin Bygrave 71798afadd #350 - ENH: Add @History findVersions() query - add default ordering to lower sys period desc 2015-07-24 16:52:58 +12:00
Robin Bygrave 1ec2f74df9 #350 - ENH: Add @History findVersions() query ... returning historic versions for a given bean using history view 2015-07-24 16:20:15 +12:00
Robin Bygrave 61a0651439 No effective change - code format 2015-07-24 12:33:35 +12:00
Robin Bygrave eae06059c9 #349 - ENH: Add @WhoCreated @WhoModified ... with CurrentUserProvider interface 2015-07-24 12:33:04 +12:00
Robin Bygrave a1ff9034b6 No effective change - format 2015-07-24 12:09:04 +12:00
Robin Bygrave 1085a8d608 #348 - ENH: Add @WhenCreated and @WhenModified ... as alias to existing @CreatedTimestamp and @UpdatedTimstamp 2015-07-24 10:50:35 +12:00
Robin Bygrave 3a547bf487 #347 - @History support with query.asOf(Timestamp) - javadoc update 2015-07-24 10:24:28 +12:00
Robin Bygrave 82489636d5 #347 - @History support with query.asOf(Timestamp) 2015-07-24 10:18:17 +12:00
Robin Bygrave 3cafb37a73 [maven-release-plugin] prepare for next development iteration 2015-07-20 20:09:05 +12:00
Robin Bygrave b4c7cf529d [maven-release-plugin] prepare release avaje-ebeanorm-6.1.1 2015-07-20 20:08:42 +12:00
Robin Bygrave ba5c67f936 #346 - ENH: Add @Nullable annotation on find by id and findUnique() methods 2015-07-20 20:06:55 +12:00
Robin Bygrave 2bd7995ca1 Bump pom to 6.1.1-SNAPSHOT 2015-07-20 12:55:33 +12:00
Robin Bygrave cc8c860709 Internal DefaultOrmQuery cleanup : timeout can default to 0 (rather than -1) 2015-07-20 12:51:24 +12:00
Robin Bygrave 7d25e31289 No effective change - unused imports 2015-07-20 12:48:08 +12:00
Robin Bygrave 936e56835c Internal SpiQuery : remove unused lazyLoadForParentsIds 2015-07-20 12:47:09 +12:00
Robin Bygrave 0d848e9311 Internal SpiQuery : remove unused context additions 2015-07-20 12:44:26 +12:00
Robin Bygrave b794b6c77e Internal SpiQuery : remove unused convertWhereNaturalKeyToId() 2015-07-20 12:40:08 +12:00
Robin Bygrave f45d240682 #345 - Expose Query.getId() and Query.getBeanType() methods ... (previously on SpiQuery) 2015-07-20 12:24:56 +12:00
Robin Bygrave 1a6f68edd3 No effective change - javadoc 2015-07-20 11:55:24 +12:00
Robin Bygrave 81683c5d2a No effective change - javadoc 2015-07-20 11:50:38 +12:00
Robin Bygrave 2b535d59b8 No effective change - javadoc 2015-07-20 11:41:23 +12:00
Robin Bygrave ae0bbaaaf8 #344 - Remove deprecated annotation @ColumnHstore ... migrate to @DbHstore 2015-07-20 11:38:40 +12:00
Robin Bygrave aaca20f9c3 #343 - Remove deprecated interface BeanFinder<T> ... migrate to BeanFindController 2015-07-20 11:34:05 +12:00
Robin Bygrave 245cbb0ea1 #342 - Remove deprecated method - JsonContext createJsonContext() ... migrate to json() 2015-07-20 11:27:00 +12:00
Robin Bygrave dbe984c668 #341 - Remove deprecated method - insert(Collection<?> beans); ... migrate to insertAll() 2015-07-20 11:22:16 +12:00
Robin Bygrave 89088f9480 #340 - Remove deprecated method - update(Collection<?> beans) ... migrate to updateAll() 2015-07-20 11:18:51 +12:00
Robin Bygrave 80253c4e07 #339 - Remove deprecated method - save(Collection<?> beans, Transaction transaction) ... migrate to saveAll() 2015-07-20 11:15:10 +12:00
Robin Bygrave f96ce11c73 #338 - Remove deprecated method - save(Iterator<?> it, Transaction transaction) ... please change to iterate yourself and save. 2015-07-20 11:11:45 +12:00
Robin Bygrave b8f8cb5ae7 #337 - Remove deprecated method - delete(Class<?> beanType, Collection<?> ids) ... migrate to deleteAll() 2015-07-20 11:07:52 +12:00
Robin Bygrave b8a2aac95a #336 - Remove deprecated method - delete(Iterator<?> it, Transaction transaction) 2015-07-20 10:59:52 +12:00
Robin Bygrave 7b090a6346 #335 - Remove deprecated method - delete(Collection<?> beans) ... migrate to deleteAll() 2015-07-20 10:54:18 +12:00
Robin Bygrave b10c68489f #334 - Remove deprecated method - delete(Iterator<?> it) ... change to iterate yourself and delete() 2015-07-20 10:47:51 +12:00
Robin Bygrave 2dbb2d9911 #333 - Remove deprecated method - save(Iterator<?> it) ... change to iterate yourself and save() 2015-07-20 10:43:37 +12:00
Robin Bygrave b3b4c72a77 #332 - Remove deprecated method - save(Collection<?> beans) ... migrate to saveAll(beans) 2015-07-20 10:39:15 +12:00
Robin Bygrave 1c040e4583 No effective change - code format 2015-07-20 10:24:10 +12:00
Robin Bygrave 9677e585b6 #331 - Remove deprecated method - EbeanServer.findVisit() ... in favor of findEachWhile() or findEach() 2015-07-20 10:22:50 +12:00
Robin Bygrave c53806224f [maven-release-plugin] prepare for next development iteration 2015-07-20 09:53:59 +12:00
Robin Bygrave 6fd5927c64 [maven-release-plugin] prepare release avaje-ebeanorm-5.1.1 2015-07-20 09:53:35 +12:00
Robin Bygrave 920635c6df #326 - API Addition - saveAll(), deleteAll() etc 2015-07-20 09:51:36 +12:00
Robin Bygrave fb1c29b57c Bump pom to 5.1.1-SNAPSHOT 2015-07-20 09:46:31 +12:00
Robin Bygrave 89bed8be67 #326 - API Addition - saveAll(), deleteAll() etc 2015-07-20 09:42:05 +12:00
Robin Bygrave 776e48a501 [maven-release-plugin] prepare for next development iteration 2015-07-20 09:06:01 +12:00
Robin Bygrave 0666a72df7 [maven-release-plugin] prepare release avaje-ebeanorm-4.9.1 2015-07-20 09:05:34 +12:00
Robin Bygrave 55000a3515 No effective change - rename parameter ctx -> parser 2015-07-20 09:01:54 +12:00
Robin Bygrave 8307e259ba bump pom to 4.9.1-SNAPSHOT 2015-07-20 08:50:54 +12:00
Robin Bygrave 95b7574d04 No effective change - format 2015-07-20 08:49:31 +12:00
Robin Bygrave f6466d3211 #280 - ENH: Add ServerConfig.setJsonInclude(...) ALL, NON_NULL, NON_EMPTY 2015-07-20 08:45:46 +12:00
Robin Bygrave 160e4d7dd1 #318 - JSON - toBean error at Transient (with support for #327, #328, #329) 2015-07-19 21:41:20 +12:00
Robin Bygrave a00980c61f #329 - JSON - Remove @Deprecated from JsonWriteOptions ... to support ObjectMapper which can be used for serialize/deserialize of @Transient properties 2015-07-19 21:38:27 +12:00
Robin Bygrave 72d2fcb59e #330 - JSON - Add ebean @JsonIgnore ... with serialize() default false and deserialize() default false 2015-07-19 21:37:37 +12:00
Robin Bygrave 0f503b2a2f No effective change - format code 2015-07-19 09:35:27 +12:00
Robin Bygrave a79e2e786a #324 - on effective change, sync internal name from primaryServer to defaultServer 2015-07-19 09:20:03 +12:00
Robin Bygrave c9ffa2673f #324 - ENH: Add Ebean.getDefaultServer() 2015-07-18 07:46:53 +12:00
Robin Bygrave 0e0fa37f0d #324 - ENH: Add Ebean.getDefaultServer() 2015-07-18 07:46:42 +12:00
Robin Bygrave f7bbd5b3bb No effective change - code format (fix variable names) 2015-07-18 07:35:19 +12:00
Robin Bygrave ba614cd287 No effective change - code format 2015-07-18 07:34:56 +12:00
Robin Bygrave 7d028f3318 [maven-release-plugin] prepare for next development iteration 2015-07-14 23:28:55 +12:00
Robin Bygrave 21b04c244b [maven-release-plugin] prepare release avaje-ebeanorm-4.8.1 2015-07-14 23:28:32 +12:00
Robin Bygrave 957c2def43 bump pom to 4.8.1-SNAPSHOT 2015-07-14 23:24:34 +12:00
Robin Bygrave 35f9cd3821 Bump pom to 4.8.1-SNAPSHOT 2015-07-14 23:18:51 +12:00
Robin Bygrave e95d3304bf #322 - RawSql fetch object with inheritance 2015-07-14 23:09:38 +12:00
rbygrave 0f7c9da5d2 #319 - Beans loaded without an @Id value ... return in NEW state rather than LOADED state (also refer to #317) 2015-07-09 22:18:03 +12:00
rbygrave b4008da70c #317 - RawSql getting error - Caused by: java.sql.SQLException: Column Index out of range, 0 < 1. 2015-07-09 21:44:45 +12:00
rbygrave 34a0f16c74 No effective change - bump mysql-connector-java test dependency version 2015-07-07 23:07:10 +12:00
Rob Bygrave a880109201 Merge pull request #316 from castovoid/master
Resolve NullPointerException on JtaTransacionManager constructor
2015-06-30 21:17:27 +12:00
Rob Bygrave 0607151ac8 Merge pull request #315 from ossd/patch-1
Update ScalarTypeEnumStandard.java
2015-06-30 21:15:47 +12:00
Leone Parise 5c4ad4c01c Resolve NullPointerException on JtaTransacionManager 2015-06-30 01:01:35 -03:00
ossd 3564504e00 Update ScalarTypeEnumStandard.java
Using toString() to calculate the Enum length is wrong. If you overwrite the Enum's toString() the length may be shorter. In this situation, the ddl script will create a to small varchar field for the value and you get an exception on save
2015-06-29 22:36:24 +02:00
rbygrave 49babef495 #314 - ServerCache API - change from int to long for ServerCacheStatistics (hitCount, missCount) and ServerCache remove putIfAbsent() method 2015-06-30 00:56:11 +12:00
rbygrave 9e3362d004 No effective change - tidy 2015-06-26 23:05:40 +12:00
Rob Bygrave 3f0dcdb6d1 Update README.md 2015-06-25 00:12:16 +12:00
rbygrave 481116251d [maven-release-plugin] prepare for next development iteration 2015-06-24 23:50:22 +12:00
947 changed files with 60981 additions and 25644 deletions
+2
View File
@@ -1,5 +1,6 @@
*.autofetch
*.sql
*.orig
.classpath
.project
.settings/
@@ -8,6 +9,7 @@ logs/
log/
/db
/mydb.db
!src/test/ddl-review/*.sql
# Intellij project files
+6 -5
View File
@@ -1,9 +1,10 @@
[![Stories in Ready](https://badge.waffle.io/ebean-orm/avaje-ebeanorm.png?label=ready&title=Ready)](https://waffle.io/ebean-orm/avaje-ebeanorm)
* [![Maven Central : avaje-ebeanorm](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebeanorm/avaje-ebeanorm/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebeanorm/avaje-ebeanorm) - avaje-ebeanorm
* [![Maven Central : avaje-ebeanorm-agent](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebeanorm/avaje-ebeanorm-agent/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebeanorm/avaje-ebeanorm-agent) - avaje-ebeanorm-agent
* [![Maven Central : avaje-ebeanorm-agent](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebeanorm/avaje-ebeanorm-mavenenhancer/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebeanorm/avaje-ebeanorm-mavenenhancer) - avaje-ebeanorm-mavenenhancer
Ebean ORM
==============
Project Website
----------------
[http://ebean-orm.github.io/](http://ebean-orm.github.io/ "Ebean ORM's Website")
@@ -12,7 +13,7 @@ Maven Dependency
<dependency>
<groupId>org.avaje.ebeanorm</groupId>
<artifactId>avaje-ebeanorm</artifactId>
<version>4.7.1</version>
<version>4.7.3</version>
</dependency>
+12 -26
View File
@@ -9,7 +9,7 @@
<groupId>org.avaje.ebeanorm</groupId>
<artifactId>avaje-ebeanorm</artifactId>
<version>4.7.3</version>
<version>6.4.1</version>
<packaging>jar</packaging>
<name>avaje-ebeanorm</name>
@@ -43,6 +43,12 @@
<dependencies>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>13.0</version>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
@@ -152,36 +158,16 @@
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.27</version>
<version>5.1.36</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-integration</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.9</version>
<groupId>org.avaje.composite</groupId>
<artifactId>avaje-composite-testing</artifactId>
<version>1.1</version>
<scope>test</scope>
<type>pom</type>
</dependency>
<dependency>
@@ -33,6 +33,11 @@ public interface BeanState {
*/
boolean isDirty();
/**
* This can be called with true to disable lazy loading on the bean.
*/
void setDisableLazyLoad(boolean disableLazyLoading);
/**
* For partially populated beans returns the properties that are loaded on the
* bean.
@@ -80,7 +80,7 @@ public interface CallableSql {
/**
* Return the label that is put into the transaction log.
*/
public String getLabel();
String getLabel();
/**
* Set the label that is put in the transaction log.
@@ -80,17 +80,16 @@ final class DRawSqlColumnsParser {
return new ColumnMapping.Column(indexPos++, sb.toString(), split[split.length - 1]);
}
private int nextComma() {
private void nextComma() {
boolean inQuote = false;
while (pos < end) {
char c = sqlSelect.charAt(pos);
if (c == '\'') {
inQuote = !inQuote;
} else if (!inQuote && c == ',') {
return pos;
return;
}
pos++;
}
return pos;
}
}
@@ -24,7 +24,7 @@ class DRawSqlParser {
private int placeHolderAndWhere;
private int placeHolderHaving;
private int placeHolderAndHaving;
private boolean hasPlaceHolders;
private final boolean hasPlaceHolders;
private int selectPos = -1;
private int distinctPos = -1;
@@ -98,19 +98,7 @@ class DRawSqlParser {
}
private boolean hasPlaceHolders() {
if (placeHolderWhere > -1) {
return true;
}
if (placeHolderAndWhere > -1) {
return true;
}
if (placeHolderHaving > -1) {
return true;
}
if (placeHolderAndHaving > -1) {
return true;
}
return false;
return placeHolderWhere > -1 || placeHolderAndWhere > -1 || placeHolderHaving > -1 || placeHolderAndHaving > -1;
}
/**
+98 -111
View File
@@ -2,7 +2,6 @@ package com.avaje.ebean;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -10,6 +9,7 @@ import java.util.concurrent.ConcurrentHashMap;
import javax.persistence.OptimisticLockException;
import javax.persistence.PersistenceException;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -101,7 +101,7 @@ import com.avaje.ebean.text.json.JsonContext;
* specific database.
* </p>
*
* <pre> {@code
* <pre>{@code
*
* // Get access to the Human Resources EbeanServer/Database
* EbeanServer hrDb = Ebean.getServer("hr");
@@ -146,9 +146,9 @@ public final class Ebean {
private final Object monitor = new Object();
/**
* The 'default/primary' EbeanServer.
* The 'default' EbeanServer.
*/
private EbeanServer primaryServer;
private EbeanServer defaultServer;
private ServerManager() {
@@ -162,31 +162,31 @@ public final class Ebean {
} else {
// look to see if there is a default server defined
String primaryName = PrimaryServer.getPrimaryServerName();
logger.debug("primaryName:" + primaryName);
if (primaryName != null && primaryName.trim().length() > 0) {
primaryServer = getWithCreate(primaryName.trim());
String defaultName = PrimaryServer.getDefaultServerName();
logger.debug("defaultName:" + defaultName);
if (defaultName != null && defaultName.trim().length() > 0) {
defaultServer = getWithCreate(defaultName.trim());
}
}
} catch (RuntimeException e) {
} catch (Throwable e) {
logger.error("Error trying to create the default EbeanServer", e);
throw e;
throw new RuntimeException(e);
}
}
private EbeanServer getPrimaryServer() {
if (primaryServer == null) {
private EbeanServer getDefaultServer() {
if (defaultServer == null) {
String msg = "The default EbeanServer has not been defined?";
msg += " This is normally set via the ebean.datasource.default property.";
msg += " Otherwise it should be registered programatically via registerServer()";
throw new PersistenceException(msg);
}
return primaryServer;
return defaultServer;
}
private EbeanServer get(String name) {
if (name == null || name.length() == 0) {
return primaryServer;
return defaultServer;
}
// non-synchronized read
EbeanServer server = concMap.get(name);
@@ -221,12 +221,12 @@ public final class Ebean {
registerWithName(server.getName(), server, isPrimaryServer);
}
private void registerWithName(String name, EbeanServer server, boolean isPrimaryServer) {
private void registerWithName(String name, EbeanServer server, boolean isDefaultServer) {
synchronized (monitor) {
concMap.put(name, server);
syncMap.put(name, server);
if (isPrimaryServer) {
primaryServer = server;
if (isDefaultServer) {
defaultServer = server;
}
}
}
@@ -254,12 +254,22 @@ public final class Ebean {
* }</pre>
*
* @param name
* the name of the server, use null for the 'default server'
* the name of the server, can use null for the 'default server'
*/
public static EbeanServer getServer(String name) {
return serverMgr.get(name);
}
/**
* Returns the default EbeanServer.
* <p>
* This is equivalent to <code>Ebean.getServer(null);</code>
* </p>
*/
public static EbeanServer getDefaultServer() {
return serverMgr.getDefaultServer();
}
/**
* Return the ExpressionFactory from the default server.
* <p>
@@ -278,23 +288,23 @@ public final class Ebean {
* </p>
*/
public static ExpressionFactory getExpressionFactory() {
return serverMgr.getPrimaryServer().getExpressionFactory();
return serverMgr.getDefaultServer().getExpressionFactory();
}
/**
* Register the server with this Ebean singleton. Specify if the registered
* server is the primary/default server.
*/
public static void register(EbeanServer server, boolean isPrimaryServer) {
serverMgr.register(server, isPrimaryServer);
public static void register(EbeanServer server, boolean defaultServer) {
serverMgr.register(server, defaultServer);
}
/**
* Backdoor for registering a mock implementation of EbeanServer as the default server.
*/
protected static EbeanServer mock(String name, EbeanServer server, boolean isPrimaryServer) {
EbeanServer originalPrimaryServer = serverMgr.primaryServer;
serverMgr.registerWithName(name, server, isPrimaryServer);
protected static EbeanServer mock(String name, EbeanServer server, boolean defaultServer) {
EbeanServer originalPrimaryServer = serverMgr.defaultServer;
serverMgr.registerWithName(name, server, defaultServer);
return originalPrimaryServer;
}
@@ -311,7 +321,7 @@ public final class Ebean {
* </p>
*/
public static Object nextId(Class<?> beanType) {
return serverMgr.getPrimaryServer().nextId(beanType);
return serverMgr.getDefaultServer().nextId(beanType);
}
/**
@@ -359,7 +369,7 @@ public final class Ebean {
* </p>
*/
public static Transaction beginTransaction() {
return serverMgr.getPrimaryServer().beginTransaction();
return serverMgr.getDefaultServer().beginTransaction();
}
/**
@@ -370,7 +380,7 @@ public final class Ebean {
*
*/
public static Transaction beginTransaction(TxIsolation isolation) {
return serverMgr.getPrimaryServer().beginTransaction(isolation);
return serverMgr.getDefaultServer().beginTransaction(isolation);
}
/**
@@ -425,7 +435,7 @@ public final class Ebean {
* }</pre>
*/
public static Transaction beginTransaction(TxScope scope){
return serverMgr.getPrimaryServer().beginTransaction(scope);
return serverMgr.getDefaultServer().beginTransaction(scope);
}
/**
@@ -433,7 +443,7 @@ public final class Ebean {
* in scope.
*/
public static Transaction currentTransaction() {
return serverMgr.getPrimaryServer().currentTransaction();
return serverMgr.getDefaultServer().currentTransaction();
}
/**
@@ -446,21 +456,21 @@ public final class Ebean {
* @throws PersistenceException if there is no currently active transaction
*/
public static void register(TransactionCallback transactionCallback) throws PersistenceException {
serverMgr.getPrimaryServer().register(transactionCallback);
serverMgr.getDefaultServer().register(transactionCallback);
}
/**
* Commit the current transaction.
*/
public static void commitTransaction() {
serverMgr.getPrimaryServer().commitTransaction();
serverMgr.getDefaultServer().commitTransaction();
}
/**
* Rollback the current transaction.
*/
public static void rollbackTransaction() {
serverMgr.getPrimaryServer().rollbackTransaction();
serverMgr.getDefaultServer().rollbackTransaction();
}
/**
@@ -489,7 +499,7 @@ public final class Ebean {
* }</pre>
*/
public static void endTransaction() {
serverMgr.getPrimaryServer().endTransaction();
serverMgr.getDefaultServer().endTransaction();
}
/**
@@ -500,7 +510,7 @@ public final class Ebean {
* </p>
*/
public static Map<String, ValuePair> diff(Object a, Object b) {
return serverMgr.getPrimaryServer().diff(a, b);
return serverMgr.getDefaultServer().diff(a, b);
}
/**
@@ -523,7 +533,6 @@ public final class Ebean {
* public class Order { ...
*
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
* @JoinColumn(name="order_id")
* List<OrderDetail> details;
* ...
* }
@@ -537,7 +546,7 @@ public final class Ebean {
* </p>
*/
public static void save(Object bean) throws OptimisticLockException {
serverMgr.getPrimaryServer().save(bean);
serverMgr.getDefaultServer().save(bean);
}
/**
@@ -545,14 +554,14 @@ public final class Ebean {
* want to explicitly insert it.
*/
public static void insert(Object bean) {
serverMgr.getPrimaryServer().insert(bean);
serverMgr.getDefaultServer().insert(bean);
}
/**
* Insert a collection of beans.
*/
public static void insert(Collection<?> beans) {
serverMgr.getPrimaryServer().insert(beans);
public static void insertAll(Collection<?> beans) {
serverMgr.getDefaultServer().insertAll(beans);
}
/**
@@ -576,7 +585,7 @@ public final class Ebean {
* }</pre>
*/
public static void markAsDirty(Object bean) throws OptimisticLockException {
serverMgr.getPrimaryServer().markAsDirty(bean);
serverMgr.getDefaultServer().markAsDirty(bean);
}
/**
@@ -616,28 +625,21 @@ public final class Ebean {
* @see ServerConfig#setUpdateChangesOnly(boolean)
*/
public static void update(Object bean) throws OptimisticLockException {
serverMgr.getPrimaryServer().update(bean);
serverMgr.getDefaultServer().update(bean);
}
/**
* Update the beans in the collection.
*/
public static void update(Collection<?> beans) throws OptimisticLockException {
serverMgr.getPrimaryServer().update(beans);
}
/**
* Save all the beans from an Iterator.
*/
public static int save(Iterator<?> iterator) throws OptimisticLockException {
return serverMgr.getPrimaryServer().save(iterator);
public static void updateAll(Collection<?> beans) throws OptimisticLockException {
serverMgr.getDefaultServer().updateAll(beans);
}
/**
* Save all the beans from a Collection.
*/
public static int save(Collection<?> beans) throws OptimisticLockException {
return serverMgr.getPrimaryServer().save(beans);
public static int saveAll(Collection<?> beans) throws OptimisticLockException {
return serverMgr.getDefaultServer().saveAll(beans);
}
/**
@@ -651,7 +653,7 @@ public final class Ebean {
* @return the number of associations deleted (from the intersection table).
*/
public static int deleteManyToManyAssociations(Object ownerBean, String propertyName) {
return serverMgr.getPrimaryServer().deleteManyToManyAssociations(ownerBean, propertyName);
return serverMgr.getDefaultServer().deleteManyToManyAssociations(ownerBean, propertyName);
}
/**
@@ -669,7 +671,7 @@ public final class Ebean {
* </p>
*/
public static void saveManyToManyAssociations(Object ownerBean, String propertyName) {
serverMgr.getPrimaryServer().saveManyToManyAssociations(ownerBean, propertyName);
serverMgr.getDefaultServer().saveManyToManyAssociations(ownerBean, propertyName);
}
/**
@@ -689,7 +691,7 @@ public final class Ebean {
* the property we want to save
*/
public static void saveAssociation(Object ownerBean, String propertyName) {
serverMgr.getPrimaryServer().saveAssociation(ownerBean, propertyName);
serverMgr.getDefaultServer().saveAssociation(ownerBean, propertyName);
}
/**
@@ -700,35 +702,28 @@ public final class Ebean {
* </p>
*/
public static void delete(Object bean) throws OptimisticLockException {
serverMgr.getPrimaryServer().delete(bean);
serverMgr.getDefaultServer().delete(bean);
}
/**
* Delete the bean given its type and id.
*/
public static int delete(Class<?> beanType, Object id) {
return serverMgr.getPrimaryServer().delete(beanType, id);
return serverMgr.getDefaultServer().delete(beanType, id);
}
/**
* Delete several beans given their type and id values.
*/
public static void delete(Class<?> beanType, Collection<?> ids) {
serverMgr.getPrimaryServer().delete(beanType, ids);
public static void deleteAll(Class<?> beanType, Collection<?> ids) {
serverMgr.getDefaultServer().deleteAll(beanType, ids);
}
/**
* Delete all the beans from an Iterator.
* Delete all the beans in the Collection.
*/
public static int delete(Iterator<?> it) throws OptimisticLockException {
return serverMgr.getPrimaryServer().delete(it);
}
/**
* Delete all the beans from a Collection.
*/
public static int delete(Collection<?> c) throws OptimisticLockException {
return delete(c.iterator());
public static int deleteAll(Collection<?> beans) throws OptimisticLockException {
return serverMgr.getDefaultServer().deleteAll(beans);
}
/**
@@ -739,7 +734,7 @@ public final class Ebean {
* </p>
*/
public static void refresh(Object bean) {
serverMgr.getPrimaryServer().refresh(bean);
serverMgr.getDefaultServer().refresh(bean);
}
/**
@@ -760,7 +755,7 @@ public final class Ebean {
* the property name of the List Set or Map to refresh.
*/
public static void refreshMany(Object bean, String manyPropertyName) {
serverMgr.getPrimaryServer().refreshMany(bean, manyPropertyName);
serverMgr.getDefaultServer().refreshMany(bean, manyPropertyName);
}
/**
@@ -788,7 +783,7 @@ public final class Ebean {
* the id value
*/
public static <T> T getReference(Class<T> beanType, Object id) {
return serverMgr.getPrimaryServer().getReference(beanType, id);
return serverMgr.getDefaultServer().getReference(beanType, id);
}
/**
@@ -834,7 +829,7 @@ public final class Ebean {
* the properties to sort the list by
*/
public static <T> void sort(List<T> list, String sortByClause) {
serverMgr.getPrimaryServer().sort(list, sortByClause);
serverMgr.getDefaultServer().sort(list, sortByClause);
}
/**
@@ -883,8 +878,9 @@ public final class Ebean {
* @param id
* the id value
*/
@Nullable
public static <T> T find(Class<T> beanType, Object id) {
return serverMgr.getPrimaryServer().find(beanType, id);
return serverMgr.getDefaultServer().find(beanType, id);
}
/**
@@ -896,7 +892,7 @@ public final class Ebean {
* </p>
*/
public static SqlQuery createSqlQuery(String sql) {
return serverMgr.getPrimaryServer().createSqlQuery(sql);
return serverMgr.getDefaultServer().createSqlQuery(sql);
}
/**
@@ -909,7 +905,7 @@ public final class Ebean {
* the name of the query
*/
public static SqlQuery createNamedSqlQuery(String namedQuery) {
return serverMgr.getPrimaryServer().createNamedSqlQuery(namedQuery);
return serverMgr.getDefaultServer().createNamedSqlQuery(namedQuery);
}
/**
@@ -927,7 +923,7 @@ public final class Ebean {
* </p>
*/
public static SqlUpdate createSqlUpdate(String sql) {
return serverMgr.getPrimaryServer().createSqlUpdate(sql);
return serverMgr.getDefaultServer().createSqlUpdate(sql);
}
/**
@@ -936,7 +932,7 @@ public final class Ebean {
* @see CallableSql
*/
public static CallableSql createCallableSql(String sql) {
return serverMgr.getPrimaryServer().createCallableSql(sql);
return serverMgr.getDefaultServer().createCallableSql(sql);
}
/**
@@ -959,7 +955,7 @@ public final class Ebean {
* }</pre>
*/
public static SqlUpdate createNamedSqlUpdate(String namedQuery) {
return serverMgr.getPrimaryServer().createNamedSqlUpdate(namedQuery);
return serverMgr.getDefaultServer().createNamedSqlUpdate(namedQuery);
}
/**
@@ -987,7 +983,7 @@ public final class Ebean {
*/
public static <T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery) {
return serverMgr.getPrimaryServer().createNamedQuery(beanType, namedQuery);
return serverMgr.getDefaultServer().createNamedQuery(beanType, namedQuery);
}
/**
@@ -1015,7 +1011,7 @@ public final class Ebean {
* the object query
*/
public static <T> Query<T> createQuery(Class<T> beanType, String query) {
return serverMgr.getPrimaryServer().createQuery(beanType, query);
return serverMgr.getDefaultServer().createQuery(beanType, query);
}
/**
@@ -1074,7 +1070,7 @@ public final class Ebean {
*/
public static <T> Update<T> createNamedUpdate(Class<T> beanType, String namedUpdate) {
return serverMgr.getPrimaryServer().createNamedUpdate(beanType, namedUpdate);
return serverMgr.getDefaultServer().createNamedUpdate(beanType, namedUpdate);
}
/**
@@ -1108,7 +1104,7 @@ public final class Ebean {
*/
public static <T> Update<T> createUpdate(Class<T> beanType, String ormUpdate) {
return serverMgr.getPrimaryServer().createUpdate(beanType, ormUpdate);
return serverMgr.getDefaultServer().createUpdate(beanType, ormUpdate);
}
/**
@@ -1116,7 +1112,7 @@ public final class Ebean {
*/
public static <T> CsvReader<T> createCsvReader(Class<T> beanType) {
return serverMgr.getPrimaryServer().createCsvReader(beanType);
return serverMgr.getDefaultServer().createCsvReader(beanType);
}
/**
@@ -1173,7 +1169,7 @@ public final class Ebean {
*/
public static <T> Query<T> createQuery(Class<T> beanType) {
return serverMgr.getPrimaryServer().createQuery(beanType);
return serverMgr.getDefaultServer().createQuery(beanType);
}
/**
@@ -1190,7 +1186,7 @@ public final class Ebean {
*/
public static <T> Query<T> find(Class<T> beanType) {
return serverMgr.getPrimaryServer().find(beanType);
return serverMgr.getDefaultServer().find(beanType);
}
/**
@@ -1204,7 +1200,7 @@ public final class Ebean {
* </p>
*/
public static <T> Filter<T> filter(Class<T> beanType) {
return serverMgr.getPrimaryServer().filter(beanType);
return serverMgr.getDefaultServer().filter(beanType);
}
/**
@@ -1251,7 +1247,7 @@ public final class Ebean {
* @see Ebean#execute(CallableSql)
*/
public static int execute(SqlUpdate sqlUpdate) {
return serverMgr.getPrimaryServer().execute(sqlUpdate);
return serverMgr.getDefaultServer().execute(sqlUpdate);
}
/**
@@ -1280,7 +1276,7 @@ public final class Ebean {
* @see Ebean#execute(SqlUpdate)
*/
public static int execute(CallableSql callableSql) {
return serverMgr.getPrimaryServer().execute(callableSql);
return serverMgr.getDefaultServer().execute(callableSql);
}
/**
@@ -1305,7 +1301,7 @@ public final class Ebean {
* }</pre>
*/
public static void execute(TxScope scope, TxRunnable r) {
serverMgr.getPrimaryServer().execute(scope, r);
serverMgr.getDefaultServer().execute(scope, r);
}
/**
@@ -1333,7 +1329,7 @@ public final class Ebean {
* }</pre>
*/
public static void execute(TxRunnable r) {
serverMgr.getPrimaryServer().execute(r);
serverMgr.getDefaultServer().execute(r);
}
/**
@@ -1360,7 +1356,7 @@ public final class Ebean {
*
*/
public static <T> T execute(TxScope scope, TxCallable<T> c) {
return serverMgr.getPrimaryServer().execute(scope, c);
return serverMgr.getDefaultServer().execute(scope, c);
}
/**
@@ -1394,7 +1390,7 @@ public final class Ebean {
* }</pre>
*/
public static <T> T execute(TxCallable<T> c) {
return serverMgr.getPrimaryServer().execute(c);
return serverMgr.getDefaultServer().execute(c);
}
/**
@@ -1431,10 +1427,9 @@ public final class Ebean {
* @param deletes
* true if rows on the table where deleted
*/
public static void externalModification(String tableName, boolean inserts, boolean updates,
boolean deletes) {
public static void externalModification(String tableName, boolean inserts, boolean updates, boolean deletes) {
serverMgr.getPrimaryServer().externalModification(tableName, inserts, updates, deletes);
serverMgr.getDefaultServer().externalModification(tableName, inserts, updates, deletes);
}
/**
@@ -1444,7 +1439,7 @@ public final class Ebean {
* </p>
*/
public static BeanState getBeanState(Object bean) {
return serverMgr.getPrimaryServer().getBeanState(bean);
return serverMgr.getDefaultServer().getBeanState(bean);
}
/**
@@ -1452,7 +1447,7 @@ public final class Ebean {
*
*/
public static ServerCacheManager getServerCacheManager() {
return serverMgr.getPrimaryServer().getServerCacheManager();
return serverMgr.getDefaultServer().getServerCacheManager();
}
/**
@@ -1460,7 +1455,7 @@ public final class Ebean {
* queries.
*/
public static BackgroundExecutor getBackgroundExecutor() {
return serverMgr.getPrimaryServer().getBackgroundExecutor();
return serverMgr.getDefaultServer().getBackgroundExecutor();
}
/**
@@ -1471,7 +1466,7 @@ public final class Ebean {
* </p>
*/
public static void runCacheWarming() {
serverMgr.getPrimaryServer().runCacheWarming();
serverMgr.getDefaultServer().runCacheWarming();
}
/**
@@ -1483,22 +1478,14 @@ public final class Ebean {
*/
public static void runCacheWarming(Class<?> beanType) {
serverMgr.getPrimaryServer().runCacheWarming(beanType);
serverMgr.getDefaultServer().runCacheWarming(beanType);
}
/**
* Return the JsonContext for reading/writing JSON.
*/
public static JsonContext json() {
return serverMgr.getPrimaryServer().json();
}
/**
* Return the JsonContext for reading/writing JSON.
* @deprecated Please use #json instead.
*/
public static JsonContext createJsonContext() {
return json();
return serverMgr.getDefaultServer().json();
}
}
+51 -68
View File
@@ -1,7 +1,6 @@
package com.avaje.ebean;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -13,8 +12,10 @@ import com.avaje.ebean.annotation.CacheStrategy;
import com.avaje.ebean.cache.ServerCacheManager;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.meta.MetaInfoManager;
import com.avaje.ebean.plugin.SpiServer;
import com.avaje.ebean.text.csv.CsvReader;
import com.avaje.ebean.text.json.JsonContext;
import org.jetbrains.annotations.Nullable;
/**
* Provides the API for fetching and saving beans to a particular DataSource.
@@ -128,6 +129,11 @@ public interface EbeanServer {
*/
MetaInfoManager getMetaInfoManager();
/**
* Return the extended API intended for use by plugins.
*/
SpiServer getPluginApi();
/**
* Return the BeanState for a given entity bean.
* <p>
@@ -148,7 +154,7 @@ public interface EbeanServer {
* difference comparison.
* </p>
*/
Map<String, ValuePair> diff(Object a, Object b);
Map<String, ValuePair> diff(Object newBean, Object oldBean);
/**
* Create a new instance of T that is an EntityBean.
@@ -905,17 +911,13 @@ public interface EbeanServer {
<T> void findEachWhile(Query<T> query, QueryEachWhileConsumer<T> consumer, Transaction transaction);
/**
* Deprecated in favor of #findEachWhile which is functionally exactly the same
* but has a much better name.
* Return versions of a @History entity bean.
* <p>
* Execute the query visiting the results. This is similar to findIterate in
* that not all the result beans need to be held in memory at the same time
* and as such is go for processing large queries.
* Generally this query is expected to be a find by id or unique predicates query.
* It will execute the query against the history returning the versions of the bean.
* </p>
*
* @deprecated
*/
<T> void findVisit(Query<T> query, QueryResultVisitor<T> visitor, Transaction transaction);
<T> List<Version<T>> findVersions(Query<T> query, Transaction transaction);
/**
* Execute a query returning a list of beans.
@@ -1109,6 +1111,7 @@ public interface EbeanServer {
*
* @see Query#findUnique()
*/
@Nullable
<T> T findUnique(Query<T> query, Transaction transaction);
/**
@@ -1185,6 +1188,7 @@ public interface EbeanServer {
*
* @see SqlQuery#findUnique()
*/
@Nullable
SqlRow findUnique(SqlQuery query, Transaction transaction);
/**
@@ -1207,7 +1211,6 @@ public interface EbeanServer {
* public class Order { ...
*
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
* @JoinColumn(name="order_id")
* List<OrderDetail> details;
* ...
* }
@@ -1222,15 +1225,10 @@ public interface EbeanServer {
*/
void save(Object bean) throws OptimisticLockException;
/**
* Save all the beans in the iterator.
*/
int save(Iterator<?> it) throws OptimisticLockException;
/**
* Save all the beans in the collection.
*/
int save(Collection<?> beans) throws OptimisticLockException;
int saveAll(Collection<?> beans) throws OptimisticLockException;
/**
* Delete the bean.
@@ -1242,14 +1240,9 @@ public interface EbeanServer {
void delete(Object bean) throws OptimisticLockException;
/**
* Delete all the beans from an Iterator.
* Delete the bean with an explicit transaction.
*/
int delete(Iterator<?> it) throws OptimisticLockException;
/**
* Delete all the beans in the collection.
*/
int delete(Collection<?> c) throws OptimisticLockException;
void delete(Object bean, Transaction transaction) throws OptimisticLockException;
/**
* Delete the bean given its type and id.
@@ -1261,16 +1254,26 @@ public interface EbeanServer {
*/
int delete(Class<?> beanType, Object id, Transaction transaction);
/**
* Delete all the beans in the collection.
*/
int deleteAll(Collection<?> beans) throws OptimisticLockException;
/**
* Delete all the beans in the collection using an explicit transaction.
*/
int deleteAll(Collection<?> beans, Transaction transaction) throws OptimisticLockException;
/**
* Delete several beans given their type and id values.
*/
void delete(Class<?> beanType, Collection<?> ids);
void deleteAll(Class<?> beanType, Collection<?> ids);
/**
* Delete several beans given their type and id values with an explicit
* transaction.
*/
void delete(Class<?> beanType, Collection<?> ids, Transaction transaction);
void deleteAll(Class<?> beanType, Collection<?> ids, Transaction transaction);
/**
* Execute a Sql Update Delete or Insert statement. This returns the number of
@@ -1328,7 +1331,7 @@ public interface EbeanServer {
* Execute a ORM insert update or delete statement with an explicit
* transaction.
*/
int execute(Update<?> update, Transaction t);
int execute(Update<?> update, Transaction transaction);
/**
* For making calls to stored procedures.
@@ -1400,27 +1403,22 @@ public interface EbeanServer {
* the type of entity bean to find
* @param beanType
* the type of entity bean to find
* @param uid
* @param id
* the bean id value
* @param transaction
* the transaction to use (can be null)
*/
<T> T find(Class<T> beanType, Object uid, Transaction transaction);
<T> T find(Class<T> beanType, Object id, Transaction transaction);
/**
* Insert or update a bean with an explicit transaction.
*/
void save(Object bean, Transaction transaction) throws OptimisticLockException;
/**
* Save all the beans in the iterator with an explicit transaction.
*/
int save(Iterator<?> it, Transaction transaction) throws OptimisticLockException;
/**
* Save all the beans in the collection with an explicit transaction.
*/
int save(Collection<?> beans, Transaction transaction) throws OptimisticLockException;
int saveAll(Collection<?> beans, Transaction transaction) throws OptimisticLockException;
/**
* Marks the entity bean as dirty.
@@ -1485,7 +1483,7 @@ public interface EbeanServer {
/**
* Update a bean additionally specifying a transaction.
*/
void update(Object bean, Transaction t) throws OptimisticLockException;
void update(Object bean, Transaction transaction) throws OptimisticLockException;
/**
* Update a bean additionally specifying a transaction and the deleteMissingChildren setting.
@@ -1505,13 +1503,13 @@ public interface EbeanServer {
* Update a collection of beans. If there is no current transaction one is created and used to
* update all the beans in the collection.
*/
void update(Collection<?> beans) throws OptimisticLockException;
void updateAll(Collection<?> beans) throws OptimisticLockException;
/**
* Update a collection of beans with an explicit transaction.
*/
void update(Collection<?> beans, Transaction transaction) throws OptimisticLockException;
void updateAll(Collection<?> beans, Transaction transaction) throws OptimisticLockException;
/**
* Insert the bean.
* <p>
@@ -1525,18 +1523,18 @@ public interface EbeanServer {
/**
* Insert the bean with a transaction.
*/
void insert(Object bean, Transaction t);
void insert(Object bean, Transaction transaction);
/**
* Insert a collection of beans. If there is no current transaction one is created and used to
* insert all the beans in the collection.
*/
void insert(Collection<?> beans);
void insertAll(Collection<?> beans);
/**
* Insert a collection of beans with an explicit transaction.
*/
void insert(Collection<?> beans, Transaction t);
void insertAll(Collection<?> beans, Transaction transaction);
/**
* Delete the associations (from the intersection table) of a ManyToMany given
@@ -1545,7 +1543,7 @@ public interface EbeanServer {
* Typically these deletions occur automatically when persisting a ManyToMany
* collection and this provides a way to invoke those deletions directly.
* </p>
*
*
* @return the number of associations deleted (from the intersection table).
*/
int deleteManyToManyAssociations(Object ownerBean, String propertyName);
@@ -1560,10 +1558,10 @@ public interface EbeanServer {
* Typically these deletions occur automatically when persisting a ManyToMany
* collection and this provides a way to invoke those deletions directly.
* </p>
*
*
* @return the number of associations deleted (from the intersection table).
*/
int deleteManyToManyAssociations(Object ownerBean, String propertyName, Transaction t);
int deleteManyToManyAssociations(Object ownerBean, String propertyName, Transaction transaction);
/**
* Save the associations of a ManyToMany given the owner bean and the
@@ -1585,7 +1583,7 @@ public interface EbeanServer {
* way to invoke those insertions directly.
* </p>
*/
void saveManyToManyAssociations(Object ownerBean, String propertyName, Transaction t);
void saveManyToManyAssociations(Object ownerBean, String propertyName, Transaction transaction);
/**
* Save the associated collection or bean given the property name.
@@ -1622,27 +1620,18 @@ public interface EbeanServer {
* @param propertyName
* the property we want to save
*/
void saveAssociation(Object ownerBean, String propertyName, Transaction t);
void saveAssociation(Object ownerBean, String propertyName, Transaction transaction);
/**
* Delete the bean with an explicit transaction.
*/
void delete(Object bean, Transaction t) throws OptimisticLockException;
/**
* Delete all the beans from an iterator.
*/
int delete(Iterator<?> it, Transaction t) throws OptimisticLockException;
/**
* Execute explicitly passing a transaction.
*/
int execute(SqlUpdate updSql, Transaction t);
int execute(SqlUpdate updSql, Transaction transaction);
/**
* Execute explicitly passing a transaction.
*/
int execute(CallableSql callableSql, Transaction t);
int execute(CallableSql callableSql, Transaction transaction);
/**
* Execute a TxRunnable in a Transaction with an explicit scope.
@@ -1665,7 +1654,7 @@ public interface EbeanServer {
*
* }</pre>
*/
void execute(TxScope scope, TxRunnable r);
void execute(TxScope scope, TxRunnable runnable);
/**
* Execute a TxRunnable in a Transaction with the default scope.
@@ -1691,7 +1680,7 @@ public interface EbeanServer {
*
* }</pre>
*/
void execute(TxRunnable r);
void execute(TxRunnable runnable);
/**
* Execute a TxCallable in a Transaction with an explicit scope.
@@ -1715,7 +1704,7 @@ public interface EbeanServer {
*
* }</pre>
*/
<T> T execute(TxScope scope, TxCallable<T> c);
<T> T execute(TxScope scope, TxCallable<T> callable);
/**
* Execute a TxCallable in a Transaction with the default scope.
@@ -1747,7 +1736,7 @@ public interface EbeanServer {
*
* }</pre>
*/
<T> T execute(TxCallable<T> c);
<T> T execute(TxCallable<T> callable);
/**
* Return the manager of the server cache ("L2" cache).
@@ -1777,12 +1766,6 @@ public interface EbeanServer {
*/
void runCacheWarming(Class<?> beanType);
/**
* Return the JsonContext for reading/writing JSON.
* @deprecated Please use #json instead.
*/
JsonContext createJsonContext();
/**
* Return the JsonContext for reading/writing JSON.
* <p>
@@ -169,7 +169,22 @@ public interface ExpressionFactory {
* In - property has a value in the collection of values.
*/
Expression in(String propertyName, Collection<?> values);
/**
* Not In - property has a value in the array of values.
*/
Expression notIn(String propertyName, Object[] values);
/**
* Not In - property has a value in the collection of values.
*/
Expression notIn(String propertyName, Collection<?> values);
/**
* Not In - using a subQuery.
*/
Expression notIn(String propertyName, Query<?> subQuery);
/**
* Exists expression
*/
@@ -1,8 +1,10 @@
package com.avaje.ebean;
import com.avaje.ebean.text.PathProperties;
import org.jetbrains.annotations.Nullable;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -94,6 +96,17 @@ public interface ExpressionList<T> extends Serializable {
*/
Query<T> apply(PathProperties pathProperties);
/**
* Perform an 'As of' query using history tables to return the object graph
* as of a time in the past.
* <p>
* To perform this query the DB must have underlying history tables.
* </p>
*
* @param asOf the date time in the past at which you want to view the data
*/
Query<T> asOf(Timestamp asOf);
/**
* Execute the query iterating over the results.
*
@@ -116,14 +129,6 @@ public interface ExpressionList<T> extends Serializable {
*/
void findEachWhile(QueryEachWhileConsumer<T> consumer);
/**
* Deprecated in favor of #findEachWhile which is functionally exactly the same
* but has a much better name.
*
* @deprecated
*/
void findVisit(QueryResultVisitor<T> visitor);
/**
* Execute the query returning a list.
*
@@ -170,6 +175,7 @@ public interface ExpressionList<T> extends Serializable {
*
* @see Query#findUnique()
*/
@Nullable
T findUnique();
/**
@@ -229,6 +235,24 @@ public interface ExpressionList<T> extends Serializable {
*/
PagedList<T> findPagedList(int pageIndex, int pageSize);
/**
* Return versions of a @History entity bean.
* <p>
* Generally this query is expected to be a find by id or unique predicates query.
* It will execute the query against the history returning the versions of the bean.
* </p>
*/
List<Version<T>> findVersions();
/**
* Return versions of a @History entity bean between the 2 timestamps.
* <p>
* Generally this query is expected to be a find by id or unique predicates query.
* It will execute the query against the history returning the versions of the bean.
* </p>
*/
List<Version<T>> findVersionsBetween(Timestamp start, Timestamp end);
/**
* Add some filter predicate expressions to the many property.
*/
@@ -242,6 +266,24 @@ public interface ExpressionList<T> extends Serializable {
*/
Query<T> select(String properties);
/**
* Set whether this query uses DISTINCT.
* <p>
* The select() clause MUST be specified when setDistinct(true) is set. The reason for this is that
* generally ORM queries include the "id" property and this doesn't make sense for distinct queries.
* </p>
* <pre>{@code
*
* List<Customer> customers =
* Ebean.find(Customer.class)
* .setDistinct(true)
* .select("name") // only select the customer name
* .findList();
*
* }</pre>
*/
Query<T> setDistinct(boolean distinct);
/**
* Set the first row to fetch.
*
@@ -473,7 +515,22 @@ public interface ExpressionList<T> extends Serializable {
* In - property has a value in the collection of values.
*/
ExpressionList<T> in(String propertyName, Collection<?> values);
/**
* Not In - property has a value in the array of values.
*/
ExpressionList<T> notIn(String propertyName, Object... values);
/**
* Not In - property has a value in the collection of values.
*/
ExpressionList<T> notIn(String propertyName, Collection<?> values);
/**
* Not In - using a subQuery.
*/
ExpressionList<T> notIn(String propertyName, Query<?> subQuery);
/**
* Exists expression
*/
+36 -36
View File
@@ -22,57 +22,57 @@ import java.io.Serializable;
* efficient loaded as 2 SQL queries.
* </p>
*
* <pre class="code">
* <pre>{@code
* // Normal fetch join results in a single SQL query
* List&lt;Order&gt; list = Ebean.find(Order.class).fetch(&quot;details&quot;).findList();
* List<Order> list = Ebean.find(Order.class).fetch("details").findList();
*
* // Find Orders join details using a single SQL query
* </pre>
* }</pre>
* <p>
* Example: Using a "query join" instead of a "fetch join" we instead use 2 SQL
* queries
* </p>
*
* <pre class="code">
* <pre>{@code
* // This will use 2 SQL queries to build this object graph
* List&lt;Order&gt; list =
* List<Order> list =
* Ebean.find(Order.class)
* .fetch(&quot;details&quot;, new FetchConfig().query())
* .fetch("details", new FetchConfig().query())
* .findList();
*
* // query 1) find order
* // query 2) find orderDetails where order.id in (?,?...) // first 100 order id's
* </pre>
* }</pre>
* <p>
* Example: Using 2 "query joins"
* </p>
*
* <pre class="code">
* <pre>{@code
* // This will use 3 SQL queries to build this object graph
* List&lt;Order&gt; list =
* List<Order> list =
* Ebean.find(Order.class)
* .fetch(&quot;details&quot;, new FetchConfig().query())
* .fetch(&quot;customer&quot;, new FetchConfig().queryFirst(5))
* .fetch("details", new FetchConfig().query())
* .fetch("customer", new FetchConfig().queryFirst(5))
* .findList();
*
* // query 1) find order
* // query 2) find orderDetails where order.id in (?,?...) // first 100 order id's
* // query 3) find customer where id in (?,?,?,?,?) // first 5 customers
* </pre>
* }</pre>
* <p>
* Example: Using "query joins" and partial objects
* </p>
*
* <pre class="code">
* <pre>{@code
* // This will use 3 SQL queries to build this object graph
* List&lt;Order&gt; list =
* List<Order> list =
* Ebean.find(Order.class)
* .select(&quot;status, shipDate&quot;)
* .fetch(&quot;details&quot;, &quot;quantity, price&quot;, new FetchConfig().query())
* .fetch(&quot;details.product&quot;, &quot;sku, name&quot;)
* .fetch(&quot;customer&quot;, &quot;name&quot;, new FetchConfig().queryFirst(5))
* .fetch(&quot;customer.contacts&quot;)
* .fetch(&quot;customer.shippingAddress&quot;)
* .select("status, shipDate")
* .fetch("details", "quantity, price", new FetchConfig().query())
* .fetch("details.product", "sku, name")
* .fetch("customer", "name", new FetchConfig().queryFirst(5))
* .fetch("customer.contacts")
* .fetch("customer.shippingAddress")
* .findList();
*
* // query 1) find order (status, shipDate)
@@ -81,22 +81,22 @@ import java.io.Serializable;
* // query 3) find customer (name) fetch contacts (*) fetch shippingAddress (*)
* // where id in (?,?,?,?,?)
*
* // Note: the fetch of &quot;details.product&quot; is automatically included into the
* // fetch of &quot;details&quot;
* // Note: the fetch of "details.product" is automatically included into the
* // fetch of "details"
* //
* // Note: the fetch of &quot;customer.contacts&quot; and &quot;customer.shippingAddress&quot;
* // are automatically included in the fetch of &quot;customer&quot;
* </pre>
* // Note: the fetch of "customer.contacts" and "customer.shippingAddress"
* // are automatically included in the fetch of "customer"
* }</pre>
* <p>
* You can use query() and lazy together on a single join. The query is executed
* immediately and the lazy defines the batch size to use for further lazy
* loading (if lazy loading is invoked).
* </p>
*
* <pre class="code">
* List&lt;Order&gt; list =
* <pre>{@code
* List<Order> list =
* Ebean.find(Order.class)
* .fetch(&quot;customer&quot;, new FetchConfig().query(10).lazy(5))
* .fetch("customer", new FetchConfig().query(10).lazy(5))
* .findList();
*
* // query 1) find order
@@ -104,7 +104,7 @@ import java.io.Serializable;
* // .. then if lazy loading of customers is invoked
* // .. use a batch size of 5 to load the customers
*
* </pre>
* }</pre>
*
* <p>
* Example of controlling the lazy loading query:
@@ -114,12 +114,12 @@ import java.io.Serializable;
* case.
* </p>
*
* <pre class="code">
* List&lt;Order&gt; list = Ebean.find(Order.class)
* .fetch(&quot;customer&quot;,&quot;name&quot;, new FetchConfig().lazy(5))
* .fetch(&quot;customer.contacts&quot;,&quotcontactName, phone, email&quot)
* .fetch(&quot;customer.shippingAddress&quot;)
* .where().eq(&quot;status&quot;,Order.Status.NEW)
* <pre>{@code
* List<Order> list = Ebean.find(Order.class)
* .fetch("customer","name", new FetchConfig().lazy(5))
* .fetch("customer.contacts",&quotcontactName, phone, email&quot)
* .fetch("customer.shippingAddress")
* .where().eq("status",Order.Status.NEW)
* .findList();
*
* // query 1) find order where status = Order.Status.NEW
@@ -132,7 +132,7 @@ import java.io.Serializable;
* fetch customer.shippingAddress (*)
* where id in (?,?,?,?,?)
*
* </pre>
* }</pre>
*
* @author mario
* @author rbygrave
@@ -2,7 +2,6 @@ package com.avaje.ebean;
import javax.persistence.PersistenceException;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+9 -8
View File
@@ -2,14 +2,13 @@ package com.avaje.ebean;
import com.avaje.ebean.text.PathProperties;
import com.avaje.ebean.util.ClassUtil;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
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;
/**
* A MappedSuperclass base class that provides convenience methods for inserting, updating and
@@ -152,7 +151,7 @@ public abstract class Model {
* }</pre>
*/
public static EbeanServer db() {
return Ebean.getServer(null);
return Ebean.getDefaultServer();
}
/**
@@ -442,6 +441,7 @@ public abstract class Model {
*
* }</pre>
*/
@SuppressWarnings("unchecked")
public Find() {
this.serverName = null;
this.type = (Class<T>)ClassUtil.getSecondArgumentType(getClass());
@@ -451,8 +451,8 @@ public abstract class Model {
* Construct passing the class literal type of the entity type.
*/
protected Find(String serverName, Class<T> type) {
this.type = type;
this.serverName = serverName;
this.type = type;
}
/**
@@ -514,6 +514,7 @@ public abstract class Model {
* <p>
* Equivalent to {@link EbeanServer#find(Class, Object)}
*/
@Nullable
public T byId(I id) {
return db().find(type, id);
}
@@ -159,6 +159,11 @@ public interface PagedList<T> {
*/
int getPageIndex();
/**
* Return the page size used for this query.
*/
int getPageSize();
/**
* Return true if there is a next page.
* <p>
@@ -34,7 +34,7 @@ class PrimaryServer {
/**
* Return the default server name.
*/
static synchronized String getPrimaryServerName() {
static synchronized String getDefaultServerName() {
getProperties();
return defaultServerName;
}
+72 -16
View File
@@ -1,8 +1,10 @@
package com.avaje.ebean;
import com.avaje.ebean.text.PathProperties;
import org.jetbrains.annotations.Nullable;
import java.io.Serializable;
import java.sql.Timestamp;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -284,6 +286,17 @@ public interface Query<T> extends Serializable {
*/
Query<T> setRawSql(RawSql rawSql);
/**
* Perform an 'As of' query using history tables to return the object graph
* as of a time in the past.
* <p>
* To perform this query the DB must have underlying history tables.
* </p>
*
* @param asOf the date time in the past at which you want to view the data
*/
Query<T> asOf(Timestamp asOf);
/**
* Cancel the query execution if supported by the underlying database and
* driver.
@@ -483,7 +496,7 @@ public interface Query<T> extends Serializable {
*
* }</pre>
*/
Query<T> fetch(String path, FetchConfig joinConfig);
Query<T> fetch(String path, FetchConfig fetchConfig);
/**
* Apply the path properties replacing the select and fetch clauses.
@@ -520,19 +533,7 @@ public interface Query<T> extends Serializable {
*/
QueryIterator<T> findIterate();
/**
* This is deprecated in favor of #findEachWhile.
* <p>
* This is functionally exactly the same as #findEachWhile. It is
* replaced by findEachWhile because the method name is much better.
* </p>
*
* @param visitor
* the visitor used to process the queried beans.
*
* @deprecated
*/
void findVisit(QueryResultVisitor<T> visitor);
/**
* Execute the query processing the beans one at a time.
@@ -716,8 +717,32 @@ public interface Query<T> extends Serializable {
* ...
* }</pre>
*/
@Nullable
T findUnique();
/**
* Return versions of a @History entity bean.
* <p>
* Note that this query will work against view based history implementations
* but not sql2011 standards based implementations that require a start and
* end timestamp to be specified.
* </p>
* <p>
* Generally this query is expected to be a find by id or unique predicates query.
* It will execute the query against the history returning the versions of the bean.
* </p>
*/
List<Version<T>> findVersions();
/**
* Return versions of a @History entity bean between the 2 timestamps.
* <p>
* Generally this query is expected to be a find by id or unique predicates query.
* It will execute the query against the history returning the versions of the bean.
* </p>
*/
List<Version<T>> findVersionsBetween(Timestamp start, Timestamp end);
/**
* Return the count of entities this query should return.
* <p>
@@ -878,6 +903,11 @@ public interface Query<T> extends Serializable {
*/
Query<T> setId(Object id);
/**
* Return the Id value.
*/
Object getId();
/**
* Add additional clause(s) to the where clause.
* <p>
@@ -1113,6 +1143,19 @@ public interface Query<T> extends Serializable {
/**
* Set whether this query uses DISTINCT.
* <p>
* The select() clause MUST be specified when setDistinct(true) is set. The reason for this is that
* generally ORM queries include the "id" property and this doesn't make sense for distinct queries.
* </p>
* <pre>{@code
*
* List<Customer> customers =
* Ebean.find(Customer.class)
* .setDistinct(true)
* .select("name")
* .findList();
*
* }</pre>
*/
Query<T> setDistinct(boolean isDistinct);
@@ -1123,8 +1166,8 @@ public interface Query<T> extends Serializable {
/**
* Set the first row to return for this query.
*
* @param firstRow
*
* @param firstRow the first row to include in the query result.
*/
Query<T> setFirstRow(int firstRow);
@@ -1235,4 +1278,17 @@ public interface Query<T> extends Serializable {
* Set root table alias.
*/
Query<T> alias(String alias);
/**
* Return the type of beans being queried.
*/
Class<T> getBeanType();
/**
* Set true if you want to disable lazy loading.
* <p>
* That is, once the object graph is returned further lazy loading is disabled.
* </p>
*/
Query<T> setDisableLazyLoading(boolean disableLazyLoading);
}
@@ -1,49 +0,0 @@
package com.avaje.ebean;
/**
* Used to process a query result one bean at a time via a callback to this
* visitor.
* <p>
* If you wish to stop further processing return false from the accept method.
* </p>
* <p>
* Unlike findList() and findSet() using a QueryResultVisitor does not require
* all the beans in the query result to be held in memory at once. This makes
* QueryResultVisitor useful for processing large queries.
* </p>
*
* <pre class="code">
*
* Query&lt;Customer&gt; query = server.find(Customer.class)
* .fetch(&quot;contacts&quot;, new FetchConfig().query(2))
* .where().gt(&quot;id&quot;, 0)
* .orderBy(&quot;id&quot;)
* .setMaxRows(2);
*
* query.findVisit(new QueryResultVisitor&lt;Customer&gt;() {
*
* public boolean accept(Customer customer) {
* // do something with customer
* System.out.println(&quot;-- visit &quot; + customer);
* return true;
* }
* });
* </pre>
*
* @author rbygrave
*
* @param <T>
* the type of entity bean being queried.
*/
public interface QueryResultVisitor<T> {
/**
* Process the bean and return true if you want to continue processing more
* beans. Return false if you want to stop processing further.
*
* @param bean
* the entity bean to process
* @return true to continue processing or false to stop.
*/
boolean accept(T bean);
}
@@ -480,6 +480,13 @@ public final class RawSql implements Serializable {
this.queryHashCode = hc;
}
/**
* Return true if the property is mapped.
*/
public boolean contains(String property) {
return this.propertyColumnMap.containsKey(property);
}
/**
* Creates an immutable copy of this ColumnMapping.
*
+1 -1
View File
@@ -153,7 +153,7 @@ public interface SqlRow extends Serializable, Map<String, Object> {
/**
* Put all the values from t into this map.
*/
void putAll(Map<? extends String, ? extends Object> t);
void putAll(Map<? extends String, ?> t);
/**
* Return the size of the map.
+12 -2
View File
@@ -2,7 +2,6 @@ package com.avaje.ebean;
import com.avaje.ebean.config.PersistBatch;
import javax.persistence.OptimisticLockException;
import javax.persistence.PersistenceException;
import javax.persistence.RollbackException;
import java.io.Closeable;
@@ -97,6 +96,17 @@ public interface Transaction extends Closeable {
*/
void setPersistCascade(boolean persistCascade);
/**
* Set to true when you want all loaded properties to be included in the update
* (rather than just the changed properties).
* <p>
* You might set this when using JDBC batch in order to get multiple updates
* with slightly different sets of changed properties into the same statement
* and hence better JDBC batch performance.
* </p>
*/
void setUpdateAllLoadedProperties(boolean updateAllLoadedProperties);
/**
* Turn on or off statement batching. Statement batching can be transparent
* for drivers and databases that support getGeneratedKeys. Otherwise you may
@@ -279,7 +289,7 @@ public interface Transaction extends Closeable {
* <li>Transaction commit occurs</li>
* </ul>
*/
void flushBatch() throws PersistenceException, OptimisticLockException;
void flushBatch() throws PersistenceException;
/**
* Return the underlying Connection object.
+1 -1
View File
@@ -46,5 +46,5 @@ public enum TxType {
* If there is an existing transaction throws an Exception. Method runs
* without a transaction.
*/
NEVER;
NEVER
}
+18 -11
View File
@@ -5,10 +5,19 @@ package com.avaje.ebean;
*/
public class ValuePair {
private final Object newValue;
protected Object newValue;
private final Object oldValue;
protected Object oldValue;
/**
* Default constructor for JSON tools.
*/
public ValuePair() {
}
/**
* Construct with the pair of new and old values.
*/
public ValuePair(Object newValue, Object oldValue) {
this.newValue = newValue;
this.oldValue = oldValue;
@@ -27,21 +36,19 @@ public class ValuePair {
public Object getOldValue() {
return oldValue;
}
/**
* Return the new value.
* Set the new value.
*/
@Deprecated
public Object getValue1() {
return newValue;
public void setNewValue(Object newValue) {
this.newValue = newValue;
}
/**
* Return the old value.
* Set the old value.
*/
@Deprecated
public Object getValue2() {
return oldValue;
public void setOldValue(Object oldValue) {
this.oldValue = oldValue;
}
public String toString() {
+101
View File
@@ -0,0 +1,101 @@
package com.avaje.ebean;
import java.sql.Timestamp;
import java.util.Map;
/**
* Wraps a version of a @History bean.
*/
public class Version<T> {
/**
* The version of the bean.
*/
protected T bean;
/**
* The effective start date time of this version.
*/
protected Timestamp start;
/**
* The effective end date time of this version.
*/
protected Timestamp end;
/**
* The map of changed properties.
*/
protected Map<String, ValuePair> diff;
/**
* Construct with bean and an effective date time range.
*/
public Version(T bean, Timestamp start, Timestamp end) {
this.bean = bean;
this.start = start;
this.end = end;
}
/**
* Default constructor - useful for JSON tools such as Jackson.
*/
public Version() {
}
/**
* Return the bean instance for this version.
*/
public T getBean() {
return bean;
}
/**
* Set the bean instance for this version.
*/
public void setBean(T bean) {
this.bean = bean;
}
/**
* Return the effective start date time of this version.
*/
public Timestamp getStart() {
return start;
}
/**
* Set the effective start date time of this version.
*/
public void setStart(Timestamp start) {
this.start = start;
}
/**
* Return the effective end date time of this version.
*/
public Timestamp getEnd() {
return end;
}
/**
* Set the effective end date time of this version.
*/
public void setEnd(Timestamp end) {
this.end = end;
}
/**
* Set the map of differences from this bean to the prior version.
*/
public void setDiff(Map<String, ValuePair> diff) {
this.diff = diff;
}
/**
* Return the map of differences from this bean to the prior version.
*/
public Map<String, ValuePair> getDiff() {
return diff;
}
}
@@ -44,4 +44,12 @@ public @interface CacheTuning {
* </p>
*/
int maxSecsToLive() default 0;
/**
* The frequency (in seconds) that cache trimming should occur.
* <p>
* This is a hint for cache implementations that use background cache trimming.
* </p>
*/
int trimFrequency() default 0;
}
@@ -0,0 +1,34 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Marks an entity bean as being included in the change logging.
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ChangeLog {
/**
* Specify if inserts should be explicitly Included or Excluded.
* <p>
* If not defined explicitly then the server default behaviour defined
* on ServerConfig is used.
* </p>
*/
ChangeLogInsertMode inserts() default ChangeLogInsertMode.DEFAULT;
/**
* When specified only include update requests that have at least one
* of the given properties as a dirty property.
* <p>
* This provides a way to filter requests to include in the change log such that
* only updates that include at least one of the given properties is included
* in the change log.
* </p>
*/
String[] updatesThatInclude() default {};
}
@@ -0,0 +1,22 @@
package com.avaje.ebean.annotation;
/**
* The mode used to determine if inserts should be included or not for a given bean type.
*/
public enum ChangeLogInsertMode {
/**
* Use the default behaviour as defined on ServerConfig.
*/
DEFAULT,
/**
* Include inserts in the change log.
*/
INCLUDE,
/**
* Exclude inserts in the change log.
*/
EXCLUDE
}
@@ -1,17 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Deprecated - please use @DbHstore instead.
* @see DbHstore
*/
@Deprecated
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ColumnHstore {
}
@@ -0,0 +1,19 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Marks an entity bean as having history support.
* <p>
* In Postgres for example this means there is an associated history table which is
* typically automatically populated via database triggers.
* </p>
*/
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface History {
}
@@ -0,0 +1,25 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Marks a property as being excluded from history.
* <p>
* This means the property values are not maintained in the history table. Typically this
* would be placed on relatively large properties (Clobs, Blobs, large varchar columns etc)
* that are considered not interesting enough to maintain history on excluding them reduces
* underlying database costs.
* </p>
* <p>
* When placed on a ManyToMany this means that the intersection table does not have history
* support.
* </p>
*/
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface HistoryExclude {
}
@@ -0,0 +1,32 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Similar to Jackson JsonIgnore but provides the option to just ignore serialize or deserialize.
* <p>
* This provides the same features as Expose but from the opposite perspective which is probably
* more common and more familiar to Jackson users.
* </p>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface JsonIgnore {
/**
* If {@code true}, the field marked with this annotation is written out in the JSON while
* serializing. If {@code false}, the field marked with this annotation is skipped from the
* serialized output. Defaults to {@code false}.
*/
boolean serialize() default false;
/**
* If {@code true}, the field marked with this annotation is deserialized from the JSON.
* If {@code false}, the field marked with this annotation is skipped during deserialization.
* Defaults to {@code false}.
*/
boolean deserialize() default false;
}
@@ -0,0 +1,38 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* For a timestamp property that is set to the datetime when the entity is
* created/inserted.
* <p>
* This is effectively an alias for @CreatedTimestamp and added to hint
* towards a better naming convention (WhenCreated, WhenModified).
* </p>
* <p>
* An alternative to using this annotation would be to use insertable=false,
* updateable=false with @Column and have the DB insert the current time
* (default value on the DB column is SYSTIME etc).
* </p>
* <p>
* The downside to this approach is that the inserted entity does not have the
* timestamp value after the insert has occurred. You need to fetch the entity
* back to get the inserted timestamp if you want to used it.
* </p>
*
* <h3>Example:</h3>
* <pre>{@code
*
* @WhenCreated
* Timestamp whenCreated;
*
* }</pre>
*/
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface WhenCreated {
}
@@ -0,0 +1,20 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* For a timestamp property that is set to the datetime when the entity was last modified.
* <p>
* This is effectively an alias for @UpdatedTimestamp and added to hint
* towards a better naming convention (WhenCreated, WhenModified).
* </p>
* </p>
*/
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface WhenModified {
}
@@ -0,0 +1,29 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Mapped onto a entity bean property that represents the user id of
* who created the entity>
* <p>
* To use this annotation you need to implement CurrentUserProvider.
* The type of the bean property should match the type returned by
* CurrentUserProvider.
*</p>
* <h3>Example:</h3>
* <pre>{@code
*
* @WhoCreated
* String whoCreated;
*
* }</pre>
*/
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface WhoCreated {
}
@@ -0,0 +1,29 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Mapped onto a entity bean property that represents the user id of
* who last modified the entity>
* <p>
* To use this annotation you need to implement CurrentUserProvider.
* The type of the bean property should match the type returned by
* CurrentUserProvider.
* </p>
*
* <h3>Example:</h3>
* <pre>{@code
*
* @WhoModified
* String whoModified;
*
* }</pre>
*/
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface WhoModified {
}
@@ -45,7 +45,7 @@ public final class EntityBeanIntercept implements Serializable {
/**
* The actual entity bean that 'owns' this intercept.
*/
private EntityBean owner;
private final EntityBean owner;
private EntityBean embeddedOwner;
private int embeddedOwnerIndex;
@@ -72,7 +72,7 @@ public final class EntityBeanIntercept implements Serializable {
/**
* Used when a bean is partially filled.
*/
private boolean[] loadedProps;
private final boolean[] loadedProps;
private boolean fullyLoadedBean;
@@ -581,7 +581,29 @@ public final class EntityBeanIntercept implements Serializable {
}
}
}
/**
* Return true if any of the given property names are dirty.
*/
public boolean hasDirtyProperty(Set<String> propertyNames) {
String[] names = owner._ebean_getPropertyNames();
int len = getPropertyLength();
for (int i = 0; i < len; i++) {
if (changedProps != null && changedProps[i]) {
// the property has been changed on this bean
if (propertyNames.contains(names[i])) {
return true;
}
} else if (embeddedDirty != null && embeddedDirty[i]) {
if (propertyNames.contains(names[i])) {
return true;
}
}
}
return false;
}
/**
* Return a map of dirty properties with their new and old values.
*/
@@ -608,7 +630,7 @@ public final class EntityBeanIntercept implements Serializable {
} else if (embeddedDirty != null && embeddedDirty[i]) {
// an embedded property has been changed - recurse
EntityBean embeddedBean = (EntityBean)owner._ebean_getField(i);
embeddedBean._ebean_getIntercept().addDirtyPropertyValues(dirtyValues, getProperty(i)+".");
embeddedBean._ebean_getIntercept().addDirtyPropertyValues(dirtyValues, getProperty(i) + ".");
}
}
}
@@ -638,6 +660,20 @@ public final class EntityBeanIntercept implements Serializable {
return hash;
}
/**
* Return a loaded property hash.
*/
public int getLoadedPropertyHash() {
int hash = 37;
int len = getPropertyLength();
for (int i = 0; i < len; i++) {
if (isLoadedProperty(i)) {
hash = hash * 31 + (i+1);
}
}
return hash;
}
/**
* Return the set of property names for changed properties.
*/
@@ -877,7 +913,7 @@ public final class EntityBeanIntercept implements Serializable {
} else {
return null;
}
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
}
/**
@@ -892,7 +928,7 @@ public final class EntityBeanIntercept implements Serializable {
} else {
return null;
}
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Integer.valueOf(oldValue), Integer.valueOf(newValue));
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
}
/**
@@ -908,7 +944,7 @@ public final class EntityBeanIntercept implements Serializable {
return null;
}
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Long.valueOf(oldValue), Long.valueOf(newValue));
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
}
/**
@@ -923,7 +959,7 @@ public final class EntityBeanIntercept implements Serializable {
} else {
return null;
}
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Double.valueOf(oldValue), Double.valueOf(newValue));
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
}
/**
@@ -938,7 +974,7 @@ public final class EntityBeanIntercept implements Serializable {
} else {
return null;
}
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Float.valueOf(oldValue), Float.valueOf(newValue));
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
}
/**
@@ -953,7 +989,7 @@ public final class EntityBeanIntercept implements Serializable {
} else {
return null;
}
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Short.valueOf(oldValue), Short.valueOf(newValue));
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
}
/**
@@ -968,7 +1004,7 @@ public final class EntityBeanIntercept implements Serializable {
} else {
return null;
}
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Character.valueOf(oldValue), Character.valueOf(newValue));
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
}
/**
@@ -983,7 +1019,7 @@ public final class EntityBeanIntercept implements Serializable {
} else {
return null;
}
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), Byte.valueOf(oldValue), Byte.valueOf(newValue));
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
}
/**
@@ -82,6 +82,7 @@ public final class ObjectGraphNode implements Serializable {
}
ObjectGraphNode e = (ObjectGraphNode) obj;
//noinspection StringEquality
return ((e.path == path) || (e.path != null && e.path.equals(path)))
&& e.originQueryPoint.equals(originQueryPoint);
}
@@ -74,12 +74,12 @@ public interface PersistenceContext {
* The bean was previously deleted from this persistence context (can't hit
* L2 cache).
*/
public static WithOption DELETED = new WithOption(true);
public static final WithOption DELETED = new WithOption();
private final boolean deleted;
private final Object bean;
private WithOption(boolean deleted) {
private WithOption() {
this.deleted = true;
this.bean = null;
}
-6
View File
@@ -48,12 +48,6 @@ public interface ServerCache {
*/
Object put(Object id, Object value);
/**
* Put the value in the cache but only if a matching value is not already in
* the cache.
*/
Object putIfAbsent(Object id, Object value);
/**
* Remove a entry from the cache given its id.
*/
+24 -5
View File
@@ -10,6 +10,7 @@ public class ServerCacheOptions {
private int maxSize;
private int maxIdleSecs;
private int maxSecsToLive;
private int trimFrequency;
/**
* Construct with no set options.
@@ -25,15 +26,17 @@ public class ServerCacheOptions {
this.maxSize = cacheTuning.maxSize();
this.maxIdleSecs = cacheTuning.maxIdleSecs();
this.maxSecsToLive = cacheTuning.maxSecsToLive();
this.trimFrequency = cacheTuning.trimFrequency();
}
/**
* Create merging default options with the deployment specified ones.
*/
public ServerCacheOptions(ServerCacheOptions d) {
this.maxSize = d.getMaxSize();
this.maxIdleSecs = d.getMaxIdleSecs();
this.maxSecsToLive = d.getMaxIdleSecs();
public ServerCacheOptions(ServerCacheOptions defaults) {
this.maxSize = defaults.getMaxSize();
this.maxIdleSecs = defaults.getMaxIdleSecs();
this.maxSecsToLive = defaults.getMaxIdleSecs();
this.trimFrequency = defaults.getTrimFrequency();
}
/**
@@ -50,6 +53,9 @@ public class ServerCacheOptions {
if (maxSecsToLive == 0) {
maxSecsToLive = defaults.getMaxSecsToLive();
}
if (trimFrequency == 0) {
trimFrequency = defaults.getTrimFrequency();
}
}
/**
@@ -61,7 +67,7 @@ public class ServerCacheOptions {
copy.maxSize = maxSize;
copy.maxIdleSecs = maxIdleSecs;
copy.maxSecsToLive = maxSecsToLive;
copy.trimFrequency = trimFrequency;
return copy;
}
@@ -107,4 +113,17 @@ public class ServerCacheOptions {
this.maxSecsToLive = maxSecsToLive;
}
/**
* Return the trim frequency in seconds.
*/
public int getTrimFrequency() {
return trimFrequency;
}
/**
* Set the trim frequency in seconds.
*/
public void setTrimFrequency(int trimFrequency) {
this.trimFrequency = trimFrequency;
}
}
+177 -24
View File
@@ -5,9 +5,9 @@ package com.avaje.ebean.cache;
* <p>
* These can be monitored to review the effectiveness of a particular cache.
* </p>
*
* @author rbygrave
*
* <p>
* Depending on the cache implementation not all the statistics may be collected.
* </p>
*/
public class ServerCacheStatistics {
@@ -17,21 +17,64 @@ public class ServerCacheStatistics {
protected int size;
protected int hitCount;
protected long hitCount;
protected int missCount;
protected long missCount;
protected long insertCount;
protected long updateCount;
protected long removeCount;
protected long clearCount;
protected long evictionRunCount;
protected long evictionRunMicros;
protected long evictByIdle;
protected long evictByTTL;
protected long evictByLRU;
public String toString() {
StringBuilder sb = new StringBuilder();
//noinspection StringBufferReplaceableByString
StringBuilder sb = new StringBuilder(80);
sb.append(cacheName);
sb.append(" maxSize:").append(maxSize);
sb.append(" size:").append(size);
sb.append(" hitRatio:").append(getHitRatio());
sb.append(" hitCount:").append(hitCount);
sb.append(" missCount:").append(missCount);
sb.append(" maxSize:").append(maxSize);
sb.append(" hit:").append(hitCount);
sb.append(" miss:").append(missCount);
sb.append(" insert:").append(insertCount);
sb.append(" update:").append(updateCount);
sb.append(" remove:").append(removeCount);
sb.append(" clear:").append(clearCount);
sb.append(" evictByIdle:").append(evictByIdle);
sb.append(" evictByTTL:").append(evictByTTL);
sb.append(" evictByLRU:").append(evictByLRU);
sb.append(" evictionRunCount:").append(evictionRunCount);
sb.append(" evictionRunMicros:").append(evictionRunMicros);
return sb.toString();
}
/**
* Returns an int from 0 to 100 (percentage) for the hit ratio.
* <p>
* A hit ratio of 100 means every get request against the cache hits an entry.
* </p>
*/
public int getHitRatio() {
long totalCount = hitCount + missCount;
if (totalCount == 0) {
return 0;
} else {
return (int)(hitCount * 100 / totalCount);
}
}
/**
* Return the name of the cache.
*/
@@ -49,28 +92,28 @@ public class ServerCacheStatistics {
/**
* Return the hit count. The number of successful gets.
*/
public int getHitCount() {
public long getHitCount() {
return hitCount;
}
/**
* Set the hit count.
*/
public void setHitCount(int hitCount) {
public void setHitCount(long hitCount) {
this.hitCount = hitCount;
}
/**
* Return the miss count. The number of gets that returned null.
*/
public int getMissCount() {
public long getMissCount() {
return missCount;
}
/**
* Set the miss count.
*/
public void setMissCount(int missCount) {
public void setMissCount(long missCount) {
this.missCount = missCount;
}
@@ -107,18 +150,128 @@ public class ServerCacheStatistics {
}
/**
* Returns an int from 0 to 100 (percentage) for the hit ratio.
* <p>
* A hit ratio of 100 means every get request against the cache hits an entry.
* </p>
* Set the put insert count.
*/
public int getHitRatio() {
int totalCount = hitCount + missCount;
if (totalCount == 0) {
return 0;
} else {
return hitCount * 100 / totalCount;
}
public void setInsertCount(long insertCount) {
this.insertCount = insertCount;
}
/**
* Return the put insert count.
*/
public long getInsertCount() {
return insertCount;
}
/**
* Set the put update count.
*/
public void setUpdateCount(long updateCount) {
this.updateCount = updateCount;
}
/**
* Return the put update count.
*/
public long getUpdateCount() {
return updateCount;
}
/**
* Set the remove count.
*/
public void setRemoveCount(long removeCount) {
this.removeCount = removeCount;
}
/**
* Return the remove count.
*/
public long getRemoveCount() {
return removeCount;
}
/**
* Set the clear count.
*/
public void setClearCount(long clearCount) {
this.clearCount = clearCount;
}
/**
* Return the clear count.
*/
public long getClearCount() {
return clearCount;
}
/**
* Set the eviction run count.
*/
public void setEvictionRunCount(long evictCount) {
this.evictionRunCount = evictCount;
}
/**
* Return the eviction run count.
*/
public long getEvictionRunCount() {
return evictionRunCount;
}
/**
* Set the eviction run time in micros.
*/
public void setEvictionRunMicros(long evictionRunMicros) {
this.evictionRunMicros = evictionRunMicros;
}
/**
* Return the eviction run time in micros.
*/
public long getEvictionRunMicros() {
return evictionRunMicros;
}
/**
* Set the count of entries evicted due to idle time.
*/
public void setEvictByIdle(long evictByIdle) {
this.evictByIdle = evictByIdle;
}
/**
* Return the count of entries evicted due to idle time.
*/
public long getEvictByIdle() {
return evictByIdle;
}
/**
* Set the count of entries evicted due to time to live.
*/
public void setEvictByTTL(long evictByTTL) {
this.evictByTTL = evictByTTL;
}
/**
* Return the count of entries evicted due to time to live.
*/
public long getEvictByTTL() {
return evictByTTL;
}
/**
* Set the count of entries evicted due to time least recently used.
*/
public void setEvictByLRU(long evictByLRU) {
this.evictByLRU = evictByLRU;
}
/**
* Return the count of entries evicted due to time least recently used.
*/
public long getEvictByLRU() {
return evictByLRU;
}
}
@@ -343,41 +343,41 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
return list.remove(o);
}
public boolean removeAll(Collection<?> c) {
public boolean removeAll(Collection<?> beans) {
checkReadOnly();
init();
if (modifyRemoveListening) {
boolean changed = false;
Iterator<?> it = c.iterator();
while (it.hasNext()) {
Object o = it.next();
if (list.remove(o)) {
modifyRemoval(o);
for (Object bean : beans) {
if (list.remove(bean)) {
// register this bean as having been removed
modifyRemoval(bean);
changed = true;
}
}
return changed;
}
return list.removeAll(c);
return list.removeAll(beans);
}
public boolean retainAll(Collection<?> c) {
public boolean retainAll(Collection<?> retainBeans) {
checkReadOnly();
init();
if (modifyRemoveListening) {
boolean changed = false;
Iterator<E> it = list.iterator();
while (it.hasNext()) {
Object o = it.next();
if (!c.contains(o)) {
Object bean = it.next();
if (!retainBeans.contains(bean)) {
// removing this bean
it.remove();
modifyRemoval(o);
modifyRemoval(bean);
changed = true;
}
}
return changed;
}
return list.retainAll(c);
return list.retainAll(retainBeans);
}
public E set(int index, E element) {
@@ -415,6 +415,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
public <T> T[] toArray(T[] a) {
init();
//noinspection SuspiciousToArrayCall
return list.toArray(a);
}
@@ -1,15 +1,14 @@
package com.avaje.ebean.common;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import com.avaje.ebean.bean.BeanCollectionLoader;
import com.avaje.ebean.bean.EntityBean;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
/**
* Map capable of lazy loading.
*/
@@ -195,9 +194,9 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
checkReadOnly();
initClear();
if (modifyRemoveListening) {
for (K key : map.keySet()) {
E o = map.remove(key);
modifyRemoval(o);
// add all beans to the removal list
for (E bean : map.values()) {
modifyRemoval(bean);
}
}
map.clear();
@@ -249,27 +248,30 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
checkReadOnly();
init();
if (modifyListening) {
Object o = map.put(key, value);
modifyAddition(value);
modifyRemoval(o);
Object oldBean = map.put(key, value);
if (value != oldBean) {
// register the add of the new and the removal of the old
modifyAddition(value);
modifyRemoval(oldBean);
}
}
return map.put(key, value);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public void putAll(Map<? extends K, ? extends E> t) {
public void putAll(Map<? extends K, ? extends E> puts) {
checkReadOnly();
init();
if (modifyListening) {
Iterator it = t.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
Object o = map.put((K) entry.getKey(), (E) entry.getValue());
modifyAddition((E) entry.getValue());
modifyRemoval(o);
for (Entry<? extends K, ? extends E> entry : puts.entrySet()) {
Object oldBean = map.put(entry.getKey(), entry.getValue());
if (entry.getValue() != oldBean) {
modifyAddition(entry.getValue());
modifyRemoval(oldBean);
}
}
}
map.putAll(t);
map.putAll(puts);
}
public E remove(Object key) {
@@ -192,32 +192,29 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
return set.add(o);
}
public boolean addAll(Collection<? extends E> c) {
public boolean addAll(Collection<? extends E> addCollection) {
checkReadOnly();
init();
if (modifyAddListening) {
boolean changed = false;
Iterator<? extends E> it = c.iterator();
while (it.hasNext()) {
E o = it.next();
if (set.add(o)) {
modifyAddition(o);
for (E bean : addCollection) {
if (set.add(bean)) {
// register the addition of the bean
modifyAddition(bean);
changed = true;
}
}
return changed;
}
return set.addAll(c);
return set.addAll(addCollection);
}
public void clear() {
checkReadOnly();
initClear();
if (modifyRemoveListening) {
Iterator<E> it = set.iterator();
while (it.hasNext()) {
E e = it.next();
modifyRemoval(e);
for (E bean : set) {
modifyRemoval(bean);
}
}
set.clear();
@@ -262,41 +259,40 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
return set.remove(o);
}
public boolean removeAll(Collection<?> c) {
public boolean removeAll(Collection<?> beans) {
checkReadOnly();
init();
if (modifyRemoveListening) {
boolean changed = false;
Iterator<?> it = c.iterator();
while (it.hasNext()) {
Object o = it.next();
if (set.remove(o)) {
modifyRemoval(o);
for (Object bean : beans) {
if (set.remove(bean)) {
modifyRemoval(bean);
changed = true;
}
}
return changed;
}
return set.removeAll(c);
return set.removeAll(beans);
}
public boolean retainAll(Collection<?> c) {
public boolean retainAll(Collection<?> beans) {
checkReadOnly();
init();
if (modifyRemoveListening) {
boolean changed = false;
Iterator<?> it = set.iterator();
while (it.hasNext()) {
Object o = it.next();
if (!c.contains(o)) {
Object bean = it.next();
if (!beans.contains(bean)) {
// not retaining this bean so add it to the removal list
it.remove();
modifyRemoval(o);
modifyRemoval(bean);
changed = true;
}
}
return changed;
}
return set.retainAll(c);
return set.retainAll(beans);
}
public int size() {
@@ -311,6 +307,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
public <T> T[] toArray(T[] a) {
init();
//noinspection SuspiciousToArrayCall
return set.toArray(a);
}
@@ -40,9 +40,7 @@ class ModifyCollection<E> implements Collection<E> {
public boolean addAll(Collection<? extends E> collection) {
boolean changed = false;
Iterator<? extends E> it = collection.iterator();
while (it.hasNext()) {
E o = it.next();
for (E o : collection) {
if (c.add(o)) {
owner.modifyAddition(o);
changed = true;
@@ -51,27 +49,33 @@ class ModifyCollection<E> implements Collection<E> {
return changed;
}
@Override
public void clear() {
c.clear();
}
@Override
public boolean contains(Object o) {
return c.contains(o);
}
@Override
public boolean containsAll(Collection<?> collection) {
return c.containsAll(collection);
}
@Override
public boolean isEmpty() {
return c.isEmpty();
}
@Override
public Iterator<E> iterator() {
Iterator<E> it = c.iterator();
return new ModifyIterator<E>(owner, it);
}
@Override
public boolean remove(Object o) {
if (c.remove(o)) {
owner.modifyRemoval(o);
@@ -80,42 +84,47 @@ class ModifyCollection<E> implements Collection<E> {
return false;
}
@Override
public boolean removeAll(Collection<?> collection) {
boolean changed = false;
Iterator<?> it = collection.iterator();
while (it.hasNext()) {
Object o = (Object) it.next();
if (c.remove(o)) {
owner.modifyRemoval(o);
for (Object bean : collection) {
if (c.remove(bean)) {
owner.modifyRemoval(bean);
changed = true;
}
}
return changed;
}
@Override
public boolean retainAll(Collection<?> collection) {
boolean changed = false;
Iterator<?> it = c.iterator();
while (it.hasNext()) {
Object o = (Object) it.next();
if (!collection.contains(o)) {
Object bean = it.next();
if (!collection.contains(bean)) {
// not retaining this bean so add to removals
it.remove();
owner.modifyRemoval(o);
owner.modifyRemoval(bean);
changed = true;
}
}
return changed;
}
@Override
public int size() {
return c.size();
}
@Override
public Object[] toArray() {
return c.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
//noinspection SuspiciousToArrayCall
return c.toArray(a);
}
@@ -58,7 +58,7 @@ class ModifyHolder<E> implements Serializable {
void modifyRemoval(Object bean) {
if (bean != null) {
// If it is to be added then just remove the addition
if (!modifyAdditions.remove((E) bean)) {
if (!modifyAdditions.remove(bean)) {
modifyDeletions.add((E) bean);
}
}
@@ -1,7 +1,6 @@
package com.avaje.ebean.common;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
@@ -39,12 +38,10 @@ class ModifyList<E> extends ModifyCollection<E> implements List<E> {
owner.modifyAddition(element);
}
public boolean addAll(int index, Collection<? extends E> co) {
if (list.addAll(index, co)) {
Iterator<? extends E> it = co.iterator();
while (it.hasNext()) {
E o = it.next();
owner.modifyAddition(o);
public boolean addAll(int index, Collection<? extends E> addCollection) {
if (list.addAll(index, addCollection)) {
for (E bean : addCollection) {
owner.modifyAddition(bean);
}
return true;
}
@@ -67,9 +67,7 @@ class ModifyListIterator<E> implements ListIterator<E> {
}
public void set(E o) {
if (last == null) {
// in theory this is not allowed
} else {
if (last != null) {
owner.modifyRemoval(last);
owner.modifyAddition(o);
}
@@ -1,12 +1,10 @@
package com.avaje.ebean.config;
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
import javax.persistence.Inheritance;
import javax.persistence.Table;
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Provides some base implementation for NamingConventions.
*
@@ -14,31 +12,39 @@ import org.slf4j.LoggerFactory;
*/
public abstract class AbstractNamingConvention implements NamingConvention {
/** The Constant logger. */
private static final Logger logger = LoggerFactory.getLogger(AbstractNamingConvention.class);
/** The Constant DEFAULT_SEQ_FORMAT. */
/**
* The Constant DEFAULT_SEQ_FORMAT.
*/
public static final String DEFAULT_SEQ_FORMAT = "{table}_seq";
/** Sequence Format that includes the Primary Key column */
/**
* Sequence Format that includes the Primary Key column
*/
public static final String TABLE_PKCOLUMN_SEQ_FORMAT = "{table}_{column}_seq";
/** The catalog. */
/**
* The catalog.
*/
private String catalog;
/** The schema. */
/**
* The schema.
*/
private String schema;
/** The sequence format. */
/**
* The sequence format.
*/
private String sequenceFormat;
/** The database platform. */
/**
* The database platform.
*/
protected DatabasePlatform databasePlatform;
/** The max length of constraint names. */
protected int maxConstraintNameLength;
/** Used to trim off extra prefix for M2M. */
/**
* Used to trim off extra prefix for M2M.
*/
protected int rhsPrefixLength = 3;
protected boolean useForeignKeyPrefix;
@@ -62,8 +68,7 @@ public abstract class AbstractNamingConvention implements NamingConvention {
}
/**
* Construct with the default sequence format ("{table}_seq") and
* useForeignKeyPrefix as true.
* Construct with the default sequence format ("{table}_seq") and useForeignKeyPrefix as true.
*/
public AbstractNamingConvention() {
this(DEFAULT_SEQ_FORMAT);
@@ -71,9 +76,6 @@ public abstract class AbstractNamingConvention implements NamingConvention {
public void setDatabasePlatform(DatabasePlatform databasePlatform) {
this.databasePlatform = databasePlatform;
this.maxConstraintNameLength = databasePlatform.getDbDdlSyntax().getMaxConstraintNameLength();
logger.trace("Using maxConstraintNameLength of " + maxConstraintNameLength);
}
public String getSequenceName(String tableName, String pkColumn) {
@@ -218,11 +220,11 @@ public abstract class AbstractNamingConvention implements NamingConvention {
}
buffer.append(rhsTableName);
int maxConstraintNameLength = databasePlatform.getDbDdlSyntax().getMaxConstraintNameLength();
int maxTableNameLength = databasePlatform.getMaxTableNameLength();
// maxConstraintNameLength is used as the max table name length.
if (buffer.length() > maxConstraintNameLength) {
buffer.setLength(maxConstraintNameLength);
if (buffer.length() > maxTableNameLength) {
buffer.setLength(maxTableNameLength);
}
return new TableName(lhsTable.getCatalog(), lhsTable.getSchema(), buffer.toString());
@@ -239,7 +241,7 @@ public abstract class AbstractNamingConvention implements NamingConvention {
if (t != null && !isEmpty(t.name())) {
// Note: empty catalog and schema are converted to null
// Only need to convert quoted identifiers from annotations
return new TableName(quoteIdentifiers(t.catalog()), quoteIdentifiers(t.schema()), quoteIdentifiers(t.name()));
return new TableName(quoteIdentifiers(t.catalog()), quoteIdentifiers(t.schema()), quoteIdentifiers(t.name()));
}
// No annotation
@@ -272,10 +274,7 @@ public abstract class AbstractNamingConvention implements NamingConvention {
* Checks string is null or empty .
*/
protected boolean isEmpty(String s) {
if (s == null || s.trim().length() == 0) {
return true;
}
return false;
return s == null || s.trim().length() == 0;
}
/**
@@ -0,0 +1,16 @@
package com.avaje.ebean.config;
/**
* Provides the current user in order to support 'Who created', 'Who modified' and other audit features.
*/
public interface CurrentUserProvider {
/**
* Return the current user id.
* <p>
* The type returned should match the type of the properties annotated
* with @WhoCreated and @WhoModified. These are typically String, Long or UUID.
* </p>
*/
Object currentUser();
}
@@ -507,8 +507,7 @@ public class DataSourceConfig {
String customProperties = properties.get("customProperties", null);
if (customProperties != null && customProperties.length() > 0) {
Map<String, String> custProps = StringHelper.delimitedToMap(customProperties, ";", "=");
this.customProperties = custProps;
this.customProperties = StringHelper.delimitedToMap(customProperties, ";", "=");
}
}
@@ -0,0 +1,192 @@
package com.avaje.ebean.config;
/**
* Naming convention used for constraint names.
* <p>
* Note that these constraint names are trimmed in the PlatformDdl which can be overridden
* but provides a decent default implementation.
* </p>
*/
public class DbConstraintNaming {
/**
* Defines how constraint names are shortened if required based on platform limitations.
*/
public interface MaxLength {
/**
* Truncate or shorten the constraint name to support DB platform limitations.
* <p>
* There is a default implementation of this which is used if an implementation is
* not specified.
* </p>
*/
String maxLength(String constraintName, int count);
}
protected String pkPrefix = "pk_";
protected String pkSuffix = "";
protected String fkPrefix = "fk_";
protected String fkMiddle = "_";
protected String fkSuffix = "";
protected String fkIndexPrefix = "ix_";
protected String fkIndexMiddle = "_";
protected String fkIndexSuffix = "";
protected String indexPrefix = "ix_";
protected String indexMiddle = "_";
protected String indexSuffix = "";
protected String uqPrefix = "uq_";
protected String uqSuffix = "";
protected String ckPrefix = "ck_";
protected String ckSuffix = "";
protected boolean lowerCaseNames = true;
protected MaxLength maxLength;
protected DbConstraintNormalise normalise = new DbConstraintNormalise();
public DbConstraintNaming() {
}
/**
* Return the MaxLength implementation used to truncate/shorten db constraint names as necessary.
*/
public MaxLength getMaxLength() {
return maxLength;
}
/**
* Set the MaxLength implementation used to truncate/shorten db constraint names as necessary.
*/
public void setMaxLength(MaxLength maxLength) {
this.maxLength = maxLength;
}
/**
* Return the primary key constraint name.
*/
public String primaryKeyName(String tableName) {
return pkPrefix + normaliseTable(tableName) + pkSuffix;
}
/**
* Return the foreign key constraint name given a single column foreign key.
*/
public String foreignKeyConstraintName(String tableName, String columnName) {
return fkPrefix + normaliseTable(tableName) + fkMiddle + normaliseColumn(columnName) + fkSuffix;
}
/**
* Return the index name associated with a foreign key constraint given multiple columns.
*/
public String foreignKeyIndexName(String tableName, String[] columns) {
String colPart = joinColumnNames(columns);
return fkIndexPrefix + normaliseTable(tableName) + fkIndexMiddle + colPart + fkIndexSuffix;
}
/**
* Return the index name associated with a foreign key constraint given a single column foreign key.
*/
public String foreignKeyIndexName(String tableName, String column) {
String colPart = normaliseTable(column);
return fkIndexPrefix + normaliseTable(tableName) + fkIndexMiddle + colPart + fkIndexSuffix;
}
/**
* Return the index name for a general index (not associated with a foreign key).
*/
public String indexName(String tableName, String column) {
String colPart = normaliseTable(column);
return indexPrefix + normaliseTable(tableName) + indexMiddle + colPart + indexSuffix;
}
/**
* Return the index name for a general index (not associated with a foreign key).
*/
public String indexName(String tableName, String[] columns) {
String colPart = joinColumnNames(columns);
return indexPrefix + normaliseTable(tableName) + indexMiddle + colPart + indexSuffix;
}
/**
* Join the column names together with underscores.
*/
protected String joinColumnNames(String[] columns) {
if (columns.length == 1) {
return normaliseColumn(columns[0]);
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < columns.length; i++) {
if (i > 0) {
sb.append("_");
}
sb.append(normaliseColumn(columns[i]));
}
return sb.toString();
}
/**
* Return the unique constraint name.
*/
public String uniqueConstraintName(String tableName, String columnName) {
return uqPrefix + normaliseTable(tableName) + "_" + normaliseColumn(columnName) + uqSuffix;
}
/**
* Return the unique constraint name.
*/
public String uniqueConstraintName(String tableName, String[] columns) {
String colPart = joinColumnNames(columns);
return uqPrefix + normaliseTable(tableName) + "_" + colPart + uqSuffix;
}
/**
* Return the check constraint name.
*/
public String checkConstraintName(String tableName, String columnName) {
return ckPrefix + normaliseTable(tableName) + "_" + normaliseColumn(columnName) + ckSuffix;
}
/**
* Normalise the table name by trimming catalog and schema and removing any
* quoted identifier characters (",',[,] etc).
*/
public String normaliseTable(String tableName) {
return normalise.normaliseTable(tableName);
}
/**
* Normalise the column name by removing any quoted identifier characters (",',[,] etc).
*/
public String normaliseColumn(String tableName) {
return normalise.normaliseColumn(tableName);
}
/**
* Lower case the table or column name checking for quoted identifiers.
*/
public String lowerName(String tableName) {
if (lowerCaseNames && normalise.notQuoted(tableName)) {
return tableName.toLowerCase();
}
return tableName;
}
}
@@ -0,0 +1,79 @@
package com.avaje.ebean.config;
/**
* Used to normalise table and column names which means stripping out
* quoted identifier characters and any catalog or schema prefix.
*/
public class DbConstraintNormalise {
protected final String[] quotedIdentifiers;
protected boolean lowerCaseTables = true;
protected boolean lowerCaseColumns = true;
public DbConstraintNormalise() {
this.quotedIdentifiers = new String[]{"\"", "'", "[", "]", "`"};
}
/**
* Normalise the table name by trimming catalog and schema and removing any
* quoted identifier characters (",',[,] etc).
*/
public String normaliseTable(String tableName) {
tableName = trimQuotes(tableName);
int lastPeriod = tableName.lastIndexOf('.');
if (lastPeriod > -1) {
// trim off catalog and schema prefix
tableName = tableName.substring(lastPeriod + 1);
}
if (lowerCaseTables) {
tableName = tableName.toLowerCase();
}
return tableName;
}
/**
* Normalise the column name by removing any quoted identifier characters.
*/
public String normaliseColumn(String columnName) {
columnName = trimQuotes(columnName);
if (lowerCaseColumns) {
columnName = columnName.toLowerCase();
}
return columnName;
}
/**
* Trim off the platform quoted identifier quotes like [ ' and ".
*/
public boolean notQuoted(String tableName) {
// remove quoted identifier characters
for (int i = 0; i < quotedIdentifiers.length; i++) {
if (tableName.contains(quotedIdentifiers[i])) {
return false;
}
}
return true;
}
/**
* Trim off the platform quoted identifier quotes like [ ' and ".
*/
public String trimQuotes(String tableName) {
if (tableName == null) {
return "";
}
// remove quoted identifier characters
for (int i = 0; i < quotedIdentifiers.length; i++) {
tableName = tableName.replace(quotedIdentifiers[i], "");
}
return tableName;
}
}
@@ -0,0 +1,39 @@
package com.avaje.ebean.config;
/**
* Configuration for the DB migration processing.
*/
public class DbMigrationConfig {
/**
* Resource path for the migration xml and sql.
* Typically you would change 'app' to be a better/more unique.
*/
private String resourcePath = "dbmigration/app";
/**
* Return the resource path for db migrations.
*/
public String getResourcePath() {
return resourcePath;
}
/**
* Set the resource path for db migrations.
* <p>
* Typically this would be something like "dbmigration/myapp" where myapp gives it a
* unique resource path in the case there are multiple EbeanServer applications in the
* single classpath.
* </p>
*/
public void setResourcePath(String resourcePath) {
this.resourcePath = resourcePath;
}
/**
* Load the settings from the PropertiesWrapper.
*/
public void loadSettings(PropertiesWrapper properties) {
resourcePath = properties.get("migration.resourcePath", resourcePath);
}
}
@@ -26,4 +26,22 @@ public abstract class JsonConfig {
ISO8601
}
public enum Include {
/**
* Include all values including null and empty collections.
*/
ALL,
/**
* Exclude null values (include empty collections).
*/
NON_NULL,
/**
* Exclude null values and empty collections.
*/
NON_EMPTY
}
}
@@ -82,8 +82,7 @@ public interface NamingConvention {
String getPropertyFromColumn(Class<?> beanClass, String dbColumnName);
/**
* Return the sequence name given the table name (for DB's that use
* sequences).
* Return the sequence name given the table name (for DB's that use sequences).
* <p>
* Typically you might append "_seq" to the table name as an example.
* </p>
@@ -99,14 +98,14 @@ public interface NamingConvention {
* Return true if a prefix should be used building a foreign key name.
* <p>
* This by default is true and this works well when the primary key column
* names are simply "ID". In this case a prefix (such as "ORDER" and
* "CUSTOMER" etc) is added to the foreign key column producing "ORDER_ID" and
* "CUSTOMER_ID".
* names are simply "id". In this case a prefix (such as "order" and
* "customer" etc) is added to the foreign key column producing "order_id" and
* "customer_id".
* </p>
* <p>
* This should return false when your primary key columns are the same as the
* foreign key columns. For example, when the primary key columns are
* "ORDER_ID", "CUST_ID" etc ... and they are the same as the foreign key
* "order_id", "cust_id" etc ... and they are the same as the foreign key
* column names.
* </p>
*/
@@ -36,7 +36,7 @@ public enum PersistBatch {
INHERIT(false);
boolean forInsert;
final boolean forInsert;
PersistBatch(boolean forInsert) {
this.forInsert = forInsert;
@@ -27,12 +27,12 @@ final class PropertyExpression {
/**
* Used to detect the start of an expression.
*/
private static String START = "${";
private static final String START = "${";
/**
* Used to detect the end of an expression.
*/
private static String END = "}";
private static final String END = "}";
/**
* Specify the PropertyHolder.
@@ -144,13 +144,7 @@ final class PropertyExpression {
}
private static boolean isJndiExpression(String exp) {
if (exp.startsWith("JNDI:")) {
return true;
}
if (exp.startsWith("jndi:")) {
return true;
}
return false;
return exp.startsWith("JNDI:") || exp.startsWith("jndi:");
}
/**
@@ -16,7 +16,7 @@ public final class PropertyMap implements Serializable {
private static final long serialVersionUID = 1L;
private LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
private final LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
public static Properties defaultProperties() {
PropertyMap propertyMap = PropertyMapLoader.loadGlobalProperties();
@@ -1,24 +0,0 @@
package com.avaje.ebean.config;
import java.sql.PreparedStatement;
/**
* Unwrap the PreparedStatement to get the specific underlying implementation.
* <p>
* This is used to handle specific JDBC driver issues. Typically this means
* getting the OraclePreparedStatement to handle Oracle specific issues etc.
* </p>
*
* @author rbygrave
*/
public interface PstmtDelegate {
/**
* Unwrap the PreparedStatement to get the specific underlying implementation.
*
* @param pstmt
* the PreparedStatement coming out of the connection pool
* @return the underlying PreparedStatement
*/
PreparedStatement unwrap(PreparedStatement pstmt);
}
@@ -8,6 +8,9 @@ import com.avaje.ebean.cache.ServerCacheManager;
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
import com.avaje.ebean.config.dbplatform.DbEncrypt;
import com.avaje.ebean.event.*;
import com.avaje.ebean.event.changelog.ChangeLogListener;
import com.avaje.ebean.event.changelog.ChangeLogPrepare;
import com.avaje.ebean.event.changelog.ChangeLogRegister;
import com.avaje.ebean.meta.MetaInfoManager;
import com.avaje.ebean.util.ClassUtil;
import com.fasterxml.jackson.core.JsonFactory;
@@ -70,6 +73,11 @@ public class ServerConfig {
private ContainerConfig containerConfig;
/**
* The underlying properties that were used during configuration.
*/
private Properties properties;
/**
* The resource directory.
*/
@@ -113,6 +121,12 @@ public class ServerConfig {
*/
private String classPathReaderClassName;
/**
* This is used to populate @WhoCreated, @WhoModified and
* support other audit features (who executed a query etc).
*/
private CurrentUserProvider currentUserProvider;
/**
* Config controlling the autofetch behaviour.
*/
@@ -123,6 +137,12 @@ public class ServerConfig {
*/
private JsonConfig.DateTime jsonDateTime = JsonConfig.DateTime.MILLIS;
/**
* For writing JSON specify if null values or empty collections should be exluded.
* By default all values are included.
*/
private JsonConfig.Include jsonInclude = JsonConfig.Include.ALL;
/**
* The database platform name. Used to imply a DatabasePlatform to use.
*/
@@ -138,6 +158,24 @@ public class ServerConfig {
*/
private int databaseSequenceBatchSize = 20;
/**
* Suffix appended to the base table to derive the view that contains the union
* of the base table and the history table in order to support asOf queries.
*/
private String asOfViewSuffix = "_with_history";
/**
* Column used to support history and 'As of' queries. This column is a timestamp range
* or equivalent.
*/
private String asOfSysPeriod = "sys_period";
/**
* Suffix appended to the base table to derive the view that contains the union
* of the base table and the history table in order to support asOf queries.
*/
private String historyTableSuffix = "_history";
/**
* Use for transaction scoped batch mode.
*/
@@ -174,11 +212,6 @@ public class ServerConfig {
private ExternalTransactionManager externalTransactionManager;
/**
* Used to unwrap PreparedStatements to perform JDBC Driver specific functions
*/
private PstmtDelegate pstmtDelegate;
/**
* The data source (if programmatically provided).
*/
private DataSource dataSource;
@@ -188,6 +221,11 @@ public class ServerConfig {
*/
private DataSourceConfig dataSourceConfig = new DataSourceConfig();
/**
* The db migration config (migration resource path etc).
*/
private DbMigrationConfig migrationConfig = new DbMigrationConfig();
/**
* Set to true if the DataSource uses autoCommit.
* <p>
@@ -215,11 +253,21 @@ public class ServerConfig {
*/
private NamingConvention namingConvention = new UnderscoreNamingConvention();
/**
* Naming convention used in DDL generation for primary keys, foreign keys etc.
*/
private DbConstraintNaming constraintNaming = new DbConstraintNaming();
/**
* Behaviour of update to include on the change properties.
*/
private boolean updateChangesOnly = true;
/**
* Behaviour of updates in JDBC batch to by default include all properties.
*/
private boolean updateAllPropertiesInBatch = true;
/**
* Default behaviour for updates when cascade save on a O2M or M2M to delete any missing children.
*/
@@ -233,12 +281,24 @@ public class ServerConfig {
private List<BeanFindController> findControllers = new ArrayList<BeanFindController>();
private List<BeanPersistController> persistControllers = new ArrayList<BeanPersistController>();
private List<BeanPostLoad> postLoaders = new ArrayList<BeanPostLoad>();
private List<BeanPersistListener> persistListeners = new ArrayList<BeanPersistListener>();
private List<BeanQueryAdapter> queryAdapters = new ArrayList<BeanQueryAdapter>();
private List<BulkTableEventListener> bulkTableEventListeners = new ArrayList<BulkTableEventListener>();
private List<ServerConfigStartup> configStartupListeners = new ArrayList<ServerConfigStartup>();
private List<TransactionEventListener> transactionEventListeners = new ArrayList<TransactionEventListener>();
/**
* By default inserts are included in the change log.
*/
private boolean changeLogIncludeInserts = true;
private ChangeLogPrepare changeLogPrepare;
private ChangeLogListener changeLogListener;
private ChangeLogRegister changeLogRegister;
private EncryptKeyManager encryptKeyManager;
private EncryptDeployManager encryptDeployManager;
@@ -293,6 +353,12 @@ public class ServerConfig {
private int queryCacheMaxIdleTime = 600;
private int queryCacheMaxTimeToLive = 60*60*6;
private Object objectMapper;
private boolean diffFlatMode = true;
/**
* Set to true if you want eq("someProperty", null) to generate 1=1 rather than "is null" sql expression.
*/
private boolean expressionEqualsWithNullAsNoop;
/**
* Construct a Server Configuration for programmatically creating an EbeanServer.
@@ -304,7 +370,7 @@ public class ServerConfig {
/**
* Return the Jackson JsonFactory to use.
* <p>
* If not set a default implmentation will be used.
* If not set a default implementation will be used.
*/
public JsonFactory getJsonFactory() {
return jsonFactory;
@@ -313,7 +379,7 @@ public class ServerConfig {
/**
* Set the Jackson JsonFactory to use.
* <p>
* If not set a default implmentation will be used.
* If not set a default implementation will be used.
*/
public void setJsonFactory(JsonFactory jsonFactory) {
this.jsonFactory = jsonFactory;
@@ -333,6 +399,23 @@ public class ServerConfig {
this.jsonDateTime = jsonDateTime;
}
/**
* Return the JSON include mode used when writing JSON.
*/
public JsonConfig.Include getJsonInclude() {
return jsonInclude;
}
/**
* Set the JSON include mode used when writing JSON.
* <p>
* Set to NON_NULL or NON_EMPTY to suppress nulls or null & empty collections respectively.
* </p>
*/
public void setJsonInclude(JsonConfig.Include jsonInclude) {
this.jsonInclude = jsonInclude;
}
/**
* Return the name of the EbeanServer.
*/
@@ -411,6 +494,22 @@ public class ServerConfig {
this.defaultServer = defaultServer;
}
/**
* Return the CurrentUserProvider. This is used to populate @WhoCreated, @WhoModified and
* support other audit features (who executed a query etc).
*/
public CurrentUserProvider getCurrentUserProvider() {
return currentUserProvider;
}
/**
* Set the CurrentUserProvider. This is used to populate @WhoCreated, @WhoModified and
* support other audit features (who executed a query etc).
*/
public void setCurrentUserProvider(CurrentUserProvider currentUserProvider) {
this.currentUserProvider = currentUserProvider;
}
/**
* Return the PersistBatch mode to use by default at the transaction level.
* <p>
@@ -438,7 +537,7 @@ public class ServerConfig {
/**
* Return the JDBC batch mode to use per save(), delete(), insert() or update() request.
* <p>
* This makes sense when a save() or delete() etc cascades and executes multiple child statements. The best caase
* This makes sense when a save() or delete() cascades and executes multiple child statements. The best case
* for this is when saving a master/parent bean this cascade inserts many detail/child beans.
* </p>
* <p>
@@ -556,6 +655,136 @@ public class ServerConfig {
this.databaseSequenceBatchSize = databaseSequenceBatchSize;
}
/**
* Return the ChangeLogPrepare.
* <p>
* This is used to set user context information to the ChangeSet in the
* foreground thread prior to the logging occurring in a background thread.
* </p>
*/
public ChangeLogPrepare getChangeLogPrepare() {
return changeLogPrepare;
}
/**
* Set the ChangeLogPrepare.
* <p>
* This is used to set user context information to the ChangeSet in the
* foreground thread prior to the logging occurring in a background thread.
* </p>
*/
public void setChangeLogPrepare(ChangeLogPrepare changeLogPrepare) {
this.changeLogPrepare = changeLogPrepare;
}
/**
* Return the ChangeLogListener which actually performs the logging of change sets
* in the background.
*/
public ChangeLogListener getChangeLogListener() {
return changeLogListener;
}
/**
* Set the ChangeLogListener which actually performs the logging of change sets
* in the background.
*/
public void setChangeLogListener(ChangeLogListener changeLogListener) {
this.changeLogListener = changeLogListener;
}
/**
* Return the ChangeLogRegister which controls which ChangeLogFilter is used for each
* bean type and in this way provide fine grained control over which persist requests
* are included in the change log.
*/
public ChangeLogRegister getChangeLogRegister() {
return changeLogRegister;
}
/**
* Set the ChangeLogRegister which controls which ChangeLogFilter is used for each
* bean type and in this way provide fine grained control over which persist requests
* are included in the change log.
*/
public void setChangeLogRegister(ChangeLogRegister changeLogRegister) {
this.changeLogRegister = changeLogRegister;
}
/**
* Return true if inserts should be included in the change log by default.
*/
public boolean isChangeLogIncludeInserts() {
return changeLogIncludeInserts;
}
/**
* Set if inserts should be included in the change log by default.
*/
public void setChangeLogIncludeInserts(boolean changeLogIncludeInserts) {
this.changeLogIncludeInserts = changeLogIncludeInserts;
}
/**
* Return the DB migration configuration.
*/
public DbMigrationConfig getMigrationConfig() {
return migrationConfig;
}
/**
* Set the DB migration configuration.
*/
public void setMigrationConfig(DbMigrationConfig migrationConfig) {
this.migrationConfig = migrationConfig;
}
/**
* Return the suffix appended to the base table to derive the view that contains the union
* of the base table and the history table in order to support asOf queries.
*/
public String getAsOfViewSuffix() {
return asOfViewSuffix;
}
/**
* Set the suffix appended to the base table to derive the view that contains the union
* of the base table and the history table in order to support asOf queries.
*/
public void setAsOfViewSuffix(String asOfViewSuffix) {
this.asOfViewSuffix = asOfViewSuffix;
}
/**
* Return the database column used to support history and 'As of' queries. This column is a timestamp range
* or equivalent.
*/
public String getAsOfSysPeriod() {
return asOfSysPeriod;
}
/**
* Set the database column used to support history and 'As of' queries. This column is a timestamp range
* or equivalent.
*/
public void setAsOfSysPeriod(String asOfSysPeriod) {
this.asOfSysPeriod = asOfSysPeriod;
}
/**
* Return the history table suffix (defaults to _history).
*/
public String getHistoryTableSuffix() {
return historyTableSuffix;
}
/**
* Set the history table suffix.
*/
public void setHistoryTableSuffix(String historyTableSuffix) {
this.historyTableSuffix = historyTableSuffix;
}
/**
* Return true if we are running in a JTA Transaction manager.
*/
@@ -860,6 +1089,20 @@ public class ServerConfig {
this.namingConvention = namingConvention;
}
/**
* Return the constraint naming convention used in DDL generation.
*/
public DbConstraintNaming getConstraintNaming() {
return constraintNaming;
}
/**
* Set the constraint naming convention used in DDL generation.
*/
public void setConstraintNaming(DbConstraintNaming constraintNaming) {
this.constraintNaming = constraintNaming;
}
/**
* Return the configuration for the Autofetch feature.
*/
@@ -874,24 +1117,6 @@ public class ServerConfig {
this.autofetchConfig = autofetchConfig;
}
/**
* Return the PreparedStatementDelegate.
*/
public PstmtDelegate getPstmtDelegate() {
return pstmtDelegate;
}
/**
* Set the PstmtDelegate which can be used to support JDBC driver specific
* features.
* <p>
* Typically this means Oracle JDBC driver specific workarounds.
* </p>
*/
public void setPstmtDelegate(PstmtDelegate pstmtDelegate) {
this.pstmtDelegate = pstmtDelegate;
}
/**
* Return the DataSource.
*/
@@ -1426,7 +1651,26 @@ public class ServerConfig {
public void setUpdateChangesOnly(boolean updateChangesOnly) {
this.updateChangesOnly = updateChangesOnly;
}
/**
* Returns true if updates in JDBC batch default to include all properties by default.
*/
public boolean isUpdateAllPropertiesInBatch() {
return updateAllPropertiesInBatch;
}
/**
* Set to false if by default updates in JDBC batch should not include all properties.
* <p>
* This mode can be explicitly set per transaction.
* </p>
*
* @see com.avaje.ebean.Transaction#setUpdateAllLoadedProperties(boolean)
*/
public void setUpdateAllPropertiesInBatch(boolean updateAllPropertiesInBatch) {
this.updateAllPropertiesInBatch = updateAllPropertiesInBatch;
}
/**
* Return true if updates by default delete missing children when cascading save to a OneToMany or
* ManyToMany. When not set this defaults to true.
@@ -1541,14 +1785,45 @@ public class ServerConfig {
persistControllers.add(beanPersistController);
}
/**
* Register a BeanPostLoad instance.
* <p>
* Note alternatively you can use {@link #setPostLoaders(List)} to set
* all the BeanPostLoad instances.
* </p>
*/
public void add(BeanPostLoad postLoad) {
postLoaders.add(postLoad);
}
/**
* Return the list of BeanFindController instances.
*/
public List<BeanFindController> getFindControllers() {
return findControllers;
}
/**
* Set the list of BeanFindController instances.
*/
public void setFindControllers(List<BeanFindController> findControllers) {
this.findControllers = findControllers;
}
/**
* Return the list of BeanPostLoader instances.
*/
public List<BeanPostLoad> getPostLoaders() {
return postLoaders;
}
/**
* Set the list of BeanPostLoader instances.
*/
public void setPostLoaders(List<BeanPostLoad> postLoaders) {
this.postLoaders = postLoaders;
}
/**
* Return the BeanPersistController instances.
*/
@@ -1693,10 +1968,18 @@ public class ServerConfig {
* Load the settings from the given properties
*/
public void loadFromProperties(Properties properties) {
// keep the properties used for configuration so that these are available for plugins
this.properties = properties;
PropertiesWrapper p = new PropertiesWrapper("ebean", name, properties);
loadSettings(p);
}
/**
* Return the properties that we used for configuration and were set via a call to loadFromProperties().
*/
public Properties getProperties() {
return properties;
}
@SuppressWarnings("unchecked")
private <T> T createInstance(PropertiesWrapper p, Class<T> pluginType, String key) {
@@ -1728,6 +2011,8 @@ public class ServerConfig {
*/
protected void loadSettings(PropertiesWrapper p) {
migrationConfig.loadSettings(p);
namingConvention = createNamingConvention(p, namingConvention);
if (namingConvention != null) {
namingConvention.loadFromProperties(p);
@@ -1745,6 +2030,7 @@ public class ServerConfig {
autoCommitMode = p.getBoolean("autoCommitMode", autoCommitMode);
useJtaTransactionManager = p.getBoolean("useJtaTransactionManager", useJtaTransactionManager);
currentUserProvider = createInstance(p, CurrentUserProvider.class, "currentUserProvider");
disableClasspathSearch = p.getBoolean("disableClasspathSearch", disableClasspathSearch);
databasePlatform = createInstance(p, DatabasePlatform.class, "databasePlatform");
encryptKeyManager = createInstance(p, EncryptKeyManager.class, "encryptKeyManager");
@@ -1769,6 +2055,7 @@ public class ServerConfig {
collectQueryStatsByNode = p.getBoolean("collectQueryStatsByNode", collectQueryStatsByNode);
collectQueryOrigins = p.getBoolean("collectQueryOrigins", collectQueryOrigins);
updateAllPropertiesInBatch = p.getBoolean("updateAllPropertiesInBatch", updateAllPropertiesInBatch);
updateChangesOnly = p.getBoolean("updateChangesOnly", updateChangesOnly);
boolean defaultDeleteMissingChildren = p.getBoolean("defaultDeleteMissingChildren", updatesDeleteMissingChildren);
@@ -1784,8 +2071,14 @@ public class ServerConfig {
int batchSize = p.getInt("batch.size", persistBatchSize);
persistBatchSize = p.getInt("persistBatchSize", batchSize);
persistenceContextScope = PersistenceContextScope.valueOf(p.get("persistenceContextScope","TRANSACTION"));
persistenceContextScope = PersistenceContextScope.valueOf(p.get("persistenceContextScope", "TRANSACTION"));
changeLogIncludeInserts = p.getBoolean("changeLogIncludeInserts", changeLogIncludeInserts);
expressionEqualsWithNullAsNoop = p.getBoolean("expressionEqualsWithNullAsNoop", expressionEqualsWithNullAsNoop);
diffFlatMode = p.getBoolean("diffFlatMode", diffFlatMode);
asOfViewSuffix = p.get("asOfViewSuffix", asOfViewSuffix);
asOfSysPeriod = p.get("asOfSysPeriod", asOfSysPeriod);
historyTableSuffix = p.get("historyTableSuffix", historyTableSuffix);
dataSourceJndiName = p.get("dataSourceJndiName", dataSourceJndiName);
databaseSequenceBatchSize = p.getInt("databaseSequenceBatchSize", databaseSequenceBatchSize);
databaseBooleanTrue = p.get("databaseBooleanTrue", databaseBooleanTrue);
@@ -1797,6 +2090,7 @@ public class ServerConfig {
lazyLoadBatchSize = p.getInt("lazyLoadBatchSize", lazyLoadBatchSize);
queryBatchSize = p.getInt("queryBatchSize", queryBatchSize);
jsonInclude = p.getEnum(JsonConfig.Include.class, "jsonInclude", jsonInclude);
String jsonDateTimeFormat = p.get("jsonDateTime", null);
if (jsonDateTimeFormat != null) {
jsonDateTime = JsonConfig.DateTime.valueOf(jsonDateTimeFormat);
@@ -1874,11 +2168,58 @@ public class ServerConfig {
return databasePlatform.isDisallowBatchOnCascade() ? PersistBatch.NONE : persistBatchOnCascade;
}
/**
* Return the Jackson ObjectMapper.
* <p>
* Note that this is not strongly typed as Jackson ObjectMapper is an optional dependency.
* </p>
*/
public Object getObjectMapper() {
return objectMapper;
}
/**
* Set the Jackson ObjectMapper.
* <p>
* Note that this is not strongly typed as Jackson ObjectMapper is an optional dependency.
* </p>
*/
public void setObjectMapper(Object objectMapper) {
this.objectMapper = objectMapper;
}
/**
* Return true if diff should return flat properties with dot notation rather than
* embedded beans or reference beans (when the associated bean id is different).
*/
public boolean isDiffFlatMode() {
return diffFlatMode;
}
/**
* Set to true if diff should return flat properties with dot notation rather than
* embedded beans or reference beans (when the associated bean id is different).
*/
public void setDiffFlatMode(boolean diffFlatMode) {
this.diffFlatMode = diffFlatMode;
}
/**
* Return true if eq("someProperty", null) should to generate "1=1" rather than "is null" sql expression.
*/
public boolean isExpressionEqualsWithNullAsNoop() {
return expressionEqualsWithNullAsNoop;
}
/**
* Set to true if you want eq("someProperty", null) to generate "1=1" rather than "is null" sql expression.
* <p>
* Setting this to true has the effect that eq(propertyName, value), ieq(propertyName, value) and
* ne(propertyName, value) have no effect when the value is null. The expression factory adds a NoopExpression
* which will add "1=1" into the SQL rather than "is null".
* </p>
*/
public void setExpressionEqualsWithNullAsNoop(boolean expressionEqualsWithNullAsNoop) {
this.expressionEqualsWithNullAsNoop = expressionEqualsWithNullAsNoop;
}
}
@@ -3,23 +3,26 @@ package com.avaje.ebean.config;
/**
* Converts between Camel Case and Underscore based names for both table and
* column names (and is the default naming convention in Ebean).
*
*
* @author emcgreal
* @author rbygrave
*/
public class UnderscoreNamingConvention extends AbstractNamingConvention {
/** Force toUnderscore to return in upper case. */
/**
* Force toUnderscore to return in upper case.
*/
private boolean forceUpperCase = false;
/** The digits compressed. */
/**
* The digits compressed.
*/
private boolean digitsCompressed = true;
/**
* Create with a given sequence format.
*
* @param sequenceFormat
* the sequence format
*
* @param sequenceFormat the sequence format
*/
public UnderscoreNamingConvention(String sequenceFormat) {
super(sequenceFormat);
@@ -34,39 +37,30 @@ public class UnderscoreNamingConvention extends AbstractNamingConvention {
/**
* Returns the last part of the class name.
*
* @param beanClass
* the bean class
*
*
* @param beanClass the bean class
* @return the table name from class
*/
public TableName getTableNameByConvention(Class<?> beanClass) {
return new TableName(getCatalog(),
getSchema(),
toUnderscoreFromCamel(beanClass.getSimpleName()));
return new TableName(getCatalog(), getSchema(), toUnderscoreFromCamel(beanClass.getSimpleName()));
}
/**
* Converts Camel case property name to underscore based column name.
*
*
* @return the column from property
*/
public String getColumnFromProperty(Class<?> beanClass, String propertyName) {// Field
// field)
// {
public String getColumnFromProperty(Class<?> beanClass, String propertyName) {
return toUnderscoreFromCamel(propertyName);
}
/**
* Converts underscore based column name to Camel case property name.
*
* @param beanClass
* the bean class
* @param dbColumnName
* the db column name
*
*
* @param beanClass the bean class
* @param dbColumnName the db column name
* @return the property from column
*/
public String getPropertyFromColumn(Class<?> beanClass, String dbColumnName) {
@@ -110,7 +104,7 @@ public class UnderscoreNamingConvention extends AbstractNamingConvention {
protected String toUnderscoreFromCamel(String camelCase) {
int lastUpper = -1;
StringBuffer sb = new StringBuffer();
StringBuilder sb = new StringBuilder(camelCase.length()+4);
for (int i = 0; i < camelCase.length(); i++) {
char c = camelCase.charAt(i);
@@ -144,16 +138,11 @@ public class UnderscoreNamingConvention extends AbstractNamingConvention {
}
/**
* To camel from underscore.
*
* @param underscore
* the underscore
*
* @return the string
* Convert and return the from string from underscore to camel case.
*/
protected String toCamelFromUnderscore(String underscore) {
StringBuffer result = new StringBuffer();
StringBuilder result = new StringBuilder(underscore.length());
String[] vals = underscore.split("_");
for (int i = 0; i < vals.length; i++) {
@@ -5,6 +5,7 @@ import java.sql.Types;
import javax.sql.DataSource;
import com.avaje.ebean.BackgroundExecutor;
import com.avaje.ebean.dbmigration.ddlgeneration.platform.DB2Ddl;
/**
* DB2 specific platform.
@@ -14,10 +15,11 @@ public class DB2Platform extends DatabasePlatform {
public DB2Platform() {
super();
this.name = "db2";
// only support getGeneratedKeys with non-batch JDBC
// so generally use SEQUENCE instead for H2
this.maxTableNameLength = 18;
this.maxConstraintNameLength = 18;
this.sqlLimiter = new Db2SqlLimiter();
this.platformDdl = new DB2Ddl(dbTypeMap, dbIdentity);
this.dbIdentity.setSupportsGetGeneratedKeys(true);
this.dbIdentity.setSupportsSequence(true);
@@ -25,8 +27,6 @@ public class DB2Platform extends DatabasePlatform {
dbTypeMap.put(Types.REAL, new DbType("real"));
dbTypeMap.put(Types.TINYINT, new DbType("smallint"));
dbTypeMap.put(Types.DECIMAL, new DbType("decimal", 15));
this.dbDdlSyntax.setIdentity("generated by default as identity");
}
/**
@@ -7,6 +7,9 @@ import javax.sql.DataSource;
import com.avaje.ebean.BackgroundExecutor;
import com.avaje.ebean.Query;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.dbmigration.ddlgeneration.DdlHandler;
import com.avaje.ebean.dbmigration.ddlgeneration.platform.PlatformDdl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -17,6 +20,7 @@ public class DatabasePlatform {
private static final Logger logger = LoggerFactory.getLogger(DatabasePlatform.class);
/**
* Behavior used when ending a query only transaction (at read committed isolation level).
*/
@@ -70,16 +74,16 @@ public class DatabasePlatform {
*/
protected DbTypeMap dbTypeMap = new DbTypeMap();
/**
* DB specific DDL syntax.
*/
protected DbDdlSyntax dbDdlSyntax = new DbDdlSyntax();
/**
/**
* Defines DB identity/sequence features.
*/
protected DbIdentity dbIdentity = new DbIdentity();
/**
* The history support for this database platform.
*/
protected DbHistorySupport historySupport;
/**
* The JDBC type to map booleans to (by default).
*/
@@ -140,6 +144,20 @@ public class DatabasePlatform {
*/
protected boolean disallowBatchOnCascade;
protected PlatformDdl platformDdl;
/**
* The maximum length of table names - used specifically when derived
* default table names for intersection tables.
*/
protected int maxTableNameLength = 60;
/**
* A value of 60 is a reasonable default for all databases except
* Oracle (limited to 30) and DB2 (limited to 18).
*/
protected int maxConstraintNameLength = 60;
/**
* Instantiates a new database platform.
*/
@@ -152,13 +170,42 @@ public class DatabasePlatform {
* "generic" is returned when no specific database platform has been set or
* found.
* </p>
*
* @return the name
*/
public String getName() {
return name;
}
/**
* Return the maximum table name length.
* <p>
* This is used when deriving names of intersection tables.
* </p>
*/
public int getMaxTableNameLength() {
return maxTableNameLength;
}
/**
* Return the maximum constraint name allowed for the platform.
*/
public int getMaxConstraintNameLength() {
return maxConstraintNameLength;
}
/**
* Return the platform specific DDL.
*/
public PlatformDdl getPlatformDdl() {
return platformDdl;
}
/**
* Create and return a DDL handler for generating DDL scripts.
*/
public DdlHandler createDdlHandler(ServerConfig serverConfig) {
return platformDdl.createDdlHandler(serverConfig);
}
/**
* Return true if the JDBC driver does not allow additional queries to execute
* when a resultSet is being 'streamed' as is the case with findEach() etc.
@@ -215,6 +262,20 @@ public class DatabasePlatform {
this.dbEncrypt = dbEncrypt;
}
/**
* Return the history support for this database platform.
*/
public DbHistorySupport getHistorySupport() {
return historySupport;
}
/**
* Set the history support for this database platform.
*/
public void setHistorySupport(DbHistorySupport historySupport) {
this.historySupport = historySupport;
}
/**
* Return the mapping of JDBC to DB types.
*
@@ -224,15 +285,6 @@ public class DatabasePlatform {
return dbTypeMap;
}
/**
* Return the DDL syntax for this platform.
*
* @return the db ddl syntax
*/
public DbDdlSyntax getDbDdlSyntax() {
return dbDdlSyntax;
}
/**
* Return the column alias prefix.
*/
@@ -442,22 +494,4 @@ public class DatabasePlatform {
return disallowBatchOnCascade;
}
/**
* Generate and return the create sequence DDL.
*/
public String ddlCreateSequence(String sequenceName, int initialValue, int allocationSize) {
StringBuilder sb = new StringBuilder("create sequence ");
sb.append(sequenceName);
if (initialValue > 1) {
sb.append(" start with ").append(initialValue);
}
if (allocationSize > 0 && allocationSize != 50) {
// at this stage ignoring allocationSize 50 as this is the 'default' and
// not consistent with the way Ebean batch fetches sequence values
sb.append(" increment by ").append(allocationSize);
}
sb.append(";");
return sb.toString();
}
}
@@ -1,333 +0,0 @@
package com.avaje.ebean.config.dbplatform;
import com.avaje.ebean.config.TableName;
/**
* Used to support DB specific syntax for DDL generation.
*/
public class DbDdlSyntax {
protected boolean renderIndexForFkey = true;
protected boolean inlinePrimaryKeyConstraint = false;
protected boolean addOneToOneUniqueContraint = true;
protected int maxConstraintNameLength = 32;
protected int columnNameWidth = 25;
/**
* Flag set when we want to disable constraints on each table (rather than globally).
*/
protected boolean dropKeyConstraints;
protected String dropTableCascade;
protected String dropIfExists;
protected String newLine = "\n";
protected String identity = "auto_increment";
protected String identitySuffix = "";
protected String pkPrefix = "pk_";
protected String disableReferentialIntegrity;
protected String enableReferentialIntegrity;
protected String foreignKeySuffix;
/**
* Return the primary key name for a given bean descriptor.
*/
public String getPrimaryKeyName(String tableName) {
String pk = pkPrefix + tableName;
if (pk.length() > maxConstraintNameLength) {
// need to trim the primary key name
pk = pk.substring(0, maxConstraintNameLength);
}
return pk;
}
/**
* Return the column definition for an identity column.
*/
public String getIdentityColumnDefn(String columnDefn) {
String identity = getIdentity();
if (identity != null && identity.length() > 0) {
return columnDefn+" "+identity;
}
return columnDefn;
}
/**
* Return the identity clause for DB's that have identities.
*/
public String getIdentity() {
return identity;
}
/**
* Set the identity clause.
*/
public void setIdentity(String identity) {
this.identity = identity;
}
/**
* Typically returns empty string but for SQLite and perhaps others
* the Identity/AutoIncrement clause comes after the primary key clause.
*/
public String getIdentitySuffix() {
return identitySuffix;
}
/**
* Set the identity clause that would appear after the primary key clause.
* <p>
* Only used for SQLite at this stage.
* </p>
*/
public void setIdentitySuffix(String identitySuffix) {
this.identitySuffix = identitySuffix;
}
/**
* Return the width for padding whitespace after column names.
*/
public int getColumnNameWidth() {
return columnNameWidth;
}
/**
* Set the amount of padding to write after the column name.
*/
public void setColumnNameWidth(int columnNameWidth) {
this.columnNameWidth = columnNameWidth;
}
/**
* Return the new line character.
*/
public String getNewLine() {
return newLine;
}
/**
* Set the new line character.
*/
public void setNewLine(String newLine) {
this.newLine = newLine;
}
/**
* Return the prefix used in naming primary keys.
*/
public String getPkPrefix() {
return pkPrefix;
}
/**
* Set the prefix used in naming primary keys.
*/
public void setPkPrefix(String pkPrefix) {
this.pkPrefix = pkPrefix;
}
/**
* Return the DB specific command to disable referential integrity
*/
public String getDisableReferentialIntegrity() {
return disableReferentialIntegrity;
}
/**
* Set the DB specific command to disable referential integrity
*/
public void setDisableReferentialIntegrity(String disableReferentialIntegrity) {
this.disableReferentialIntegrity = disableReferentialIntegrity;
}
/**
* Return the DB specific command to enable referential integrity
*/
public String getEnableReferentialIntegrity() {
return enableReferentialIntegrity;
}
/**
* Set the DB specific command to enable referential integrity
*/
public void setEnableReferentialIntegrity(String enableReferentialIntegrity) {
this.enableReferentialIntegrity = enableReferentialIntegrity;
}
/**
* Return true to is constraints are disabled on each table.
*/
public boolean isDropKeyConstraints() {
return dropKeyConstraints;
}
/**
* Return some DDL to disable constraints on the given table.
*/
public String dropKeyConstraintPrefix(String tableName, String fkName) {
return null;
}
/**
* Return true if indexes should be created for the foreign keys.
*/
public boolean isRenderIndexForFkey() {
return renderIndexForFkey;
}
/**
* Set whether indexes should be created for the foreign keys.
*/
public void setRenderIndexForFkey(boolean renderIndexForFkey) {
this.renderIndexForFkey = renderIndexForFkey;
}
/**
* Typically returns IF EXISTS (if that is supported by the database platform)
* or null.
*/
public String getDropIfExists() {
return dropIfExists;
}
/**
* Set the IF EXISTS clause for dropping tables if that is supported by the
* database platform.
*/
public void setDropIfExists(String dropIfExists) {
this.dropIfExists = dropIfExists;
}
/**
* Return prefix text that goes before drop table.
*/
public String dropTablePrefix(String tableName) {
return "";
}
/**
* Return the cascade option for the drop table command.
*/
public String getDropTableCascade() {
return dropTableCascade;
}
/**
* Set the cascade option for the drop table command.
*/
public void setDropTableCascade(String dropTableCascade) {
this.dropTableCascade = dropTableCascade;
}
/**
* Return the foreign key suffix.
*/
public String getForeignKeySuffix() {
return foreignKeySuffix;
}
/**
* Set the foreign key suffix.
*/
public void setForeignKeySuffix(String foreignKeySuffix) {
this.foreignKeySuffix = foreignKeySuffix;
}
/**
* Return the maximum length that constraint names can be for this database.
*/
public int getMaxConstraintNameLength() {
return maxConstraintNameLength;
}
/**
* Set the maximum length that constraint names can be for this database.
*/
public void setMaxConstraintNameLength(int maxFkeyLength) {
this.maxConstraintNameLength = maxFkeyLength;
}
/**
* Return true if imported side of OneToOne's should have unique constraints
* generated.
*/
public boolean isAddOneToOneUniqueContraint() {
return addOneToOneUniqueContraint;
}
/**
* Set to false for DB's that don't want both a unique and index on the
* imported OneToOne.
*/
public void setAddOneToOneUniqueContraint(boolean addOneToOneUniqueContraint) {
this.addOneToOneUniqueContraint = addOneToOneUniqueContraint;
}
/**
* Return true if primary key constraints should be inlined when they are a
* single column.
*/
public boolean isInlinePrimaryKeyConstraint() {
return inlinePrimaryKeyConstraint;
}
/**
* Set whether to inline primary key constraints.
*/
public void setInlinePrimaryKeyConstraint(boolean inlinePrimaryKeyConstraint) {
this.inlinePrimaryKeyConstraint = inlinePrimaryKeyConstraint;
}
/**
* Builds and returns a fully index name.
*/
public String getIndexName(String table, String propName, int ixCount) {
StringBuilder buffer = new StringBuilder(30);
buffer.append("ix_").append(TableName.parse(table));
buffer.append("_").append(propName);
addSuffix(buffer, ixCount);
return buffer.toString();
}
/**
* Builds and returns a fully qualified foreign key constraint name.
*/
public String getForeignKeyName(String table, String propName, int fkCount) {
StringBuilder buffer = new StringBuilder(30);
buffer.append("fk_").append(TableName.parse(table));
buffer.append("_").append(propName);
addSuffix(buffer, fkCount);
return buffer.toString();
}
/**
* Adds the suffix.
*/
protected void addSuffix(StringBuilder buffer, int count) {
String suffixNr = Integer.toString(count);
int suffixLen = suffixNr.length() + 1;
if (buffer.length() + suffixLen > maxConstraintNameLength) {
buffer.setLength(maxConstraintNameLength - suffixLen);
}
buffer.append("_");
buffer.append(suffixNr);
}
}
@@ -0,0 +1,64 @@
package com.avaje.ebean.config.dbplatform;
/**
* History support for the database platform.
*/
public interface DbHistorySupport {
/**
* Return true if the 'As of' predicate is part of the from clause
* (more standard sql2011). So true for Oracle total recall and false
* for Postgres and MySql (where we use views and history tables).
*/
boolean isBindWithFromClause();
/**
* Return the number of columns bound in a 'As Of' predicate.
* <p>
* This is 1 for more standard sql2011 style and Postgres which has the
* special range type and 2 for view based solutions with 2 columns such as
* MySql.
* </p>
*/
int getBindCount();
/**
* For sql2011 style this ignores the passed in view suffix and returns something
* like the ' as of timestamp ?' clause to be appended after the base table name.
*
* @param asOfViewSuffix the configured view suffix (typically "_with_history").
* @return The suffix appended after the base table name in the from and join clauses.
*/
String getAsOfViewSuffix(String asOfViewSuffix);
/**
* Return the 'versions between timestamp' suffix.
*/
String getVersionsBetweenSuffix(String asOfViewSuffix);
/**
* Return the 'as of' predicate added for the given table alias.
*
* @param tableAlias The table alias this predicate is added for
* @param sysPeriod The name of the 'sys_period' column used for effective date time range.
* @return The predicate containing a single ? bind parameter which will be bound to the 'as at' timestamp value
*/
String getAsOfPredicate(String tableAlias, String sysPeriod);
/**
* Return the column for the system period lower bound that will be included in findVersions() queries.
*
* @param tableAlias the table alias which will typically be 't0'
* @param sysPeriod the name of the sys_period column
*/
String getSysPeriodLower(String tableAlias, String sysPeriod);
/**
* Return the column for the system period upper bound that will be included in findVersions() queries.
*
* @param tableAlias the table alias which will typically be 't0'
* @param sysPeriod the name of the sys_period column
*/
String getSysPeriodUpper(String tableAlias, String sysPeriod);
}
@@ -1,5 +1,7 @@
package com.avaje.ebean.config.dbplatform;
import com.avaje.ebean.dbmigration.migration.IdentityType;
/**
* Defines the identity/sequence behaviour for the database.
*/
@@ -114,4 +116,28 @@ public class DbIdentity {
this.idType = idType;
}
/**
* Determine the id type to use based on requested identityType and
* the support for that in the database platform.
*/
public IdType useIdentityType(IdentityType identityType) {
if (identityType == null) {
// use the default
return idType;
}
switch (identityType) {
case GENERATOR:
return IdType.GENERATOR;
case EXTERNAL:
return IdType.EXTERNAL;
case SEQUENCE:
return supportsSequence ? IdType.SEQUENCE : idType;
case IDENTITY:
return supportsIdentity ? IdType.IDENTITY : idType;
}
// use the default
return idType;
}
}
@@ -0,0 +1,47 @@
package com.avaje.ebean.config.dbplatform;
/**
* Built in supported platforms.
*/
public enum DbPlatformName {
/**
* Generic base platform configured via properties or code.
*/
GENERIC,
/**
* H2.
*/
H2,
/**
* Postgres.
*/
POSTGRES,
/**
* MySql.
*/
MYSQL,
/**
* Oracle.
*/
ORACLE,
/**
* Microsoft SQL Server.
*/
SQLSERVER,
/**
* DB2.
*/
DB2,
/**
* SQLite.
*/
SQLITE
}
@@ -0,0 +1,32 @@
package com.avaje.ebean.config.dbplatform;
/**
* SQL2011 based history support using 'as of timestamp' type clause appended as part of the the from or join clause.
*/
public abstract class DbStandardHistorySupport implements DbHistorySupport {
/**
* Return true as with sql2011 the 'as of timestamp' clause included in from or join clause.
*/
@Override
public boolean isBindWithFromClause() {
return true;
}
/**
* Return 1 as the bind count (not 2 for effective start and effective end columns).
*/
@Override
public int getBindCount() {
return 1;
}
/**
* Return null - not used for sql2011 based history.
*/
@Override
public String getAsOfPredicate(String tableAlias, String sysPeriod) {
// not used for sql2011 based history
return null;
}
}
@@ -9,16 +9,80 @@ import java.util.Map;
*/
public class DbTypeMap {
private static final DbType JSON_CLOB_PLACEHOLDER = new DbType("jsonClobPlaceholder");
private static final DbType JSON_BLOB_PLACEHOLDER = new DbType("jsonBlobPlaceholder");
private static final DbType JSON_VARCHAR_PLACEHOLDER = new DbType("jsonVarcharPlaceholder");
/**
* A map to reverse lookup the type by name.
* <p>
* Used when converting from logical types to platform types which we
* want to do with 2 phase DDL generation.
*/
static Map<String, Integer> lookup = new HashMap<String, Integer>();
static {
lookup.put("BOOLEAN", Types.BOOLEAN);
lookup.put("BIT", Types.BIT);
lookup.put("INTEGER", Types.INTEGER);
lookup.put("BIGINT", Types.BIGINT);
lookup.put("REAL", Types.REAL);
// Float is most common REAL mapping to have that as well
lookup.put("FLOAT", Types.REAL);
lookup.put("DOUBLE", Types.DOUBLE);
lookup.put("SMALLINT", Types.SMALLINT);
lookup.put("TINYINT", Types.TINYINT);
lookup.put("DECIMAL", Types.DECIMAL);
lookup.put("VARCHAR", Types.VARCHAR);
// VARCHAR2 - extra for Oracle specific column definition
lookup.put("VARCHAR2", Types.VARCHAR);
lookup.put("CHAR", Types.CHAR);
lookup.put("BLOB", Types.BLOB);
lookup.put("CLOB", Types.CLOB);
lookup.put("LONGVARBINARY", Types.LONGVARBINARY);
lookup.put("LONGVARCHAR", Types.LONGVARCHAR);
lookup.put("VARBINARY", Types.VARBINARY);
lookup.put("BINARY", Types.BINARY);
lookup.put("DATE", Types.DATE);
lookup.put("TIME", Types.TIME);
lookup.put("TIMESTAMP", Types.TIMESTAMP);
// Not standard java.sql.Types
// logical JSON storage types
lookup.put("JSON", DbType.JSON);
lookup.put("JSONB", DbType.JSONB);
lookup.put("JSONCLOB", DbType.JSONClob);
lookup.put("JSONBLOB", DbType.JSONBlob);
lookup.put("JSONVARCHAR", DbType.JSONVarchar);
}
private final Map<Integer, DbType> typeMap = new HashMap<Integer, DbType>();
/**
* Return the DbTypeMap with standard (not platform specific) types.
*
* This has some extended JSON types (JSON, JSONB, JSONVarchar, JSONClob, JSONBlob).
* These types get translated to specific database platform types during DDL generation.
*/
public static DbTypeMap logicalTypes() {
return new DbTypeMap(true);
}
public DbTypeMap() {
loadDefaults();
loadDefaults(false);
}
private DbTypeMap(boolean logicalTypes) {
loadDefaults(logicalTypes);
}
/**
* Load the standard types. These can be overridden by DB specific platform.
*/
private void loadDefaults() {
private void loadDefaults(boolean logicalTypes) {
put(Types.BOOLEAN, new DbType("boolean"));
put(Types.BIT, new DbType("bit"));
@@ -37,11 +101,22 @@ public class DbTypeMap {
put(Types.BLOB, new DbType("blob"));
put(Types.CLOB, new DbType("clob"));
put(DbType.JSON, new DbType("clob")); // Postgres maps this to JSON
put(DbType.JSONB, new DbType("clob")); // Postgres maps this to JSONB
put(DbType.JSONClob, new DbType("clob"));
put(DbType.JSONBlob, new DbType("blob"));
put(DbType.JSONVarchar, new DbType("varchar", 1000));
if (logicalTypes) {
// keep it logical for 2 layer DDL generation
put(DbType.HSTORE, new DbType("hstore"));
put(DbType.JSON, new DbType("json"));
put(DbType.JSONB, new DbType("jsonb"));
put(DbType.JSONClob, new DbType("jsonclob"));
put(DbType.JSONBlob, new DbType("jsonblob"));
put(DbType.JSONVarchar, new DbType("jsonvarchar", 1000));
} else {
put(DbType.JSON, JSON_CLOB_PLACEHOLDER); // Postgres maps this to JSON
put(DbType.JSONB, JSON_CLOB_PLACEHOLDER); // Postgres maps this to JSONB
put(DbType.JSONClob, JSON_CLOB_PLACEHOLDER);
put(DbType.JSONBlob, JSON_BLOB_PLACEHOLDER);
put(DbType.JSONVarchar, JSON_VARCHAR_PLACEHOLDER);
}
put(Types.LONGVARBINARY, new DbType("longvarbinary"));
put(Types.LONGVARCHAR, new DbType("lonvarchar"));
@@ -54,24 +129,58 @@ public class DbTypeMap {
}
/**
* Lookup the platform specific DbType given the standard sql type name.
*/
public DbType lookup(String name) {
name = name.trim().toUpperCase();
Integer typeKey = lookup.get(name);
if (typeKey == null) {
throw new IllegalArgumentException("Unknown type [" + name + "] - not standard sql type");
}
// handle JSON types mapped to clob, blob and varchar
switch (typeKey) {
case DbType.JSONBlob:
return get(Types.BLOB);
case DbType.JSONClob:
return get(Types.CLOB);
case DbType.JSONVarchar:
return get(Types.VARCHAR);
case DbType.JSON:
return getJsonType(DbType.JSON);
case DbType.JSONB:
return getJsonType(DbType.JSONB);
default:
return get(typeKey);
}
}
private DbType getJsonType(int type) {
DbType dbType = get(type);
if (dbType == JSON_CLOB_PLACEHOLDER) {
return get(Types.CLOB);
}
if (dbType == JSON_BLOB_PLACEHOLDER) {
return get(Types.BLOB);
}
if (dbType == JSON_VARCHAR_PLACEHOLDER) {
return get(Types.VARCHAR);
}
// Postgres has specific type
return get(type);
}
/**
* Override the type for a given JDBC type.
*/
public void put(int jdbcType, DbType dbType) {
typeMap.put(Integer.valueOf(jdbcType), dbType);
typeMap.put(jdbcType, dbType);
}
/**
* Return the type for a given jdbc type.
*/
public DbType get(int jdbcType) {
DbType dbType = typeMap.get(Integer.valueOf(jdbcType));
if (dbType == null) {
String m = "No DB type for JDBC type " + jdbcType;
throw new RuntimeException(m);
}
return dbType;
return typeMap.get(jdbcType);
}
}
@@ -0,0 +1,82 @@
package com.avaje.ebean.config.dbplatform;
/**
* Database view based implementation of DbHistorySupport.
* <p>
* These implementations have explicit history tables, a view to union the
* base table and history table and triggers to maintain the history.
* </p>
*/
public abstract class DbViewHistorySupport implements DbHistorySupport {
/**
* Return false for view based implementations where we append extra 'as of' predicates to the end.
*/
@Override
public boolean isBindWithFromClause() {
return false;
}
/**
* Returns the configured view suffix.
*
* @param asOfViewSuffix the configured view suffix (typically "_with_history").
*/
@Override
public String getAsOfViewSuffix(String asOfViewSuffix) {
// just return the configured suffix
return asOfViewSuffix;
}
/**
* Returns the configured view suffix (same as getAsOfViewSuffix()).
*
* @param asOfViewSuffix the configured view suffix (typically "_with_history").
*/
@Override
public String getVersionsBetweenSuffix(String asOfViewSuffix) {
// just return the configured asOfViewSuffix (using the view for versions between query)
return asOfViewSuffix;
}
/**
* Return 2 if we have effective start and effective end as 2 columns.
* Note that for postgres we can use a single range type so that returns 1.
*/
@Override
public int getBindCount() {
return 2;
}
/**
* Return the 'as of' predicate clause appended to the end of the normal query predicates.
*/
@Override
public String getAsOfPredicate(String asOfTableAlias, String asOfSysPeriod) {
// (sys_period_start < ? and (sys_period_end is null or sys_period_end > ?));
return "(" + asOfTableAlias + "." + asOfSysPeriod + "_start" + " < ? and (" + asOfTableAlias + "." + asOfSysPeriod + "_end" + " is null or " + asOfTableAlias + "." + asOfSysPeriod + "_end" + " > ?))";
}
/**
* Return the lower bound column prepended with the table alias.
*
* @param tableAlias the table alias
* @param sysPeriod the name of the sys_period column
*/
@Override
public String getSysPeriodLower(String tableAlias, String sysPeriod) {
return tableAlias + "." + sysPeriod + "_start";
}
/**
* Return the upper bound column prepended with the table alias.
*
* @param tableAlias the table alias
* @param sysPeriod the name of the sys_period column
*/
@Override
public String getSysPeriodUpper(String tableAlias, String sysPeriod) {
return tableAlias + "." + sysPeriod + "_end";
}
}
@@ -1,6 +1,7 @@
package com.avaje.ebean.config.dbplatform;
import com.avaje.ebean.BackgroundExecutor;
import com.avaje.ebean.dbmigration.ddlgeneration.platform.H2Ddl;
import javax.sql.DataSource;
@@ -13,9 +14,7 @@ public class H2Platform extends DatabasePlatform {
super();
this.name = "h2";
this.dbEncrypt = new H2DbEncrypt();
// 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 ?";
this.platformDdl = new H2Ddl(this.dbTypeMap, dbIdentity);
// only support getGeneratedKeys with non-batch JDBC
// so generally use SEQUENCE instead of IDENTITY for H2
@@ -24,16 +23,12 @@ public class H2Platform extends DatabasePlatform {
this.dbIdentity.setSupportsSequence(true);
this.dbIdentity.setSupportsIdentity(true);
this.openQuote = "\"";
this.closeQuote = "\"";
// 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 ?";
// H2 data types match default JDBC types
// so no changes to dbTypeMap required
this.dbDdlSyntax.setDropIfExists("if exists");
this.dbDdlSyntax.setDisableReferentialIntegrity("SET REFERENTIAL_INTEGRITY FALSE");
this.dbDdlSyntax.setEnableReferentialIntegrity("SET REFERENTIAL_INTEGRITY TRUE");
this.dbDdlSyntax.setForeignKeySuffix("on delete restrict on update restrict");
}
/**
@@ -1,6 +1,7 @@
package com.avaje.ebean.config.dbplatform;
import com.avaje.ebean.BackgroundExecutor;
import com.avaje.ebean.dbmigration.ddlgeneration.platform.HsqldbDdl;
import javax.sql.DataSource;
import java.sql.Types;
@@ -14,32 +15,18 @@ public class HsqldbPlatform extends DatabasePlatform {
super();
this.name = "hsqldb";
this.dbEncrypt = new H2DbEncrypt();
this.platformDdl = new HsqldbDdl(dbTypeMap, dbIdentity);
this.dbIdentity.setIdType(IdType.IDENTITY);
this.dbIdentity.setSupportsGetGeneratedKeys(true);
this.dbIdentity.setSupportsSequence(true);
this.dbIdentity.setSupportsIdentity(true);
this.openQuote = "\"";
this.closeQuote = "\"";
// H2 data types match default JDBC types
// so no changes to dbTypeMap required
dbTypeMap.put(Types.INTEGER, new DbType("integer", false));
this.dbDdlSyntax.setDropIfExists("if exists");
this.dbDdlSyntax.setDisableReferentialIntegrity("SET DATABASE REFERENTIAL INTEGRITY FALSE");
this.dbDdlSyntax.setEnableReferentialIntegrity("SET DATABASE REFERENTIAL INTEGRITY TRUE");
this.dbDdlSyntax.setForeignKeySuffix("on delete restrict on update restrict");
this.dbDdlSyntax.setIdentity("GENERATED BY DEFAULT AS IDENTITY (START WITH 1) ");
}
/**
* Return a H2 specific sequence IdGenerator that supports batch fetching
* sequence values.
*/
@Override
public IdGenerator createSequenceIdGenerator(BackgroundExecutor be,
DataSource ds, String seqName, int batchSize) {
public IdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
return new H2SequenceIdGenerator(be, ds, seqName, batchSize);
}
@@ -16,7 +16,7 @@ public interface IdGenerator {
/**
* The name of the default UUID generator.
*/
static final String AUTO_UUID = "auto.uuid";
String AUTO_UUID = "auto.uuid";
/**
* Return the name of the IdGenerator. For sequences this is the sequence
@@ -26,6 +26,15 @@ public enum IdType {
* id properties of type UUID.
* </p>
*/
GENERATOR;
GENERATOR,
/**
* Expected that the identity is externally set (for example a ISO code for
* country or currency or a user defined code for lookup tables).
* <p>
* Used when the key is a compound key or lookup table code.
* </p>
*/
EXTERNAL
}
@@ -1,5 +1,7 @@
package com.avaje.ebean.config.dbplatform;
import com.avaje.ebean.dbmigration.ddlgeneration.platform.MsSqlServerDdl;
import java.sql.Types;
/**
@@ -21,8 +23,9 @@ public class MsSqlServer2005Platform extends DatabasePlatform {
// due to lack of support for getGeneratedKeys in batch mode
this.disallowBatchOnCascade = true;
this.idInExpandedForm = true;
this.selectCountWithAlias = true;
this.sqlLimiter = new MsSqlServer2005SqlLimiter();
this.dbDdlSyntax = new MsDdlSyntax();
this.platformDdl = new MsSqlServerDdl(dbTypeMap, dbIdentity);
this.dbIdentity.setIdType(IdType.IDENTITY);
this.dbIdentity.setSupportsGetGeneratedKeys(true);
this.dbIdentity.setSupportsIdentity(true);
@@ -44,35 +47,9 @@ public class MsSqlServer2005Platform extends DatabasePlatform {
dbTypeMap.put(Types.LONGVARBINARY, new DbType("image"));
dbTypeMap.put(Types.LONGVARCHAR, new DbType("text"));
dbTypeMap.put(Types.DATE, new DbType("datetime"));
dbTypeMap.put(Types.TIME, new DbType("datetime"));
dbTypeMap.put(Types.TIMESTAMP, new DbType("datetime"));
}
/**
* MS SQL Server specific DDL Syntax.
*/
public class MsDdlSyntax extends DbDdlSyntax {
MsDdlSyntax() {
this.identity = "identity(1,1)";
this.dropKeyConstraints = true;
}
/**
* Return some DDL to disable constraints on the given table.
*/
public String dropKeyConstraintPrefix(String tableName, String fkName) {
return "IF OBJECT_ID('"+fkName+"', 'F') IS NOT NULL";
}
/**
* Return prefix text that goes before drop table.
*/
public String dropTablePrefix(String tableName) {
return "IF OBJECT_ID('"+tableName+"', 'U') IS NOT NULL ";
}
dbTypeMap.put(Types.DATE, new DbType("date"));
dbTypeMap.put(Types.TIME, new DbType("time"));
dbTypeMap.put(Types.TIMESTAMP, new DbType("datetime2"));
}
@@ -31,10 +31,11 @@ public class MsSqlServer2005SqlLimiter implements SqlLimiter {
if (firstRow < 1) {
// just use top n
sb.append(" select top ").append(lastRow).append(" ");
sb.append(" select ");
if (request.isDistinct()) {
sb.append("distinct ");
}
sb.append(" top ").append(lastRow).append(" ");
sb.append(request.getDbSql());
return new SqlLimitResponse(sb.toString(), false);
}
@@ -0,0 +1,9 @@
package com.avaje.ebean.config.dbplatform;
/**
* Runtime support for @History with MySql.
*/
public class MySqlHistorySupport extends DbViewHistorySupport {
}
@@ -1,6 +1,7 @@
package com.avaje.ebean.config.dbplatform;
import com.avaje.ebean.BackgroundExecutor;
import com.avaje.ebean.dbmigration.ddlgeneration.platform.MySqlDdl;
import javax.sql.DataSource;
import java.sql.Types;
@@ -24,6 +25,8 @@ public class MySqlPlatform extends DatabasePlatform {
this.likeClause = "like ? escape''";
this.selectCountWithAlias = true;
this.dbEncrypt = new MySqlDbEncrypt();
this.platformDdl = new MySqlDdl(this.dbTypeMap, this.dbIdentity);
this.historySupport = new MySqlHistorySupport();
this.dbIdentity.setIdType(IdType.IDENTITY);
this.dbIdentity.setSupportsGetGeneratedKeys(true);
@@ -43,12 +46,6 @@ public class MySqlPlatform extends DatabasePlatform {
dbTypeMap.put(Types.BLOB, new MySqlBlob());
dbTypeMap.put(Types.BINARY, new DbType("binary", 255));
dbTypeMap.put(Types.VARBINARY, new DbType("varbinary", 255));
dbDdlSyntax.setMaxConstraintNameLength(64);
dbDdlSyntax.setDisableReferentialIntegrity("SET FOREIGN_KEY_CHECKS=0");
dbDdlSyntax.setEnableReferentialIntegrity("SET FOREIGN_KEY_CHECKS=1");
dbDdlSyntax.setForeignKeySuffix("on delete restrict on update restrict");
}
/**
@@ -1,15 +0,0 @@
package com.avaje.ebean.config.dbplatform;
/**
* Since Ebean v2.2.0 Oracle9 is no different from Oracle10.
* <p>
* This will be removed in the future.
* </p>
*/
public class Oracle9Platform extends Oracle10Platform {
public Oracle9Platform() {
super();
}
}
@@ -43,25 +43,25 @@ package com.avaje.ebean.config.dbplatform;
*
* @author rbygrave
*/
public class Oracle10DbEncrypt extends AbstractDbEncrypt {
public class OracleDbEncrypt extends AbstractDbEncrypt {
/**
* Constructs the Oracle10DbEncrypt with default encrypt and decrypt stored procedures.
*/
public Oracle10DbEncrypt() {
public OracleDbEncrypt() {
this("eb_encrypt", "eb_decrypt");
}
/**
* Constructs the Oracle10DbEncrypt specifying encrypt and decrypt stored procedures.
*
* @param encryptfunction the encrypt stored procedure
* @param decryptfunction the decrypt stored procedure
* @param encryptFunction the encrypt stored procedure
* @param decryptFunction the decrypt stored procedure
*/
public Oracle10DbEncrypt(String encryptfunction, String decryptfunction) {
public OracleDbEncrypt(String encryptFunction, String decryptFunction) {
this.varcharEncryptFunction = new OraVarcharFunction(encryptfunction, decryptfunction);
this.dateEncryptFunction = new OraDateFunction(encryptfunction, decryptfunction);
this.varcharEncryptFunction = new OraVarcharFunction(encryptFunction, decryptFunction);
this.dateEncryptFunction = new OraDateFunction(encryptFunction, decryptFunction);
}
/**
@@ -0,0 +1,37 @@
package com.avaje.ebean.config.dbplatform;
/**
* Oracle Total recall based history support.
*/
public class OracleDbHistorySupport extends DbStandardHistorySupport {
/**
* Return the ' as of timestamp ?' clause appended after the table name.
*/
@Override
public String getAsOfViewSuffix(String asOfViewSuffix) {
return " as of TIMESTAMP ?";
}
@Override
public String getVersionsBetweenSuffix(String asOfViewSuffix) {
return " versions between timestamp ? and ?";
}
/**
* Returns the Oracle specific effective start column.
*/
@Override
public String getSysPeriodLower(String tableAlias, String sysPeriod) {
return "versions_starttime";
}
/**
* Returns the Oracle specific effective end column.
*/
@Override
public String getSysPeriodUpper(String tableAlias, String sysPeriod) {
return "versions_endtime";
}
}
@@ -1,6 +1,7 @@
package com.avaje.ebean.config.dbplatform;
import com.avaje.ebean.BackgroundExecutor;
import com.avaje.ebean.dbmigration.ddlgeneration.platform.Oracle10Ddl;
import javax.sql.DataSource;
import java.sql.Types;
@@ -8,15 +9,19 @@ import java.sql.Types;
/**
* Oracle10 and greater specific platform.
*/
public class Oracle10Platform extends DatabasePlatform {
public class OraclePlatform extends DatabasePlatform {
public Oracle10Platform() {
public OraclePlatform() {
super();
this.name = "oracle";
this.maxTableNameLength = 30;
this.maxConstraintNameLength = 30;
// OnQueryOnly.CLOSE as a performance optimisation on Oracle
this.onQueryOnly = OnQueryOnly.CLOSE;
this.dbEncrypt = new Oracle10DbEncrypt();
this.dbEncrypt = new OracleDbEncrypt();
this.sqlLimiter = new RownumSqlLimiter();
this.platformDdl = new Oracle10Ddl(this.dbTypeMap, this.dbIdentity);
this.historySupport = new OracleDbHistorySupport();
// Not using getGeneratedKeys as instead we will
// batch load sequences which enables JDBC batch execution
@@ -48,15 +53,10 @@ public class Oracle10Platform extends DatabasePlatform {
dbTypeMap.put(Types.BINARY, new DbType("raw", 255));
dbTypeMap.put(Types.TIME, new DbType("timestamp"));
dbDdlSyntax.setDropTableCascade("cascade constraints purge");
dbDdlSyntax.setIdentity(null);
dbDdlSyntax.setMaxConstraintNameLength(30);
}
@Override
public IdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds,
String seqName, int batchSize) {
public IdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
return new OracleSequenceIdGenerator(be, ds, seqName, batchSize);
}
@@ -1,67 +1,20 @@
package com.avaje.ebean.config.dbplatform;
import com.avaje.ebean.BackgroundExecutor;
import javax.sql.DataSource;
import java.sql.Types;
/**
* Postgres v8.3 specific platform.
* <p>
* No support for getGeneratedKeys.
* </p>
*/
public class Postgres8Platform extends DatabasePlatform {
public class Postgres8Platform extends PostgresPlatform {
public Postgres8Platform() {
super();
this.name = "postgres";
this.selectCountWithAlias = true;
this.blobDbType = Types.LONGVARBINARY;
this.clobDbType = Types.VARCHAR;
this.dbEncrypt = new PostgresDbEncrypt();
this.dbIdentity.setSupportsGetGeneratedKeys(false);
this.dbIdentity.setIdType(IdType.SEQUENCE);
this.dbIdentity.setSupportsSequence(true);
this.dbIdentity.setSupportsIdentity(true);
this.columnAliasPrefix = "as c";
this.openQuote = "\"";
this.closeQuote = "\"";
// dbTypeMap.put(Types.BOOLEAN, new DbType("bit default 0"));
dbTypeMap.put(Types.INTEGER, new DbType("integer", false));
dbTypeMap.put(Types.DOUBLE, new DbType("float"));
dbTypeMap.put(Types.TINYINT, new DbType("smallint"));
dbTypeMap.put(Types.DECIMAL, new DbType("decimal", 38));
dbTypeMap.put(Types.BINARY, new DbType("bytea", false));
dbTypeMap.put(Types.VARBINARY, new DbType("bytea", false));
dbTypeMap.put(Types.BLOB, new DbType("bytea", false));
dbTypeMap.put(Types.CLOB, new DbType("text"));
dbTypeMap.put(Types.LONGVARBINARY, new DbType("bytea", false));
dbTypeMap.put(Types.LONGVARCHAR, new DbType("text"));
dbDdlSyntax.setDropTableCascade("cascade");
dbDdlSyntax.setDropIfExists("if exists");
}
/**
* Create a Postgres specific sequence IdGenerator.
*/
@Override
public IdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds,
String seqName, int batchSize) {
return new PostgresSequenceIdGenerator(be, ds, seqName, batchSize);
}
@Override
protected String withForUpdate(String sql) {
return sql + " for update";
}
}
@@ -1,25 +0,0 @@
package com.avaje.ebean.config.dbplatform;
public class PostgresDdlSyntax extends DbDdlSyntax {
/**
* Map bigint, integer and smallint into their equivilent serial types.
*/
@Override
public String getIdentityColumnDefn(String columnDefn) {
//smallserial, serial and bigserial
if ("bigint".equalsIgnoreCase(columnDefn)) {
return "bigserial";
}
if ("integer".equalsIgnoreCase(columnDefn)) {
return "serial";
}
if ("smallint".equalsIgnoreCase(columnDefn)) {
return "smallserial";
}
return columnDefn;
}
}
@@ -0,0 +1,39 @@
package com.avaje.ebean.config.dbplatform;
/**
* Postgres support for history features.
*/
public class PostgresHistorySupport extends DbViewHistorySupport {
/**
* Return 1 as we are using the postgres range type and hence don't need 2 bind variables.
*/
@Override
public int getBindCount() {
return 1;
}
/**
* Build and return the 'as of' predicate for a given table alias.
* <p>
* Each @History entity involved in the query has this predicate added using the related table alias.
* </p>
*/
@Override
public String getAsOfPredicate(String asOfTableAlias, String asOfSysPeriod) {
// for Postgres we are using the 'timestamp with timezone range' data type
// as our sys_period column so hence the predicate below
return asOfTableAlias + "." + asOfSysPeriod + " @> ?::timestamptz";
}
@Override
public String getSysPeriodLower(String tableAlias, String sysPeriod) {
return "lower(" + tableAlias + "." + sysPeriod + ")";
}
@Override
public String getSysPeriodUpper(String tableAlias, String sysPeriod) {
return "upper(" + tableAlias + "." + sysPeriod + ")";
}
}
@@ -1,6 +1,9 @@
package com.avaje.ebean.config.dbplatform;
import com.avaje.ebean.BackgroundExecutor;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.dbmigration.ddlgeneration.DdlHandler;
import com.avaje.ebean.dbmigration.ddlgeneration.platform.PostgresDdl;
import javax.sql.DataSource;
import java.sql.Types;
@@ -16,28 +19,32 @@ public class PostgresPlatform extends DatabasePlatform {
public PostgresPlatform() {
super();
this.name = "postgres";
// OnQueryOnly.CLOSE as a performance optimisation on Postgres
this.onQueryOnly = OnQueryOnly.CLOSE;
this.likeClause = "like ? escape''";
this.dbDdlSyntax = new PostgresDdlSyntax();
this.selectCountWithAlias = true;
this.blobDbType = Types.LONGVARBINARY;
this.clobDbType = Types.VARCHAR;
this.dbEncrypt = new PostgresDbEncrypt();
this.historySupport = new PostgresHistorySupport();
this.platformDdl = new PostgresDdl(this.dbTypeMap, this.dbIdentity);
// Use Identity and getGeneratedKeys
this.dbIdentity.setIdType(IdType.IDENTITY);
this.dbIdentity.setSupportsGetGeneratedKeys(true);
this.dbIdentity.setSupportsSequence(true);
this.columnAliasPrefix = "as c";
//this.columnAliasPrefix = "as c";
this.openQuote = "\"";
this.closeQuote = "\"";
DbType dbTypeText = new DbType("text");
DbType dbBytea = new DbType("bytea", false);
dbTypeMap.put(DbType.HSTORE, new DbType("hstore"));
dbTypeMap.put(DbType.JSON, new DbType("json"));
dbTypeMap.put(DbType.JSONB, new DbType("jsonb"));
@@ -47,25 +54,28 @@ public class PostgresPlatform extends DatabasePlatform {
dbTypeMap.put(Types.TINYINT, new DbType("smallint"));
dbTypeMap.put(Types.DECIMAL, new DbType("decimal", 38));
dbTypeMap.put(Types.BINARY, new DbType("bytea", false));
dbTypeMap.put(Types.VARBINARY, new DbType("bytea", false));
dbTypeMap.put(Types.BINARY, dbBytea);
dbTypeMap.put(Types.VARBINARY, dbBytea);
dbTypeMap.put(Types.BLOB, new DbType("bytea", false));
dbTypeMap.put(Types.CLOB, new DbType("text"));
dbTypeMap.put(Types.LONGVARBINARY, new DbType("bytea", false));
dbTypeMap.put(Types.LONGVARCHAR, new DbType("text"));
dbTypeMap.put(Types.BLOB, dbBytea);
dbTypeMap.put(Types.CLOB, dbTypeText);
dbTypeMap.put(Types.LONGVARBINARY, dbBytea);
dbTypeMap.put(Types.LONGVARCHAR, dbTypeText);
dbDdlSyntax.setDropTableCascade("cascade");
dbDdlSyntax.setDropIfExists("if exists");
}
/**
* Return a DdlHandler instance for generating DDL for the specific platform.
*/
public DdlHandler createDdlHandler(ServerConfig serverConfig) {
return this.platformDdl.createDdlHandler(serverConfig);
}
/**
* Create a Postgres specific sequence IdGenerator.
*/
@Override
public IdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds,
String seqName, int batchSize) {
public IdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
return new PostgresSequenceIdGenerator(be, ds, seqName, batchSize);
}
@@ -1,22 +1,20 @@
package com.avaje.ebean.config.dbplatform;
import com.avaje.ebean.dbmigration.ddlgeneration.platform.SQLiteDdl;
import java.sql.Types;
import javax.sql.DataSource;
import com.avaje.ebean.BackgroundExecutor;
public class SQLitePlatform extends DatabasePlatform {
public SQLitePlatform() {
super();
this.name = "sqlite";
this.platformDdl = new SQLiteDdl(dbTypeMap, dbIdentity);
this.dbIdentity.setIdType(IdType.IDENTITY);
this.dbIdentity.setSupportsGetGeneratedKeys(false);
this.dbIdentity.setSupportsSequence(false);
this.dbIdentity.setSelectLastInsertedIdTemplate("select last_insert_rowid()");
this.openQuote = "\"";
this.closeQuote = "\"";
this.booleanDbType = Types.INTEGER;
@@ -24,25 +22,7 @@ public class SQLitePlatform extends DatabasePlatform {
dbTypeMap.put(Types.BOOLEAN, new DbType("int default 0"));
dbTypeMap.put(Types.BIGINT, new DbType("integer"));
dbTypeMap.put(Types.SMALLINT, new DbType("integer"));
dbDdlSyntax.setInlinePrimaryKeyConstraint(true);
// AutoIncrement goes the primary key declaration
dbDdlSyntax.setIdentity("");
dbDdlSyntax.setIdentitySuffix("AUTOINCREMENT");
dbDdlSyntax.setDisableReferentialIntegrity("PRAGMA foreign_keys = OFF");
dbDdlSyntax.setEnableReferentialIntegrity("PRAGMA foreign_keys = ON");
}
/**
* Return null in case there is a sequence annotation.
*/
@Override
public IdGenerator createSequenceIdGenerator(BackgroundExecutor be,
DataSource ds, String seqName, int batchSize) {
return null;
}
}
@@ -42,7 +42,7 @@ public abstract class SequenceIdGenerator implements IdGenerator {
protected final ArrayList<Long> idList = new ArrayList<Long>(50);
protected int batchSize;
protected final int batchSize;
protected int currentlyBackgroundLoading;
@@ -61,8 +61,7 @@ public class SimpleSequenceIdGenerator implements IdGenerator {
pstmt = c.prepareStatement(sql);
rset = pstmt.executeQuery();
if (rset.next()) {
int val = rset.getInt(1);
return Integer.valueOf(val);
return rset.getInt(1);
} else {
String m = "Always expecting 1 row from " + sql;
throw new PersistenceException(m);
@@ -11,7 +11,6 @@ import java.sql.Types;
* </ul>
* </p>
*/
public class SqlAnywherePlatform extends DatabasePlatform {
public SqlAnywherePlatform() {
@@ -11,12 +11,7 @@ public interface SqlLimiter {
* Note that this is removed for logging sql to the transaction log.
* </p>
*/
static final char NEW_LINE = '\n';
/**
* The carriage return character.
*/
static final char CARRIAGE_RETURN = '\r';
char NEW_LINE = '\n';
/**
* Add the SQL limiting statements around the query.
@@ -0,0 +1,327 @@
package com.avaje.ebean.dbmigration;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.EbeanServer;
import com.avaje.ebean.config.DbConstraintNaming;
import com.avaje.ebean.config.DbMigrationConfig;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.config.dbplatform.DB2Platform;
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
import com.avaje.ebean.config.dbplatform.DbPlatformName;
import com.avaje.ebean.config.dbplatform.H2Platform;
import com.avaje.ebean.config.dbplatform.MsSqlServer2005Platform;
import com.avaje.ebean.config.dbplatform.MySqlPlatform;
import com.avaje.ebean.config.dbplatform.OraclePlatform;
import com.avaje.ebean.config.dbplatform.PostgresPlatform;
import com.avaje.ebean.config.dbplatform.SQLitePlatform;
import com.avaje.ebean.dbmigration.ddlgeneration.DdlWrite;
import com.avaje.ebean.dbmigration.migration.Migration;
import com.avaje.ebean.dbmigration.migrationreader.MigrationXmlWriter;
import com.avaje.ebean.dbmigration.model.CurrentModel;
import com.avaje.ebean.dbmigration.model.MConfiguration;
import com.avaje.ebean.dbmigration.model.MigrationModel;
import com.avaje.ebean.dbmigration.model.ModelContainer;
import com.avaje.ebean.dbmigration.model.PlatformDdlWriter;
import com.avaje.ebean.dbmigration.model.ModelDiff;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Generates DB Migration xml and sql scripts.
* <p>
* Reads the prior migrations and compares with the current model of the EbeanServer
* and generates a migration 'diff' in the form of xml document with the logical schema
* changes and a series of sql scripts to apply, rollback the applied changes if necessary
* and drop objects (drop tables, drop columns).
* </p>
* <p>
* This does not run the migration or ddl scripts but just generates them.
* </p>
* <pre>{@code
*
* DbMigration migration = new DbMigration();
* migration.setPathToResources("src/main/resources");
* migration.setPlatform(DbPlatformName.ORACLE);
*
* migration.generateMigration();
*
* }</pre>
*/
public class DbMigration {
protected static final Logger logger = LoggerFactory.getLogger(DbMigration.class);
protected SpiEbeanServer server;
protected DbMigrationConfig migrationConfig;
protected String pathToResources = "src/main/resources";
protected DatabasePlatform databasePlatform;
protected List<Pair> platforms = new ArrayList<Pair>();
protected ServerConfig serverConfig;
protected DbConstraintNaming constraintNaming;
public DbMigration() {
}
/**
* Set the path from the current working directory to the application resources.
*
* This defaults to maven style 'src/main/resources'.
*/
public void setPathToResources(String pathToResources) {
this.pathToResources = pathToResources;
}
/**
* Set the server to use to determine the current model.
* Typically this is not called explicitly.
*/
public void setServer(EbeanServer ebeanServer) {
this.server = (SpiEbeanServer) ebeanServer;
setServerConfig(server.getServerConfig());
}
/**
* Set the serverConfig to use. Typically this is not called explicitly.
*/
public void setServerConfig(ServerConfig config) {
if (this.serverConfig == null) {
this.serverConfig = config;
}
if (migrationConfig == null) {
this.migrationConfig = serverConfig.getMigrationConfig();
}
if (constraintNaming == null) {
this.constraintNaming = serverConfig.getConstraintNaming();
}
}
/**
* Set the specific platform to generate DDL for.
* <p>
* If not set this defaults to the platform of the default server.
* </p>
*/
public void setPlatform(DbPlatformName platform) {
setPlatform(getPlatform(platform));
}
/**
* Set the specific platform to generate DDL for.
* <p>
* If not set this defaults to the platform of the default server.
* </p>
*/
public void setPlatform(DatabasePlatform databasePlatform) {
this.databasePlatform = databasePlatform;
DbOffline.setPlatform(databasePlatform.getName());
}
/**
* Add an additional platform to write the migration DDL.
* <p>
* Use this when you want to generate sql scripts for multiple database platforms
* from the migration (e.g. generate migration sql for MySql, Postgres and Oracle).
* </p>
*/
public void addPlatform(DbPlatformName platform, String prefix) {
if (!prefix.endsWith("-")) {
prefix += "-";
}
platforms.add(new Pair(getPlatform(platform), prefix));
}
/**
* Generate the next migration xml file and associated apply and rollback sql scripts.
* <p>
* This does not run the migration or ddl scripts but just generates them.
* </p>
* <h3>Example: Run for a single specific platform</h3>
* <pre>{@code
*
* DbMigration migration = new DbMigration();
* migration.setPathToResources("src/main/resources");
* migration.setPlatform(DbPlatformName.ORACLE);
*
* migration.generateMigration();
*
* }</pre>
*
* <h3>Example: Run migration generating DDL for multiple platforms</h3>
* <pre>{@code
*
* DbMigration migration = new DbMigration();
* migration.setPathToResources("src/main/resources");
*
* migration.addPlatform(DbPlatformName.POSTGRES, "pg");
* migration.addPlatform(DbPlatformName.MYSQL, "mysql");
* migration.addPlatform(DbPlatformName.ORACLE, "mysql");
*
* migration.generateMigration();
*
* }</pre>
*/
public void generateMigration() throws IOException {
// use this flag to stop other plugins like full DDL generation
DbOffline.setRunningMigration();
setDefaults();
try {
MigrationModel migrationModel = new MigrationModel(migrationConfig.getResourcePath());
ModelContainer migrated = migrationModel.read();
int nextMajorVersion = migrationModel.getNextMajorVersion();
logger.info("next migration version {}", nextMajorVersion);
CurrentModel currentModel = new CurrentModel(server, constraintNaming);
ModelContainer current = currentModel.read();
ModelDiff diff = new ModelDiff(migrated);
diff.compareTo(current);
if (diff.isEmpty()) {
logger.info("no changes detected - no migration written");
return;
}
// there were actually changes to write
Migration dbMigration = diff.getMigration();
File writePath = getWritePath();
logger.info("migration writing version {} to {}", nextMajorVersion, writePath.getAbsolutePath());
writeMigrationXml(dbMigration, writePath, nextMajorVersion);
if (databasePlatform != null) {
// writer needs the current model to provide table/column details for
// history ddl generation (triggers, history tables etc)
DdlWrite write = new DdlWrite(new MConfiguration(), currentModel.read());
PlatformDdlWriter writer = new PlatformDdlWriter(databasePlatform, serverConfig);
writer.processMigration(dbMigration, write, writePath, nextMajorVersion);
}
writeExtraPlatformDdl(nextMajorVersion, currentModel, dbMigration, writePath);
} finally {
DbOffline.reset();
}
}
/**
* Write any extra platform ddl.
*/
protected void writeExtraPlatformDdl(int nextMajorVersion, CurrentModel currentModel, Migration dbMigration, File writePath) throws IOException {
for (Pair pair : platforms) {
DdlWrite platformBuffer = new DdlWrite(new MConfiguration(), currentModel.read());
PlatformDdlWriter platformWriter = new PlatformDdlWriter(pair.platform, serverConfig, pair.prefix);
platformWriter.processMigration(dbMigration, platformBuffer, writePath, nextMajorVersion);
}
}
/**
* Write the migration xml.
*/
protected void writeMigrationXml(Migration dbMigration, File resourcePath, int migrationVersion) {
File file = new File(resourcePath, "v"+migrationVersion+".0.xml");
MigrationXmlWriter xmlWriter = new MigrationXmlWriter();
xmlWriter.write(dbMigration, file);
}
/**
* Set default server and platform if necessary.
*/
protected void setDefaults() {
if (server == null) {
setServer(Ebean.getDefaultServer());
}
if (databasePlatform == null && platforms.isEmpty()) {
// not explicitly set not set a list of platforms so
// default to the platform of the default server
databasePlatform = server.getDatabasePlatform();
logger.debug("set platform to {}", databasePlatform.getName());
}
}
/**
* Return the file path to write the xml and sql to.
*/
protected File getWritePath() {
// path to src/main/resources in typical maven project
File resourceRootDir = new File(pathToResources);
String resourcePath = migrationConfig.getResourcePath();
// expect to be a path to something like - src/main/resources/dbmigration/myapp
File path = new File(resourceRootDir, resourcePath);
if (!path.exists()) {
if (!path.mkdirs()) {
logger.debug("Unable to ensure migration directory exists at {}", path.getAbsolutePath());
}
}
return path;
}
/**
* Return the DatabasePlatform given the platform key.
*/
protected DatabasePlatform getPlatform(DbPlatformName platform) {
switch (platform) {
case H2:
return new H2Platform();
case POSTGRES:
return new PostgresPlatform();
case MYSQL:
return new MySqlPlatform();
case ORACLE:
return new OraclePlatform();
case SQLSERVER:
return new MsSqlServer2005Platform();
case DB2:
return new DB2Platform();
case SQLITE:
return new SQLitePlatform();
default:
throw new IllegalArgumentException("Platform missing? " + platform);
}
}
/**
* Holds a platform and prefix. Used to generate multiple platform specific DDL
* for a single migration.
*/
public static class Pair {
/**
* The platform to generate the DDL for.
*/
public final DatabasePlatform platform;
/**
* A prefix included into the file/resource names indicating the platform.
*/
public final String prefix;
public Pair(DatabasePlatform platform, String prefix) {
this.platform = platform;
this.prefix = prefix;
}
}
}
@@ -0,0 +1,79 @@
package com.avaje.ebean.dbmigration;
import com.avaje.ebean.config.dbplatform.DbPlatformName;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Helper to indicate that an EbeanServer should come up offline
* typically for DDL generation purposes.
*/
public class DbOffline {
private static final Logger logger = LoggerFactory.getLogger(DbOffline.class);
private static final String KEY = "ebean.dboffline";
private static boolean runningMigration;
/**
* Set the platform to use when creating the next EbeanServer instance.
*/
public static void setPlatform(DbPlatformName dbPlatform) {
System.setProperty(KEY, dbPlatform.name());
}
/**
* Set the platform to use when creating the next EbeanServer instance.
*/
public static void setPlatform(String platformName) {
System.setProperty(KEY, platformName);
}
/**
* Return the platform to use when creating the next EbeanServer instance.
*/
public static String getPlatform() {
return System.getProperty(KEY);
}
/**
* Bring up the next EbeanServer instance using the H2 platform.
*/
public static void asH2() {
setPlatform(DbPlatformName.H2);
}
/**
* Return true if the offline platform has been set.
*/
public static boolean isSet() {
return getPlatform() != null;
}
/**
* Return true if the migration is running. This typically means don't run the
* plugins like full DDL generation.
*/
public static boolean isRunningMigration() {
return runningMigration;
}
/**
* Called when the migration is running is order to stop other plugins
* like the full DDL generation from executing.
*/
public static void setRunningMigration() {
runningMigration = true;
}
/**
* Reset the offline platform and runningMigration flag.
*/
public static void reset() {
runningMigration = false;
System.clearProperty(KEY);
logger.debug("reset");
}
}
@@ -1,5 +1,14 @@
package com.avaje.ebeaninternal.server.ddl;
package com.avaje.ebean.dbmigration;
import com.avaje.ebean.Transaction;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.dbmigration.model.CurrentModel;
import com.avaje.ebeaninternal.api.SpiEbeanPlugin;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.persistence.PersistenceException;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
@@ -13,18 +22,6 @@ import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.PersistenceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.avaje.ebean.Transaction;
import com.avaje.ebean.config.NamingConvention;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
import com.avaje.ebeaninternal.api.SpiEbeanPlugin;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
/**
* Controls the generation of DDL and potentially runs the resulting scripts.
*/
@@ -34,24 +31,17 @@ public class DdlGenerator implements SpiEbeanPlugin {
private SpiEbeanServer server;
private DatabasePlatform dbPlatform;
private int summaryLength = 80;
private boolean generateDdl;
private boolean runDdl;
private CurrentModel currentModel;
private String dropContent;
private String createContent;
private NamingConvention namingConvention;
public void setup(SpiEbeanServer server, DatabasePlatform dbPlatform, ServerConfig serverConfig) {
public void setup(SpiEbeanServer server, ServerConfig serverConfig) {
this.server = server;
this.dbPlatform = dbPlatform;
this.generateDdl = serverConfig.isDdlGenerate();
this.runDdl = serverConfig.isDdlRun();
this.namingConvention = serverConfig.getNamingConvention();
}
/**
@@ -103,10 +93,8 @@ public class DdlGenerator implements SpiEbeanPlugin {
try {
String c = generateDropDdl();
writeFile(dropFile, c);
} catch (IOException e) {
String msg = "Error generating Drop DDL";
throw new PersistenceException(msg, e);
throw new PersistenceException("Error generating Drop DDL", e);
}
}
@@ -115,65 +103,44 @@ public class DdlGenerator implements SpiEbeanPlugin {
try {
String c = generateCreateDdl();
writeFile(createFile, c);
} catch (IOException e) {
String msg = "Error generating Create DDL";
throw new PersistenceException(msg, e);
throw new PersistenceException("Error generating Create DDL", e);
}
}
public String generateDropDdl() {
DdlGenContext ctx = createContext();
if (ctx.getDdlSyntax().isDropKeyConstraints()) {
// generate drop foreign key constraint statements (sql server joy)
AddForeignKeysVisitor fkeys = new AddForeignKeysVisitor(false, ctx);
VisitorUtil.visit(server, fkeys);
ctx.writeNewLine();
try {
dropContent = currentModel().getDropDdl();
return dropContent;
} catch (IOException e) {
throw new RuntimeException(e);
}
DropTableVisitor drop = new DropTableVisitor(ctx);
VisitorUtil.visit(server, drop);
DropSequenceVisitor dropSequence = new DropSequenceVisitor(ctx);
VisitorUtil.visit(server, dropSequence);
ctx.flush();
dropContent = ctx.getContent();
return dropContent;
}
public String generateCreateDdl() {
DdlGenContext ctx = createContext();
CreateTableVisitor create = new CreateTableVisitor(ctx);
VisitorUtil.visit(server, create);
CreateSequenceVisitor createSequence = new CreateSequenceVisitor(ctx);
VisitorUtil.visit(server, createSequence);
AddForeignKeysVisitor fkeys = new AddForeignKeysVisitor(true, ctx);
VisitorUtil.visit(server, fkeys);
CreateIndexVisitor indexes = new CreateIndexVisitor(ctx);
VisitorUtil.visit(server, indexes);
ctx.flush();
createContent = ctx.getContent();
return createContent;
try {
createContent = currentModel().getCreateDdl();
return createContent;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
protected String getDropFileName() {
return server.getName() + "-drop.sql";
return server.getName() + "-drop-all.sql";
}
protected String getCreateFileName() {
return server.getName() + "-create.sql";
return server.getName() + "-create-all.sql";
}
protected DdlGenContext createContext() {
return new DdlGenContext(dbPlatform, namingConvention);
protected CurrentModel currentModel() {
if (currentModel == null) {
currentModel = new CurrentModel(server);
}
return currentModel;
}
protected void writeFile(String fileName, String fileContent) throws IOException {
@@ -201,7 +168,7 @@ public class DdlGenerator implements SpiEbeanPlugin {
FileReader fr = new FileReader(f);
LineNumberReader lr = new LineNumberReader(fr);
try {
String s = null;
String s;
while ((s = lr.readLine()) != null) {
buf.append(s).append("\n");
}
@@ -233,8 +200,7 @@ public class DdlGenerator implements SpiEbeanPlugin {
t.commit();
} catch (Exception e) {
String msg = "Error: " + e.getMessage();
throw new PersistenceException(msg, e);
throw new PersistenceException("Error: " + e.getMessage(), e);
} finally {
t.end();
}
@@ -274,7 +240,7 @@ public class DdlGenerator implements SpiEbeanPlugin {
stmt = stmt.substring(0, stmt.length() - 1);
}
logger.trace("executing " + oneOf + " " + getSummary(stmt));
logger.info("executing " + oneOf + " " + getSummary(stmt));
pstmt = c.prepareStatement(stmt);
pstmt.execute();
@@ -340,8 +306,8 @@ public class DdlGenerator implements SpiEbeanPlugin {
}
private String getSummary(String s) {
if (s.length() > summaryLength) {
return s.substring(0, summaryLength).trim() + "...";
if (s.length() > 80) {
return s.substring(0, 80).trim() + "...";
}
return s;
}
@@ -0,0 +1,108 @@
package com.avaje.ebean.dbmigration.ddlgeneration;
import com.avaje.ebean.config.ServerConfig;
import com.avaje.ebean.dbmigration.ddlgeneration.platform.BaseTableDdl;
import com.avaje.ebean.dbmigration.ddlgeneration.platform.PlatformDdl;
import com.avaje.ebean.dbmigration.migration.AddColumn;
import com.avaje.ebean.dbmigration.migration.AddHistoryTable;
import com.avaje.ebean.dbmigration.migration.AlterColumn;
import com.avaje.ebean.dbmigration.migration.ChangeSet;
import com.avaje.ebean.dbmigration.migration.CreateIndex;
import com.avaje.ebean.dbmigration.migration.CreateTable;
import com.avaje.ebean.dbmigration.migration.DropColumn;
import com.avaje.ebean.dbmigration.migration.DropHistoryTable;
import com.avaje.ebean.dbmigration.migration.DropIndex;
import com.avaje.ebean.dbmigration.migration.DropTable;
import java.io.IOException;
import java.util.List;
/**
*
*/
public class BaseDdlHandler implements DdlHandler {
protected final TableDdl tableDdl;
public BaseDdlHandler(ServerConfig serverConfig, PlatformDdl platformDdl) {
this.tableDdl = new BaseTableDdl(serverConfig, platformDdl);
}
@Override
public void generate(DdlWrite writer, ChangeSet changeSet) throws IOException {
List<Object> changeSetChildren = changeSet.getChangeSetChildren();
for (Object change : changeSetChildren) {
if (change instanceof CreateTable) {
generate(writer, (CreateTable) change);
} else if (change instanceof DropTable) {
generate(writer, (DropTable) change);
} else if (change instanceof CreateIndex) {
generate(writer, (CreateIndex) change);
} else if (change instanceof DropIndex) {
generate(writer, (DropIndex) change);
} else if (change instanceof AddColumn) {
generate(writer, (AddColumn) change);
} else if (change instanceof DropColumn) {
generate(writer, (DropColumn) change);
} else if (change instanceof AlterColumn) {
generate(writer, (AlterColumn) change);
} else if (change instanceof AddHistoryTable) {
generate(writer, (AddHistoryTable) change);
} else if (change instanceof DropHistoryTable) {
generate(writer, (DropHistoryTable) change);
}
}
}
@Override
public void generateExtra(DdlWrite write) throws IOException {
tableDdl.generateExtra(write);
}
@Override
public void generate(DdlWrite writer, CreateTable createTable) throws IOException {
tableDdl.generate(writer, createTable);
}
@Override
public void generate(DdlWrite writer, DropTable dropTable) throws IOException {
tableDdl.generate(writer, dropTable);
}
@Override
public void generate(DdlWrite writer, AddColumn addColumn) throws IOException {
tableDdl.generate(writer, addColumn);
}
@Override
public void generate(DdlWrite writer, DropColumn dropColumn) throws IOException {
tableDdl.generate(writer, dropColumn);
}
@Override
public void generate(DdlWrite writer, AlterColumn alterColumn) throws IOException {
tableDdl.generate(writer, alterColumn);
}
@Override
public void generate(DdlWrite writer, AddHistoryTable addHistoryTable) throws IOException {
tableDdl.generate(writer, addHistoryTable);
}
@Override
public void generate(DdlWrite writer, DropHistoryTable dropHistoryTable) throws IOException {
tableDdl.generate(writer, dropHistoryTable);
}
@Override
public void generate(DdlWrite writer, CreateIndex createIndex) throws IOException {
tableDdl.generate(writer, createIndex);
}
@Override
public void generate(DdlWrite writer, DropIndex dropIndex) throws IOException {
tableDdl.generate(writer, dropIndex);
}
}
@@ -0,0 +1,28 @@
package com.avaje.ebean.dbmigration.ddlgeneration;
import com.avaje.ebean.dbmigration.migration.AddColumn;
import com.avaje.ebean.dbmigration.migration.AlterColumn;
import com.avaje.ebean.dbmigration.migration.DropColumn;
import java.io.IOException;
/**
* Write DDL for AddColumn , DropColumn or AlterColumn.
*/
public interface ColumnDdl {
/**
* Write the add column change.
*/
void generate(DdlWrite writer, AddColumn addColumn) throws IOException;
/**
* Write the drop column change.
*/
void generate(DdlWrite writer, DropColumn dropColumn) throws IOException;
/**
* Write the alter column changes.
*/
void generate(DdlWrite writer, AlterColumn alterColumn) throws IOException;
}
@@ -0,0 +1,57 @@
package com.avaje.ebean.dbmigration.ddlgeneration;
import com.avaje.ebean.dbmigration.model.MConfiguration;
import java.io.IOException;
/**
* Buffer to append generated DDL to.
*/
public interface DdlBuffer {
/**
* Return the configuration (default tablespaces etc).
*/
MConfiguration getConfiguration();
/**
* Return true if the buffer is empty.
*/
boolean isEmpty();
/**
* Append DDL content to the buffer.
*/
DdlBuffer append(String content) throws IOException;
/**
* Append DDL content to the buffer with space padding.
*/
DdlBuffer append(String type, int space) throws IOException;
/**
* Append a value that is potentially null or empty and proceed it with a space if so.
*/
DdlBuffer appendWithSpace(String foreignKeyRestrict) throws IOException;
/**
* Append new line character to the buffer.
*/
DdlBuffer newLine() throws IOException;
/**
* Append the end of statement content.
*/
DdlBuffer endOfStatement() throws IOException;
/**
* End of a change - add some whitespace.
*/
DdlBuffer end() throws IOException;
/**
* Return the buffer content.
*/
String getBuffer();
}
@@ -0,0 +1,41 @@
package com.avaje.ebean.dbmigration.ddlgeneration;
import com.avaje.ebean.dbmigration.migration.AddColumn;
import com.avaje.ebean.dbmigration.migration.AddHistoryTable;
import com.avaje.ebean.dbmigration.migration.AlterColumn;
import com.avaje.ebean.dbmigration.migration.ChangeSet;
import com.avaje.ebean.dbmigration.migration.CreateIndex;
import com.avaje.ebean.dbmigration.migration.CreateTable;
import com.avaje.ebean.dbmigration.migration.DropColumn;
import com.avaje.ebean.dbmigration.migration.DropHistoryTable;
import com.avaje.ebean.dbmigration.migration.DropIndex;
import com.avaje.ebean.dbmigration.migration.DropTable;
import java.io.IOException;
/**
*/
public interface DdlHandler {
void generate(DdlWrite writer, ChangeSet changeSet) throws IOException;
void generate(DdlWrite writer, CreateTable createTable) throws IOException;
void generate(DdlWrite writer, DropTable dropTable) throws IOException;
void generate(DdlWrite writer, AddColumn addColumn) throws IOException;
void generate(DdlWrite writer, DropColumn dropColumn) throws IOException;
void generate(DdlWrite writer, AlterColumn alterColumn) throws IOException;
void generate(DdlWrite writer, AddHistoryTable addHistoryTable) throws IOException;
void generate(DdlWrite writer, DropHistoryTable dropHistoryTable) throws IOException;
void generate(DdlWrite writer, CreateIndex createIndex) throws IOException;
void generate(DdlWrite writer, DropIndex dropIndex) throws IOException;
void generateExtra(DdlWrite write) throws IOException;
}
@@ -0,0 +1,160 @@
package com.avaje.ebean.dbmigration.ddlgeneration;
import com.avaje.ebean.dbmigration.ddlgeneration.platform.BaseDdlBuffer;
import com.avaje.ebean.dbmigration.model.MConfiguration;
import com.avaje.ebean.dbmigration.model.MTable;
import com.avaje.ebean.dbmigration.model.ModelContainer;
/**
* Write context holding the buffers for both apply and rollback DDL.
*/
public class DdlWrite {
private final ModelContainer currentModel;
private final DdlBuffer apply;
private final DdlBuffer applyForeignKeys;
private final DdlBuffer applyHistory;
private final DdlBuffer rollbackForeignKeys;
private final DdlBuffer rollback;
/**
* For DDL that drops tables and columns etc.
*
* This DDL typically can not run automatically in production as there is most commonly
* existing servers running the application using these tables and columns. Typically
* these drop statements may be executed AFTER all the servers in the application have
* migrated onto new code.
*/
private final DdlBuffer drop;
/**
* For use when History is turned off for a base table or history is no longer
* desired on specific columns. This DDL should typically execute manually after review
* by DBA's.
*/
private final DdlBuffer dropHistory;
/**
* Create without any configuration or current model (no history support).
*/
public DdlWrite() {
this(new MConfiguration(), new ModelContainer());
}
/**
* Create with a configuration.
*/
public DdlWrite(MConfiguration configuration, ModelContainer currentModel) {
this.currentModel = currentModel;
this.apply = new BaseDdlBuffer(configuration);
this.applyForeignKeys = new BaseDdlBuffer(configuration);
this.applyHistory = new BaseDdlBuffer(configuration);
this.rollbackForeignKeys = new BaseDdlBuffer(configuration);
this.rollback = new BaseDdlBuffer(configuration);
this.drop = new BaseDdlBuffer(configuration);
this.dropHistory = new BaseDdlBuffer(configuration);
}
/**
* Return the Table information from the current model.
* <p>
* This is typically required for the history support (used to determine the list of columns
* included in the history when creating or recreating the associated trigger/stored procedure).
* </p>
*/
public MTable getTable(String tableName) {
return currentModel.getTable(tableName);
}
/**
* Return true if the apply buffers are all empty.
*/
public boolean isApplyEmpty() {
return apply.getBuffer().isEmpty()
&& applyForeignKeys.getBuffer().isEmpty()
&& applyHistory.getBuffer().isEmpty();
}
/**
* Return true if the apply rollback buffers are all empty.
*/
public boolean isApplyRollbackEmpty() {
return rollback.getBuffer().isEmpty()
&& rollbackForeignKeys.getBuffer().isEmpty();
}
/**
* Return true the drop buffers are empty.
*/
public boolean isDropEmpty() {
return drop.getBuffer().isEmpty() && dropHistory.getBuffer().isEmpty();
}
/**
* Return the buffer that APPLY DDL is written to.
*/
public DdlBuffer apply() {
return apply;
}
/**
* Return the buffer that APPLY DDL is written to for foreign keys and their associated indexes.
* <p>
* Statements added to this buffer are executed after all the normal apply statements and
* typically 'add foreign key' is added to this buffer.
*/
public DdlBuffer applyForeignKeys() {
return applyForeignKeys;
}
/**
* Return the buffer that apply history DDL is written to.
*/
public DdlBuffer applyHistory() {
return applyHistory;
}
/**
* Return the buffer that ROLLBACK DDL is written to for foreign keys and associated indexes.
*/
public DdlBuffer rollbackForeignKeys() {
return rollbackForeignKeys;
}
/**
* Return the buffer that ROLLBACK DDL is written to which is considered safe to run when
* apply changes fail to execute. This will reverse the apply changes typically dropping
* newly created tables, foreign keys etc.
* <p>
* When apply changes are made against DB's that support transactional DDL you could argue
* that these rollback statements are not necessary.
* <p>
* Note that statements added to this rollback buffer are executed after foreign key rollback
* has been executed.
*/
public DdlBuffer rollback() {
return rollback;
}
/**
* Return the buffer that destructive changes are written to. This is typically drop table and
* drop column.
*/
public DdlBuffer drop() {
return drop;
}
/**
* Return the buffer that is used when history is no longer required on a table or specific columns.
*/
public DdlBuffer dropHistory() {
return dropHistory;
}
}

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