Compare commits

...
Author SHA1 Message Date
rob bygrave 4ac3a8d1ad [maven-release-plugin] prepare release ebean-12.3.6 2020-06-29 18:07:27 +12:00
rob bygrave 5a8f8b3a83 #2027 - querybean generator support for @EbeanComponent 2020-06-29 18:01:28 +12:00
rob bygrave 7c01cec466 [maven-release-plugin] prepare for next development iteration 2020-06-29 17:21:19 +12:00
rob bygrave 30ad4260f0 [maven-release-plugin] prepare release ebean-12.3.5 2020-06-29 17:21:08 +12:00
rob bygrave ab421d6f2b No effective change - trim whitespace in BaseTableDdl 2020-06-29 17:15:35 +12:00
rob bygrave 0b807addc7 No effective change - test tidy 2020-06-29 17:09:02 +12:00
rob bygrave bb03ef5693 No effective change - test tidy 2020-06-29 15:51:34 +12:00
rob bygrave 248a7b1062 #2004 - MariaDB DDL review 2020-06-29 15:50:08 +12:00
rob bygrave 9da28262b4 #2004 - MariaDB History useLegacyDatetimeCode=false required to properly handle server timezone 2020-06-29 14:51:24 +12:00
rob bygrave fc8dd18fd1 #2004 - MariaDB History DDL using add/drop system versioning 2020-06-29 14:03:21 +12:00
rob bygrave 70ba658442 #2026 - Postgres DDL - modify type generates wrong alter sql. Needs explicit cast / using clause. 2020-06-29 12:12:10 +12:00
rob bygrave 70b730657f #2028 - Refactor internals of smart persistence context to reference "parent" rather than copy beans (adjustment of #2021) 2020-06-29 08:48:24 +12:00
rob bygrave bf3cb7e2e2 No effective change - tidy test BeanDescriptor_registerTest 2020-06-26 15:49:35 +12:00
rob bygrave c2708ecc76 No effective change - Refactor tidy BeanDescriptor internals - trimQueryPlans() etc 2020-06-23 22:14:11 +12:00
rob bygrave 896aba3053 No effective change - trim whitespace 2020-06-23 22:03:21 +12:00
rob bygrave f78b602a90 No effective change - trim whitespace 2020-06-23 21:08:30 +12:00
rob bygrave 306c1b5cf6 No effective change - EntityBeanIntercept tidy javadoc 2020-06-23 20:57:31 +12:00
rob bygrave cdf2718ca9 No effective change - refactor EntityBeanIntercept reverse internal notEqual() method 2020-06-23 20:43:08 +12:00
rob bygrave 967ca0c9f3 No effective change - add some more tests for EntityBeanIntercept 2020-06-23 17:09:15 +12:00
rob bygrave 607acb1b4e No effective change - tidy DefaultPersistenceContext 2020-06-23 16:35:53 +12:00
rob bygrave 5f923945e9 No effective change - trim whitespace 2020-06-23 16:35:36 +12:00
rob bygrave 11fbe8bf5b [maven-release-plugin] prepare for next development iteration 2020-06-19 23:23:32 +12:00
rob bygrave 0544fa7ab4 [maven-release-plugin] prepare release ebean-12.3.4 2020-06-19 23:23:21 +12:00
rob bygrave 51eed9bfe4 Testing - default to h2 2020-06-19 23:20:46 +12:00
Rob BygraveandGitHub 32ce1f1d59 #2004 - MariaDb specific platform with @History support (initial) (#2023)
#2004 - MariaDb specific platform with @History support (initial)
2020-06-19 23:20:07 +12:00
rob bygrave f445c118a0 #2025 - Make findStream & findLargeStream the same - deprecate findLargeStream 2020-06-19 23:17:47 +12:00
rob bygrave a8ff918bb3 #2024 - Change default "fetchBuffer" for findEach/iterate/stream queries to 100 2020-06-19 22:36:24 +12:00
rob bygrave 729aeae0d7 No effective change - trim whitespace 2020-06-19 22:13:50 +12:00
rob bygrave 17a9341287 #2006 - Auto register AttributeConverter with Ebean (using @Converter) 2020-06-19 20:33:58 +12:00
rob bygrave c863014fec Javadoc improvements for #2022 - use of index params like ?1, ?2, ?3 etc 2020-06-18 16:04:13 +12:00
rob bygrave 8170db4101 Bump ebean-annotation which has MariaDB platform enum
As a step for #2004
Means we can add a specific platform for MariaDB separate from MySql
2020-06-18 11:30:43 +12:00
rob bygrave 434a5117a2 Bump to ebean-datasource 5.1
This will expose pool size which can be exposed as a gauge metric (the current size of main connection pool and readonly connection pool)
2020-06-18 11:10:01 +12:00
rob bygrave 85ed8cd784 Test update only - TestSqlUpdateBindMultipleLists 2020-06-18 11:07:45 +12:00
rob bygrave 9b70900267 #2021 - Use smarter persistence context for findEach/iterate/stream queries - improve performance of un-tuned findEach/iterate/stream queries that invoke lazy loading 2020-06-17 21:50:11 +12:00
rob bygrave 0e33d58bb2 Bump ebean-maven-plugin to 12.3.4 2020-06-17 21:47:14 +12:00
rob bygrave 9d9d13060c #2020 - Fix potential connection leak in query-iterator WITH lazyLoadBufferSize (Refer #1164) 2020-06-17 17:10:16 +12:00
rob bygrave e071eecd59 Tidy test only - TestQueryFindEachWhile 2020-06-17 15:37:58 +12:00
rob bygrave bc8e254a65 Tidy tests - delete duplicate test TestQueryFindVisit.java 2020-06-17 13:31:18 +12:00
rob bygrave e0e369904c Tidy test only - TestQueryFindIterate 2020-06-17 13:30:34 +12:00
rob bygrave bd85ba17a1 No effective change - tidy TestQueryFindEach 2020-06-16 17:00:23 +12:00
rob bygrave 8801b8d8ca No effective change - tidy TestQueryFindEach 2020-06-16 16:55:49 +12:00
rob bygrave ebd6c535ab No effective change - tidy TestRawSqlParsing 2020-06-12 15:04:36 +12:00
rob bygrave 5c771a7219 Add tests for RawSql with ${where} and ${andWhere} placeholders 2020-06-12 15:03:05 +12:00
rob bygrave eb6f722385 Put back javadoc maven plugin 2020-06-09 20:03:47 +12:00
rob bygrave cef4f59b2c [maven-release-plugin] prepare for next development iteration 2020-06-08 21:58:31 +12:00
rob bygrave 67352ab3b2 [maven-release-plugin] prepare release ebean-12.3.3 2020-06-08 21:58:19 +12:00
rob bygrave 4a21395cda Comment out javadoc maven plugin temporarily 2020-06-08 21:56:07 +12:00
rob bygrave fcd7f8b6cf Bump ebean-maven-plugin 2020-06-08 20:00:22 +12:00
rob bygrave 4565719728 #2017 - ENH: Add option for different initialDelay to BackgroundExecutor.executePeriodically() 2020-06-05 18:31:07 +12:00
rob bygrave cbdf5609b2 #2015 - Dto instance id fields are not populated when queried using DtoQuery (and no select clause is specified) 2020-05-27 22:05:39 +12:00
rob bygrave f97359502b Refactor internals - DtoMeta DtoMappingRequest
Refactor move most of the code mapping DB columns to bean setters from DtoMeta to DtoMappingRequest
2020-05-27 22:04:03 +12:00
rob bygrave ffaf00c064 Improve error message throw on DTO unmapped DB column 2020-05-27 21:39:16 +12:00
rob bygrave f6f9511d2a #2014 - IllegalArgumentException: No rule for io.ebeaninternal.dbmigration.migration.RenameColumn 2020-05-27 21:00:42 +12:00
rob bygrave 5e94c26094 No effective change - update TestQueryInIdTypeConversion 2020-05-27 15:53:01 +12:00
rob bygrave 5aaed4e12b #2016 - L2 Cache - missing puts with explicit bean cache + findByIds/keys + after transaction writes 2020-05-26 23:42:44 +12:00
rob bygrave c29a57b5ec No effective change - update TestBeanCache Ebean -> DB 2020-05-26 23:19:23 +12:00
rob bygrave 998b8cc192 #2011 - Change query.orderBy() to not be deprecated 2020-05-15 14:06:28 +12:00
rob bygrave 9c1d930fb8 #2012 - Change ExpressionList.orderBy(String) to return ExpressionList<T>
Plus #2011 remove @Deprecated for orderBy
2020-05-15 14:06:06 +12:00
rob bygrave d6d7537a9c #2012 - Change ExpressionList.orderBy(String) to return ExpressionList<T> 2020-05-15 14:05:15 +12:00
rob bygrave 92e83c49d9 [maven-release-plugin] prepare for next development iteration 2020-05-12 22:39:42 +12:00
rob bygrave d758590da4 [maven-release-plugin] prepare release ebean-12.3.2 2020-05-12 22:39:31 +12:00
rob bygrave 21a5efa9b9 Tidy tests - tidy up TestCsvReader and TestCsvReaderWithCallback 2020-05-12 21:28:31 +12:00
rob bygrave 55a2cb12bb #2007 - Encrypted fields unable to be mapped when using DtoQuery 2020-05-12 21:11:28 +12:00
rob bygrave 293700acc0 #2007 - Encrypted fields unable to be mapped when using DtoQuery 2020-05-12 20:25:56 +12:00
rob bygrave 8980a3b6fd No functional change - tidy DbEncrypt, AbstractDbEncrypt 2020-05-12 16:34:08 +12:00
rob bygrave 72efc5d7d6 #2005 - Mark Ebean as deprecated - migrate to io.ebean.Database (EbeanServer -> Database) 2020-05-11 23:15:02 +12:00
rob bygrave 84589fcce6 Bump the versions of ebean-maven-plugin and maven-surefire-plugin 2020-05-11 23:09:24 +12:00
rob bygrave a0e44aedf3 Fix IllegalStateException to use correct dependency io.ebean:ebean-elastic in error message 2020-05-11 20:29:58 +12:00
rob bygrave 41102aca35 Add clearBatch() on BatchedPstmt construction 2020-05-08 23:32:24 +12:00
rob bygrave 548cea432e Fix test UpdateQueryTest for PG 2020-05-08 23:22:23 +12:00
rob bygrave 592cb37693 Reset test default to H2 2020-05-08 23:01:59 +12:00
rob bygrave f2178bf0a6 #2003 - Bump ebean-datasource to 4.9.2 with optional driver 2020-05-04 12:41:14 +12:00
rob bygrave 5cae425b09 #2002 - Support maxRows with delete query 2020-05-04 12:28:52 +12:00
rob bygrave 94b78f1c2d [maven-release-plugin] prepare for next development iteration 2020-04-30 23:41:07 +12:00
rob bygrave 561affef0f [maven-release-plugin] prepare release ebean-12.3.1 2020-04-30 23:40:56 +12:00
Rob BygraveandGitHub 3310d2186d Remove autoCommitMode and explicitTransactionBeginMode (#1993)
These are legacy options that we don't want anyone using going forward.
2020-04-30 23:36:24 +12:00
Rob BygraveandGitHub 02bdace144 Change OraclePlatform to default to use Identity (rather than sequence) (#1976)
* Change OraclePlatform to default to use Identity

- Keep Oracle11Platform to default to Sequence
- Refactor rename Oracle10Ddl to OracleDdl

* Change OraclePlatform to default to use Identity

- DDL review changes in src/test

* Bump ebean-test-docker for StartOracle
2020-04-30 23:35:20 +12:00
rob bygrave 7c17098f17 Bump pom version to 12.3.1-SNAPSHOT 2020-04-30 23:34:13 +12:00
rob bygrave 6f194ce95d #2001 - Add convenient alternative to set read-only url (on the main DataSourceConfig) 2020-04-30 23:19:08 +12:00
rob bygrave dbe473d5a1 #1996 - Fix for MySQLSyntaxErrorException when update in bulk using idIn(). 2020-04-30 21:33:02 +12:00
rob bygrave ed0e9e7006 #1999 - Additionally support empty string for read only url with config.isAutoReadOnlyDataSource() 2020-04-29 22:15:15 +12:00
rob bygrave 2a03198393 #1999 - Additionally support "none" for read only url
"none" can then be used as a special literal value in configuration for "no read-only jdbc url"
2020-04-29 22:07:27 +12:00
rob bygrave 6f1472abe0 #2000 - Tests only - bump sql server to 2019-GA-ubuntu-16.04 2020-04-28 22:13:57 +12:00
rob bygrave 6dea4f0890 #1996 - MySQLSyntaxErrorException when update in bulk. 2020-04-28 21:24:25 +12:00
rob bygrave 4a4ec42cdc #1999 - Refactor read-only DataSource initialisation 2020-04-28 21:10:43 +12:00
rob bygrave 92ea8e3738 #1998 - Refactor internals rename createQueryTransaction() to createReadOnlyTransaction() 2020-04-25 17:38:54 +12:00
rob bygrave c349832d35 #1997 - Modify @Transactional(readOnly=true) to use the read only DataSource 2020-04-25 17:33:33 +12:00
rob bygrave 90493ad57d #1995 - Fix for DatabaseConfig.isLocalOnlyL2Cache() ... to set localL2Caching = true
This has the effect that the l2 cache notification occurs in the foreground when isLocalOnlyL2Cache is true (not background)
2020-04-23 13:11:20 +12:00
rob bygrave 5012f59371 [maven-release-plugin] prepare for next development iteration 2020-04-21 23:01:48 +12:00
rob bygrave 149e63a272 [maven-release-plugin] prepare release ebean-12.2.6 2020-04-21 23:01:37 +12:00
rob bygrave d52a00a8fb #1995 - ENH: Add DatabaseConfig.isLocalOnlyL2Cache() ... to support disabling l2 cache plugins 2020-04-21 23:00:13 +12:00
rob bygrave f0dcec95dd [maven-release-plugin] prepare for next development iteration 2020-04-21 22:00:29 +12:00
rob bygrave 2653931881 [maven-release-plugin] prepare release ebean-12.2.5 2020-04-21 22:00:18 +12:00
rob bygrave 85207086e6 #1995 - ENH: Add DatabaseConfig.isLocalOnlyL2Cache() ... to support disabling l2 cache plugins 2020-04-21 21:55:51 +12:00
rob bygrave d0b0b02d6a [maven-release-plugin] prepare for next development iteration 2020-04-15 08:47:38 +12:00
rob bygrave 34fa1def77 [maven-release-plugin] prepare release ebean-12.2.4 2020-04-15 08:47:26 +12:00
rob bygrave 9f1aa958fc Bump ebean-maven-plugin 2020-04-15 08:35:24 +12:00
rob bygrave cdc5eefc69 EntityBeanIntercept.isOrphanDelete() - Additional refactor for #1988 2020-04-14 23:17:56 +12:00
Jonas PöhlerandGitHub c9588586c9 Removing elements with @OrderColumn with a tree depth > 1 doesn't work (#1988)
* ADD: failing testcase for orderColumn when tree depth > 1

* FIX: no update with @OrderColumn on treeDepth > 1 and avoid needless updates

* ADD: failing testcase for removing models in oneToMany relation with @OrderColumn

Signed-off-by: Jonas Pöhler (JPo) <jonas.poehler@foconis.de>

* ADD: failing test for faulty element reordering in a entityBean tree with version

Signed-off-by: Jonas Pöhler (JPo) <jonas.poehler@foconis.de>

* FIX: incorrect behaviour when reordering or removing elements from collection with @OrderColumn.

Signed-off-by: Jonas Pöhler (JPo) <jonas.poehler@foconis.de>
2020-04-14 23:07:00 +12:00
rob bygrave 52735179d9 Bump maven plugin 2020-04-14 22:44:46 +12:00
rob bygrave cef1fb9e80 #1992 - IllegalArgumentException: Expecting only yaml or properties file but got [ort] 2020-04-14 22:42:26 +12:00
rob bygrave c7e1964aae #1991 - NPE in MCompoundUniqueConstraint.<init>(MCompoundUniqueConstraint.java:66) 2020-04-14 21:28:03 +12:00
rob bygrave 6d43883f77 #1990 - NPE with @Cache and setting naturalKey to null 2020-04-14 20:57:42 +12:00
rob bygrave f06f99dfc3 Refactor remove unnecessary BeanDescriptorManager.setProfileIds() method
As it is no longer necessary (profileIds no longer used)
2020-04-12 17:13:54 +12:00
rob bygrave 41e600be45 Merge branch 'bugfix/order_column_l1_cache' of https://github.com/FOCONIS/ebean into FOCONIS-bugfix/order_column_l1_cache 2020-04-12 16:37:00 +12:00
Rob BygraveandGitHub 62a81c531a Merge pull request #1986 from FOCONIS/bugfix/order_column_reference_abstract
@OrderColumn is ignored on relations referencing a abstract inheritance-model
2020-04-12 16:32:15 +12:00
Rob BygraveandGitHub 2cb1a626c4 Merge pull request #1985 from FOCONIS/bugfix/order_column_tree_depth
Update is missing for relations with @OrderColumn from a tree depth > 1
2020-04-12 16:19:01 +12:00
Jonas Pöhler (JPo) 18cde36b9d FIX: cache not being cleared in persistence context on reorder with @OrderColumn
Signed-off-by: Jonas Pöhler (JPo) <jonas.poehler@foconis.de>
2020-04-08 16:05:09 +02:00
Jonas Pöhler (JPo) e05b6b78ad ADD: failing testcase for not cleared beancache in persistence context on reorder with @OrderColumn
Signed-off-by: Jonas Pöhler (JPo) <jonas.poehler@foconis.de>
2020-04-08 16:04:49 +02:00
rob bygrave 58c49deb06 [maven-release-plugin] prepare for next development iteration 2020-04-08 14:59:42 +12:00
rob bygrave 4a41e88162 [maven-release-plugin] prepare release ebean-12.2.3 2020-04-08 14:59:30 +12:00
rob bygrave 2e5becf48c Refactor rename to MySqlDataTimeZone and OracleDataTimeZone 2020-04-08 14:57:58 +12:00
rob bygrave 4094339407 #1984 - ENH: Add DB.script() ... to access ScriptRunner from DB 2020-04-08 14:13:57 +12:00
rob bygrave bf24949efb #1982 - conflict with eureka config generate StringIndexOutOfBoundsException with 12.2.1 version 2020-04-08 13:49:13 +12:00
Jonas Pöhler (JPo) 3b4549a7ee FIX: @OrderColumn not working when referencing the parent of a inheritance structure 2020-04-06 16:22:33 +02:00
Jonas Pöhler (JPo) f194fdb132 ADD: failing testcase for @OrderColumn working when referencing the parent of a inheritance structure 2020-04-06 16:08:21 +02:00
Jonas Pöhler (JPo) 2d274c46fa FIX: no update with @OrderColumn on treeDepth > 1 and avoid needless updates 2020-04-06 15:34:43 +02:00
Jonas Pöhler (JPo) b61e9af750 ADD: failing testcase for orderColumn when tree depth > 1 2020-04-06 15:14:23 +02:00
rob bygrave a01362abad #1980 Remove the volatile that was added for NPE in EntityBeanIntercept 2020-03-25 22:03:52 +13:00
Rob BygraveandGitHub 4387c662b6 Merge pull request #1981 from tobias-/issue_1980_NPE
Use temp variable to avoid NPE race
2020-03-25 21:06:00 +13:00
Tobias ecdd027b3e Use temp variable to avoid NPE race
resolve #1980
2020-03-25 07:01:32 +01:00
rob bygrave 2b0f572f4d [maven-release-plugin] prepare for next development iteration 2020-03-25 16:15:44 +13:00
rob bygrave 0a1704e6a9 [maven-release-plugin] prepare release ebean-12.2.2 2020-03-25 16:15:32 +13:00
rob bygrave 854c208f92 Bump ebean-maven-plugin 2020-03-25 15:55:57 +13:00
rob bygrave e6f604764c #1980 - NullPointerException in EntityBeanIntercept 2020-03-25 15:54:16 +13:00
Rob BygraveandGitHub 9b501b3dc8 Merge pull request #1979 from FOCONIS/bugfix/order_column_on_inheritance_model
@OrderColumn does not work on inheritance models
2020-03-23 22:28:57 +13:00
Jonas PöhlerandGitHub c2fb23a25c "insert into table default values" is invalid MySQL syntax (#1978)
* ADD: failing testcase for "insert into table default values;" is invalid MySql syntax

* FIX: "insert into table default values;" is invalid MySql syntax
2020-03-23 22:09:28 +13:00
Jonas Pöhler (JPo) 1ad7ace9bd FIX: error with @OrderColumn on model with inheritance 2020-03-20 10:22:16 +01:00
Jonas Pöhler (JPo) 6a3a7eafea ADD: failing testcase for @OrderColumn on model with inheritance 2020-03-20 10:20:52 +01:00
rob bygrave 896aed0b38 No effective change - change to avaje-jsr305 2020-03-17 22:38:05 +13:00
rob bygrave f7359aacd7 No effective change - update tests for oracle ddl 2020-03-17 22:25:52 +13:00
rob bygrave d77fb9265b No effective change - update oracle ddl review 2020-03-17 22:25:04 +13:00
rob bygrave db27844eca [maven-release-plugin] prepare for next development iteration 2020-03-13 09:28:33 +13:00
rob bygrave 61be1683b2 [maven-release-plugin] prepare release ebean-12.2.1 2020-03-13 09:28:23 +13:00
rob bygrave 27a1f35356 Bump ebean-maven-plugin to 12.2.1 2020-03-12 23:46:40 +13:00
rob bygrave f0c0b7ebcc #1974 - Turn on by default loadModuleInfo - aka auto register entity beans using query bean generated code 2020-03-12 23:45:35 +13:00
rob bygrave f4c646cdc1 Bump pom to 12.2.1-SNAPSHOT 2020-03-10 23:00:10 +13:00
rob bygrave 48abc73e50 #1973 - L2Cache, Inheritance and Lazy-Loading loads the parent Class not the Child 2020-03-10 22:52:13 +13:00
rob bygrave 91a327a5e7 #1972 - Change BigDecimal to map by default DB type DECIMAL(16,3) rather than DECIMAL(38) 2020-03-09 17:05:08 +13:00
Rob BygraveandGitHub a861e8bdcc Remove reading mapping annotations from "Getters" with associated refactoring for performance (#1971)
* #1970 - Change test code only moving mapping annotations to fields

First step in remove support for mapping annotations on "Getters" (so field only target for mapping annotations)

* #1970 - Remove reading mapping annotations from "Getters"

* #1970 - Refactor to use simple annotation lookup where possible

* #1970 - Remove GenerationType.TABLE and SequenceGenerator from type/class

* #1970 - Refactor meta annotation reading

* #1970 - Read @Aggregation as a meta annotation
2020-03-09 16:09:41 +13:00
Rob BygraveandGitHub 7692d9782a Merge pull request #1968 from ebean-orm/feature/refactorRenameTxnBatchMethods
Refactor rename Transaction methods - setBatchGetGeneratedKeys(), setBatchFlushOnMixed() setBatchFlushOnQuery() ... (remove the "batch" part)
2020-03-05 09:31:13 +13:00
rob bygrave 524e3e31f0 Refactor rename Transaction setGetGeneratedKeys(), setFlushOnMixed() setFlushOnQuery() ... (remove the "batch" part) 2020-03-05 01:10:41 +13:00
rob bygrave d69d96a400 #1967 - Refactor internals reverse default columnAliasPrefix to null from "c" 2020-03-05 00:56:22 +13:00
rob bygrave 0ce39c73f1 Test only update postgres DDL review 2020-03-05 00:21:36 +13:00
rob bygrave 82d6294dcb Test only update h2 DDL review 2020-03-05 00:13:41 +13:00
rob bygrave ba01103f48 #1965 @Identity with sequence ddl generation 2020-03-05 00:13:08 +13:00
Rob BygraveandGitHub 3e14ec6a5a Merge pull request #1965 from ebean-orm/feature/identityMode2
Support for @Identity - with cache, generated by (ALWAYS/BY DEFAULT), start, increment options
2020-03-04 22:56:44 +13:00
rob bygrave b9d5d35850 Set testing default back to H2 2020-03-04 22:55:51 +13:00
rob bygrave 04adc35ccd Support for @Identity - Fix sequence name propagation 2020-03-04 22:49:08 +13:00
rob bygrave bfc2b57df5 Support for @Identity - use identity options with sequence 2020-03-04 21:29:56 +13:00
rob bygrave a5880fca97 Support for @Identity - update sql server ddl review 2020-03-04 21:23:50 +13:00
rob bygrave 8685f2056a Support for @Identity - update ddl review 2020-03-04 17:18:01 +13:00
rob bygrave 2ac19bea1a Support for @Identity - with start, increment, cache 2020-03-04 16:59:42 +13:00
rob bygrave 9410f82f5a Support for @Identity - update default sequence increment 2020-03-03 22:36:59 +13:00
rob bygrave 21382a52ed Support for @Identity - split IdentityMode and DeployIdentityMode 2020-03-03 22:36:27 +13:00
rob bygrave f871259f20 Support for @Identity - split IdentityMode and DeployIdentityMode 2020-03-03 22:36:27 +13:00
rob bygrave eb765056fd Support for @Identity - initial refactor to add IdentityMode 2020-03-03 22:36:27 +13:00
rob bygrave ddf3c753d6 Ability to use order(<orderByClause>) on filterMany() (related to #1943) #1964 2020-03-03 22:31:01 +13:00
rob bygrave 4767aff046 Test only update sql server DDL review 2020-03-03 22:03:24 +13:00
rob bygrave 75846edd97 Test only update H2 DDL review 2020-03-03 21:20:19 +13:00
rob bygrave f7c6745de1 Ci Testing - remove test/resources/dbmigration/migrationtest/postgres9 2020-03-01 13:09:37 +13:00
rob bygrave f080f16e63 #1962 - Refactor simplify Postgres platforms to POSTGRES and POSTGRES9 2020-03-01 12:53:34 +13:00
rob bygrave 9135f87253 CI Testing - ParentQueryTest cascade on parent.data 2020-03-01 12:42:03 +13:00
rob bygrave 90ccf2d8b4 CI Testing - ParentQueryTest cascade on parent.data 2020-03-01 12:29:54 +13:00
rob bygrave 11409f8c09 CI Testing - ParentQueryTest cascade on parent.data 2020-03-01 12:23:16 +13:00
rob bygrave fb472a0304 CI Testing - ParentQueryTest truncate 2020-03-01 12:12:01 +13:00
rob bygrave 04c9007d22 CI Testing - Update travis to not both with oraclejdk8 which is no longer available 2020-03-01 11:55:31 +13:00
rob bygrave 8f75a04ad0 CI Testing - Update travis to xenial & postgresql: 10 2020-03-01 11:45:56 +13:00
Rob BygraveandGitHub 2236e4bfd7 Refactor PlatformDdl separate call to asIdentityColumn() (#1961) 2020-03-01 10:42:41 +13:00
rob bygrave 6d1c3738de #1960 - CVEs - Update postgresql and h2 jdbc drivers (provided scope only) 2020-02-28 16:22:48 +13:00
rob bygrave 20160144f5 No effective change - remove unused snakeyaml.version from pom 2020-02-22 14:42:00 +13:00
rob bygrave 891166507d Test only - restore postgres9 and postgres10 migration resources for CI postgres 2020-02-22 13:36:33 +13:00
rob bygrave bce97b1063 Test only - add dummy files for pg9 and pg10 DbMigrationTest for running on CI (with old postgres) 2020-02-22 12:54:16 +13:00
Rob BygraveandGitHub c5b960c588 Merge pull request #1959 from ebean-orm/feature/1955
#1953 - Do we need SqlServer2005Platform and SqlServer2005SqlLimiter?
2020-02-22 12:47:13 +13:00
rob bygrave 009b400ed3 Test only - delete test/resources/dbmigration/migrationtest/postgres10 and postgres9 2020-02-22 12:45:07 +13:00
rob bygrave b6ee6ade8c Test only - update ddl review for postgres 2020-02-22 12:44:00 +13:00
rob bygrave 0891c067d5 #1953 - Do we need SqlServer2005Platform and SqlServer2005SqlLimiter? 2020-02-22 11:48:16 +13:00
Rob BygraveandGitHub 7b3b32f0ff Merge pull request #1957 from ebean-orm/feature/1955
#1955 #1956  SqlQuery.mapToScalar() and SqlQuery.mapTo(RowMapper)
2020-02-22 11:25:48 +13:00
rob bygrave 3878b02cff #1956 - Add SqlQuery - mapTo( RowMapper) ... to deprecate findOne(RowMapper) 2020-02-22 10:50:23 +13:00
rob bygrave 92995b807e #1955 - mapToScalar - Add SqlQuery.mapToScalar( <class> ).findOne() / findList() ... to deprecate findSingleAttribute() 2020-02-22 10:09:44 +13:00
Rob BygraveandGitHub 907d36123d OraclePlatform update (ANSI row limiting with OFFSET), Oracle11Platform for old behaviour (#1951)
* #1947 - Oracle change to use concat operator rather than function

* #1947 - setMaxRows(1).findIds() under Oracle returns wrong result

* #1950 - Change OraclePlatform to use ANSI row limiting - OFFSET and NEXT ROWS, old platform as Oracle11Platform

* Revert test default to H2

* #1947 - Oracle & Oracle11 platform
2020-02-22 09:28:34 +13:00
Rob BygraveandGitHub 2db95f909d Merge pull request #1944 from ebean-orm/feature/1943
#1943 - Use limit & offset via setFirstRow() and setMaxRows() on filterMany()
2020-02-22 09:26:03 +13:00
rob bygrave 5213e8b653 Fix test merge for StartPostgres9 - using int for port 2020-02-22 09:24:58 +13:00
Rob BygraveandGitHub 2314fd267f Split Postgres platform into Postgres10 & Postgres9 (DDL - generated by default as identity) (#1921)
* Split Postgres platform into Postgres10 & Postgres9

- Use "generated by default as identity" for Postgres10 identity columns

* Add postgres9 migrationtest resources

* Set default back to h2

* Add postgres10 migration test resources
2020-02-22 09:18:05 +13:00
Rob BygraveandGitHub b24f093bbb Remove io.ebean.meta.MetricType as it is unnecessary (#1923) 2020-02-22 09:17:14 +13:00
Rob BygraveandGitHub 444c868124 Refactor to use avaje config (#1894)
* Move to use Avaje Config for properties loading
2020-02-22 09:11:37 +13:00
rob bygrave 81b16b8f73 [maven-release-plugin] prepare for next development iteration 2020-02-22 08:59:33 +13:00
rob bygrave 850db70be3 [maven-release-plugin] prepare release ebean-12.1.13 2020-02-22 08:59:20 +13:00
rob bygrave ee81ee4d7c test only update of ddl review for mysql-create-all.sql 2020-02-22 08:50:32 +13:00
Rob BygraveandGitHub 4cbeb282eb Merge pull request #1954 from boeckers/added_MySqlDbExpression.json
Add JSON expression handing for MySql - MySqlDbExpression.json
2020-02-22 08:40:09 +13:00
Michael Böckers 5278c010ba added MySqlDbExpression.json 2020-02-21 12:58:18 +01:00
rob bygrave ea490a5ac3 Collect the DB schemas in the model via MTable 2020-02-21 17:16:28 +13:00
rob bygrave e4390ed8a2 #1952 - Entity bean with @Id and ONLY @WhenCreated treated as reference bean - not inserted 2020-02-21 00:14:23 +13:00
Rob BygraveandGitHub a23d9f7db8 Merge pull request #1949 from sebastianmrozek/master
Test usingDatabase with a non default db
2020-02-20 22:43:53 +13:00
Sebastian Mrozek b1704ff5dc Test usingDatabase with a non default db
Move the test to separate class with better name.
2020-02-20 22:13:38 +13:00
rob bygrave c0d752b445 #1941 - @History it seems does not work well when it got generated with ebean.allQuotedIdentifiers enabled 2020-02-20 16:51:07 +13:00
Rob BygraveandGitHub ef5ea59559 Merge pull request #1948 from ebean-orm/feature/queryUsingDatabase
ENH: Add query.usingDatabase(database)
2020-02-20 16:42:25 +13:00
rob bygrave de42655bbd Refactor tests using assertSql() helper method
This helper method trims column alias from the sql (for Oracle)
2020-02-20 15:08:43 +13:00
rob bygrave 661230909c ENH: Add query.usingDatabase(database) - add better test 2020-02-19 11:48:47 +13:00
rob bygrave e9325a81f7 ENH: Add query.usingDatabase(database) 2020-02-19 11:41:06 +13:00
Rob BygraveandGitHub 78b9066345 Merge pull request #1946 from ebean-orm/feature/orderByDeprecate
Deprecate orderBy() migrate to order()
2020-02-19 10:00:15 +13:00
rob bygrave 1959e01844 Javadoc update only - change server to database in examples 2020-02-18 23:43:39 +13:00
rob bygrave cf6179c86b Deprecate orderBy() migrate to order() - update javadoc 2020-02-18 23:36:48 +13:00
rob bygrave 168dacffa7 Deprecate orderBy() migrate to order() 2020-02-18 23:27:43 +13:00
rob bygrave e0d322d80a #1943 - Return ExpressionList<T> from setMaxRows() setFirstRow() to allow fluid style
This is to allow fluid style use of setMaxRows() setFirstRow() with filterMany query
2020-02-17 17:19:27 +13:00
rob bygrave 1dd0f3cbf8 #1943 - Use limit & offset via setFirstRow() and setMaxRows() on filterMany() 2020-02-17 17:05:01 +13:00
rob bygrave 6961bf5787 #1945 - ENH: Add query.orderById(boolean) to ExpressionList ... improve fluid style 2020-02-17 16:47:37 +13:00
rob bygrave a14288b06d Refactor tidy DefaultExpressionList, no functional change 2020-02-17 16:40:03 +13:00
rob bygrave 171d1a19f4 #1937 - When add a new col with @DbComment in Entity,the DbMigration does not generate comment ddl 2020-02-17 14:19:19 +13:00
rob bygrave cbaaad89ab #1942 - Bump datasource to 4.7.3, includes - datasource.offline() closes busy connections ... should let them close on return 2020-02-17 11:51:40 +13:00
Rob BygraveandGitHub 413290a040 Merge pull request #1939 from ebean-orm/feature/1938
#1938 - API consistency add setParameters(varargs) & setParameter() - migrate from setNextParameter() and setParams()
2020-02-17 11:37:34 +13:00
rob bygrave 8feb100ac6 #1938 - API consistency add setParameters(varargs) & setParameter() - migrate from setNextParameter() and setParams() 2020-02-15 02:01:02 +13:00
rob bygrave d236988035 [maven-release-plugin] prepare for next development iteration 2020-02-09 22:23:59 +13:00
rob bygrave df0d84424c [maven-release-plugin] prepare release ebean-12.1.12 2020-02-09 22:23:48 +13:00
rob bygrave fb30a15a5b Update to ebean-maven-plugin 12.1.12 2020-02-09 22:21:14 +13:00
rob bygrave 3707d611b1 No effective change - EBasicVer extend Model 2020-02-07 22:07:38 +13:00
rob bygrave 60aa720777 No effective change - javadoc format SpiTransaction 2020-02-07 20:53:08 +13:00
rob bygrave 427152a894 Add test for IllegalStateException("Transaction is Inactive") 2020-02-07 20:15:59 +13:00
rob bygrave 3e43d544fb #1936 - ENH: Add saveAll(Object... beans) ... using varargs for DB and Database 2020-02-07 16:10:11 +13:00
rob bygrave 62b1da1be2 #1935 - ENH: Add DB.createTransaction() 2020-02-07 15:52:26 +13:00
rob bygrave 8b4eae2f91 #1934 - ENH: Add methods to Model that take explicit transaction - save(transaction), delete(transaction) ... 2020-02-07 13:00:59 +13:00
rob bygrave 4ed3a18b9d #1933 - ENH: Add DtoQuery.usingTransaction(Transaction) ... dto query with supplied transaction 2020-02-07 12:42:10 +13:00
Rob BygraveandGitHub 3c9d7e3127 Merge pull request #1925 from ebean-orm/feature/refatorTxnProfile
#1924 - Refactor for Transaction profiling - base on ProfileLocation / remove profileId
2020-02-04 22:38:44 +13:00
rob bygrave a89744a7bd No functional change - fix error message in DataSourceConfigurationException throw by Ebean 2020-02-03 22:34:10 +13:00
Rob BygraveandGitHub 5962f14874 Merge pull request #1928 from ebean-orm/feature/1755
FIX: Regression of #1775 - set date for other platforms (non MySQL) broken, when ebean.dataTimeZone is set to GMT
2020-02-01 16:03:33 +13:00
Roland Pramlandrob bygrave f161a38334 FIX: Regression of #1775 - set date for other platfroms broken, when ebean.dataTimeZone is set to GMT 2020-02-01 15:59:18 +13:00
Roland Pramlandrob bygrave 13f8da6b2e FIX: Add cause to exception 2020-02-01 14:07:09 +13:00
rob bygrave 9ad14c5306 #1926 - Postgres (Multi value bind) fix related to empty idIn() expression 2020-02-01 14:05:12 +13:00
rob bygrave 61ed4a5a74 Merge branch 'master' of github.com:ebean-orm/ebean 2020-02-01 13:51:48 +13:00
Rob BygraveandGitHub 275f2dbc98 Merge pull request #1927 from ebean-orm/foconis-cache-emptylist
Fix cache emptylist and Fix / improvement for UUIDv1Generator mac address detection
2020-02-01 13:51:25 +13:00
Roland Pramlandrob bygrave 521b6a36ef changed ip.ebeaninternal.api.SpiQuery to io.ebean.Query in Server.exists 2020-02-01 13:46:28 +13:00
Roland Pramlandrob bygrave 0a6c26e5d3 FIX: Virtual Prüfung 2020-02-01 13:38:56 +13:00
Roland Pramlandrob bygrave 33416bffd0 FIX: Detecting MAC address improved 2020-02-01 13:38:44 +13:00
Roland Pramlandrob bygrave 4ce484f3f2 FIX: Cache also empty lists 2020-02-01 13:38:21 +13:00
rob bygrave cacf033647 Merge branch 'foc-imports' 2020-02-01 13:18:55 +13:00
rob bygrave e3dba6bfe1 Failing test for idIn() empty 2020-02-01 13:18:42 +13:00
Roland Pramlandrob bygrave c0b6f291a1 FIX: handle empty collection in "in (...)" queries 2020-02-01 13:06:37 +13:00
rob bygrave 9eab67d82e #1924 - Refactor for Transaction profiling - base on ProfileLocation / remove profileId 2020-02-01 11:31:43 +13:00
rob bygrave 840cb2ee7b [maven-release-plugin] prepare for next development iteration 2020-01-30 18:53:46 +13:00
rob bygrave e0f171b638 [maven-release-plugin] prepare release ebean-12.1.11 2020-01-30 18:53:35 +13:00
rob bygrave 2bb52a9581 #1922 - Performance - Too pessimistic synchronized block for lazy loading on reference bean or l2 cache bean 2020-01-30 18:48:39 +13:00
Rob BygraveandGitHub f1cf94365c Merge pull request #1920 from ebean-orm/feature/createIndexConcurrently
ENH: Add support for Postgres create index concurrently
2020-01-29 20:36:44 +13:00
rob bygrave a894924e96 #1920 Support @Index concurrently and definition 2020-01-29 20:22:32 +13:00
rob bygrave 680a11a532 No effective change - postgres ddl review update 2020-01-29 16:54:23 +13:00
rob bygrave 605150de5c Update ebean-migration to 12.1.3 with support for Postgres create index concurrently 2020-01-29 11:29:29 +13:00
rob bygrave 5ff44703cf [maven-release-plugin] prepare for next development iteration 2020-01-28 14:01:58 +13:00
rob bygrave 99175bf679 [maven-release-plugin] prepare release ebean-12.1.10 2020-01-28 14:01:47 +13:00
rob bygrave acff330b37 #1918 - Ebean 12.1.9 breaks Guice in Stage.PRODUCTION mode for multi tenant apps 2020-01-28 12:07:07 +13:00
rob bygrave df63eeaa8c #1915 - Regression with DiscriminatorValue since #1361 2020-01-28 10:21:29 +13:00
rob bygrave 07aa39c5de #1917 - PostgresPlatform (9+) does not support IdType.IDENTITY? 2020-01-28 09:46:24 +13:00
Rob BygraveandGitHub c51a1b07a4 Merge pull request #1914 from ebean-orm/feature/indexPlatform
ENH: Support @Index platforms attribute - platform specific indexes
2020-01-16 09:23:28 +13:00
rob bygrave bb56725b12 Use unique index rather than constraint when using formula [like lower(column)] 2020-01-15 16:58:55 +13:00
rob bygrave 099adcf6cd Refactor tidy ModelBuildPropertyVisitor - no functional change 2020-01-15 15:52:37 +13:00
rob bygrave 05be24b8b2 ENH: Support @Index platforms attribute - platform specific indexes
This is a potential alternative to using extra-dll.xml. Might be
appropriate to use over extra-dll in small simple cases.

We might look to extend this in the future to allow full raw platform specific ddl - the ability to specify the entire create index statement.
2020-01-15 15:47:14 +13:00
Rob BygraveandGitHub 7d98355d39 Merge pull request #1913 from ebean-orm/feature/MaxMin
Change to use @Aggregation as meta annotation - support newly added @Max, @Min, @Avg annotations
2020-01-14 16:41:44 +13:00
rob bygrave 56562915bf #1912 - Allow @Index(unique=true) to support formula in columns 2020-01-14 16:20:02 +13:00
rob bygrave 07f4ad2500 Change to use @Aggregation as meta annotation - support newly added @Max, @Min, @Avg annotations 2020-01-14 16:14:14 +13:00
rob bygrave 22e43f5fa7 [maven-release-plugin] prepare for next development iteration 2020-01-11 00:01:01 +13:00
rob bygrave 3127bc2154 [maven-release-plugin] prepare release ebean-12.1.9 2020-01-11 00:00:50 +13:00
Rob BygraveandGitHub 8aa1ed6676 Merge pull request #1909 from ebean-orm/feature/mySqlJson
For MySql map @DbJson to mysql JSON db type
2020-01-10 23:59:18 +13:00
rob bygrave 8a0dea1218 #1910 - Change javadoc generation to no longer use pygments doclet (code highlighting) 2020-01-10 23:37:19 +13:00
rob bygrave 1e266a1532 #1895 - Ebean creates invalid sql for particular @ManyToOne 2020-01-10 23:32:58 +13:00
rob bygrave 57cfd25eb5 #1903 - Add ability to set migration path via DbMigration 2020-01-10 16:06:18 +13:00
rob bygrave 2bcce2e648 For MySql map @DbJson to mysql JSON db type 2020-01-10 14:48:26 +13:00
rob bygrave f6e45a6999 For MySql map @DbJson to mysql JSON db type 2020-01-10 14:39:55 +13:00
rob bygrave fa3de7158e No effective change - update mysql ddl review in src/test/ddl-review 2020-01-10 14:15:50 +13:00
rob bygrave 792785dabe Fix for #1902 #1908 - change allowing view based entities to be autoTunable 2020-01-10 14:02:12 +13:00
Rob BygraveandGitHub d0cd74b400 Merge pull request #1908 from FOCONIS/test-setdefaultselectclause
Testcase for #1902
2020-01-10 13:41:24 +13:00
rob bygrave 71d762ab97 #1907 - SQL Server DB Migration for uuid property @NotNull - should drop index before drop constraint 2020-01-10 13:09:11 +13:00
Roland Praml e00713aa29 Testcase for #1902 2020-01-10 01:03:38 +01:00
rob bygrave d70a49e105 No effective change - refactor tidy DefaultOrmQuery 2020-01-10 12:55:05 +13:00
Roland Pramlandrob bygrave 159a9a8e54 #1902 - SingleAttributeQueries with child selection only does not work with autoTune=false (e.g. Views) 2020-01-10 12:49:20 +13:00
rob bygrave db027eb030 #1904 - Bump datasource to 4.7.1 2020-01-09 15:19:17 +13:00
rob bygrave ec55b2f096 Refactor for query plan capture with initial threshold micros - part 3
Use QueryPlanInit
2019-12-24 02:02:11 +13:00
Rob BygraveandGitHub b854943a86 Merge pull request #1899 from ebean-orm/feature/queryPlanCapture
Refactor for query plan capture with initial threshold micros
2019-12-24 00:54:37 +13:00
rob bygrave 8a263d243c Refactor for query plan capture with initial threshold micros - part 2 2019-12-24 00:29:46 +13:00
Rob BygraveandGitHub 0a4f93adc5 #1897 - Indexes names, like index, unique, primary and foreign keys does not honor ebean.allQuotedIdentifiers (#1898) 2019-12-23 18:43:41 +13:00
rob bygrave ffb11019fa #1896 - ebean.allQuotedIdentifiers is ignored for @JoinColumn 2019-12-23 13:30:28 +13:00
rob bygrave 6fcac27dfe Refactor for query plan capture with initial threshold micros 2019-12-23 10:28:08 +13:00
rob bygrave 71295077a5 [maven-release-plugin] prepare for next development iteration 2019-12-17 23:44:36 +13:00
rob bygrave ddbad284ad [maven-release-plugin] prepare release ebean-12.1.8 2019-12-17 23:44:25 +13:00
rob bygrave 1fcec429b0 #1893 - @DbArray with @NotNull ... should persist empty db array rather than fail NOT NULL constraint 2019-12-17 20:33:03 +13:00
rob bygrave c6062fe93e #1893 - @DbArray with @NotNull ... should persist empty db array rather than fail NOT NULL constraint 2019-12-17 20:27:53 +13:00
rob bygrave d8d35b7dd9 #1893 - Failing test for @DbArray with @NotNull 2019-12-17 16:42:09 +13:00
rob bygrave 590cd07d67 #1892 - Refactor change internal use of Ebean to DB 2019-12-13 14:20:51 +13:00
rob bygrave 5cd74bc468 #1892 - Refactor change internal use of Ebean to DB 2019-12-13 14:17:05 +13:00
rob bygrave 502b20be67 #1891 - Deprecate createSqlQuery() ... migrate to sqlQuery() 2019-12-13 13:58:14 +13:00
rob bygrave b3077d44f6 #1890 - Deprecate createSqlUpdate() ... migrate to sqlUpdate() 2019-12-13 13:48:53 +13:00
rob bygrave d4b35cb445 #1889 - NPE at Str.java:16) when using DB.sqlUpdate(...).addBatch() without any bind parameters 2019-12-13 13:35:54 +13:00
rob bygrave 91e7540a39 #1888 - Bump ebean-migration 12.1.2 with updated avaje classpath scanner 2019-12-13 13:06:13 +13:00
rob bygrave 06bd60aaf7 Bump to 12.1.8-SNAPSHOT to align version with query bean generator 2019-12-13 12:42:42 +13:00
rob bygrave 3db2a69312 #1885 - ENH: Add ModuleInfoLoader ... to support automatic registration of entity classes (via generated code using querybean generator) 2019-12-12 01:33:27 +13:00
rob bygrave 5a983b9e0d No effective change - fix spelling in comments 2019-12-11 23:22:30 +13:00
rob bygrave ab7b34779a [maven-release-plugin] prepare for next development iteration 2019-12-06 20:22:43 +13:00
rob bygrave c7aad6078e [maven-release-plugin] prepare release ebean-12.1.6 2019-12-06 20:22:33 +13:00
rob bygrave ccfe9c39cd Bump enhancement plugin 2019-12-06 20:19:17 +13:00
rob bygrave dbdac04883 Add more tests for cascade save on tree structure 2019-12-06 20:18:50 +13:00
rob bygrave 1d369c002d #1880 - Change javadoc references from Cdir to Cidr 2019-12-05 21:20:19 +13:00
rob bygrave 5a1be81603 #1881 - Update Postgres init helper procedures for DB table partitions 2019-12-05 20:10:15 +13:00
rob bygrave dee73da1aa Drop travis Postgres back to 9.6 2019-12-05 17:22:39 +13:00
rob bygrave a7dde87c5f Bump travis to Postgres 11.2 maybe ? 2019-12-05 17:20:23 +13:00
rob bygrave 60fadd448d Bump travis to Postgres 11 2019-12-05 17:12:58 +13:00
rob bygrave 0140d09007 Update tests to use io.avaje:mod-uuid 2019-12-05 10:32:19 +13:00
rob bygrave da5604a38d #1880 - Cidr type stored as INET (instead of CIDR) + named as Cdir (typo) 2019-12-05 08:59:39 +13:00
rob bygrave 937df1395c #1882 - ENH: Add JsonContext.toJsonPretty() ... for pretty JSON output of beans and lists of beans 2019-12-04 22:55:52 +13:00
rob bygrave 89c05007c2 #1881 - Update Postgres init helper procedures for DB table partitions 2019-12-04 22:07:05 +13:00
rob bygrave 4cc9278183 Update review ddl for Postgres 2019-12-04 21:29:58 +13:00
rob bygrave 9841a2c03a #1880 - Cidr type stored as INET (instead of CIDR) + named as Cdir (typo) 2019-12-04 21:28:27 +13:00
rob bygrave 74929472d9 #1879 - For metrics reporting for timed metrics with location by default only report on initial collection 2019-12-03 23:53:13 +13:00
rob bygrave e274a4c512 #1878 - Remove metric type from metric json output 2019-12-03 21:06:13 +13:00
rob bygrave 5d93c44475 #1877 - Adjust metric names add "orm." prefix for orm queries, "dto." for dto queries 2019-12-03 21:01:03 +13:00
rob bygrave 63b802d0b8 [maven-release-plugin] prepare for next development iteration 2019-12-03 10:19:47 +13:00
rob bygrave 1d7e751b60 [maven-release-plugin] prepare release ebean-12.1.5 2019-12-03 10:19:37 +13:00
rob bygrave 5f8690fb87 #1876 - findMap() does not use/hit natural key cache 2019-12-02 18:37:42 +13:00
rob bygrave e093675444 #1875 - Refactor simplify MetaTimedMetric removing unrequired getStartTime() and getBeanCount() 2019-11-29 23:42:00 +13:00
Rob BygraveandGitHub a04594540c #1873 - Refactor metrics reporting and collection, simplify removing MetricOrmQueryNode, MetricOrmQueryOrigin (#1874)
* #1873 - Refactor metrics reporting and collection, simplify removing MetricOrmQueryNode, MetricOrmQueryOrigin

* #1873 - fix test
2019-11-29 23:35:21 +13:00
rob bygrave 269f2de333 #1872 - Reporting ORM metrics defaults to suppressing sql and location after initial collection 2019-11-29 22:15:51 +13:00
rob bygrave be12910aec #1872 - Reporting ORM metrics defaults to suppressing sql and location after initial collection 2019-11-29 22:05:58 +13:00
rob bygrave 996e582a85 No effective change - add simple UnderscoreNamingConvention tests 2019-11-29 21:03:44 +13:00
rob bygrave aa4c6b7889 No effective change - add simple UnderscoreNamingConvention tests 2019-11-29 21:01:23 +13:00
rob bygrave 27a4e8951d #1870 - Whether DtoMeta.findproperty needs to add is prefix 2019-11-29 20:54:28 +13:00
rob bygrave 1fc4082abe #1869 - out of order nextId() sequence generation 2019-11-29 19:58:12 +13:00
rob bygrave 1c5d7a97e1 Bump pom to 12.1.5-SNAPSHOT 2019-11-29 17:19:23 +13:00
rob bygrave 67c2e1d24c #1871 - Add ability to write metrics in JSON form to Appendable 2019-11-29 17:19:01 +13:00
rob bygrave eb292e017e #1868 - Change the Metric "sqlHash" into a hash of the SQL + name + location 2019-11-20 20:15:32 +13:00
Rob BygraveandGitHub 88839f7613 Refactor rename method ProfileLocation.shortDescription() to location() (#1859) 2019-11-20 20:01:45 +13:00
rob bygrave ca71fef74a #1867 - Change enhancement for @DbArray ... to handle nulls (like OneToMany and ManyToMany) 2019-11-20 19:59:01 +13:00
rob bygrave 6c91ed0c76 #1866 - Refactor logging messages for L2 cache - "PUT ALL" -> "MPUT" 2019-11-20 00:26:26 +13:00
rob bygrave 8761c0486d #1865 - ENH: Add metric collection for ORM insert update and delete 2019-11-19 20:31:48 +13:00
rob bygrave fee6a9f04a Bump to 12.1.4 of the maven plugin 2019-11-19 20:28:23 +13:00
rob bygrave 17ff04e2b9 #1865 - ENH: Add metric collection for ORM insert update and delete 2019-11-19 20:27:04 +13:00
rob bygrave aa11095d17 Reduce to package visibility for internals BatchDepthComparator, BatchedBeanHolder, BatchedPstmtHolder 2019-11-18 23:14:25 +13:00
rob bygrave c2a30f786f #1864 - L2 cache miss for natural key property of type UUID 2019-11-17 17:06:38 +13:00
rob bygrave 9b0dd2b0c4 Turn off logging 2019-11-16 21:54:31 +13:00
rob bygrave aa96d10491 Refactor tidy after #1863. Add NaturalKeyEntrySimple for single property natural key lookup. 2019-11-16 21:48:37 +13:00
rob bygrave dfefbecf44 #1863 - L2 cache miss on natural key cache when multiple properties that include a ManyToOne 2019-11-16 17:03:34 +13:00
rob bygrave 738f19491a #1860 - Non failing test for - @PreUpdate is not working with .update()
Add a "other" property that is made dirty/set on preUpdate
2019-11-11 22:00:19 +13:00
rob bygrave 61257bea7f #1860 - Non failing test for - @PreUpdate is not working with .update() 2019-11-11 21:54:26 +13:00
rob bygrave 566a01d815 #1858 - Modify JSON dumped metrics to include metric type and location for timed metrics 2019-11-10 21:23:26 +13:00
rob bygrave a7116d1606 No effective change - tidy only 2019-11-10 11:36:28 +13:00
rob bygrave 615a2aea46 [maven-release-plugin] prepare for next development iteration 2019-11-07 16:43:25 +13:00
rob bygrave 20d538c428 [maven-release-plugin] prepare release ebean-12.1.3 2019-11-07 16:43:15 +13:00
rob bygrave 01054bf470 #1855 - Add MetaInfoManager collectMetricsAsJson() 2019-11-07 16:35:25 +13:00
rob bygrave affd720390 #1854 - Use profile location label to automatically give good metric name for @Transactional (with profile location enhancement) 2019-11-07 11:18:26 +13:00
rob bygrave 7d77df58c5 #1780 - Add tests for this RawSql case 2019-11-06 23:30:21 +13:00
rob bygrave 51fad2dec6 Refactor CQueryBuilder extract method, no effective change. 2019-11-06 23:29:33 +13:00
rob bygrave 997378ce72 Refactor internal XServiceProvider service loading 2019-11-06 22:01:37 +13:00
rob bygrave 1a8a43603e #1849 - JoinColumn not found when using @Encrypted(dbEncryption = true) and findCount 2019-11-06 20:33:56 +13:00
rob bygrave d2c88bf7c6 #1853 - Classpath problem with avaje-classpath-scanner 2019-11-06 19:53:35 +13:00
rob bygrave 0929147b08 No effective change - tidy test TestQueryFindPagedList 2019-10-18 17:23:31 +13:00
rob bygrave ecab219635 #1848 - ENH: Add EmptyPagedList ... as helper implementation of PagedList<T> 2019-10-18 17:22:19 +13:00
rob bygrave 7a974320ed #1846 - Test for - Inheritance cascade of fields with bean inheritance
Note this includes the workaround RootBean.preRemove(), so doesn't fail
2019-10-18 16:20:38 +13:00
rob bygrave 1b7dc83a9a ENH: Add DB.getBeanId() ... to match database.getBeanId() 2019-10-18 16:08:42 +13:00
rob bygrave 9827d9056f No effective change - add delete batch test with M2M generated sql 2019-10-18 15:51:18 +13:00
rob bygrave c8d5d9b552 No effective change - update test 2019-10-18 15:38:50 +13:00
rob bygrave dac55ab8e9 #1847 - Delete bean with ManyToMany to always delete from intersection (not required cascade REMOVE) 2019-10-18 15:35:21 +13:00
rob bygrave de75bcdaf9 [maven-release-plugin] prepare for next development iteration 2019-10-17 15:25:28 +13:00
rob bygrave 5785124a2b [maven-release-plugin] prepare release ebean-12.1.2 2019-10-17 15:25:18 +13:00
rob bygrave 4d1c0bfaa8 Change parent to java8-oss 2.1 2019-10-17 15:23:35 +13:00
rob bygrave 9a29c988cd #1845 - Refactor for Persisting ElementCollection to limit max JDBC batch size 2019-10-17 15:18:43 +13:00
rob bygrave 80309f844e #1844 - Persisting an update of ElementCollection with JDBC batch, ensure delete, insert batch order 2019-10-17 12:32:13 +13:00
rob bygrave 56ddc49ab4 Element collection persist - initial 2019-10-17 10:17:03 +13:00
rob bygrave 1e7de83019 Element collection persist - initial 2019-10-17 10:15:58 +13:00
rob bygrave 1db1f0312a No effective change - bump provided jaxb-runtime dependency to 2.3.2 2019-10-14 16:03:56 +13:00
rob bygrave d27bf14887 touch readme 2019-10-14 09:21:41 +13:00
rob bygrave d4e7d4eebc [maven-release-plugin] prepare for next development iteration 2019-10-13 12:22:55 +13:00
rob bygrave 30c44d0928 [maven-release-plugin] prepare release ebean-12.1.1 2019-10-13 12:22:44 +13:00
rob bygrave 443c5dba58 Bump ebean-migration version 2019-10-13 12:20:59 +13:00
rob bygrave f24b4dba71 #1837 (#1740 and #1744) - Inheritance on both sides of @ManyToOne
This change also relates back to #1740 and #1744 and changes the way that issue was fixed (by SqlTreeNodeBean on partially populated non-id inheritance bean).
2019-10-13 11:46:11 +13:00
Rob BygraveandGitHub a474880735 #1837 - Inheritance on both sides of @ManyToOne confuses columns (#1843)
* #1837 - Inheritance on both sides of @ManyToOne confuses columns

* #1837 - Inheritance on both sides of @ManyToOne confuses columns

Tidy up whitespace in SQL
2019-10-12 00:25:53 +13:00
rob bygrave 4cfab3a2de #1842 - Refactor persisting to delay the setting of generated Id value (sequences and deferred imported ids) 2019-10-11 20:50:47 +13:00
rob bygrave 4807070147 #1841 - SqlServer findCount with @Aggregation gives SQLException:No column name was specified for column 2 of 'c' 2019-10-11 20:26:35 +13:00
rob bygrave e00aa479ae #1841 - SqlServer findCount with @Aggregation gives SQLException:No column name was specified for column 2 of 'c' 2019-10-11 20:18:18 +13:00
rob bygrave b665d8375c #1831 - Update query with maxRows does not include the limit in the generated SQL 2019-10-11 17:01:30 +13:00
Rob BygraveandGitHub 4e74c68603 Merge pull request #1840 from FOCONIS/exists-use-query-copy
exists() limits the max rows on the query, this should be done on a copy
2019-10-10 23:28:48 +13:00
Manuel Danisch 2694aa3fe1 Fixed test 2019-10-10 11:28:24 +02:00
rob bygrave f7a28aa904 Javadoc fixes 2019-10-10 22:07:14 +13:00
rob bygrave 4bc2559e8e Refactor tidy PersistRequestBean 2019-10-10 21:51:31 +13:00
rob bygrave c2faf0e0a7 No effective change - tidy tests 2019-10-10 21:42:34 +13:00
Manuel Danisch 895b331e8f exists() limits the max rows on the query, this should be done on a copy 2019-10-10 10:42:04 +02:00
rob bygrave 8890079b80 #1839 - Fix JSON marshalling of @ElementCollection maps and scalar 2019-10-10 21:32:44 +13:00
rob bygrave 20dd33ebca Fix DbMigration test for MySql without I__create_procs.sql 2019-10-10 19:07:36 +13:00
rob bygrave e2a1489743 Fix DbMigration test for MySql without I__create_procs.sql 2019-10-10 15:26:50 +13:00
rob bygrave d6bab46ac3 #1838 - Fix for Joda LocalTime timezone handling for MySql 2019-10-10 15:16:12 +13:00
rob bygrave 573673ef2b Fix for tests, make MySql like escape consistent with others 2019-10-10 15:14:38 +13:00
rob bygrave eb69499ca3 #1835 Fix with Refactor batch escalation for deferred imported Id 2019-10-10 15:13:21 +13:00
rob bygrave d9323b8ab6 Fix DbMigration test for MySql without I__create_procs.sql 2019-10-10 15:11:25 +13:00
rob bygrave a01ba128e5 Fix test for TestDbArray_basic.nullItems() for DB's that don't support ARRAY type 2019-10-10 15:10:44 +13:00
rob bygrave fdc67b3ce5 #1823 - ENH: Add query.findStream() and query.findLargeStream() 2019-10-10 13:44:29 +13:00
rob bygrave 5d433ff603 Make it easier for people building using JDK11
Note that our javadoc doclet isn't JDK11 compatible yet
2019-10-10 12:04:09 +13:00
rob bygrave a3f9c4c889 #1836 - NPE with findCount() on bean with @Aggregation, Regression in 11.45.1 2019-10-10 08:55:01 +13:00
Rob BygraveandGitHub 769fc485ec Merge pull request #1835 from ebean-orm/feature/persistCascadeEscalate
Refactor JDBC batch escalation and detection of deferred persist relationship (circular imported ids)
2019-10-09 17:08:09 +13:00
rob bygrave 61ef4fa420 #1835 Refactor JDBC batch escalation 2019-10-09 00:37:06 +13:00
rob bygrave 8cf37e2f0a #1835 Refactor JDBC batch escalation 2019-10-09 00:18:15 +13:00
rob bygrave 80a764a448 #1835 Refactor JDBC batch escalation 2019-10-09 00:17:34 +13:00
rob bygrave 6621c5dfbb Refactor detection of deferred persist relationship (circular imported ids) 2019-10-08 21:49:22 +13:00
rob bygrave 5e7dda1ec8 #1834 - DDL for ElementCollection that is referenced multiple times includes foreign key constraint 2019-10-08 15:53:29 +13:00
rob bygrave 7bc6368f69 #1833 - When cascade persisting twice to ElementCollection ... we get do extra delete and inserts 2019-10-08 13:25:33 +13:00
rob bygrave fb5a69adea #1833 - When cascade persisting twice to ElementCollection ... we get do extra delete and inserts 2019-10-08 13:25:18 +13:00
rob bygrave 0e7607bb27 Log warning when initSql or seedSql is not found as a resource 2019-10-08 09:15:20 +13:00
rob bygrave 1098b572fe #1832 - Cascade insert @ElementCollection when marshalled from JSON 2019-10-07 15:48:31 +13:00
rob bygrave 7a6662a2dc #1830 - Bump ebean-migration dependency to 11.22.1 2019-10-07 13:49:20 +13:00
rob bygrave 1c6c812d4d Update tests change AssertJ StrictAssertions to Assertions 2019-10-06 16:34:44 +13:00
rob bygrave e58a85f0af #1356 - allQuotedIdentifiers must be respected by DDL 2019-10-06 16:32:06 +13:00
rob bygrave e3551152bb #1829 - Bump Jackson core dependency from 2.9.9 to 2.10.0 2019-10-05 23:41:16 +13:00
rob bygrave 5138d1723f Merge branch 'feature/1656' 2019-10-05 23:20:26 +13:00
rob bygrave 9b5ab542d7 #1827 - @UniqueConstraint columnNames should be respecting ebean.allQuotedIdentifiers 2019-10-05 22:37:06 +13:00
rob bygrave f0bc4c786c #1826 - Remove PrivateOwned, migrate to orphanRemoval=true attribute on OneToMany 2019-09-24 22:36:17 +12:00
rob bygrave b98739bb49 #1656 #1824 Stateless updates - Remove update deleteMissingChildren option, instead always use orphanRemoval
Adjust test that doesn't have orphanRemoval (so missing children are not removed here now)
2019-09-20 17:18:07 +12:00
rob bygrave fcadc63338 #1656 #1824 Stateless updates - Remove update deleteMissingChildren option, instead always use orphanRemoval 2019-09-20 17:12:32 +12:00
rob bygrave 3574479627 #1821 - Remove serverConfig updateChangesOnly mode ... as always true 2019-09-15 21:29:25 +12:00
rob bygrave cecf2fc650 [maven-release-plugin] prepare for next development iteration 2019-09-12 23:09:28 +12:00
rob bygrave a1dab24414 [maven-release-plugin] prepare release ebean-11.45.1 2019-09-12 23:09:17 +12:00
rob bygrave c12ea28ea9 #1818 - Cannot auto-generate UUID 2019-09-12 22:02:22 +12:00
rob bygrave a2b418df8b #1820 - ENH: For DB Migration add setLockTimeout(10); ... to add Postgres set lock_timeout = to generated migrations 2019-09-12 20:59:52 +12:00
rob bygrave 2fb533a606 #1819 - ENH: For DB Migration support dbMigration.setAddForeignKeySkipCheck(true); 2019-09-12 20:34:37 +12:00
rob bygrave 5d89897bbd #1817 - Rename @DbHstore to @DbMap 2019-09-12 17:02:53 +12:00
rob bygrave 9640e02b6a #1817 - Rename @DbHstore to @DbMap 2019-09-12 16:58:15 +12:00
rob bygrave 8a0ef33f79 git push origin masterMerge branch 'Ryszard-Trojnacki-master' 2019-09-12 14:55:50 +12:00
rob bygrave d2ece76ca8 #1816 Fix for OneToMany relation to non-cached target bean. 2019-09-12 14:55:37 +12:00
rob bygrave 3495d03706 Merge branch 'master' of https://github.com/Ryszard-Trojnacki/avaje-ebeanorm into Ryszard-Trojnacki-master 2019-09-12 13:58:50 +12:00
Rob BygraveandGitHub bc90fa50d7 #1802 - Completely remove MySQL init stored procedures for drop column with foreign key (#1815) 2019-09-12 09:34:14 +12:00
Ryszard Trojnacki 777fc0ff30 Merge branch 'ebean-orm-master' 2019-09-11 14:24:04 +02:00
Ryszard Trojnacki 9413f72939 Merge from origin. 2019-09-11 14:22:47 +02:00
Ryszard Trojnacki 1416647d04 Test case for changing OneToMany collection in a cached bean, by editing target bean that is not cached (annotated with @Cache). 2019-09-11 14:05:31 +02:00
rob bygrave 63bddb4d54 #1810 - Whan paging over query with @Aggregation ( grouping by) wrong total count is calculated 2019-09-11 23:38:12 +12:00
rob bygrave 6fddd418a1 #1811 Fix for Entity with EmbeddedId not found in cache 2019-09-11 22:28:22 +12:00
RienandRob Bygrave faba55d772 Fix EmbeddedId not found cache (#1811) 2019-09-11 22:06:05 +12:00
rob bygrave ac6db11e3d #1802 - Change MySQL DDL to not use helper stored procedures by default - was auto-generated script containing create procedures fails 2019-09-11 22:04:30 +12:00
rob bygrave ca7d8ecfc1 #1814 - Support older MySQL 5.5 2019-09-11 21:38:16 +12:00
rob bygrave 46eeee68c9 #1814 - Support older MySQL 5.5 2019-09-11 21:37:52 +12:00
rob bygrave c1487daea8 #1812 No effective change - Format code only 2019-09-11 15:33:21 +12:00
Ryszard TrojnackiandRob Bygrave b329ae42db Allow for null items in @DbArray lists. (#1812)
* Added code to allow for null items in @DbArray lists.

* Test case for changing OneToMany collection by editing target bean.
2019-09-11 15:30:32 +12:00
Ryszard Trojnacki 13429daddc Test case for changing OneToMany collection by editing target bean. 2019-09-10 20:43:31 +02:00
Ryszard Trojnacki 98a80295fe Added code to allow for null items in @DbArray lists. 2019-09-10 20:07:33 +02:00
Ryszard TrojnackiandGitHub f8587368ee Merge pull request #2 from ebean-orm/master
Update to master
2019-09-10 19:39:27 +02:00
rob bygrave 8ae2ae7f8b [maven-release-plugin] prepare for next development iteration 2019-08-31 00:16:48 +12:00
rob bygrave 46f3b74b38 [maven-release-plugin] prepare release ebean-11.44.1 2019-08-31 00:16:37 +12:00
rob bygrave df51ccd2c4 Bump to 11.44.1-SNAPSHOT 2019-08-31 00:15:03 +12:00
rob bygrave 730d43c008 #1807 - ENH: Add SerializableConflictException 2019-08-30 23:43:00 +12:00
rob bygrave 81c2c804a6 #1806 - SQLException:Data conversion error converting "c5866ffb-2e1c-457e-bdad-61ba4466f86e" [22018-197] Bind values:[1, ] Query was: 2019-08-26 21:12:07 +12:00
rob bygrave 533be356f2 [maven-release-plugin] prepare for next development iteration 2019-08-25 17:02:57 +12:00
rob bygrave 589191f3f4 [maven-release-plugin] prepare release ebean-11.43.3 2019-08-25 17:02:47 +12:00
rob bygrave 0e65efea57 #1804 - Kotlin: Generating collection with wildcard type - Get error BeanNotRegisteredException: Error with association to [null] from [...Foo.manyProperty]. Is null registered? 2019-08-25 15:58:46 +12:00
rob bygrave be66872249 #1800 Adjust to allow for null schema and table names 2019-08-25 11:32:08 +12:00
rob bygrave 85a0354d42 #1800 No effective change, test only, static imports and organise imports 2019-08-25 11:19:07 +12:00
rob bygrave 0b8613fd4c #1800 - Additional test exercising RawSqlBuilder.sqlRow(resultSet, ...); 2019-08-25 11:16:07 +12:00
Manuel DanischandRob Bygrave e734c0010c If the map already contains the column name, add schema and table names before the key to make it unique again (#1800) 2019-08-25 11:09:32 +12:00
rob bygrave e08333ef26 Improve error message when trying to use predicates etc when creating FetchGroup 2019-08-20 22:47:14 +12:00
rob bygrave 4a3eabbd6b [maven-release-plugin] prepare for next development iteration 2019-08-20 22:01:16 +12:00
rob bygrave ae68d41519 [maven-release-plugin] prepare release ebean-11.43.2 2019-08-20 22:01:04 +12:00
rob bygrave 722692d934 reduce logging for testing 2019-08-20 10:29:31 +12:00
rob bygrave 21a3f322e1 #1798 - Fix automatic query label set on nested secondary query when using profileLocation 2019-08-19 23:15:27 +12:00
rob bygrave 0d175557b0 No effective change - update test clearing data 2019-08-19 21:50:17 +12:00
rob bygrave 57ccd19fe6 #1797 - Bump ebean-migration to 11.20.1 ... which inserts a <init> row into db_migration table 2019-08-19 21:37:01 +12:00
rob bygrave 9674711516 #1796 - ENH: add query.fetchCache(path) ... for explicitly building part of graph from L2 cache 2019-08-19 21:36:19 +12:00
rob bygrave 9155716752 #1795 - Refactor bind padding for Id IN expressions (based on internal multiValueSupport and simple id) 2019-08-18 16:33:36 +12:00
rob bygrave d7d8c3e651 Refactor tidy on Load context 2019-08-18 12:17:36 +12:00
rob bygrave 16f6f2ee7f [maven-release-plugin] prepare for next development iteration 2019-08-16 00:00:42 +12:00
988 changed files with 34030 additions and 14006 deletions
+2 -3
View File
@@ -1,15 +1,14 @@
dist: trusty
dist: xenial
sudo: required
language: java
jdk:
- oraclejdk8
- openjdk11
git:
depth: 3
addons:
postgresql: "9.6"
postgresql: 10
# apt:
# packages:
# - mysql-server-5.7
-1
View File
@@ -44,4 +44,3 @@ Goto [https://ebean.io/docs/](https://ebean.io/docs/)
## Other versions
* [![Maven Central : ebean-agent](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean-agent/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean-agent) - ebean-agent
* [![Maven Central : ebean-maven-plugin](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean-maven-plugin/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean-maven-plugin) - ebean-maven-plugin
+43 -88
View File
@@ -3,57 +3,29 @@
<parent>
<groupId>org.avaje</groupId>
<artifactId>java8-parent</artifactId>
<version>1.3</version>
<artifactId>java8-oss</artifactId>
<version>2.1</version>
</parent>
<groupId>io.ebean</groupId>
<artifactId>ebean</artifactId>
<version>11.43.1</version>
<version>12.3.6</version>
<packaging>jar</packaging>
<name>ebean</name>
<url>http://ebean-orm.github.io/</url>
<properties>
<jackson-core.version>2.9.9</jackson-core.version>
<jackson-databind.version>2.9.9.2</jackson-databind.version>
<snakeyaml.version>1.21</snakeyaml.version>
<jackson-core.version>2.10.0</jackson-core.version>
<jackson-databind.version>2.10.0</jackson-databind.version>
</properties>
<scm>
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
<tag>ebean-11.43.1</tag>
<tag>ebean-12.3.6</tag>
</scm>
<profiles>
<profile>
<!-- Note: to use this profile, you need credentials for the oracle repository in your
settings.xml as described here:
http://docs.oracle.com/middleware/1213/core/MAVEN/config_maven_repo.htm#MAVEN9010 -->
<id>oracle</id>
<dependencies>
<dependency>
<groupId>com.oracle.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>12.2.0.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<id>maven.oracle.com</id>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
<url>https://maven.oracle.com</url>
<layout>default</layout>
</repository>
</repositories>
</profile>
<profile>
<!-- Note: to use this profile, you need to download manually the db2jcc4 driver.
After that, install it into your local maven repository:
@@ -89,13 +61,10 @@
<scope>provided</scope>
</dependency>
<!--
Exclude snakeyaml if you desire - it is not strictly required.
-->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>${snakeyaml.version}</version>
<groupId>io.avaje</groupId>
<artifactId>config</artifactId>
<version>1.2</version>
</dependency>
<!--
@@ -103,46 +72,40 @@
to assist with IDE auto-completion with Ebean API
-->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-jsr305</artifactId>
<version>1.1</version>
<groupId>io.avaje</groupId>
<artifactId>avaje-jsr305</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>persistence-api</artifactId>
<version>2.2.2</version>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-annotation</artifactId>
<version>4.12</version>
<version>6.13</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-types</artifactId>
<version>1.3</version>
<version>2.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-datasource</artifactId>
<version>4.6.1</version>
</dependency>
<dependency>
<groupId>org.avaje</groupId>
<artifactId>avaje-classpath-scanner</artifactId>
<version>3.1.1</version>
<version>5.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>11.19.1</version>
<version>12.1.4</version>
</dependency>
<dependency>
@@ -199,7 +162,7 @@
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.4.0-b180830.0438</version>
<version>2.3.2</version>
<scope>provided</scope>
</dependency>
@@ -214,7 +177,7 @@
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.2</version>
<version>42.2.10</version>
<scope>provided</scope>
</dependency>
@@ -227,17 +190,17 @@
<scope>test</scope>
</dependency>
<!--<dependency>-->
<!--<groupId>oracle</groupId>-->
<!--<artifactId>oracle-jdbc</artifactId>-->
<!--<version>7.0</version>-->
<!--<scope>test</scope>-->
<!--</dependency>-->
<dependency>
<groupId>com.oracle.ojdbc</groupId>
<artifactId>ojdbc10</artifactId>
<version>19.3.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean.test</groupId>
<artifactId>ebean-test-docker</artifactId>
<version>2.10.1</version>
<version>3.1.5</version>
<scope>test</scope>
</dependency>
@@ -253,7 +216,7 @@
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.197</version>
<version>1.4.199</version>
<scope>provided</scope>
</dependency>
@@ -285,6 +248,13 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>2.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.sap.cloud.db.jdbc</groupId>
<artifactId>ngdbc</artifactId>
@@ -301,10 +271,9 @@
<dependency>
<groupId>org.avaje.composite</groupId>
<artifactId>avaje-composite-testing</artifactId>
<artifactId>junit</artifactId>
<version>1.1</version>
<scope>test</scope>
<type>pom</type>
</dependency>
<dependency>
@@ -315,9 +284,9 @@
</dependency>
<dependency>
<groupId>org.avaje.moduuid</groupId>
<artifactId>avaje-moduuid</artifactId>
<version>2.1</version>
<groupId>io.avaje</groupId>
<artifactId>mod-uuid</artifactId>
<version>1.1</version>
<scope>test</scope>
</dependency>
@@ -330,13 +299,13 @@
<plugin>
<groupId>io.ebean</groupId>
<artifactId>ebean-maven-plugin</artifactId>
<version>11.42.1</version>
<version>12.3.4</version>
<executions>
<execution>
<id>test</id>
<phase>process-test-classes</phase>
<configuration>
<transformArgs>debug=1</transformArgs>
<transformArgs>debug=0</transformArgs>
</configuration>
<goals>
<goal>testEnhance</goal>
@@ -348,7 +317,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<version>3.0.0-M4</version>
<configuration>
<useSystemClassLoader>false</useSystemClassLoader>
<trimStackTrace>false</trimStackTrace>
@@ -387,25 +356,11 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<version>3.1.1</version>
<configuration>
<doctitle>Ebean 11</doctitle>
<doctitle>Ebean 12</doctitle>
<overview>src/main/java/io/ebean/overview.html</overview>
<source>1.8</source>
<doclet>org.avaje.doclet.PygmentsDoclet</doclet>
<excludePackageNames>io.ebeaninternal.*:io.ebeanservice:io.ebean.common:io.ebean.bean:io.ebean.service:io.ebean.metric:io.ebean.util:io.ebean.config.properties:io.ebean.config.dbplatform</excludePackageNames>
<docletArtifact>
<groupId>org.avaje</groupId>
<artifactId>pygments-doclet</artifactId>
<version>1.0.0</version>
</docletArtifact>
<additionalparam>
-Xdoclint:none
-include-basedir ${project.basedir}
-attributes "idseparator=-; project_name=${project.name}; \
project_version=${project.version}; \
project_desc=${project.description}"
</additionalparam>
<linksource>true</linksource>
<overview>src/main/java/com/avaje/ebean/overview.html</overview>
</configuration>
@@ -31,15 +31,18 @@ public interface BackgroundExecutor {
* Execute a task periodically with a fixed delay between each execution.
* <p>
* For example, execute a runnable every minute.
* </p>
* <p>
* The delay is the time between executions no matter how long the task took.
* That is, this method has the same behaviour characteristics as
* {@link ScheduledExecutorService#scheduleWithFixedDelay(Runnable, long, long, TimeUnit)}
* </p>
*/
void executePeriodically(Runnable r, long delay, TimeUnit unit);
/**
* Execute a task periodically additionally with an initial delay different from delay.
*/
void executePeriodically(Runnable r, long initialDelay, long delay, TimeUnit unit);
/**
* Schedules a Runnable for one-shot action that becomes enabled after the given delay.
*
+51 -16
View File
@@ -2,7 +2,6 @@ package io.ebean;
import io.ebean.annotation.TxIsolation;
import io.ebean.cache.ServerCacheManager;
import io.ebean.config.DatabaseConfig;
import io.ebean.plugin.Property;
import io.ebean.text.csv.CsvReader;
import io.ebean.text.json.JsonContext;
@@ -87,14 +86,14 @@ public class DB {
// /**
// * Register the server with this Ebean singleton. Specify if the registered
// * server is the primary/default server.
// * server is the primary/default database.
// */
// public static void register(EbeanServer server, boolean defaultServer) {
// serverMgr.register(server, defaultServer);
// }
//
// /**
// * Backdoor for registering a mock implementation of EbeanServer as the default server.
// * Backdoor for registering a mock implementation of EbeanServer as the default database.
// */
// protected static EbeanServer mock(String name, EbeanServer server, boolean defaultServer) {
// EbeanServer originalPrimaryServer = serverMgr.defaultServer;
@@ -102,6 +101,22 @@ public class DB {
// return originalPrimaryServer;
// }
/**
* Return the ScriptRunner for the default database.
* <p>
* Useful to run SQL scripts that are resources. For example a test script
* for inserting seed data for a particular test.
*
* <pre>{@code
*
* DB.script().run("/scripts/test-script.sql")
*
* }</pre>
*/
public static ScriptRunner script() {
return getDefault().script();
}
/**
* Return the ExpressionFactory from the default database.
* <p>
@@ -177,6 +192,18 @@ public class DB {
return getDefault().beginTransaction();
}
/**
* Create a new transaction that is not held in TransactionThreadLocal.
* <p>
* You will want to do this if you want multiple Transactions in a single
* thread or generally use transactions outside of the TransactionThreadLocal
* management.
* </p>
*/
public static Transaction createTransaction() {
return getDefault().createTransaction();
}
/**
* Start a transaction additionally specifying the isolation level.
*
@@ -396,15 +423,6 @@ public class DB {
* called then no optimistic locking is performed (internally ConcurrencyMode.NONE is used).
* </p>
* <p>
* <b>{@link DatabaseConfig#setUpdatesDeleteMissingChildren(boolean)}: </b> When cascade saving to a
* OneToMany or ManyToMany the updatesDeleteMissingChildren setting controls if any other children
* that are in the database but are not in the collection are deleted.
* </p>
* <p>
* <b>{@link DatabaseConfig#setUpdateChangesOnly(boolean)}: </b> The updateChangesOnly setting
* controls if only the changed properties are included in the update or if all the loaded
* properties are included instead.
* </p>
* <pre>{@code
*
* // A 'stateless update' example
@@ -414,9 +432,6 @@ public class DB {
* database.update(customer);
*
* }</pre>
*
* @see DatabaseConfig#setUpdatesDeleteMissingChildren(boolean)
* @see DatabaseConfig#setUpdateChangesOnly(boolean)
*/
public static void update(Object bean) throws OptimisticLockException {
getDefault().update(bean);
@@ -455,6 +470,13 @@ public class DB {
return getDefault().saveAll(beans);
}
/**
* Save all the beans from a Collection.
*/
public static int saveAll(Object... beans) throws OptimisticLockException {
return getDefault().saveAll(beans);
}
/**
* This method checks the uniqueness of a bean. I.e. if the save will work. It will return the
* properties that violates an unique / primary key. This may be done in an UI save action to
@@ -663,7 +685,7 @@ public class DB {
* // find orders and their customers
* List<Order> list = DB.find(Order.class)
* .fetch("customer")
* .orderBy("id")
* .order("id")
* .findList();
*
* // sort by customer name ascending, then by order shipDate
@@ -749,8 +771,11 @@ public class DB {
}
/**
* Deprecated - migrate to sqlQuery().
* <p>
* This is an alias for {@link #sqlQuery(String)}.
*/
@Deprecated
public static SqlQuery createSqlQuery(String sql) {
return sqlQuery(sql);
}
@@ -773,8 +798,11 @@ public class DB {
}
/**
* Deprecated - migrate to sqlUpdate().
* <p>
* This is an alias for {@link #sqlUpdate(String)}.
*/
@Deprecated
public static SqlUpdate createSqlUpdate(String sql) {
return sqlUpdate(sql);
}
@@ -1215,6 +1243,13 @@ public class DB {
return getDefault().getBeanState(bean);
}
/**
* Return the value of the Id property for a given bean.
*/
public static Object getBeanId(Object bean) {
return getDefault().getBeanId(bean);
}
/**
* Return the manager of the level 2 cache ("L2" cache).
*/
+16 -31
View File
@@ -3,7 +3,6 @@ package io.ebean;
import io.ebean.annotation.TxIsolation;
import io.ebean.cache.ServerCacheManager;
import io.ebean.config.DatabaseConfig;
import io.ebean.config.ServerConfig;
import io.ebean.meta.MetaInfoManager;
import io.ebean.plugin.Property;
import io.ebean.plugin.SpiServer;
@@ -123,7 +122,7 @@ public interface Database {
String getName();
/**
* Return the ExpressionFactory for this server.
* Return the ExpressionFactory for this database.
*/
ExpressionFactory getExpressionFactory();
@@ -376,7 +375,7 @@ public interface Database {
* // find orders and their customers
* List<Order> list = database.find(Order.class)
* .fetch("customer")
* .orderBy("id")
* .order("id")
* .findList();
*
* // sort by customer name ascending, then by order shipDate
@@ -465,8 +464,11 @@ public interface Database {
SqlQuery sqlQuery(String sql);
/**
* Deprecated - migrate to sqlQuery().
* <p>
* This is an alias for {@link #sqlQuery(String)}.
*/
@Deprecated
SqlQuery createSqlQuery(String sql);
/**
@@ -485,8 +487,11 @@ public interface Database {
SqlUpdate sqlUpdate(String sql);
/**
* Deprecated - migrate to sqlUpdate().
* <p>
* This is an alias for {@link #sqlUpdate(String)}.
*/
@Deprecated
SqlUpdate createSqlUpdate(String sql);
/**
@@ -856,7 +861,7 @@ public interface Database {
* <pre>{@code
* public class Order { ...
*
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
* List<OrderDetail> details;
* ...
* }
@@ -876,6 +881,11 @@ public interface Database {
*/
int saveAll(Collection<?> beans) throws OptimisticLockException;
/**
* Save all the beans.
*/
int saveAll(Object... beans) throws OptimisticLockException;
/**
* Delete the bean.
* <p>
@@ -1051,7 +1061,6 @@ public interface Database {
* Integer returnValue = (Integer) cs.getObject(3);
*
* }</pre>
*
*/
int execute(CallableSql callableSql);
@@ -1196,17 +1205,6 @@ public interface Database {
* <b>Optimistic Locking: </b> Note that if the version property is not set when update() is
* called then no optimistic locking is performed (internally ConcurrencyMode.NONE is used).
* </p>
* <p>
* <b>{@link ServerConfig#setUpdatesDeleteMissingChildren(boolean)}: </b> When cascade saving to a
* OneToMany or ManyToMany the updatesDeleteMissingChildren setting controls if any other children
* that are in the database but are not in the collection are deleted.
* </p>
* <p>
* <b>{@link ServerConfig#setUpdateChangesOnly(boolean)}: </b> The updateChangesOnly setting
* controls if only the changed properties are included in the update or if all the loaded
* properties are included instead.
* </p>
* <p>
* <pre>{@code
*
* // A 'stateless update' example
@@ -1216,9 +1214,6 @@ public interface Database {
* database.update(customer);
*
* }</pre>
*
* @see ServerConfig#setUpdatesDeleteMissingChildren(boolean)
* @see ServerConfig#setUpdateChangesOnly(boolean)
*/
void update(Object bean) throws OptimisticLockException;
@@ -1227,16 +1222,6 @@ public interface Database {
*/
void update(Object bean, Transaction transaction) throws OptimisticLockException;
/**
* Update a bean additionally specifying a transaction and the deleteMissingChildren setting.
*
* @param bean the bean to update
* @param transaction the transaction to use (can be null).
* @param deleteMissingChildren specify false if you do not want 'missing children' of a OneToMany
* or ManyToMany to be automatically deleted.
*/
void update(Object bean, Transaction transaction, boolean deleteMissingChildren) throws OptimisticLockException;
/**
* Update a collection of beans. If there is no current transaction one is created and used to
* update all the beans in the collection.
@@ -1323,7 +1308,7 @@ public interface Database {
* public void run() {
* User u1 = database.find(User.class, 1);
* ...
* }
* }
* });
*
* }</pre>
@@ -1372,7 +1357,7 @@ public interface Database {
* User u1 = database.find(User.class, 1);
* ...
* return u1.getEmail();
* }
* }
* });
*
* }</pre>
+2 -2
View File
@@ -34,14 +34,14 @@ public class DatabaseFactory {
}
/**
* Create using ebean.properties to configure the server.
* Create using ebean.properties to configure the database.
*/
public static synchronized Database create(String name) {
return EbeanServerFactory.create(name);
}
/**
* Create using the ServerConfig object to configure the server.
* Create using the ServerConfig object to configure the database.
*/
public static synchronized Database create(DatabaseConfig config) {
return EbeanServerFactory.create(config);
+8 -8
View File
@@ -61,7 +61,7 @@ public interface DocumentStore {
* <pre>{@code
*
* Customer customer =
* server.find(Customer.class)
* database.find(Customer.class)
* .setUseDocStore(true)
* .setId(42)
* .findOne();
@@ -79,7 +79,7 @@ public interface DocumentStore {
* <pre>{@code
*
* List<Customer> newCustomers =
* server.find(Customer.class)
* database.find(Customer.class)
* .setUseDocStore(true)
* .where().eq("status, Customer.Status.NEW)
* .findList();
@@ -99,7 +99,7 @@ public interface DocumentStore {
* <pre>{@code
*
* PagedList<Customer> newCustomers =
* server.find(Customer.class)
* database.find(Customer.class)
* .setUseDocStore(true)
* .where().eq("status, Customer.Status.NEW)
* .setMaxRows(50)
@@ -120,7 +120,7 @@ public interface DocumentStore {
* </p>
* <pre>{@code
*
* server.find(Order.class)
* database.find(Order.class)
* .setUseDocStore(true)
* .where()... // perhaps add predicates
* .findEach((Order order) -> {
@@ -145,7 +145,7 @@ public interface DocumentStore {
* </p>
* <pre>{@code
*
* server.find(Order.class)
* database.find(Order.class)
* .setUseDocStore(true)
* .where()... // perhaps add predicates
* .findEachWhile(new Predicate<Order>() {
@@ -190,7 +190,7 @@ public interface DocumentStore {
* Drop the index from the document store (similar to DDL drop table).
* <pre>{@code
*
* DocumentStore documentStore = server.docStore();
* DocumentStore documentStore = database.docStore();
*
* documentStore.dropIndex("product_copy");
*
@@ -202,7 +202,7 @@ public interface DocumentStore {
* Create an index given a mapping file as a resource in the classPath (similar to DDL create table).
* <pre>{@code
*
* DocumentStore documentStore = server.docStore();
* DocumentStore documentStore = database.docStore();
*
* // uses product_copy.mapping.json resource
* // ... to define mappings for the index
@@ -289,7 +289,7 @@ public interface DocumentStore {
* <pre>{@code
*
* // predicates to select the source documents to copy
* Query<Product> query = server.find(Product.class)
* Query<Product> query = database.find(Product.class)
* .where()
* .ge("whenModified", new Timestamp(since))
* .ge("name", "A")
+23 -2
View File
@@ -77,12 +77,29 @@ public interface DtoQuery<T> {
Optional<T> findOneOrEmpty();
/**
* The same as bind for named parameters.
* Bind all the parameters using index positions.
* <p>
* Binds each parameter moving the index position each time.
* <p>
* A convenience for multiple calls to {@link #setParameter(Object)}
*/
DtoQuery<T> setParameters(Object... value);
/**
* Bind the next parameter using index position.
* <p>
* Bind the parameter using index position starting at 1 and incrementing.
* <p>
*/
DtoQuery<T> setParameter(Object value);
/**
* Bind the named parameter.
*/
DtoQuery<T> setParameter(String name, Object value);
/**
* The same as bind for positioned parameters.
* Bind the parameter by its index position (1 based like JDBC).
*/
DtoQuery<T> setParameter(int position, Object value);
@@ -136,4 +153,8 @@ public interface DtoQuery<T> {
*/
DtoQuery<T> setBufferFetchSizeHint(int bufferFetchSizeHint);
/**
* Use the explicit transaction to execute the query.
*/
DtoQuery<T> usingTransaction(Transaction transaction);
}
+19 -15
View File
@@ -24,12 +24,15 @@ import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
/**
* Deprecated - please migrate to use <code>io.ebean.DB</code>.
* <p>
* Ebean is a registry of {@link Database} by name. Ebean has now been renamed to {@link DB}.
* <p>
* Ebean is effectively this is an alias for {@link DB} which is the new and improved name for Ebean.
* <p>
* The preference is to use DB and Database rather than Ebean and EbeanServer.
*/
@Deprecated
public final class Ebean {
private static final Logger logger = LoggerFactory.getLogger(Ebean.class);
@@ -80,7 +83,7 @@ public final class Ebean {
} catch (DataSourceConfigurationException e) {
String msg = "Configuration error creating DataSource for the default Database." +
" This typically means a missing application-test.yaml or missing ebean-test-config dependency." +
" This typically means a missing application-test.yaml or missing ebean-test dependency." +
" See https://ebean.io/docs/trouble-shooting#datasource";
throw new DataSourceConfigurationException(msg, e);
@@ -185,7 +188,7 @@ public final class Ebean {
}
/**
* Return the ExpressionFactory from the default server.
* Return the ExpressionFactory from the default database.
* <p>
* The ExpressionFactory is used internally by the query and ExpressionList to
* build the WHERE and HAVING clauses. Alternatively you can use the
@@ -207,14 +210,14 @@ public final class Ebean {
/**
* Register the server with this Ebean singleton. Specify if the registered
* server is the primary/default server.
* server is the primary/default database.
*/
public static void register(EbeanServer server, boolean defaultServer) {
serverMgr.register(server, defaultServer);
}
/**
* Backdoor for registering a mock implementation of EbeanServer as the default server.
* Backdoor for registering a mock implementation of EbeanServer as the default database.
*/
protected static EbeanServer mock(String name, EbeanServer server, boolean defaultServer) {
EbeanServer originalPrimaryServer = serverMgr.defaultServer;
@@ -462,7 +465,7 @@ public final class Ebean {
* <pre>{@code
* public class Order { ...
*
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
* List<OrderDetail> details;
* ...
* }
@@ -548,9 +551,6 @@ public final class Ebean {
* DB.update(customer);
*
* }</pre>
*
* @see ServerConfig#setUpdatesDeleteMissingChildren(boolean)
* @see ServerConfig#setUpdateChangesOnly(boolean)
*/
public static void update(Object bean) throws OptimisticLockException {
serverMgr.getDefaultServer().update(bean);
@@ -797,7 +797,7 @@ public final class Ebean {
* // find orders and their customers
* List<Order> list = Ebean.find(Order.class)
* .fetch("customer")
* .orderBy("id")
* .order("id")
* .findList();
*
* // sort by customer name ascending, then by order shipDate
@@ -868,6 +868,8 @@ public final class Ebean {
}
/**
* Deprecated - migrate to DB.sqlQuery().
* <p>
* Create a SqlQuery for executing native sql
* query statements.
* <p>
@@ -875,22 +877,24 @@ public final class Ebean {
* annotation for examples.
* </p>
*/
@Deprecated
public static SqlQuery createSqlQuery(String sql) {
return serverMgr.getDefaultServer().createSqlQuery(sql);
return serverMgr.getDefaultServer().sqlQuery(sql);
}
/**
* Deprecated - migrate to DB.sqlUpdate().
* <p>
* Create a sql update for executing native dml statements.
* <p>
* Use this to execute a Insert Update or Delete statement. The statement will
* be native to the database and contain database table and column names.
* </p>
* <p>
* See {@link SqlUpdate} for example usage.
* </p>
*/
@Deprecated
public static SqlUpdate createSqlUpdate(String sql) {
return serverMgr.getDefaultServer().createSqlUpdate(sql);
return serverMgr.getDefaultServer().sqlUpdate(sql);
}
/**
@@ -1196,7 +1200,7 @@ public final class Ebean {
* public void run() {
* User u1 = Ebean.find(User.class, 1);
* ...
* }
* }
* });
*
* }</pre>
@@ -1248,7 +1252,7 @@ public final class Ebean {
* User u1 = Ebean.find(User.class, 1);
* ...
* return u1.getEmail();
* }
* }
* });
*
* }</pre>
+2
View File
@@ -1,6 +1,7 @@
package io.ebean;
/**
* Deprecated - please migrate to <code>io.ebean.Database</code>.
* Provides the API for fetching and saving beans to a particular Database.
* <p>
* Effectively this is an alias for {@link Database} which is now the new
@@ -8,6 +9,7 @@ package io.ebean;
* <p>
* The preference is to use DB and Database rather than Ebean and EbeanServer.
*/
@Deprecated
public interface EbeanServer extends Database {
}
@@ -11,6 +11,8 @@ import java.util.Properties;
import java.util.ServiceLoader;
/**
* Deprecated - please migrate to DatabaseFactory.
* <p>
* Creates EbeanServer instances.
* <p>
* This uses either a ServerConfig or properties in the ebean.properties file to
@@ -28,6 +30,7 @@ import java.util.ServiceLoader;
* convenient way of using the 'default/primary' EbeanServer.
* </p>
*/
@Deprecated
public class EbeanServerFactory {
@@ -48,7 +51,7 @@ public class EbeanServerFactory {
}
/**
* Create using ebean.properties to configure the server.
* Create using ebean.properties to configure the database.
*/
public static synchronized EbeanServer create(String name) {
@@ -59,7 +62,7 @@ public class EbeanServerFactory {
}
/**
* Create using the ServerConfig object to configure the server.
* Create using the ServerConfig object to configure the database.
*/
public static synchronized EbeanServer create(ServerConfig config) {
+1 -1
View File
@@ -21,7 +21,7 @@ public class EbeanVersion {
static {
try {
Properties prop = new Properties();
try (InputStream in = Ebean.class.getResourceAsStream("/META-INF/maven/io.ebean/ebean/pom.properties")) {
try (InputStream in = DB.class.getResourceAsStream("/META-INF/maven/io.ebean/ebean/pom.properties")) {
if (in != null) {
prop.load(in);
in.close();
@@ -0,0 +1,74 @@
package io.ebean;
import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Future;
/**
* An empty PagedList.
* <p>
* For use in application code when we need to return a PagedList but don't want to
* execute a query.
* </p>
*
* <pre>{@code
*
* PagedList<Customer> empty = PagedList.emptyList();
*
* }</pre>
*/
public class EmptyPagedList<T> implements PagedList<T> {
@Override
public void loadCount() {
// do nothing
}
@Nonnull
@Override
public Future<Integer> getFutureCount() {
return null;
}
@Nonnull
@Override
public List<T> getList() {
return Collections.emptyList();
}
@Override
public int getTotalCount() {
return 0;
}
@Override
public int getTotalPageCount() {
return 0;
}
@Override
public int getPageSize() {
return 0;
}
@Override
public int getPageIndex() {
return 0;
}
@Override
public boolean hasNext() {
return false;
}
@Override
public boolean hasPrev() {
return false;
}
@Override
public String getDisplayXtoYofZ(String to, String of) {
return "";
}
}
+39 -39
View File
@@ -34,14 +34,14 @@ public class Expr {
* Equal To - property equal to the given value.
*/
public static Expression eq(String propertyName, Object value) {
return Ebean.getExpressionFactory().eq(propertyName, value);
return DB.getExpressionFactory().eq(propertyName, value);
}
/**
* Not Equal To - property not equal to the given value.
*/
public static Expression ne(String propertyName, Object value) {
return Ebean.getExpressionFactory().ne(propertyName, value);
return DB.getExpressionFactory().ne(propertyName, value);
}
/**
@@ -49,7 +49,7 @@ public class Expr {
* using a lower() function to make it case insensitive).
*/
public static Expression ieq(String propertyName, String value) {
return Ebean.getExpressionFactory().ieq(propertyName, value);
return DB.getExpressionFactory().ieq(propertyName, value);
}
/**
@@ -59,28 +59,28 @@ public class Expr {
* </p>
*/
public static Expression inRange(String propertyName, Object value1, Object value2) {
return Ebean.getExpressionFactory().inRange(propertyName, value1, value2);
return DB.getExpressionFactory().inRange(propertyName, value1, value2);
}
/**
* Between - property between the two given values.
*/
public static Expression between(String propertyName, Object value1, Object value2) {
return Ebean.getExpressionFactory().between(propertyName, value1, value2);
return DB.getExpressionFactory().between(propertyName, value1, value2);
}
/**
* Between - value between two given properties.
*/
public static Expression between(String lowProperty, String highProperty, Object value) {
return Ebean.getExpressionFactory().betweenProperties(lowProperty, highProperty, value);
return DB.getExpressionFactory().betweenProperties(lowProperty, highProperty, value);
}
/**
* Greater Than - property greater than the given value.
*/
public static Expression gt(String propertyName, Object value) {
return Ebean.getExpressionFactory().gt(propertyName, value);
return DB.getExpressionFactory().gt(propertyName, value);
}
/**
@@ -88,42 +88,42 @@ public class Expr {
* value.
*/
public static Expression ge(String propertyName, Object value) {
return Ebean.getExpressionFactory().ge(propertyName, value);
return DB.getExpressionFactory().ge(propertyName, value);
}
/**
* Less Than - property less than the given value.
*/
public static Expression lt(String propertyName, Object value) {
return Ebean.getExpressionFactory().lt(propertyName, value);
return DB.getExpressionFactory().lt(propertyName, value);
}
/**
* Less Than or Equal to - property less than or equal to the given value.
*/
public static Expression le(String propertyName, Object value) {
return Ebean.getExpressionFactory().le(propertyName, value);
return DB.getExpressionFactory().le(propertyName, value);
}
/**
* Is Null - property is null.
*/
public static Expression isNull(String propertyName) {
return Ebean.getExpressionFactory().isNull(propertyName);
return DB.getExpressionFactory().isNull(propertyName);
}
/**
* Is Not Null - property is not null.
*/
public static Expression isNotNull(String propertyName) {
return Ebean.getExpressionFactory().isNotNull(propertyName);
return DB.getExpressionFactory().isNotNull(propertyName);
}
/**
* Case insensitive {@link #exampleLike(Object)}
*/
public static ExampleExpression iexampleLike(Object example) {
return Ebean.getExpressionFactory().iexampleLike(example);
return DB.getExpressionFactory().iexampleLike(example);
}
/**
@@ -131,14 +131,14 @@ public class Expr {
* LikeType.RAW (you need to add you own wildcards % and _).
*/
public static ExampleExpression exampleLike(Object example) {
return Ebean.getExpressionFactory().exampleLike(example);
return DB.getExpressionFactory().exampleLike(example);
}
/**
* Create the query by Example expression specifying more options.
*/
public static ExampleExpression exampleLike(Object example, boolean caseInsensitive, LikeType likeType) {
return Ebean.getExpressionFactory().exampleLike(example, caseInsensitive, likeType);
return DB.getExpressionFactory().exampleLike(example, caseInsensitive, likeType);
}
/**
@@ -146,7 +146,7 @@ public class Expr {
* characters % (percentage) and _ (underscore).
*/
public static Expression like(String propertyName, String value) {
return Ebean.getExpressionFactory().like(propertyName, value);
return DB.getExpressionFactory().like(propertyName, value);
}
/**
@@ -155,14 +155,14 @@ public class Expr {
* a lower() function to make the expression case insensitive.
*/
public static Expression ilike(String propertyName, String value) {
return Ebean.getExpressionFactory().ilike(propertyName, value);
return DB.getExpressionFactory().ilike(propertyName, value);
}
/**
* Starts With - property like value%.
*/
public static Expression startsWith(String propertyName, String value) {
return Ebean.getExpressionFactory().startsWith(propertyName, value);
return DB.getExpressionFactory().startsWith(propertyName, value);
}
/**
@@ -170,14 +170,14 @@ public class Expr {
* lower() function to make the expression case insensitive.
*/
public static Expression istartsWith(String propertyName, String value) {
return Ebean.getExpressionFactory().istartsWith(propertyName, value);
return DB.getExpressionFactory().istartsWith(propertyName, value);
}
/**
* Ends With - property like %value.
*/
public static Expression endsWith(String propertyName, String value) {
return Ebean.getExpressionFactory().endsWith(propertyName, value);
return DB.getExpressionFactory().endsWith(propertyName, value);
}
/**
@@ -185,14 +185,14 @@ public class Expr {
* function to make the expression case insensitive.
*/
public static Expression iendsWith(String propertyName, String value) {
return Ebean.getExpressionFactory().iendsWith(propertyName, value);
return DB.getExpressionFactory().iendsWith(propertyName, value);
}
/**
* Contains - property like %value%.
*/
public static Expression contains(String propertyName, String value) {
return Ebean.getExpressionFactory().contains(propertyName, value);
return DB.getExpressionFactory().contains(propertyName, value);
}
/**
@@ -200,42 +200,42 @@ public class Expr {
* function to make the expression case insensitive.
*/
public static Expression icontains(String propertyName, String value) {
return Ebean.getExpressionFactory().icontains(propertyName, value);
return DB.getExpressionFactory().icontains(propertyName, value);
}
/**
* For collection properties that are empty (have not existing elements).
*/
public static Expression isEmpty(String propertyName) {
return Ebean.getExpressionFactory().isEmpty(propertyName);
return DB.getExpressionFactory().isEmpty(propertyName);
}
/**
* For collection properties that are not empty (have existing elements).
*/
public static Expression isNotEmpty(String propertyName) {
return Ebean.getExpressionFactory().isNotEmpty(propertyName);
return DB.getExpressionFactory().isNotEmpty(propertyName);
}
/**
* In - property has a value in the array of values.
*/
public static Expression in(String propertyName, Object[] values) {
return Ebean.getExpressionFactory().in(propertyName, values);
return DB.getExpressionFactory().in(propertyName, values);
}
/**
* In - using a subQuery.
*/
public static Expression in(String propertyName, Query<?> subQuery) {
return Ebean.getExpressionFactory().in(propertyName, subQuery);
return DB.getExpressionFactory().in(propertyName, subQuery);
}
/**
* In - property has a value in the collection of values.
*/
public static Expression in(String propertyName, Collection<?> values) {
return Ebean.getExpressionFactory().in(propertyName, values);
return DB.getExpressionFactory().in(propertyName, values);
}
/**
@@ -272,14 +272,14 @@ public class Expr {
* }</pre>
*/
public static Expression inOrEmpty(String propertyName, Collection<?> values) {
return Ebean.getExpressionFactory().inOrEmpty(propertyName, values);
return DB.getExpressionFactory().inOrEmpty(propertyName, values);
}
/**
* Id Equal to - ID property is equal to the value.
*/
public static Expression idEq(Object value) {
return Ebean.getExpressionFactory().idEq(value);
return DB.getExpressionFactory().idEq(value);
}
/**
@@ -292,7 +292,7 @@ public class Expr {
* @param propertyMap a map keyed by property names.
*/
public static Expression allEq(Map<String, Object> propertyMap) {
return Ebean.getExpressionFactory().allEq(propertyMap);
return DB.getExpressionFactory().allEq(propertyMap);
}
/**
@@ -303,7 +303,7 @@ public class Expr {
* </p>
*/
public static Expression raw(String raw, Object value) {
return Ebean.getExpressionFactory().raw(raw, value);
return DB.getExpressionFactory().raw(raw, value);
}
/**
@@ -314,14 +314,14 @@ public class Expr {
* </p>
*/
public static Expression raw(String raw, Object[] values) {
return Ebean.getExpressionFactory().raw(raw, values);
return DB.getExpressionFactory().raw(raw, values);
}
/**
* Add raw expression with no parameters.
*/
public static Expression raw(String raw) {
return Ebean.getExpressionFactory().raw(raw);
return DB.getExpressionFactory().raw(raw);
}
/**
@@ -329,7 +329,7 @@ public class Expr {
*/
public static Expression and(Expression expOne, Expression expTwo) {
return Ebean.getExpressionFactory().and(expOne, expTwo);
return DB.getExpressionFactory().and(expOne, expTwo);
}
/**
@@ -337,7 +337,7 @@ public class Expr {
*/
public static Expression or(Expression expOne, Expression expTwo) {
return Ebean.getExpressionFactory().or(expOne, expTwo);
return DB.getExpressionFactory().or(expOne, expTwo);
}
/**
@@ -345,7 +345,7 @@ public class Expr {
*/
public static Expression not(Expression exp) {
return Ebean.getExpressionFactory().not(exp);
return DB.getExpressionFactory().not(exp);
}
/**
@@ -353,7 +353,7 @@ public class Expr {
*/
public static <T> Junction<T> conjunction(Query<T> query) {
return Ebean.getExpressionFactory().conjunction(query);
return DB.getExpressionFactory().conjunction(query);
}
/**
@@ -361,6 +361,6 @@ public class Expr {
*/
public static <T> Junction<T> disjunction(Query<T> query) {
return Ebean.getExpressionFactory().disjunction(query);
return DB.getExpressionFactory().disjunction(query);
}
}
+65 -35
View File
@@ -30,7 +30,7 @@ import java.util.function.Predicate;
* </p>
* <p>
* The ExpressionList also duplicates methods that are found on the Query such
* as findList() and orderBy(). The purpose of these methods is provide a fluid
* as findList() and order(). The purpose of these methods is provide a fluid
* API. The upside of this approach is that you can build and execute a query
* via chained methods. The down side is that this ExpressionList object has
* more methods than you would initially expect (the ones duplicated from
@@ -52,6 +52,14 @@ public interface ExpressionList<T> {
*/
Query<T> query();
/**
* Controls, if paginated queries should always append an 'order by id' statement at the end to
* guarantee a deterministic sort result. This may affect performance.
* If this is not enabled, and an orderBy is set on the query, it's up to the programmer that
* this query provides a deterministic result.
*/
Query<T> orderById(boolean orderById);
/**
* Set the order by clause replacing the existing order by clause if there is
* one.
@@ -59,12 +67,18 @@ public interface ExpressionList<T> {
* This follows SQL syntax using commas between each property with the
* optional asc and desc keywords representing ascending and descending order
* respectively.
* </p>
* <p>
* This is EXACTLY the same as {@link #orderBy(String)}.
* </p>
*/
Query<T> order(String orderByClause);
ExpressionList<T> order(String orderByClause);
/**
* Set the order by clause replacing the existing order by clause if there is
* one.
* <p>
* This follows SQL syntax using commas between each property with the
* optional asc and desc keywords representing ascending and descending order
* respectively.
*/
ExpressionList<T> orderBy(String orderBy);
/**
* Return the OrderBy so that you can append an ascending or descending
@@ -72,7 +86,8 @@ public interface ExpressionList<T> {
* <p>
* This will never return a null. If no order by clause exists then an 'empty'
* OrderBy object is returned.
* </p>
* <p>
* This is the same as <code>orderBy()</code>
*/
OrderBy<T> order();
@@ -82,22 +97,15 @@ public interface ExpressionList<T> {
* <p>
* This will never return a null. If no order by clause exists then an 'empty'
* OrderBy object is returned.
* </p>
* <p>
* This is the same as <code>order()</code>
*/
OrderBy<T> orderBy();
/**
* Add an orderBy clause to the query.
*
* @see Query#orderBy(String)
*/
Query<T> orderBy(String orderBy);
/**
* Add an orderBy clause to the query.
*
* @see Query#orderBy(String)
* Deprecated migrate to {@link #orderBy(String)}
*/
@Deprecated
Query<T> setOrderBy(String orderBy);
/**
@@ -334,7 +342,7 @@ public interface ExpressionList<T> {
* List<String> names =
* DB.find(Customer.class)
* .select("name")
* .orderBy().asc("name")
* .order().asc("name")
* .findSingleAttributeList();
*
* }</pre>
@@ -347,7 +355,7 @@ public interface ExpressionList<T> {
* .setDistinct(true)
* .select("name")
* .where().eq("status", Customer.Status.NEW)
* .orderBy().asc("name")
* .order().asc("name")
* .setMaxRows(100)
* .findSingleAttributeList();
*
@@ -508,7 +516,7 @@ public interface ExpressionList<T> {
* @param expressions Filter expressions with and, or and ? or ?1 type bind parameters
* @param params Bind parameters used in the expressions
*/
Query<T> filterMany(String manyProperty, String expressions, Object... params);
ExpressionList<T> filterMany(String manyProperty, String expressions, Object... params);
/**
* Specify specific properties to fetch on the main/root bean (aka partial
@@ -559,14 +567,14 @@ public interface ExpressionList<T> {
*
* @see Query#setFirstRow(int)
*/
Query<T> setFirstRow(int firstRow);
ExpressionList<T> setFirstRow(int firstRow);
/**
* Set the maximum number of rows to fetch.
*
* @see Query#setMaxRows(int)
*/
Query<T> setMaxRows(int maxRows);
ExpressionList<T> setMaxRows(int maxRows);
/**
* Set the name of the property which values become the key of a map.
@@ -1243,26 +1251,37 @@ public interface ExpressionList<T> {
/**
* Add raw expression with a single parameter.
* <p>
* The raw expression should contain a single ? at the location of the
* parameter.
* The raw expression should contain a single ? or ?1
* at the location of the parameter. We use ?1 when binding a
* collection for an IN expression.
* </p>
* <p>
* <p>>
* When properties in the clause are fully qualified as table-column names
* then they are not translated. logical property name names (not fully
* qualified) will still be translated to their physical name.
* </p>
* <p>
* <h4>Example:</h4>
* <h4>Examples:</h4>
* <pre>{@code
*
* // use a database function
* raw("add_days(orderDate, 10) < ?", someDate)
*
* raw("name like ?", "Rob%")
*
* raw("name in (?1)", asList("Rob", "Fiona", "Jack"))
*
* raw("name = any(?)", asList("Rob", "Fiona", "Jack"))
*
* }</pre>
*
* <h4>Subquery example:</h4>
* <h4>Subquery examples:</h4>
* <pre>{@code
*
* // Bind collection using ?1
* .raw("id in (select c.id from o_customer c where c.name in (?1))", asList("Rob", "Fiona", "Jack"))
*
* // Using Postgres ANY expression
* .raw("t0.customer_id in (select customer_id from customer_group where group_id = any(?::uuid[]))", groupIds)
*
* }</pre>
@@ -1272,14 +1291,25 @@ public interface ExpressionList<T> {
/**
* Add raw expression with an array of parameters.
* <p>
* The raw expression should contain the same number of ? as there are
* parameters.
* </p>
* The raw expression should contain the same number of ? or ?1, ?2 ... bind parameters
* as there are values. We use ?1, ?2 etc when binding a collection for an IN expression.
* <p>
* When properties in the clause are fully qualified as table-column names
* then they are not translated. logical property name names (not fully
* qualified) will still be translated to their physical name.
* </p>
*
* <h4>Examples:</h4>
* <pre>{@code
*
* raw("unitPrice > ? and product.id > ?", 2, 3)
*
* raw("(status = ? or (orderDate < ? and shipDate is null) or customer.name like ?)",
* Order.Status.APPROVED,
* new Timestamp(System.currentTimeMillis()),
* "Rob")
*
* }</pre></pre>
*/
ExpressionList<T> raw(String raw, Object... values);
@@ -1451,7 +1481,7 @@ public interface ExpressionList<T> {
* .eq("status", Customer.Status.ACTIVE)
* .gt("id", 0)
* .endAnd()
* .orderBy().asc("name")
* .order().asc("name")
* .findList();
* }</pre>
*/
@@ -1472,7 +1502,7 @@ public interface ExpressionList<T> {
* .or()
* .eq("status", Customer.Status.ACTIVE)
* .isNull("anniversary")
* .orderBy().asc("name")
* .order().asc("name")
* .findList();
*
* }</pre>
@@ -1492,7 +1522,7 @@ public interface ExpressionList<T> {
* .eq("status", Customer.Status.ACTIVE)
* .gt("id", 0)
* .endAnd()
* .orderBy().asc("name")
* .order().asc("name")
* .findList();
*
* }</pre>
@@ -1526,7 +1556,7 @@ public interface ExpressionList<T> {
* .gt("id", 1)
* .eq("anniversary", onAfter)
* .endNot()
* .orderBy()
* .order()
* .asc("name")
* .findList();
*
+30 -8
View File
@@ -1,8 +1,5 @@
package io.ebean;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.api.SpiTransaction;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.persistence.NonUniqueResultException;
@@ -13,6 +10,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
/**
* The extended API for Database.
@@ -69,7 +67,7 @@ public interface ExtendedServer {
*
* @return True if the query finds a matching row in the database
*/
<T> boolean exists(SpiQuery<?> ormQuery, SpiTransaction transaction);
<T> boolean exists(Query<?> ormQuery, Transaction transaction);
/**
* Return the number of 'top level' or 'root' entities this query should return.
@@ -94,11 +92,9 @@ public interface ExtendedServer {
* {@link #findEachWhile(Query, Predicate, Transaction)} is preferred
* to findIterate(). The reason is that those methods automatically take care of
* closing the queryIterator (and the underlying jdbc statement and resultSet).
* </p>
* <p>
* This is similar to findEach in that not all the result beans need to be held
* in memory at the same time and as such is good for processing large queries.
* </p>
*
* @see Query#findIterate()
* @see Query#findEach(Consumer)
@@ -107,6 +103,32 @@ public interface ExtendedServer {
@Nonnull
<T> QueryIterator<T> findIterate(Query<T> query, Transaction transaction);
/**
* Execute the query returning the result as a Stream.
* <p>
* Note that this can support very large queries iterating any number of results.
* To do so internally it can use multiple persistence contexts.
* <p>
* Note that the stream needs to be closed so use with try with resources.
* </p>
*/
@Nonnull
<T> Stream<T> findStream(Query<T> query, Transaction transaction);
/**
* Deprecated - migrate to findStream().
* <p>
* Execute the query returning the result as a Stream.
* <p>
* Note that this can support very large queries iterating any number of results.
* To do so internally it can use multiple persistence contexts.
* <p>
* Note that the stream needs to be closed so use with try with resources.
*/
@Nonnull
@Deprecated
<T> Stream<T> findLargeStream(Query<T> query, Transaction transaction);
/**
* Execute the query visiting the each bean one at a time.
* <p>
@@ -341,7 +363,7 @@ public interface ExtendedServer {
* List<String> names =
* DB.find(Customer.class)
* .select("name")
* .orderBy().asc("name")
* .order().asc("name")
* .findSingleAttributeList();
*
* }</pre>
@@ -353,7 +375,7 @@ public interface ExtendedServer {
* .setDistinct(true)
* .select("name")
* .where().eq("status", Customer.Status.NEW)
* .orderBy().asc("name")
* .order().asc("name")
* .setMaxRows(100)
* .findSingleAttributeList();
*
+22
View File
@@ -148,6 +148,8 @@ public class FetchConfig implements Serializable {
private boolean queryAll;
private boolean cache;
/**
* Construct the fetch configuration object.
*/
@@ -188,6 +190,17 @@ public class FetchConfig implements Serializable {
return this;
}
/**
* Eagerly fetch the beans fetching the beans from the L2 bean cache
* and using the DB for beans not in the cache.
*/
public FetchConfig cache() {
this.cache = true;
this.queryBatchSize = 0;
this.queryAll = true;
return this;
}
/**
* Eagerly fetch the beans in this path as a separate query (rather than as
* part of the main query).
@@ -247,6 +260,13 @@ public class FetchConfig implements Serializable {
return queryAll;
}
/**
* Return true if this uses L2 bean cache.
*/
public boolean isCache() {
return cache;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -255,6 +275,7 @@ public class FetchConfig implements Serializable {
FetchConfig that = (FetchConfig) o;
if (lazyBatchSize != that.lazyBatchSize) return false;
if (queryBatchSize != that.queryBatchSize) return false;
if (cache != that.cache) return false;
return queryAll == that.queryAll;
}
@@ -263,6 +284,7 @@ public class FetchConfig implements Serializable {
int result = lazyBatchSize;
result = 92821 * result + queryBatchSize;
result = 92821 * result + (queryAll ? 1 : 0);
result = 92821 * result + (cache ? 1 : 0);
return result;
}
}
@@ -67,12 +67,26 @@ public interface FetchGroupBuilder<T> {
@Nonnull
FetchGroupBuilder<T> fetchQuery(String path);
/**
* Fetch the path including all its properties using L2 cache.
* Cache misses fallback to fetchQuery().
*/
@Nonnull
FetchGroupBuilder<T> fetchCache(String path);
/**
* Fetch the path including specified properties using a query join.
*/
@Nonnull
FetchGroupBuilder<T> fetchQuery(String path, String properties);
/**
* Fetch the path including specified properties using L2 cache.
* Cache misses fallback to fetchQuery().
*/
@Nonnull
FetchGroupBuilder<T> fetchCache(String path, String properties);
/**
* Fetch the path including all its properties lazily.
*/
+1 -1
View File
@@ -86,7 +86,7 @@ public interface Filter<T> {
* expressions.
* </p>
* <p>
* Refer to {@link Ebean#sort(List, String)} for more detail.
* Refer to {@link DB#sort(List, String)} for more detail.
* </p>
*/
Filter<T> sort(String sortByClause);
+1 -1
View File
@@ -32,7 +32,7 @@ import java.util.List;
* public List<Customer> findNew() {
* return query().where()
* .eq("status", Customer.Status.NEW)
* .orderBy("name")
* .order("name")
* .findList()
* }
* }
+35
View File
@@ -192,6 +192,13 @@ public abstract class Model {
db().save(this);
}
/**
* Save this entity with an explicit transaction.
*/
public void save(Transaction transaction) {
db().save(this, transaction);
}
/**
* Flush any batched changes to the database.
* <p>
@@ -212,6 +219,13 @@ public abstract class Model {
db().update(this);
}
/**
* Update this entity with an explicit transaction.
*/
public void update(Transaction transaction) {
db().update(this, transaction);
}
/**
* Insert this entity.
*
@@ -221,6 +235,13 @@ public abstract class Model {
db().insert(this);
}
/**
* Insert with an explicit transaction.
*/
public void insert(Transaction transaction) {
db().insert(this, transaction);
}
/**
* Delete this bean.
* <p>
@@ -242,6 +263,13 @@ public abstract class Model {
return db().delete(this);
}
/**
* Delete this entity with an explicit transaction.
*/
public boolean delete(Transaction transaction) {
return db().delete(this, transaction);
}
/**
* Delete a bean permanently without soft delete.
* <p>
@@ -255,6 +283,13 @@ public abstract class Model {
return db().deletePermanent(this);
}
/**
* Delete a bean permanently without soft delete using an explicit transaction.
*/
public boolean deletePermanent(Transaction transaction) {
return db().deletePermanent(this, transaction);
}
/**
* Refreshes this entity from the database.
*
+7
View File
@@ -60,6 +60,13 @@ import java.util.concurrent.Future;
*/
public interface PagedList<T> {
/**
* Return an empty PagedList.
*/
static <B> PagedList<B> emptyList() {
return new EmptyPagedList<>();
}
/**
* Initiate the loading of the total row count in the background.
* <pre>{@code
+1 -1
View File
@@ -30,7 +30,7 @@ import java.util.List;
* .where()
* .eq("store", "def")
* .inPairs(pairs) // IN clause with 'pairs' of values
* .orderBy("sku desc")
* .order("sku desc")
*
* // query expressions cover the natural key properties
* // so we can choose to hit the L2 bean cache if we want
+9 -21
View File
@@ -1,38 +1,36 @@
package io.ebean;
import io.ebean.config.properties.PropertiesLoader;
import io.avaje.config.Config;
import java.util.Properties;
/**
* Provides singleton state for the default server.
* Provides singleton state for the default database.
* <p/>
* Intended for internal use as part of bootup, construction, registration of the default server.
* Intended for internal use as part of bootup, construction, registration of the default database.
*/
class PrimaryServer {
private static Properties globalProperties;
private static String defaultServerName;
private static boolean skip;
/**
* Set whether to skip automatically creating the primary server.
* Set whether to skip automatically creating the primary database.
*/
static synchronized void setSkip(boolean skip) {
PrimaryServer.skip = skip;
}
/**
* Return true to skip automatically creating the primary server.
* Return true to skip automatically creating the primary database.
*/
static synchronized boolean isSkip() {
return skip;
}
/**
* Return the default server name.
* Return the default database name.
*/
static synchronized String getDefaultServerName() {
getProperties();
@@ -43,14 +41,10 @@ class PrimaryServer {
* Return the default configuration Properties.
*/
static synchronized Properties getProperties() {
if (globalProperties == null) {
globalProperties = PropertiesLoader.load();
}
if (defaultServerName == null) {
defaultServerName = determineDefaultServerName();
}
return globalProperties;
return Config.asProperties();
}
/**
@@ -62,15 +56,9 @@ class PrimaryServer {
defaultServerName = System.getProperty("db", defaultServerName);
defaultServerName = System.getProperty("ebean_db", defaultServerName);
if (isEmpty(defaultServerName)) {
defaultServerName = System.getProperty("datasource.default");
defaultServerName = Config.get("datasource.default", null);
if (isEmpty(defaultServerName)) {
defaultServerName = System.getProperty("ebean.default.datasource");
if (isEmpty(defaultServerName)) {
defaultServerName = globalProperties.getProperty("datasource.default");
if (isEmpty(defaultServerName)) {
defaultServerName = globalProperties.getProperty("ebean.default.datasource");
}
}
defaultServerName = Config.get("ebean.default.datasource", null);
}
}
if (defaultServerName == null) {
+18 -3
View File
@@ -31,22 +31,37 @@ public interface ProfileLocation {
}
/**
* Obtain the location description.
* Obtain the description returning true if this is the initial call.
*/
String obtain();
boolean obtain();
/**
* Return a short version of the location description.
*/
String shortDescription();
String location();
/**
* Return the short label.
*/
String label();
/**
* Return the full location.
*/
String fullLocation();
/**
* Add execution time.
*/
void add(long executionTime);
/**
* Return true if this request should be traced.
*/
boolean trace();
/**
* Set the number of times to trace the transactions for this profile location.
*/
void setTraceCount(int traceCount);
}
+94 -34
View File
@@ -11,6 +11,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
/**
* Object relational query for finding a List, Set, Map or single entity bean.
@@ -24,7 +25,7 @@ import java.util.function.Predicate;
* .where()
* .like("customer.name","rob%")
* .gt("orderDate",lastWeek)
* .orderBy("customer.id, id desc")
* .order("customer.id, id desc")
* .setMaxRows(50)
* .findList();
*
@@ -501,6 +502,14 @@ public interface Query<T> {
*/
Query<T> fetchQuery(String path, String fetchProperties);
/**
* Fetch the path and properties using L2 bean cache.
*
* @param path The path of the beans we are fetching from L2 cache.
* @param fetchProperties The properties that should be loaded.
*/
Query<T> fetchCache(String path, String fetchProperties);
/**
* Fetch the path and properties lazily (via batch lazy loading).
* <p>
@@ -587,6 +596,11 @@ public interface Query<T> {
*/
Query<T> fetchQuery(String path);
/**
* Fetch the path eagerly using L2 cache.
*/
Query<T> fetchCache(String path);
/**
* Fetch the path lazily (via batch lazy loading).
* <p>
@@ -642,6 +656,11 @@ public interface Query<T> {
*/
Query<T> usingConnection(Connection connection);
/**
* Execute the query using the given database.
*/
Query<T> usingDatabase(Database database);
/**
* Execute the query returning the list of Id's.
* <p>
@@ -689,6 +708,52 @@ public interface Query<T> {
@Nonnull
QueryIterator<T> findIterate();
/**
* Execute the query returning the result as a Stream.
* <p>
* Note that this can support very large queries iterating
* any number of results. To do so internally it can use
* multiple persistence contexts.
* </p>
* <pre>{@code
*
* // use try with resources to ensure Stream is closed
*
* try (Stream<Customer> stream = query.findStream()) {
* stream
* .map(...)
* .collect(...);
* }
*
* }</pre>
*/
@Nonnull
Stream<T> findStream();
/**
* Deprecated - migrate to findStream.
* <p>
* Execute the query returning the result as a Stream.
* <p>
* Note that this uses multiple persistence contexts such that we can use
* it with a large number of results.
* </p>
* <pre>{@code
*
* // use try with resources to ensure Stream is closed
*
* try (Stream<Customer> stream = query.findLargeStream()) {
* stream
* .map(...)
* .collect(...);
* }
*
* }</pre>
*/
@Nonnull
@Deprecated
Stream<T> findLargeStream();
/**
* Execute the query processing the beans one at a time.
* <p>
@@ -828,7 +893,7 @@ public interface Query<T> {
* List<String> names =
* DB.find(Customer.class)
* .select("name")
* .orderBy().asc("name")
* .order().asc("name")
* .findSingleAttributeList();
*
* }</pre>
@@ -841,7 +906,7 @@ public interface Query<T> {
* .setDistinct(true)
* .select("name")
* .where().eq("status", Customer.Status.NEW)
* .orderBy().asc("name")
* .order().asc("name")
* .setMaxRows(100)
* .findSingleAttributeList();
*
@@ -1126,6 +1191,30 @@ public interface Query<T> {
*/
Query<T> setParameter(int position, Object value);
/**
* Bind the next positioned parameter.
*
* <pre>{@code
*
* // a query with a positioned parameters
* String oql = "where status = ? and name = ?";
*
* List<Order> list = DB.createQuery(Order.class, oql)
* .setParameter(OrderStatus.NEW)
* .setParameter("Rob")
* .findList();
*
* }</pre>
*/
Query<T> setParameter(Object value);
/**
* Bind all the positioned parameters.
* <p>
* A convenience for multiple calls to {@link #setParameter(Object)}
*/
Query<T> setParameters(Object... values);
/**
* Set the Id value to query. This is used with findOne().
* <p>
@@ -1272,10 +1361,6 @@ public interface Query<T> {
* This follows SQL syntax using commas between each property with the
* optional asc and desc keywords representing ascending and descending order
* respectively.
* </p>
* <p>
* This is EXACTLY the same as {@link #order(String)}.
* </p>
*/
Query<T> orderBy(String orderByClause);
@@ -1286,10 +1371,6 @@ public interface Query<T> {
* This follows SQL syntax using commas between each property with the
* optional asc and desc keywords representing ascending and descending order
* respectively.
* </p>
* <p>
* This is EXACTLY the same as {@link #orderBy(String)}.
* </p>
*/
Query<T> order(String orderByClause);
@@ -1299,10 +1380,8 @@ public interface Query<T> {
* <p>
* This will never return a null. If no order by clause exists then an 'empty'
* OrderBy object is returned.
* </p>
* <p>
* This is EXACTLY the same as {@link #orderBy()}.
* </p>
* This is the same as <code>orderBy()</code>
*/
OrderBy<T> order();
@@ -1312,26 +1391,18 @@ public interface Query<T> {
* <p>
* This will never return a null. If no order by clause exists then an 'empty'
* OrderBy object is returned.
* </p>
* <p>
* This is EXACTLY the same as {@link #order()}.
* </p>
* This is the same as <code>order()</code>
*/
OrderBy<T> orderBy();
/**
* Set an OrderBy object to replace any existing OrderBy clause.
* <p>
* This is EXACTLY the same as {@link #setOrderBy(OrderBy)}.
* </p>
*/
Query<T> setOrder(OrderBy<T> orderBy);
/**
* Set an OrderBy object to replace any existing OrderBy clause.
* <p>
* This is EXACTLY the same as {@link #setOrder(OrderBy)}.
* </p>
*/
Query<T> setOrderBy(OrderBy<T> orderBy);
@@ -1467,17 +1538,6 @@ public interface Query<T> {
return setUseQueryCache(enabled ? CacheMode.ON : CacheMode.OFF);
}
/**
* Set an id to identify this query for profiling purposes.
* <p>
* The profileId is expected to be unique for a given bean type.
* </p>
* <p>
* Note that the profileId is treated as a short internally and has a MAX value of 32,767.
* </p>
*/
Query<T> setProfileId(int profileId);
/**
* Set the profile location of this query. This is used to relate query execution metrics
* back to a location like a specific line of code.
+2 -2
View File
@@ -23,9 +23,9 @@ import java.util.Iterator;
* <h3>Try finally style</h3>
* <pre>{@code
*
* Query<Customer> query = server.find(Customer.class)
* Query<Customer> query = database.find(Customer.class)
* .where().gt("id", 0)
* .orderBy("id")
* .order("id")
* .setMaxRows(2);
*
* QueryIterator<Customer> it = query.findIterate();
+3 -2
View File
@@ -18,7 +18,7 @@ import java.sql.SQLException;
* <pre>{@code
*
* //
* // A mapper from ResultSet into our CustomerDto bean
* // Map from ResultSet to CustomerDto bean
* //
* class CustomerMapper implements RowMapper<CustomerDto> {
*
@@ -42,7 +42,8 @@ import java.sql.SQLException;
*
* CustomerDto rob = DB.sqlQuery(sql)
* .setParameter(1, "Rob")
* .findOne(CUSTOMER_MAPPER);
* .mapTo(CUSTOMER_MAPPER)
* .findOne();
*
*
* }</pre>
+9
View File
@@ -50,4 +50,13 @@ public interface ScriptRunner {
*/
void run(URL resource, Map<String, String> placeholderMap);
/**
* Run the raw provided DDL or SQL script.
*
* @param name The name of the script for logging purposes
* @param content The SQL content
* @param useAutoCommit Set to true to use auto commit true and continue when any errors occur
*/
void runScript(String name, String content, boolean useAutoCommit);
}
@@ -0,0 +1,18 @@
package io.ebean;
import javax.persistence.OptimisticLockException;
/**
* Thrown at SERIALIZABLE isolation level for non-recoverable concurrent conflict.
*/
public class SerializableConflictException extends OptimisticLockException {
private static final long serialVersionUID = 1L;
/**
* Create with a message and cause.
*/
public SerializableConflictException(String message, Throwable cause) {
super(message, cause);
}
}
+168 -62
View File
@@ -75,17 +75,15 @@ public interface SqlQuery extends Serializable {
SqlRow findOne();
/**
* Execute the query returning a single result using the mapper.
*
* @param mapper Used to map each ResultSet row into the result object.
* Deprecated migrate to use {@link #mapTo(RowMapper)}
*/
@Deprecated
<T> T findOne(RowMapper<T> mapper);
/**
* Execute the query returning a list using the mapper.
*
* @param mapper Used to map each ResultSet row into the result object.
* Deprecated migrate to use {@link #mapTo(RowMapper)}
*/
@Deprecated
<T> List<T> findList(RowMapper<T> mapper);
/**
@@ -125,77 +123,53 @@ public interface SqlQuery extends Serializable {
Optional<SqlRow> findOneOrEmpty();
/**
* Execute the query returning a single scalar attribute.
* <pre>@{code
* Deprecated - migrate to <code>.mapToScalar(attributeType).findOne()</code>.
* <pre>{@code
*
* String sql = "select max(unit_price) from o_order_detail where order_qty > ?";
*
* BigDecimal maxPrice = DB.sqlQuery(sql)
* .setParameter(1, 2)
* .findSingleAttribute(BigDecimal.class);
*
* }</pre>
*
* <p>
* The attributeType can be any scalar type that Ebean supports (includes javax time types, Joda types etc).
* </p>
*
* @param attributeType The type of the returned value
* .mapToScalar(BigDecimal.class)
* .findOne();
* }
*/
@Deprecated
<T> T findSingleAttribute(Class<T> attributeType);
/**
* Execute the query returning a single BigDecimal value.
* <p>
* This is an alias for <code>findSingleAttribute(BigDecimal.class)</code>
* </p>
* Deprecated - migrate to <code>.mapToScalar(BigDecimal.class).findOne()</code>.
* <pre>{@code
*
* .mapToScalar(BigDecimal.class)
* .findOne();
* }
*/
@Deprecated
BigDecimal findSingleDecimal();
/**
* Execute the query returning a single Long value.
* <p>
* This is an alias for <code>findSingleAttribute(Long.class)</code>
* </p>
* Deprecated - migrate to <code>.mapToScalar(Long.class).findOne()</code>.
* <pre>{@code
*
* .mapToScalar(Long.class)
* .findOne();
* }
*/
@Deprecated
Long findSingleLong();
/**
* Execute the query returning a list of scalar attribute values.
*
* Deprecated - migrate to <code>.mapToScalar(Long.class).findList()</code>.
* <pre>{@code
*
* String sql =
* " select (unit_price * order_qty) " +
* " from o_order_detail " +
* " where unit_price > ? " +
* " order by (unit_price * order_qty) desc";
*
* //
* List<BigDecimal> lineAmounts =
* DB.sqlQuery(sql)
* .setParameter(1, 3)
* .findSingleAttributeList(BigDecimal.class);
*
* }</pre>
*
* <p>
* The attributeType can be any scalar type that Ebean supports (includes javax time types, Joda types etc).
* </p>
*
* @param attributeType The type of the returned value
* .mapToScalar(Long.class)
* .findList();
* }
*/
@Deprecated
<T> List<T> findSingleAttributeList(Class<T> attributeType);
/**
* The same as bind for named parameters.
*/
SqlQuery setParameter(String name, Object value);
/**
* Set one of more positioned parameters.
* <p>
* This is a convenient alternative to multiple calls setParameter().
* This is a convenient alternative to multiple calls to {@link #setParameter(Object)}.
*
* <pre>{@code
*
@@ -203,27 +177,104 @@ public interface SqlQuery extends Serializable {
*
* List<SqlRow> list =
* DB.sqlQuery(sql)
* .setParams("Rob", Status.NEW)
* .setParameters("Rob", Status.NEW)
* .findList();
*
*
* // is the same as ...
* // effectively the same as ...
*
* .setParameter("Rob")
* .setParameter("Status.NEW)
*
* // and ...
*
* List<SqlRow> list =
* DB.sqlQuery(sql)
* .setParameter(1, "Rob")
* .setParameter(2, "Status.NEW)
* .findList();
*
* }</pre>
*/
SqlQuery setParameters(Object... values);
/**
* Deprecated migrate to setParameters(Object... values)
*/
@Deprecated
SqlQuery setParams(Object... values);
/**
* The same as bind for positioned parameters.
* Set the next bind parameter by position.
* <pre>{@code
*
* String sql = "select id, name from customer where name like ? and status = ?";
*
* List<SqlRow> list =
* DB.sqlQuery(sql)
* .setParameter("Rob")
* .setParameter("Status.NEW)
* .findList();
*
* // the same as ...
*
* .setParameters("Rob", Status.NEW)
*
* // and ...
*
* .setParameter(1, "Rob")
* .setParameter(2, "Status.NEW)
*
* }</pre>
*
* <p>
* When binding a collection of values into a IN expression we should use
* indexed parameters like ?1, ?2, ?3 etc rather than just ?.
* </p>
*
* <pre>{@code
*
* String sql = "select c.id, c.name from customer c where c.name in (?1)";
*
* List<SqlRow> rows = DB.sqlQuery(sql)
* .setParameter(asList("Rob", "Fiona", "Jack"))
* .findList();
*
*
* List<SqlRow> rows = DB.sqlQuery(sql)
* .setParameter(1, asList("Rob", "Fiona", "Jack"))
* .findList();
* }</pre>
*
* @param value The value to bind
*/
SqlQuery setParameter(Object value);
/**
* Bind the parameter by its index position (1 based like JDBC).
* <p>
* When binding a collection of values into a IN expression we should use
* indexed parameters like ?1, ?2, ?3 etc rather than just ?.
* </p>
*
* <pre>{@code
*
* String sql = "select c.id, c.name from customer c where c.name in (?1)";
*
* List<SqlRow> rows = DB.sqlQuery(sql)
* .setParameter(asList("Rob", "Fiona", "Jack"))
* .findList();
*
*
* List<SqlRow> rows = DB.sqlQuery(sql)
* .setParameter(1, asList("Rob", "Fiona", "Jack"))
* .findList();
* }</pre>
*/
SqlQuery setParameter(int position, Object value);
/**
* Bind the named parameter value.
*/
SqlQuery setParameter(String name, Object value);
/**
* Set the index of the first row of the results to return.
*/
@@ -260,4 +311,59 @@ public interface SqlQuery extends Serializable {
*/
SqlQuery setBufferFetchSizeHint(int bufferFetchSizeHint);
/**
* The query result maps to a single scalar value like Long, BigDecimal,
* String, UUID, OffsetDateTime etc.
* <p>
* Any scalar type Ebean is aware of can be used including java time
* types like Instant, LocalDate, OffsetDateTime, UUID, Inet, Cdir etc.
*
* <pre>{@code
*
* String sql = " select min(updtime) from o_order_detail " +
* " where unit_price > ? and updtime is not null ";
*
* OffsetDateTime minCreated = DB.sqlQuery(sql)
* .setParameter(42)
* .mapToScalar(OffsetDateTime.class)
* .findOne();
*
* }</pre>
*
* @param attributeType The type the result is returned as
* @return The query to execute via findOne() findList() etc
*/
<T> TypeQuery<T> mapToScalar(Class<T> attributeType);
/**
* Use a RowMapper to map the result to beans.
*
* @param mapper Maps rows to beans
* @param <T> The type of beans mapped to
* @return The query to execute by findOne() findList() etc
*/
<T> TypeQuery<T> mapTo(RowMapper<T> mapper);
/**
* Query mapping to single scalar values.
*
* @param <T> The type of the scalar values
*/
interface TypeQuery<T> {
/**
* Return the single value.
*/
T findOne();
/**
* Return the single value that is optional.
*/
Optional<T> findOneOrEmpty();
/**
* Return the list of values.
*/
List<T> findList();
}
}
+66 -27
View File
@@ -5,18 +5,16 @@ package io.ebean;
* <p>
* Provides a simple way to execute raw SQL insert update or delete statements
* without having to resort to JDBC.
* </p>
* <p>
* Supports the use of positioned or named parameters and can automatically
* notify Ebean of the table modified so that Ebean can maintain its cache.
* </p>
* <p>
* Note that {@link #setAutoTableMod(boolean)} and
* Ebean#externalModification(String, boolean, boolean, boolean)} can be to
* notify Ebean of external changes and enable Ebean to maintain it's "L2"
* server cache.
* </p>
*
* <h2>Positioned parameter example</h2>
* <pre>{@code
*
* // example using 'positioned' parameters
@@ -30,6 +28,7 @@ package io.ebean;
*
* }</pre>
*
* <h2>Named parameter example</h2>
* <pre>{@code
*
* // example using 'named' parameters
@@ -45,8 +44,31 @@ package io.ebean;
* String msg = "There were " + rows + " rows updated";
*
* }</pre>
*
* <h2>Index parameter examples (e.g. ?1, ?2, ?3 ...)</h2>
* <p>
* <h3>Example: Using setNextParameter()</h3>
* We can use index parameters like ?1, ?2, ?3 etc when binding arrays/collections
* of values into an IN expression.
* </p>
* <pre>{@code
*
* // Binding a list of 3 values (9991, 9992, 9993) into an IN expression
*
* DB.sqlUpdate("delete from o_customer where name = ? and id in (?2)")
* .setParameter(1, "Foo")
* .setParameter(2, asList(9991, 9992, 9993))
* .execute();
*
* // note this effectively is the same as
*
* DB.sqlUpdate("delete from o_customer where name = ? and id in (?2)")
* .setParameter("Foo")
* .setParameter(asList(9991, 9992, 9993))
* .execute();
*
* }</pre>
*
* <h3>Example: Using setParameter()</h3>
* <pre>{@code
*
* String sql = "insert into audit_log (id, description, modified_description) values (?,?,?)";
@@ -56,19 +78,19 @@ package io.ebean;
* try (Transaction txn = DB.beginTransaction()) {
* txn.setBatchMode(true);
*
* insert.setNextParameter(10000);
* insert.setNextParameter("hello");
* insert.setNextParameter("rob");
* insert.setParameter(10000);
* insert.setParameter("hello");
* insert.setParameter("rob");
* insert.execute();
*
* insert.setNextParameter(10001);
* insert.setNextParameter("goodbye");
* insert.setNextParameter("rob");
* insert.setParameter(10001);
* insert.setParameter("goodbye");
* insert.setParameter("rob");
* insert.execute();
*
* insert.setNextParameter(10002);
* insert.setNextParameter("chow");
* insert.setNextParameter("bob");
* insert.setParameter(10002);
* insert.setParameter("chow");
* insert.setParameter("bob");
* insert.execute();
*
* txn.commit();
@@ -81,19 +103,19 @@ package io.ebean;
*
* try (Transaction txn = DB.beginTransaction()) {
*
* insert.setNextParameter(10000);
* insert.setNextParameter("hello");
* insert.setNextParameter("rob");
* insert.setParameter(10000);
* insert.setParameter("hello");
* insert.setParameter("rob");
* insert.addBatch();
*
* insert.setNextParameter(10001);
* insert.setNextParameter("goodbye");
* insert.setNextParameter("rob");
* insert.setParameter(10001);
* insert.setParameter("goodbye");
* insert.setParameter("rob");
* insert.addBatch();
*
* insert.setNextParameter(10002);
* insert.setNextParameter("chow");
* insert.setNextParameter("bob");
* insert.setParameter(10002);
* insert.setParameter("chow");
* insert.setParameter("bob");
* insert.addBatch();
*
* int[] rows = insert.executeBatch();
@@ -126,8 +148,6 @@ public interface SqlUpdate {
* {@link Transaction#setBatchMode(boolean)} and
* {@link Transaction#setBatchSize(int)}.
* </p>
*
* @see Ebean#execute(SqlUpdate)
*/
int execute();
@@ -241,28 +261,47 @@ public interface SqlUpdate {
* String sql = "insert into audit_log (id, name, version) values (?,?,?)";
*
* DB.sqlUpdate(sql)
* .setParams(UUID.randomUUID(), "Hello", 1)
* .setParameters(UUID.randomUUID(), "Hello", 1)
* .executeNow();
*
*
* // is the same as ...
*
* DB.sqlUpdate(sql)
* .setParameter(UUID.randomUUID())
* .setParameter("Hello")
* .setParameter(1)
* .executeNow();
*
* // which is the same as ...
*
* DB.sqlUpdate(sql)
* .setParameter(1, UUID.randomUUID())
* .setParameter(2, "Hello")
* .setParameter(3, 1)
* .executeNow();
*
* }</pre>
*
*/
SqlUpdate setParameters(Object... values);
/**
* Deprecated migrate to setParameters(Object... values).
*/
@Deprecated
SqlUpdate setParams(Object... values);
/**
* Set the next positioned parameter.
* Set the next bind parameter by position.
*
* @param value The value to bind
*/
SqlUpdate setParameter(Object value);
/**
* Deprecated migrate to setParameter(value).
*/
@Deprecated
SqlUpdate setNextParameter(Object value);
/**
+41 -9
View File
@@ -27,7 +27,7 @@ public interface Transaction extends AutoCloseable {
* @see Database#currentTransaction()
*/
static Transaction current() {
return Ebean.currentTransaction();
return DB.currentTransaction();
}
/**
@@ -295,7 +295,7 @@ public interface Transaction extends AutoCloseable {
*
* <pre>{@code
*
* try (Transaction transaction = server.beginTransaction()) {
* try (Transaction transaction = database.beginTransaction()) {
*
* // turn on JDBC batch
* transaction.setBatchMode(true);
@@ -313,12 +313,12 @@ public interface Transaction extends AutoCloseable {
* <h3>getGeneratedKeys</h3>
* <p>
* Often with large batch inserts we want to turn off getGeneratedKeys. We do
* this via {@link #setBatchGetGeneratedKeys(boolean)}.
* this via {@link #setGetGeneratedKeys(boolean)}.
* Also note that some JDBC drivers do not support getGeneratedKeys in JDBC batch mode.
* </p>
* <pre>{@code
*
* try (Transaction transaction = server.beginTransaction()) {
* try (Transaction transaction = database.beginTransaction()) {
*
* transaction.setBatchMode(true);
* transaction.setBatchSize(100);
@@ -342,7 +342,7 @@ public interface Transaction extends AutoCloseable {
* </p>
* <p>
* We use {@link #flush()} to explicitly flush the batch and we can use
* {@link #setBatchFlushOnQuery(boolean)} and {@link #setBatchFlushOnMixed(boolean)}
* {@link #setFlushOnQuery(boolean)} and {@link #setFlushOnMixed(boolean)}
* to control the automatic flushing behaviour.
* </p>
* <p>
@@ -432,7 +432,15 @@ public interface Transaction extends AutoCloseable {
* number of objects and you don't care about getting back the ids.
* </p>
*/
void setBatchGetGeneratedKeys(boolean getGeneratedKeys);
void setGetGeneratedKeys(boolean getGeneratedKeys);
/**
* Deprecated renamed to setGetGeneratedKeys().
*/
@Deprecated
default void setBatchGetGeneratedKeys(boolean getGeneratedKeys) {
setGetGeneratedKeys(getGeneratedKeys);
}
/**
* By default when mixing UpdateSql (or CallableSql) with Beans the batch is
@@ -449,7 +457,15 @@ public interface Transaction extends AutoCloseable {
* have a 2 step process (delayed binding).
* </p>
*/
void setBatchFlushOnMixed(boolean batchFlushOnMixed);
void setFlushOnMixed(boolean batchFlushOnMixed);
/**
* Deprecated renamed to setFlushOnMixed().
*/
@Deprecated
default void setBatchFlushOnMixed(boolean batchFlushOnMixed) {
setFlushOnMixed(batchFlushOnMixed);
}
/**
* By default executing a query will automatically flush any batched
@@ -459,7 +475,15 @@ public interface Transaction extends AutoCloseable {
* execute a query and the batch will not be automatically flushed.
* </p>
*/
void setBatchFlushOnQuery(boolean batchFlushOnQuery);
void setFlushOnQuery(boolean batchFlushOnQuery);
/**
* Deprecated renamed to setFlushOnQuery().
*/
@Deprecated
default void setBatchFlushOnQuery(boolean batchFlushOnQuery) {
setFlushOnQuery(batchFlushOnQuery);
}
/**
* Return true if the batch (of persisted beans or executed UpdateSql etc)
@@ -468,7 +492,15 @@ public interface Transaction extends AutoCloseable {
* The default is for this to be true.
* </p>
*/
boolean isBatchFlushOnQuery();
boolean isFlushOnQuery();
/**
* Deprecated renamed to isFlushOnQuery().
*/
@Deprecated
default boolean isBatchFlushOnQuery() {
return isFlushOnQuery();
}
/**
* The batch will be flushing automatically but you can use this to explicitly
+4 -4
View File
@@ -12,16 +12,16 @@ import java.util.concurrent.Callable;
* <p>
* This information matches the features of the Transactional annotation. You
* can use it directly with Runnable or Callable via
* {@link Ebean#execute(TxScope, Runnable)} or
* {@link Ebean#executeCall(TxScope, Callable)}.
* {@link DB#execute(TxScope, Runnable)} or
* {@link DB#executeCall(TxScope, Callable)}.
* </p>
* <p>
* This object is used internally with the enhancement of a method with
* Transactional annotation.
* </p>
*
* @see Ebean#execute(TxScope, Runnable)
* @see Ebean#executeCall(TxScope, Callable)
* @see DB#execute(TxScope, Runnable)
* @see DB#executeCall(TxScope, Callable)
*/
public final class TxScope {
+7 -13
View File
@@ -20,29 +20,23 @@ class XServiceProvider {
private static SpiFetchGroupService fetchGroupService = initSpiFetchGroupService();
private static SpiFetchGroupService initSpiFetchGroupService() {
Iterator<SpiFetchGroupService> loader = ServiceLoader.load(SpiFetchGroupService.class).iterator();
if (loader.hasNext()) {
return loader.next();
}
throw new IllegalStateException("No service implementation found for SpiFetchGroupService?");
return loadFirstService(SpiFetchGroupService.class);
}
private static SpiRawSqlService initRawSql() {
Iterator<SpiRawSqlService> loader = ServiceLoader.load(SpiRawSqlService.class).iterator();
if (loader.hasNext()) {
return loader.next();
}
throw new IllegalStateException("No service implementation found for SpiRawSqlService?");
return loadFirstService(SpiRawSqlService.class);
}
private static SpiProfileLocationFactory initProfileLocation() {
return loadFirstService(SpiProfileLocationFactory.class);
}
Iterator<SpiProfileLocationFactory> loader = ServiceLoader.load(SpiProfileLocationFactory.class).iterator();
private static <T> T loadFirstService(Class<T> cls) {
Iterator<T> loader = ServiceLoader.load(cls).iterator();
if (loader.hasNext()) {
return loader.next();
}
throw new IllegalStateException("No service implementation found for SpiProfileLocationFactory?");
throw new IllegalStateException("No service implementation found for " + cls);
}
/**
@@ -1,6 +1,7 @@
package io.ebean.bean;
import io.ebean.Ebean;
import io.ebean.DB;
import io.ebean.Database;
import io.ebean.ValuePair;
import javax.persistence.EntityNotFoundException;
@@ -39,6 +40,8 @@ public final class EntityBeanIntercept implements Serializable {
private String ebeanServerName;
private boolean deletedFromCollection;
/**
* The actual entity bean that 'owns' this intercept.
*/
@@ -79,14 +82,14 @@ public final class EntityBeanIntercept implements Serializable {
private static final byte FLAG_CHANGED_PROP = 2;
/**
* Flags indicating if a property is a dirty embedded bean. Used to distingush
* Flags indicating if a property is a dirty embedded bean. Used to distinguish
* between an embedded bean being completely overwritten and one of its
* embedded properties being made dirty.
*/
private static final byte FLAG_EMBEDDED_DIRTY = 4;
/**
* Flags indicating if a property is a dirty embedded bean. Used to distingush
* Flags indicating if a property is a dirty embedded bean. Used to distinguish
* between an embedded bean being completely overwritten and one of its
* embedded properties being made dirty.
*/
@@ -95,21 +98,15 @@ public final class EntityBeanIntercept implements Serializable {
private final byte[] flags;
private boolean fullyLoadedBean;
private boolean loadedFromCache;
private Object[] origValues;
private Exception[] loadErrors;
private int lazyLoadProperty = -1;
private Object ownerId;
private int sortOrder;
/**
* Create a intercept with a given entity.
* <p>
* Refer to agent ProxyConstructor.
* </p>
*/
public EntityBeanIntercept(Object ownerBean) {
this.owner = (EntityBean) ownerBean;
@@ -311,6 +308,22 @@ public final class EntityBeanIntercept implements Serializable {
}
}
/**
* Set true when the bean has been loaded from L2 bean cache.
* The effect of this is that we should skip the cache if there
* is subsequent lazy loading (bean cache partially populated).
*/
public void setLoadedFromCache(boolean loadedFromCache) {
this.loadedFromCache = loadedFromCache;
}
/**
* Return true if this bean was loaded from L2 bean cache.
*/
public boolean isLoadedFromCache() {
return loadedFromCache;
}
/**
* Return true if the bean should be treated as readOnly. If a setter method
* is called when it is readOnly an Exception is thrown.
@@ -358,13 +371,11 @@ public final class EntityBeanIntercept implements Serializable {
/**
* Set the loaded state to true.
* <p>
* Calls to setter methods after the bean is loaded can result in 'Old Values'
* being created to support ConcurrencyMode.ALL
* </p>
* Calls to setter methods after the bean is loaded can result in
* 'Old Values' being created.
* <p>
* Worth noting that this is also set after a insert/update. By doing so it
* 'resets' the bean for making further changes and saving again.
* </p>
*/
public void setLoaded() {
this.state = STATE_LOADED;
@@ -378,8 +389,7 @@ public final class EntityBeanIntercept implements Serializable {
}
/**
* When finished loading for lazy or refresh on an already partially populated
* bean.
* When finished loading for lazy or refresh on an already partially populated bean.
*/
public void setLoadedLazy() {
this.state = STATE_LOADED;
@@ -410,9 +420,6 @@ public final class EntityBeanIntercept implements Serializable {
/**
* Set true to turn off lazy loading.
* <p>
* Typically used to disable lazy loading on SQL based report beans.
* </p>
*/
public void setDisableLazyLoad(boolean disableLazyLoad) {
this.disableLazyLoad = disableLazyLoad;
@@ -432,7 +439,6 @@ public final class EntityBeanIntercept implements Serializable {
* Return true if the embedded bean is new or dirty and hence needs saving.
*/
public boolean isEmbeddedNewOrDirty(Object embeddedBean) {
if (embeddedBean == null) {
// if it was previously set then the owning bean would
// have oldValues containing the previous embedded bean
@@ -440,7 +446,6 @@ public final class EntityBeanIntercept implements Serializable {
}
if (embeddedBean instanceof EntityBean) {
return ((EntityBean) embeddedBean)._ebean_getIntercept().isNewOrDirty();
} else {
// non-enhanced so must assume it is new and needs to be saved
return true;
@@ -458,8 +463,8 @@ public final class EntityBeanIntercept implements Serializable {
}
/**
* Finds the index position of a given property. Returns -1 if the property
* can not be found.
* Finds the index position of a given property. Returns -1 if the
* property can not be found.
*/
public int findProperty(String propertyName) {
String[] names = owner._ebean_getPropertyNames();
@@ -482,7 +487,7 @@ public final class EntityBeanIntercept implements Serializable {
}
/**
* Return the number of properties.s
* Return the number of properties.
*/
public int getPropertyLength() {
return owner._ebean_getPropertyNames().length;
@@ -504,8 +509,7 @@ public final class EntityBeanIntercept implements Serializable {
}
/**
* Set the property to be treated as unloaded. Used for properties initialised in default
* constructor.
* Set the property to be treated as unloaded. Used for properties initialised in default constructor.
*/
public void setPropertyUnloaded(int propertyIndex) {
flags[propertyIndex] &= ~FLAG_LOADED_PROP;
@@ -592,7 +596,6 @@ public final class EntityBeanIntercept implements Serializable {
* For forced update on a 'New' bean set all the loaded properties to changed.
*/
public void setNewBeanForUpdate() {
for (int i = 0; i < flags.length; i++) {
if ((flags[i] & FLAG_LOADED_PROP) != 0) {
flags[i] |= FLAG_CHANGED_PROP;
@@ -647,8 +650,7 @@ public final class EntityBeanIntercept implements Serializable {
for (int i = 0; i < len; i++) {
if ((flags[i] & FLAG_CHANGED_PROP) != 0) {
// the property has been changed on this bean
String propName = (prefix == null ? getProperty(i) : prefix + getProperty(i));
props.add(propName);
props.add((prefix == null ? getProperty(i) : prefix + getProperty(i)));
} else if ((flags[i] & FLAG_EMBEDDED_DIRTY) != 0) {
// an embedded property has been changed - recurse
EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
@@ -661,12 +663,10 @@ 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 ((flags[i] & FLAG_CHANGED_PROP) != 0) {
// the property has been changed on this bean
if (propertyNames.contains(names[i])) {
return true;
}
@@ -699,10 +699,9 @@ public final class EntityBeanIntercept implements Serializable {
String propName = (prefix == null ? getProperty(i) : prefix + getProperty(i));
Object newVal = owner._ebean_getField(i);
Object oldVal = getOrigValue(i);
if (!areEqual(oldVal, newVal)) {
if (notEqual(oldVal, newVal)) {
dirtyValues.put(propName, new ValuePair(newVal, oldVal));
}
} else if ((flags[i] & FLAG_EMBEDDED_DIRTY) != 0) {
// an embedded property has been changed - recurse
EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
@@ -721,10 +720,9 @@ public final class EntityBeanIntercept implements Serializable {
// the property has been changed on this bean
Object newVal = owner._ebean_getField(i);
Object oldVal = getOrigValue(i);
if (!areEqual(oldVal, newVal)) {
if (notEqual(oldVal, newVal)) {
visitor.visit(i, newVal, oldVal);
}
} else if ((flags[i] & FLAG_EMBEDDED_DIRTY) != 0) {
// an embedded property has been changed - recurse
EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
@@ -745,7 +743,7 @@ public final class EntityBeanIntercept implements Serializable {
}
/**
* Add and return a dirty property hash recursing into embedded beans.
* Add and return a dirty property hash.
*/
private void addDirtyPropertyKey(StringBuilder sb) {
if (sortOrder > 0) {
@@ -780,7 +778,7 @@ public final class EntityBeanIntercept implements Serializable {
}
public boolean[] getLoaded() {
boolean[] ret= new boolean[flags.length];
boolean[] ret = new boolean[flags.length];
for (int i = 0; i < ret.length; i++) {
ret[i] = (flags[i] & FLAG_LOADED_PROP) != 0;
}
@@ -805,21 +803,18 @@ public final class EntityBeanIntercept implements Serializable {
* Load the bean when it is a reference.
*/
protected void loadBean(int loadProperty) {
synchronized (this) {
if (beanLoader == null) {
BeanLoader serverLoader = (BeanLoader) Ebean.getServer(ebeanServerName);
if (serverLoader == null) {
throw new PersistenceException("Server [" + ebeanServerName + "] was not found?");
final Database database = DB.byName(ebeanServerName);
if (database == null) {
throw new PersistenceException("Database [" + ebeanServerName + "] was not found?");
}
// For stand alone reference bean or after deserialisation lazy load
// using the ebeanServer. Synchronise only on the bean.
loadBeanInternal(loadProperty, serverLoader);
loadBeanInternal(loadProperty, database.getPluginApi());
return;
}
}
synchronized (beanLoader) {
// Lazy loading using LoadBeanContext which supports batch loading
// Synchronise on the beanLoader (a 'node' of the LoadBeanContext 'tree')
@@ -831,32 +826,24 @@ public final class EntityBeanIntercept implements Serializable {
* Invoke the lazy loading. This method is synchronised externally.
*/
private void loadBeanInternal(int loadProperty, BeanLoader loader) {
if ((flags[loadProperty] & FLAG_LOADED_PROP) != 0) {
// race condition where multiple threads calling preGetter concurrently
return;
}
if (lazyLoadFailure) {
// failed when batch lazy loaded by another bean in the batch
throw new EntityNotFoundException("(Lazy) loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted");
}
if (lazyLoadProperty == -1) {
lazyLoadProperty = loadProperty;
if (nodeUsageCollector != null) {
nodeUsageCollector.setLoadProperty(getProperty(lazyLoadProperty));
}
loader.loadBean(this);
if (lazyLoadFailure) {
// failed when lazy loading this bean
throw new EntityNotFoundException("Lazy loading failed on type:" + owner.getClass().getName() + " id:" + ownerId + " - Bean has been deleted.");
}
// bean should be loaded and intercepting now. setLoaded() has
// been called by the lazy loading mechanism
}
@@ -866,32 +853,31 @@ public final class EntityBeanIntercept implements Serializable {
* Helper method to check if two objects are equal.
*/
@SuppressWarnings({"unchecked", "rawtypes"})
protected boolean areEqual(Object obj1, Object obj2) {
protected static boolean notEqual(Object obj1, Object obj2) {
if (obj1 == null) {
return (obj2 == null);
return (obj2 != null);
}
if (obj2 == null) {
return false;
return true;
}
if (obj1 == obj2) {
return true;
return false;
}
if (obj1 instanceof BigDecimal) {
// Use comparable for BigDecimal as equals
// uses scale in comparison...
if (obj2 instanceof BigDecimal) {
Comparable com1 = (Comparable) obj1;
return (com1.compareTo(obj2) == 0);
return (com1.compareTo(obj2) != 0);
} else {
return false;
return true;
}
}
if (obj1 instanceof URL) {
// use the string format to determine if dirty
return obj1.toString().equals(obj2.toString());
return !obj1.toString().equals(obj2.toString());
}
return obj1.equals(obj2);
return !obj1.equals(obj2);
}
/**
@@ -902,6 +888,7 @@ public final class EntityBeanIntercept implements Serializable {
}
private void preGetterCallback(int propertyIndex) {
PreGetterCallback preGetterCallback = this.preGetterCallback;
if (preGetterCallback != null) {
preGetterCallback.preGetterTrigger(propertyIndex);
}
@@ -931,25 +918,20 @@ public final class EntityBeanIntercept implements Serializable {
}
/**
* OneToMany and ManyToMany don't have any interception so just check for
* PropertyChangeSupport.
* OneToMany and ManyToMany only set loaded state.
*/
public void preSetterMany(boolean interceptField, int propertyIndex, Object oldValue, Object newValue) {
if (readOnly) {
throw new IllegalStateException("This bean is readOnly");
}
setLoadedProperty(propertyIndex);
}
private void setChangedPropertyValue(int propertyIndex, boolean setDirtyState, Object origValue) {
if (readOnly) {
throw new IllegalStateException("This bean is readOnly");
}
setChangedProperty(propertyIndex);
if (setDirtyState) {
setOriginalValue(propertyIndex, origValue);
setDirtyStatus();
@@ -974,10 +956,9 @@ public final class EntityBeanIntercept implements Serializable {
* the old values for use with ConcurrencyMode.ALL.
*/
public void preSetter(boolean intercept, int propertyIndex, Object oldValue, Object newValue) {
if (state == STATE_NEW) {
setLoadedProperty(propertyIndex);
} else if (!areEqual(oldValue, newValue)) {
} else if (notEqual(oldValue, newValue)) {
setChangedPropertyValue(propertyIndex, intercept, oldValue);
}
}
@@ -987,7 +968,6 @@ public final class EntityBeanIntercept implements Serializable {
* Check for primitive boolean.
*/
public void preSetter(boolean intercept, int propertyIndex, boolean oldValue, boolean newValue) {
if (state == STATE_NEW) {
setLoadedProperty(propertyIndex);
} else if (oldValue != newValue) {
@@ -999,7 +979,6 @@ public final class EntityBeanIntercept implements Serializable {
* Check for primitive int.
*/
public void preSetter(boolean intercept, int propertyIndex, int oldValue, int newValue) {
if (state == STATE_NEW) {
setLoadedProperty(propertyIndex);
} else if (oldValue != newValue) {
@@ -1011,7 +990,6 @@ public final class EntityBeanIntercept implements Serializable {
* long.
*/
public void preSetter(boolean intercept, int propertyIndex, long oldValue, long newValue) {
if (state == STATE_NEW) {
setLoadedProperty(propertyIndex);
} else if (oldValue != newValue) {
@@ -1023,7 +1001,6 @@ public final class EntityBeanIntercept implements Serializable {
* double.
*/
public void preSetter(boolean intercept, int propertyIndex, double oldValue, double newValue) {
if (state == STATE_NEW) {
setLoadedProperty(propertyIndex);
} else if (Double.compare(oldValue, newValue) != 0) {
@@ -1035,7 +1012,6 @@ public final class EntityBeanIntercept implements Serializable {
* float.
*/
public void preSetter(boolean intercept, int propertyIndex, float oldValue, float newValue) {
if (state == STATE_NEW) {
setLoadedProperty(propertyIndex);
} else if (Float.compare(oldValue, newValue) != 0) {
@@ -1047,7 +1023,6 @@ public final class EntityBeanIntercept implements Serializable {
* short.
*/
public void preSetter(boolean intercept, int propertyIndex, short oldValue, short newValue) {
if (state == STATE_NEW) {
setLoadedProperty(propertyIndex);
} else if (oldValue != newValue) {
@@ -1059,7 +1034,6 @@ public final class EntityBeanIntercept implements Serializable {
* char.
*/
public void preSetter(boolean intercept, int propertyIndex, char oldValue, char newValue) {
if (state == STATE_NEW) {
setLoadedProperty(propertyIndex);
} else if (oldValue != newValue) {
@@ -1071,7 +1045,6 @@ public final class EntityBeanIntercept implements Serializable {
* byte.
*/
public void preSetter(boolean intercept, int propertyIndex, byte oldValue, byte newValue) {
if (state == STATE_NEW) {
setLoadedProperty(propertyIndex);
} else if (oldValue != newValue) {
@@ -1083,7 +1056,6 @@ public final class EntityBeanIntercept implements Serializable {
* char[].
*/
public void preSetter(boolean intercept, int propertyIndex, char[] oldValue, char[] newValue) {
if (state == STATE_NEW) {
setLoadedProperty(propertyIndex);
} else if (!Arrays.equals(oldValue, newValue)) {
@@ -1095,7 +1067,6 @@ public final class EntityBeanIntercept implements Serializable {
* byte[].
*/
public void preSetter(boolean intercept, int propertyIndex, byte[] oldValue, byte[] newValue) {
if (state == STATE_NEW) {
setLoadedProperty(propertyIndex);
} else if (!Arrays.equals(oldValue, newValue)) {
@@ -1126,6 +1097,17 @@ public final class EntityBeanIntercept implements Serializable {
this.sortOrder = sortOrder;
}
/**
* Set if the entity was deleted from a BeanCollection.
*/
public void setDeletedFromCollection(final boolean deletedFromCollection) {
this.deletedFromCollection = deletedFromCollection;
}
public boolean isOrphanDelete() {
return deletedFromCollection && !isNew();
}
/**
* Set the load error that happened on this property.
*/
@@ -61,6 +61,22 @@ public interface PersistenceContext {
*/
int size(Class<?> rootType);
/**
* Return a copy of the Persistence context to use for large query iteration.
*/
PersistenceContext forIterate();
/**
* Return a new Persistence context during iteration of large query result.
*/
PersistenceContext forIterateReset();
/**
* Return true if the persistence context has grown and hit the 'reset limit'
* during large query iteration.
*/
boolean resetLimit();
/**
* Wrapper on a bean to also indicate if a bean has been deleted.
* <p>
@@ -0,0 +1,48 @@
package io.ebean.bean;
import io.ebean.Database;
/**
* BeanLoader used when single beans are loaded (which is usually not ideal / N+1).
*/
public abstract class SingleBeanLoader implements BeanLoader {
protected final Database database;
SingleBeanLoader(Database database) {
this.database = database;
}
@Override
public String getName() {
return database.getName();
}
/**
* Single bean lazy loaded when bean from L2 cache.
*/
public static class L2 extends SingleBeanLoader {
public L2(Database database) {
super(database);
}
@Override
public void loadBean(EntityBeanIntercept ebi) {
database.getPluginApi().loadBeanL2(ebi);
}
}
/**
* Single bean lazy loaded when a reference bean.
*/
public static class Ref extends SingleBeanLoader {
public Ref(Database database) {
super(database);
}
@Override
public void loadBean(EntityBeanIntercept ebi) {
database.getPluginApi().loadBeanRef(ebi);
}
}
}
@@ -1,6 +1,6 @@
package io.ebean.common;
import io.ebean.Ebean;
import io.ebean.DB;
import io.ebean.ExpressionList;
import io.ebean.bean.BeanCollection;
import io.ebean.bean.BeanCollectionLoader;
@@ -93,7 +93,7 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
void lazyLoadCollection(boolean onlyIds) {
if (loader == null) {
loader = (BeanCollectionLoader) Ebean.getServer(ebeanServerName);
loader = (BeanCollectionLoader) DB.byName(ebeanServerName);
}
loader.loadMany(this, onlyIds);
checkEmptyLazyLoad();
@@ -1,5 +1,7 @@
package io.ebean.common;
import io.ebean.bean.EntityBean;
import java.io.Serializable;
import java.util.Collection;
import java.util.LinkedHashSet;
@@ -54,6 +56,11 @@ class ModifyHolder<E> implements Serializable {
void modifyAddition(E bean) {
if (bean != null) {
touched = true;
if (bean instanceof EntityBean) {
((EntityBean) bean)._ebean_getIntercept().setDeletedFromCollection(false);
}
// If it is to delete then just remove the deletion
if (!undoDeletion(bean)) {
// Insert
@@ -70,6 +77,11 @@ class ModifyHolder<E> implements Serializable {
void modifyRemoval(Object bean) {
if (bean != null) {
touched = true;
if (bean instanceof EntityBean) {
((EntityBean) bean)._ebean_getIntercept().setDeletedFromCollection(true);
}
// If it is to be added then just remove the addition
if (!undoAddition(bean)) {
modifyDeletions.add((E) bean);
@@ -83,10 +83,13 @@ public abstract class AbstractNamingConvention implements NamingConvention {
}
@Override
public String getSequenceName(String tableName, String pkColumn) {
String s = TABLE_REPLACE.matcher(sequenceFormat).replaceAll(Matcher.quoteReplacement(tableName));
public String getSequenceName(String rawTableName, String pkColumn) {
final String tableNameUnquoted = databasePlatform.unQuote(rawTableName);
String s = TABLE_REPLACE.matcher(sequenceFormat).replaceAll(Matcher.quoteReplacement(tableNameUnquoted));
if (pkColumn == null) {
pkColumn = "";
} else {
pkColumn = databasePlatform.unQuote(pkColumn);
}
return COLUMN_REPLACE.matcher(s).replaceAll(Matcher.quoteReplacement(pkColumn));
}
@@ -219,8 +222,8 @@ public abstract class AbstractNamingConvention implements NamingConvention {
* Return true if this class is part of entity inheritance.
*/
protected boolean hasInheritance(Class<?> supCls) {
return AnnotationUtil.findAnnotationRecursive(supCls, Inheritance.class) != null
|| AnnotationUtil.findAnnotation(supCls, DiscriminatorValue.class) != null;
return AnnotationUtil.typeHas(supCls, Inheritance.class)
|| AnnotationUtil.has(supCls, DiscriminatorValue.class);
}
@@ -252,16 +255,12 @@ public abstract class AbstractNamingConvention implements NamingConvention {
* Gets the table name from annotation.
*/
protected TableName getTableNameFromAnnotation(Class<?> beanClass) {
final Table t = AnnotationUtil.findAnnotationRecursive(beanClass, Table.class);
// Take the annotation if defined
if (t != null && !isEmpty(t.name())) {
final Table table = AnnotationUtil.typeGet(beanClass, Table.class);
if (table != null && !isEmpty(table.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(table.catalog()), quoteIdentifiers(table.schema()), quoteIdentifiers(table.name()));
}
// No annotation
return null;
}
@@ -88,7 +88,6 @@ public class DbConstraintNaming {
* Return the primary key constraint name.
*/
public String primaryKeyName(String tableName) {
return pkPrefix + normaliseTable(tableName) + pkSuffix;
}
@@ -103,7 +102,6 @@ public class DbConstraintNaming {
* 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;
}
@@ -112,7 +110,6 @@ public class DbConstraintNaming {
* 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;
}
@@ -121,7 +118,6 @@ public class DbConstraintNaming {
* 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;
}
@@ -130,7 +126,6 @@ public class DbConstraintNaming {
* 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;
}
@@ -139,7 +134,6 @@ public class DbConstraintNaming {
* Join the column names together with underscores.
*/
protected String joinColumnNames(String[] columns) {
if (columns.length == 1) {
return normaliseColumn(columns[0]);
}
@@ -157,7 +151,6 @@ public class DbConstraintNaming {
* Return the unique constraint name.
*/
public String uniqueConstraintName(String tableName, String columnName) {
return uqPrefix + normaliseTable(tableName) + "_" + normaliseColumn(columnName) + uqSuffix;
}
@@ -165,7 +158,6 @@ public class DbConstraintNaming {
* Return the unique constraint name.
*/
public String uniqueConstraintName(String tableName, String[] columns) {
String colPart = joinColumnNames(columns);
return uqPrefix + normaliseTable(tableName) + "_" + colPart + uqSuffix;
}
@@ -174,7 +166,6 @@ public class DbConstraintNaming {
* Return the check constraint name.
*/
public String checkConstraintName(String tableName, String columnName) {
return ckPrefix + normaliseTable(tableName) + "_" + normaliseColumn(columnName) + ckSuffix;
}
@@ -41,17 +41,20 @@ public class DbConstraintNormalise {
}
/**
* Normalise the column name by removing any quoted identifier characters.
* Normalise the column name by removing any quoted identifier characters and formula brackets.
*/
public String normaliseColumn(String columnName) {
columnName = trimQuotes(columnName);
columnName = trimBrackets(trimQuotes(columnName));
if (lowerCaseColumns) {
columnName = columnName.toLowerCase();
}
return columnName;
}
private String trimBrackets(String value) {
return value.replace("(","").replace(")","");
}
/**
* Lower case the table name checking for quoted identifiers.
*/
@@ -29,7 +29,7 @@ public class DocStoreConfig {
protected boolean create;
/**
* The URL of the Document store server. For example: http://localhost:9200.
* The URL of the Document store. For example: http://localhost:9200.
*/
protected String url;
@@ -131,7 +131,7 @@ public class DocStoreConfig {
}
/**
* Set the URL to the Document store server.
* Set the URL to the Document store.
* <p>
* For a local ElasticSearch server this would be: http://localhost:9200
*/
@@ -36,8 +36,7 @@ public class MatchingNamingConvention extends AbstractNamingConvention {
@Override
public TableName getTableNameByConvention(Class<?> beanClass) {
return new TableName(getCatalog(), getSchema(), beanClass.getSimpleName());
return new TableName(quoteIdentifiers(getCatalog()), quoteIdentifiers(getSchema()), quoteIdentifiers(beanClass.getSimpleName()));
}
@Override
@@ -0,0 +1,26 @@
package io.ebean.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Used by generated code to hold entity classes to register with Ebean.
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ModuleInfo {
/**
* Returns the entity classes with db name prefix.
* <p>
* The db name prefix is added to entity classes for non default databases.
*/
String[] entities() default {};
/**
* Other classes like Attribute Converters.
*/
String[] other() default {};
}
@@ -0,0 +1,19 @@
package io.ebean.config;
import java.util.List;
/**
* Loads and returns entity classes to register with Ebean databases.
*/
public interface ModuleInfoLoader {
/**
* Return the entity classes to register with the default DB.
*/
List<Class<?>> entityClasses();
/**
* Return entity classes to register for a named DB (not default DB).
*/
List<Class<?>> entityClassesFor(String dbName);
}
@@ -17,6 +17,13 @@ public class PlatformConfig {
private boolean allQuotedIdentifiers;
private DbConstraintNaming constraintNaming;
/**
* Flag set when a supplied constraintNaming is used.
*/
private boolean customConstraintNaming;
/**
* The database boolean true value (typically either 1, T, or Y).
*/
@@ -63,7 +70,7 @@ public class PlatformConfig {
* Construct with defaults.
*/
public PlatformConfig() {
this.constraintNaming = new DbConstraintNaming();
}
/**
@@ -80,6 +87,19 @@ public class PlatformConfig {
this.allQuotedIdentifiers = platformConfig.allQuotedIdentifiers;
this.databaseInetAddressVarchar = platformConfig.databaseInetAddressVarchar;
this.customDbTypeMappings = platformConfig.customDbTypeMappings;
this.constraintNaming = new DbConstraintNaming(!allQuotedIdentifiers);
}
public DbConstraintNaming getConstraintNaming() {
return constraintNaming;
}
/**
* Set a custom database constraint naming convention.
*/
public void setConstraintNaming(DbConstraintNaming constraintNaming) {
this.customConstraintNaming = true;
this.constraintNaming = constraintNaming;
}
/**
@@ -94,6 +114,9 @@ public class PlatformConfig {
*/
public void setAllQuotedIdentifiers(boolean allQuotedIdentifiers) {
this.allQuotedIdentifiers = allQuotedIdentifiers;
if (!customConstraintNaming) {
this.constraintNaming = new DbConstraintNaming(!allQuotedIdentifiers);
}
}
/**
+97 -172
View File
@@ -1,6 +1,7 @@
package io.ebean.config;
import com.fasterxml.jackson.core.JsonFactory;
import io.avaje.config.Config;
import io.ebean.DatabaseFactory;
import io.ebean.PersistenceContextScope;
import io.ebean.Query;
@@ -13,7 +14,6 @@ import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.config.dbplatform.DbEncrypt;
import io.ebean.config.dbplatform.DbType;
import io.ebean.config.dbplatform.IdType;
import io.ebean.config.properties.PropertiesLoader;
import io.ebean.datasource.DataSourceConfig;
import io.ebean.event.BeanFindController;
import io.ebean.event.BeanPersistController;
@@ -28,7 +28,6 @@ import io.ebean.event.changelog.ChangeLogPrepare;
import io.ebean.event.changelog.ChangeLogRegister;
import io.ebean.event.readaudit.ReadAuditLogger;
import io.ebean.event.readaudit.ReadAuditPrepare;
import io.ebean.meta.MetaInfoManager;
import io.ebean.migration.MigrationRunner;
import io.ebean.util.StringHelper;
@@ -45,6 +44,8 @@ import java.util.Properties;
import java.util.ServiceLoader;
/**
* Deprecated - please migrate to <code>io.ebean.DatabaseConfig</code>.
*
* The configuration used for creating a Database.
* <p>
* Used to programmatically construct a Database and optionally register it
@@ -81,6 +82,7 @@ import java.util.ServiceLoader;
* @author rbygrave
* @see DatabaseFactory
*/
@Deprecated
public class ServerConfig {
/**
@@ -133,6 +135,15 @@ public class ServerConfig {
private TenantCatalogProvider tenantCatalogProvider;
/**
* When true will load entity classes via ModuleInfoLoader.
* <p>
* NB: ModuleInfoLoader implementations are generated by querybean generator.
* Having this on and registering entity classes means we don't need to manually
* write that code or use classpath scanning to find entity classes.
*/
private boolean loadModuleInfo = true;
/**
* List of interesting classes such as entities, embedded, ScalarTypes,
* Listeners, Finders, Controllers etc.
@@ -323,18 +334,6 @@ public class ServerConfig {
*/
private ClassLoadConfig classLoadConfig = new ClassLoadConfig();
/**
* Set to true if the DataSource uses autoCommit.
* <p>
* Indicates that Ebean should use autoCommit friendly Transactions and TransactionManager.
*/
private boolean autoCommitMode;
/**
* Set to true if transaction begin should be started with explicit statement.
*/
private boolean explicitTransactionBeginMode;
/**
* The data source JNDI name if using a JNDI DataSource.
*/
@@ -345,26 +344,11 @@ 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;
/**
* Default behaviour for updates when cascade save on a O2M or M2M to delete any missing children.
*/
private boolean updatesDeleteMissingChildren = true;
/**
* Database platform configuration.
*/
@@ -425,10 +409,6 @@ public class ServerConfig {
private ServerCachePlugin serverCachePlugin;
private boolean collectQueryStatsByNode = true;
private boolean collectQueryOrigins = true;
/**
* The default PersistenceContextScope used if one is not explicitly set on a query.
*/
@@ -486,6 +466,11 @@ public class ServerConfig {
private String enabledL2Regions;
/**
* Set to true to effectively disable L2 cache plugins.
*/
private boolean localOnlyL2Cache;
/**
* Should the javax.validation.constraints.NotNull enforce a notNull column in DB.
* If set to false, use io.ebean.annotation.NotNull or Column(nullable=true).
@@ -503,6 +488,11 @@ public class ServerConfig {
*/
private boolean collectQueryPlans;
/**
* The default threshold in micros for collecting query plans.
*/
private long collectQueryPlanThresholdMicros = Long.MAX_VALUE;
/**
* The time in millis used to determine when a query is alerted for being slow.
*/
@@ -1615,14 +1605,14 @@ public class ServerConfig {
* Return the constraint naming convention used in DDL generation.
*/
public DbConstraintNaming getConstraintNaming() {
return constraintNaming;
return platformConfig.getConstraintNaming();
}
/**
* Set the constraint naming convention used in DDL generation.
*/
public void setConstraintNaming(DbConstraintNaming constraintNaming) {
this.constraintNaming = constraintNaming;
platformConfig.setConstraintNaming(constraintNaming);
}
/**
@@ -1746,42 +1736,6 @@ public class ServerConfig {
this.dataSourceJndiName = dataSourceJndiName;
}
/**
* Return true if autoCommit mode is on. This indicates to Ebean to use autoCommit friendly Transactions and TransactionManager.
*/
public boolean isAutoCommitMode() {
return autoCommitMode;
}
/**
* Set to true if autoCommit mode is on and Ebean should use autoCommit friendly Transactions and TransactionManager.
*/
public void setAutoCommitMode(boolean autoCommitMode) {
this.autoCommitMode = autoCommitMode;
}
/**
* Return true if transaction begin should be started with explicit statement.
*/
public boolean isExplicitTransactionBeginMode() {
return explicitTransactionBeginMode;
}
/**
* Set to true if transaction begin should be started with explicit statement.
* <p>
* This works for H2 and Postgres but not for Oracle - only use this if you first name
* is Daryl or you have explicitly talked to Rob about this feature.
* </p>
* <p>
* This is generally not expected to be turned on but instead allow transactions to start
* implicitly which is generally the standard approach.
* </p>
*/
public void setExplicitTransactionBeginMode(boolean explicitTransactionBeginMode) {
this.explicitTransactionBeginMode = explicitTransactionBeginMode;
}
/**
* Return a value used to represent TRUE in the database.
* <p>
@@ -1892,7 +1846,7 @@ public class ServerConfig {
}
/**
* Return the database platform to use for this server.
* Return the database platform to use for this database.
*/
public DatabasePlatform getDatabasePlatform() {
return databasePlatform;
@@ -2288,15 +2242,21 @@ public class ServerConfig {
* </p>
*
* @param cls the entity type (or other type) that should be registered by this
* server.
* database.
*/
public void addClass(Class<?> cls) {
if (classes == null) {
classes = new ArrayList<>();
}
classes.add(cls);
}
/**
* Register all the classes (typically entity classes).
*/
public void addAll(List<Class<?>> classList) {
if (classList != null && !classList.isEmpty()) {
classes.addAll(classList);
}
}
/**
* Add a package to search for entities via class path search.
* <p>
@@ -2304,9 +2264,6 @@ public class ServerConfig {
* </p>
*/
public void addPackage(String packageName) {
if (packages == null) {
packages = new ArrayList<>();
}
packages.add(packageName);
}
@@ -2332,7 +2289,7 @@ public class ServerConfig {
/**
* Set the list of classes (entities, listeners, scalarTypes etc) that should
* be used for this server.
* be used for this database.
* <p>
* If no classes are specified then the classes are found automatically via
* searching the class path.
@@ -2346,7 +2303,7 @@ public class ServerConfig {
}
/**
* Return the classes registered for this server. Typically this includes
* Return the classes registered for this database. Typically this includes
* entities and perhaps listeners.
*/
public List<Class<?>> getClasses() {
@@ -2409,20 +2366,6 @@ public class ServerConfig {
this.skipCacheAfterWrite = skipCacheAfterWrite;
}
/**
* Return true to only update changed properties.
*/
public boolean isUpdateChangesOnly() {
return updateChangesOnly;
}
/**
* Set to true to only update changed properties.
*/
public void setUpdateChangesOnly(boolean updateChangesOnly) {
this.updateChangesOnly = updateChangesOnly;
}
/**
* Returns true if updates in JDBC batch default to include all properties by default.
*/
@@ -2442,68 +2385,6 @@ public class ServerConfig {
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.
*/
public boolean isUpdatesDeleteMissingChildren() {
return updatesDeleteMissingChildren;
}
/**
* Set if updates by default delete missing children when cascading save to a OneToMany or
* ManyToMany. When not set this defaults to true.
*/
public void setUpdatesDeleteMissingChildren(boolean updatesDeleteMissingChildren) {
this.updatesDeleteMissingChildren = updatesDeleteMissingChildren;
}
/**
* Return true if query statistics should be collected by ObjectGraphNode.
*/
public boolean isCollectQueryStatsByNode() {
return collectQueryStatsByNode;
}
/**
* Set to true to collection query execution statistics by ObjectGraphNode.
* <p>
* These statistics can be used to highlight code/query 'origin points' that result in lots of lazy loading.
* </p>
* <p>
* It is considered safe/fine to have this set to true for production.
* </p>
* <p>
* This information can be later retrieved via {@link MetaInfoManager}.
* </p>
*
* @see MetaInfoManager
*/
public void setCollectQueryStatsByNode(boolean collectQueryStatsByNode) {
this.collectQueryStatsByNode = collectQueryStatsByNode;
}
/**
* Return true if query plans should also collect their 'origins'. This means for a given query plan you
* can identify the code/origin points where this query resulted from including lazy loading origins.
*/
public boolean isCollectQueryOrigins() {
return collectQueryOrigins;
}
/**
* Set to true if query plans should collect their 'origin' points. This means for a given query plan you
* can identify the code/origin points where this query resulted from including lazy loading origins.
* <p>
* This information can be later retrieved via {@link MetaInfoManager}.
* </p>
*
* @see MetaInfoManager
*/
public void setCollectQueryOrigins(boolean collectQueryOrigins) {
this.collectQueryOrigins = collectQueryOrigins;
}
/**
* Returns the resource directory.
*/
@@ -2825,7 +2706,7 @@ public class ServerConfig {
* Load settings from ebean.properties.
*/
public void loadFromProperties() {
this.properties = PropertiesLoader.load();
this.properties = Config.asProperties();
configureFromProperties();
}
@@ -2834,7 +2715,7 @@ public class ServerConfig {
*/
public void loadFromProperties(Properties properties) {
// keep the properties used for configuration so that these are available for plugins
this.properties = PropertiesLoader.eval(properties);
this.properties = Config.asConfiguration().eval(properties);
configureFromProperties();
}
@@ -2878,7 +2759,7 @@ public class ServerConfig {
*/
protected void loadDataSourceSettings(PropertiesWrapper p) {
dataSourceConfig.loadSettings(p.properties, name);
readOnlyDataSourceConfig.loadSettings(p.properties, name);
readOnlyDataSourceConfig.loadSettings(p.properties, name + "-ro");
}
/**
@@ -2929,18 +2810,19 @@ public class ServerConfig {
}
loadDocStoreSettings(p);
loadModuleInfo = p.getBoolean("loadModuleInfo", loadModuleInfo);
maxCallStack = p.getInt("maxCallStack", maxCallStack);
dumpMetricsOnShutdown = p.getBoolean("dumpMetricsOnShutdown", dumpMetricsOnShutdown);
dumpMetricsOptions = p.get("dumpMetricsOptions", dumpMetricsOptions);
queryPlanTTLSeconds = p.getInt("queryPlanTTLSeconds", queryPlanTTLSeconds);
slowQueryMillis = p.getLong("slowQueryMillis", slowQueryMillis);
collectQueryPlans = p.getBoolean("collectQueryPlans", collectQueryPlans);
collectQueryPlanThresholdMicros = p.getLong("collectQueryPlanThresholdMicros", collectQueryPlanThresholdMicros);
docStoreOnly = p.getBoolean("docStoreOnly", docStoreOnly);
disableL2Cache = p.getBoolean("disableL2Cache", disableL2Cache);
localOnlyL2Cache = p.getBoolean("localOnlyL2Cache", localOnlyL2Cache);
enabledL2Regions = p.get("enabledL2Regions", enabledL2Regions);
notifyL2CacheInForeground = p.getBoolean("notifyL2CacheInForeground", notifyL2CacheInForeground);
explicitTransactionBeginMode = p.getBoolean("explicitTransactionBeginMode", explicitTransactionBeginMode);
autoCommitMode = p.getBoolean("autoCommitMode", autoCommitMode);
useJtaTransactionManager = p.getBoolean("useJtaTransactionManager", useJtaTransactionManager);
useJavaxValidationNotNull = p.getBoolean("useJavaxValidationNotNull", useJavaxValidationNotNull);
autoReadOnlyDataSource = p.getBoolean("autoReadOnlyDataSource", autoReadOnlyDataSource);
@@ -2961,15 +2843,8 @@ public class ServerConfig {
String packagesProp = p.get("search.packages", p.get("packages", null));
packages = getSearchList(packagesProp, packages);
collectQueryStatsByNode = p.getBoolean("collectQueryStatsByNode", collectQueryStatsByNode);
collectQueryOrigins = p.getBoolean("collectQueryOrigins", collectQueryOrigins);
skipCacheAfterWrite = p.getBoolean("skipCacheAfterWrite", skipCacheAfterWrite);
updateAllPropertiesInBatch = p.getBoolean("updateAllPropertiesInBatch", updateAllPropertiesInBatch);
updateChangesOnly = p.getBoolean("updateChangesOnly", updateChangesOnly);
boolean defaultDeleteMissingChildren = p.getBoolean("defaultDeleteMissingChildren", updatesDeleteMissingChildren);
updatesDeleteMissingChildren = p.getBoolean("updatesDeleteMissingChildren", defaultDeleteMissingChildren);
if (p.get("batch.mode") != null || p.get("persistBatching") != null) {
throw new IllegalArgumentException("Property 'batch.mode' or 'persistBatching' is being set but no longer used. Please change to use 'persistBatchMode'");
@@ -3060,20 +2935,20 @@ public class ServerConfig {
return classes;
}
List<Class<?>> classes = new ArrayList<>();
List<Class<?>> classList = new ArrayList<>();
String[] split = StringHelper.splitNames(classNames);
for (String cn : split) {
if (!"class".equalsIgnoreCase(cn)) {
try {
classes.add(Class.forName(cn));
classList.add(Class.forName(cn));
} catch (ClassNotFoundException e) {
String msg = "Error registering class [" + cn + "] from [" + classNames + "]";
throw new RuntimeException(msg, e);
}
}
}
return classes;
return classList;
}
private List<String> getSearchList(String searchNames, List<String> defaultValue) {
@@ -3184,6 +3059,20 @@ public class ServerConfig {
this.disableL2Cache = disableL2Cache;
}
/**
* Return true to use local only L2 cache. Effectively ignore l2 cache plugin like ebean-redis etc.
*/
public boolean isLocalOnlyL2Cache() {
return localOnlyL2Cache;
}
/**
* Force the use of local only L2 cache. Effectively ignore l2 cache plugin like ebean-redis etc.
*/
public void setLocalOnlyL2Cache(boolean localOnlyL2Cache) {
this.localOnlyL2Cache = localOnlyL2Cache;
}
/**
* Returns if we use javax.validation.constraints.NotNull
*/
@@ -3327,6 +3216,20 @@ public class ServerConfig {
this.collectQueryPlans = collectQueryPlans;
}
/**
* Return the query plan collection threshold in microseconds.
*/
public long getCollectQueryPlanThresholdMicros() {
return collectQueryPlanThresholdMicros;
}
/**
* Set the query plan collection threshold in microseconds.
*/
public void setCollectQueryPlanThresholdMicros(long collectQueryPlanThresholdMicros) {
this.collectQueryPlanThresholdMicros = collectQueryPlanThresholdMicros;
}
/**
* Return true if metrics should be dumped when the server is shutdown.
*/
@@ -3357,6 +3260,28 @@ public class ServerConfig {
this.dumpMetricsOptions = dumpMetricsOptions;
}
/**
* Return true if entity classes should be loaded and registered via ModuleInfoLoader.
* <p>
* When false we either register entity classes via application code or use classpath
* scanning to find and register entity classes.
* </p>
*/
public boolean isAutoLoadModuleInfo() {
return loadModuleInfo && classes.isEmpty();
}
/**
* Set false to turn off automatic registration of entity beans.
* <p>
* When using query beans that also generates a module info class that
* can register the entity bean classes (to avoid classpath scanning).
* This is on by default and setting this to false turns it off.
*/
public void setLoadModuleInfo(boolean loadModuleInfo) {
this.loadModuleInfo = loadModuleInfo;
}
public enum UuidVersion {
VERSION4,
VERSION1,
@@ -43,11 +43,8 @@ public abstract class AbstractDbEncrypt implements DbEncrypt {
public DbEncryptFunction getDbEncryptFunction(int jdbcType) {
switch (jdbcType) {
case Types.VARCHAR:
return varcharEncryptFunction;
case Types.CLOB:
return varcharEncryptFunction;
case Types.CHAR:
return varcharEncryptFunction;
case Types.LONGVARCHAR:
return varcharEncryptFunction;
@@ -18,5 +18,10 @@ public enum DataErrorType {
/**
* Data integrity error like an invalid foreign key.
*/
DataIntegrity
DataIntegrity,
/**
* Non recoverable concurrency conflict.
*/
SerializableConflict
}
@@ -75,6 +75,11 @@ public class DatabasePlatform {
protected boolean caseSensitiveCollation = true;
/**
* Set true if the Database support LIMIT clause on sql update.
*/
protected boolean inlineSqlUpdateLimit;
/**
* For limit/offset, row_number etc limiting of SQL queries.
*/
@@ -141,9 +146,7 @@ public class DatabasePlatform {
protected String truncateTable = "truncate table %s";
protected String columnAliasPrefix = "c";
protected String tableAliasPlaceHolder = "${ta}";
protected String columnAliasPrefix;
/**
* Use a BackTick ` at the beginning and end of table or column names that you
@@ -171,13 +174,14 @@ public class DatabasePlatform {
/**
* Characters escaped for startsWith, endsWith and contains.
*/
protected char[] likeSpecialCharacters = { '%', '_', '|' };
protected char[] likeSpecialCharacters = {'%', '_', '|'};
protected DbEncrypt dbEncrypt;
protected boolean idInExpandedForm;
protected boolean selectCountWithAlias;
protected boolean selectCountWithColumnAlias;
/**
* If set then use the FORWARD ONLY hint when creating ResultSets for
@@ -187,7 +191,7 @@ public class DatabasePlatform {
/**
* If set then use the CONCUR_UPDATABLE hint when creating ResultSets.
*
* <p>
* This is {@code false} for HANA
*/
protected boolean supportsResultSetConcurrencyModeUpdatable = true;
@@ -274,7 +278,7 @@ public class DatabasePlatform {
* Return true if this matches the given platform.
*/
public boolean isPlatform(Platform platform) {
return this.platform == platform;
return this.platform.base() == platform;
}
/**
@@ -339,6 +343,13 @@ public class DatabasePlatform {
return supportsSavepointId;
}
/**
* Return true if the platform supports LIMIT with sql update.
*/
public boolean isInlineSqlUpdateLimit() {
return inlineSqlUpdateLimit;
}
/**
* Return the maximum table name length.
* <p>
@@ -370,11 +381,11 @@ public class DatabasePlatform {
/**
* Return a DB Sequence based IdGenerator.
*
* @param be the BackgroundExecutor that can be used to load the sequence if
* desired
* @param ds the DataSource
* @param stepSize the sequence allocation size as defined by mapping (defaults to 50)
* @param seqName the name of the sequence
* @param be the BackgroundExecutor that can be used to load the sequence if
* desired
* @param ds the DataSource
* @param stepSize the sequence allocation size as defined by mapping (defaults to 50)
* @param seqName the name of the sequence
*/
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int stepSize, String seqName) {
return null;
@@ -466,20 +477,6 @@ public class DatabasePlatform {
this.columnAliasPrefix = columnAliasPrefix;
}
/**
* Return the table alias placeholder.
*/
public String getTableAliasPlaceHolder() {
return tableAliasPlaceHolder;
}
/**
* Set the table alias placeholder.
*/
public void setTableAliasPlaceHolder(String tableAliasPlaceHolder) {
this.tableAliasPlaceHolder = tableAliasPlaceHolder;
}
/**
* Return the close quote for quoted identifiers.
*/
@@ -659,7 +656,7 @@ public class DatabasePlatform {
if (dbName != null && !dbName.isEmpty()) {
if (dbName.startsWith(openQuote)) {
// trim off the open and close quotes
return dbName.substring(1, dbName.length()-1);
return dbName.substring(1, dbName.length() - 1);
}
}
return dbName;
@@ -672,6 +669,14 @@ public class DatabasePlatform {
return selectCountWithAlias;
}
/**
* Return true if select count with subquery needs column alias (SQL Server).
*/
public boolean isSelectCountWithColumnAlias() {
return selectCountWithColumnAlias;
}
public String completeSql(String sql, Query<?> query) {
if (query.isForUpdate()) {
sql = withForUpdate(sql, query.getForUpdateMode());
@@ -786,7 +791,7 @@ public class DatabasePlatform {
for (int i = 0; i < value.length(); i++) {
char ch = value.charAt(i);
boolean escaped = false;
for (char escapeChar: likeSpecialCharacters) {
for (char escapeChar : likeSpecialCharacters) {
if (ch == escapeChar) {
if (sb == null) {
sb = new StringBuilder(value.substring(0, i));
@@ -7,30 +7,18 @@ package io.ebean.config.dbplatform;
* As an alternative to using DB encryption you can encrypt/decrypt in java via
* a special ScalarType but this has the limitation that you can't include that
* property in query where clauses.
* </p>
*
* @author rbygrave
*/
public interface DbEncrypt {
// /**
// * Return the SQL for decrypting a column returning a VARCHAR.
// */
// String getDecryptSql(String columnWithTableAlias);
//
// /**
// * Return the DB function with bind variables used to encrypt a VARCHAR
// * value.
// */
// String getEncryptBindSql();
/**
* Return the DB encrypt function for the given JDBC type.
*/
DbEncryptFunction getDbEncryptFunction(int jdbcType);
/**
* Return the DB type that encrypted Strings are stored in.
* <p>
* This is VARCHAR for MySql and VARBINARY for most others.
* </p>
*/
int getEncryptDbType();
@@ -29,6 +29,8 @@ public class DbPlatformTypeMapping {
private static final DbPlatformType INET_NATIVE = new DbPlatformType("inet", false);
private static final DbPlatformType INET_VARCHAR = new DbPlatformType("varchar", 50);
private static final DbPlatformType CIDR_NATIVE = new DbPlatformType("cidr", false);
private static final DbPlatformType CIDR_VARCHAR = new DbPlatformType("varchar", 50);
private static final DbPlatformType UUID_NATIVE = new DbPlatformType("uuid", false);
@SuppressWarnings("unused")
@@ -110,10 +112,11 @@ public class DbPlatformTypeMapping {
put(DbType.JSONVARCHAR, new DbPlatformType("jsonvarchar", 1000));
put(DbType.UUID, UUID_NATIVE);
put(DbType.INET, INET_NATIVE);
put(DbType.CIDR, CIDR_NATIVE);
} else {
put(DbType.VARCHAR, new DbPlatformType("varchar", 255));
put(DbType.DECIMAL, new DbPlatformType("decimal", 38));
put(DbType.DECIMAL, new DbPlatformType("decimal", 16, 3));
put(DbType.VARBINARY, new DbPlatformType("varbinary", 255));
put(DbType.BINARY, new DbPlatformType("binary", 255));
put(DbType.CHAR, new DbPlatformType("char", 1));
@@ -126,6 +129,7 @@ public class DbPlatformTypeMapping {
// default to native UUID and override on platform configure()
put(DbType.UUID, UUID_NATIVE);
put(DbType.INET, INET_VARCHAR);
put(DbType.CIDR, CIDR_VARCHAR);
}
}
@@ -36,7 +36,7 @@ public enum DbType {
UUID(ExtraDbTypes.UUID),
INET(ExtraDbTypes.INET),
CDIR(ExtraDbTypes.CDIR),
CIDR(ExtraDbTypes.CIDR),
POINT(ExtraDbTypes.POINT),
POLYGON(ExtraDbTypes.POLYGON),
@@ -41,7 +41,7 @@ public interface ExtraDbTypes {
int JSONBlob = 5005;
int INET = 5020;
int CDIR = 5021;
int CIDR = 5021;
/**
* Geo Point
@@ -35,6 +35,11 @@ public enum IdType {
* Used when the key is a compound key or lookup table code.
* </p>
*/
EXTERNAL
EXTERNAL,
/**
* Auto mapping to platform preferred identity strategy.
*/
AUTO
}
@@ -40,8 +40,7 @@ public class LimitOffsetSqlLimiter implements SqlLimiter {
}
String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
return new SqlLimitResponse(sql, false);
return new SqlLimitResponse(sql);
}
}
@@ -1,75 +0,0 @@
package io.ebean.config.dbplatform;
/**
* Adds the ROW_NUMBER() OVER function to a query.
*/
public class RowNumberSqlLimiter implements SqlLimiter {
/**
* ROW_NUMBER() OVER (ORDER BY
*/
private static final String ROW_NUMBER_OVER = "row_number() over (order by ";
/**
* ) as rn,
*/
private static final String ROW_NUMBER_AS = ") as rn, ";
private final String rowNumberWindowAlias;
/**
* Specify the name of the rowNumberWindowAlias.
*/
public RowNumberSqlLimiter(String rowNumberWindowAlias) {
this.rowNumberWindowAlias = rowNumberWindowAlias;
}
public RowNumberSqlLimiter() {
this("as limitresult");
}
@Override
public SqlLimitResponse limit(SqlLimitRequest request) {
String dbSql = request.getDbSql();
StringBuilder sb = new StringBuilder(60 + dbSql.length());
int firstRow = request.getFirstRow();
int lastRow = request.getMaxRows();
if (lastRow > 0) {
lastRow += firstRow;
}
sb.append("select * from ( ");
sb.append("select ");
if (request.isDistinct()) {
sb.append("distinct ");
}
sb.append(ROW_NUMBER_OVER);
sb.append(request.getDbOrderBy());
sb.append(ROW_NUMBER_AS);
sb.append(dbSql);
sb.append(" ) ");
sb.append(rowNumberWindowAlias);
sb.append(" where ");
if (firstRow > 0) {
sb.append(" rn > ").append(firstRow);
if (lastRow > 0) {
sb.append(" and ");
}
}
if (lastRow > 0) {
sb.append(" rn <= ").append(lastRow);
}
String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
return new SqlLimitResponse(sql, true);
}
}
@@ -1,81 +0,0 @@
package io.ebean.config.dbplatform;
/**
* Add ROWNUM column etc around SQL query to limit results.
*/
public class RownumSqlLimiter implements SqlLimiter {
private final String rnum;
private final boolean useFirstRowsHint;
/**
* Create with default inner rownum column alias and used FIRST_ROWS hint.
*/
public RownumSqlLimiter() {
this("rn_", true);
}
/**
* Specify the inner rownum column alias and whether to include the FIRST_ROWS
* hint.
*/
public RownumSqlLimiter(String rnum, boolean useFirstRowsHint) {
this.rnum = rnum;
this.useFirstRowsHint = useFirstRowsHint;
}
@Override
public SqlLimitResponse limit(SqlLimitRequest request) {
// select *
// from ( select /*+ FIRST_ROWS(n) */ ROWNUM rnum, a.*
// from ( your_query_goes_here,
// with order by ) a
// where ROWNUM <=
// :MAX_ROW_TO_FETCH )
// where rnum >= :MIN_ROW_TO_FETCH;
String dbSql = request.getDbSql();
StringBuilder sb = new StringBuilder(60 + dbSql.length());
int firstRow = request.getFirstRow();
int lastRow = request.getMaxRows();
if (lastRow > 0) {
lastRow += firstRow;
}
sb.append("select * from ( ");
sb.append("select ");
if (useFirstRowsHint && request.getMaxRows() > 0) {
sb.append("/*+ FIRST_ROWS(").append(request.getMaxRows()).append(") */ ");
}
sb.append("rownum ").append(rnum).append(", a.* ");
sb.append(" from (");
sb.append(" select ");
if (request.isDistinct()) {
sb.append("distinct ");
}
sb.append(dbSql);
sb.append(NEW_LINE).append(" ) a ");
if (lastRow > 0) {
sb.append(" where rownum <= ").append(lastRow);
}
sb.append(" ) ");
if (firstRow > 0) {
sb.append(" where ");
sb.append(rnum).append(" > ").append(firstRow);
}
String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
return new SqlLimitResponse(sql, true);
}
}
@@ -12,9 +12,10 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.NavigableSet;
import java.util.TreeSet;
/**
* Database sequence based IdGenerator.
@@ -42,7 +43,7 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
protected final BackgroundExecutor backgroundExecutor;
protected final ArrayList<Long> idList = new ArrayList<>(50);
protected final NavigableSet<Long> idList = new TreeSet<>();
protected final int allocationSize;
@@ -97,15 +98,13 @@ public abstract class SequenceIdGenerator implements PlatformIdGenerator {
@Override
public Object nextId(Transaction t) {
synchronized (monitor) {
int size = idList.size();
if (size > 0) {
maybeLoadMoreInBackground(size);
} else {
loadMore(allocationSize);
}
return idList.remove(0);
return idList.pollFirst();
}
}
@@ -3,6 +3,7 @@ package io.ebean.config.dbplatform;
import io.ebean.AcquireLockException;
import io.ebean.DataIntegrityException;
import io.ebean.DuplicateKeyException;
import io.ebean.SerializableConflictException;
import javax.persistence.PersistenceException;
import java.sql.SQLException;
@@ -14,12 +15,12 @@ import java.util.Map;
*/
public class SqlCodeTranslator implements SqlExceptionTranslator {
private final Map<String,DataErrorType> map;
private final Map<String, DataErrorType> map;
/**
* Create given the map of SQLState codes to error types.
*/
public SqlCodeTranslator(Map<String,DataErrorType> map) {
public SqlCodeTranslator(Map<String, DataErrorType> map) {
this.map = map;
}
@@ -46,6 +47,8 @@ public class SqlCodeTranslator implements SqlExceptionTranslator {
return new DuplicateKeyException(message, e);
case DataIntegrity:
return new DataIntegrityException(message, e);
case SerializableConflict:
return new SerializableConflictException(message, e);
}
}
// return a generic exception
@@ -8,7 +8,7 @@ import java.util.Map;
*/
public class SqlErrorCodes {
private final Map<String,DataErrorType> map = new HashMap<>();
private final Map<String, DataErrorType> map = new HashMap<>();
/**
* Map the codes to AcquireLockException.
@@ -31,6 +31,13 @@ public class SqlErrorCodes {
return add(DataErrorType.DuplicateKey, codes);
}
/**
* Map the codes to SerializableConflictException.
*/
public SqlErrorCodes addSerializableConflict(String... codes) {
return add(DataErrorType.SerializableConflict, codes);
}
private SqlErrorCodes add(DataErrorType type, String... codes) {
for (String code : codes) {
map.put(code, type);
@@ -7,14 +7,11 @@ public class SqlLimitResponse {
final String sql;
final boolean includesRowNumberColumn;
/**
* Create the response.
*/
public SqlLimitResponse(String sql, boolean includesRowNumberColumn) {
public SqlLimitResponse(String sql) {
this.sql = sql;
this.includesRowNumberColumn = includesRowNumberColumn;
}
/**
@@ -24,11 +21,4 @@ public class SqlLimitResponse {
return sql;
}
/**
* Returns true if a ROW_NUMBER column is used in the query.
*/
public boolean isIncludesRowNumberColumn() {
return includesRowNumberColumn;
}
}
@@ -16,10 +16,8 @@ public class ClickHousePlatform extends DatabasePlatform {
//this.dbEncrypt =
//this.historySupport =
//this.exceptionTranslator =
this.nativeUuidType = true;
this.dbDefaultValue.setNow("now()");
this.columnAliasPrefix = null;
this.dbIdentity.setIdType(IdType.IDENTITY);
this.dbIdentity.setSupportsGetGeneratedKeys(false);
@@ -34,7 +32,7 @@ public class ClickHousePlatform extends DatabasePlatform {
dbTypeMap.put(DbType.SMALLINT, new DbPlatformType("UInt16", false));
dbTypeMap.put(DbType.INTEGER, new DbPlatformType("UInt32", false));
dbTypeMap.put(DbType.BIGINT, new DbPlatformType("UInt64", false));
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("Decimal", 16,4));
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("Decimal", 16, 3));
dbTypeMap.put(DbType.DOUBLE, new DbPlatformType("Float64", false));
dbTypeMap.put(DbType.DATE, new DbPlatformType("Date", false));
@@ -47,7 +45,7 @@ public class ClickHousePlatform extends DatabasePlatform {
dbTypeMap.put(DbType.UUID, new DbPlatformType("UUID", false));
dbTypeMap.put(DbType.INET, new DbPlatformType("String", false));
dbTypeMap.put(DbType.CDIR, new DbPlatformType("String", false));
dbTypeMap.put(DbType.CIDR, new DbPlatformType("String", false));
}
@Override
@@ -0,0 +1,4 @@
/**
* Clickhouse DB specific support.
*/
package io.ebean.config.dbplatform.clickhouse;
@@ -0,0 +1,4 @@
/**
* Cockroach DB specific support.
*/
package io.ebean.config.dbplatform.cockroach;
@@ -42,8 +42,7 @@ public class DB2Platform extends DatabasePlatform {
dbTypeMap.put(DbType.INTEGER, new DbPlatformType("integer", false));
dbTypeMap.put(DbType.BIGINT, new DbPlatformType("bigint", false));
dbTypeMap.put(DbType.REAL, new DbPlatformType("real"));
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("decimal", 15));
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("decimal", 16, 3));
persistBatchOnCascade = PersistBatch.NONE;
}
@@ -22,6 +22,6 @@ public class Db2SqlLimiter implements SqlLimiter {
}
String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
return new SqlLimitResponse(sql, false);
return new SqlLimitResponse(sql);
}
}
@@ -24,8 +24,8 @@ public class H2Platform extends DatabasePlatform {
this.historySupport = new H2HistorySupport();
this.nativeUuidType = true;
this.supportsDeleteTableAlias = true;
this.inlineSqlUpdateLimit = true;
this.dbDefaultValue.setNow("now()");
this.columnAliasPrefix = null;
this.exceptionTranslator =
new SqlErrorCodes()
.addAcquireLock("50200","HYT00")
@@ -17,7 +17,6 @@ public class HanaPlatform extends DatabasePlatform {
this.sqlLimiter = new HanaSqlLimiter();
this.persistBatchOnCascade = PersistBatch.NONE;
this.supportsResultSetConcurrencyModeUpdatable = false;
this.columnAliasPrefix = null;
this.historySupport = new HanaHistorySupport();
this.basicSqlLimiter = new HanaBasicSqlLimiter();
@@ -29,7 +29,6 @@ public class HanaSqlLimiter implements SqlLimiter {
}
String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
return new SqlLimitResponse(sql, false);
return new SqlLimitResponse(sql);
}
}
}
@@ -0,0 +1,38 @@
package io.ebean.config.dbplatform.mariadb;
import io.ebean.config.dbplatform.DbStandardHistorySupport;
/**
* History support for MariaDB.
*/
public class MariaDbHistorySupport extends DbStandardHistorySupport {
/**
* Return the ' as of timestamp ?' clause appended after the table name.
*/
@Override
public String getAsOfViewSuffix(String asOfViewSuffix) {
return " for system_time as of ?";
}
@Override
public String getVersionsBetweenSuffix(String asOfViewSuffix) {
return " for system_time between ? and ?";
}
/**
* Returns the SQL Server specific effective start column.
*/
@Override
public String getSysPeriodLower(String tableAlias, String sysPeriod) {
return tableAlias + ".row_start";
}
/**
* Returns the SQL Server specific effective end column.
*/
@Override
public String getSysPeriodUpper(String tableAlias, String sysPeriod) {
return tableAlias + ".row_end";
}
}
@@ -0,0 +1,16 @@
package io.ebean.config.dbplatform.mariadb;
import io.ebean.annotation.Platform;
import io.ebean.config.dbplatform.mysql.BaseMySqlPlatform;
/**
* MariaDB platform.
*/
public class MariaDbPlatform extends BaseMySqlPlatform {
public MariaDbPlatform() {
super();
this.platform = Platform.MARIADB;
this.historySupport = new MariaDbHistorySupport();
}
}
@@ -0,0 +1,68 @@
package io.ebean.config.dbplatform.mysql;
import io.ebean.Query;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.config.dbplatform.DbPlatformType;
import io.ebean.config.dbplatform.DbType;
import io.ebean.config.dbplatform.IdType;
import io.ebean.config.dbplatform.SqlErrorCodes;
import java.sql.Types;
/**
* Base platform for both MySql and MariaDB.
*/
public abstract class BaseMySqlPlatform extends DatabasePlatform {
public BaseMySqlPlatform() {
super();
this.useExtraTransactionOnIterateSecondaryQueries = true;
this.selectCountWithAlias = true;
this.supportsSavepointId = false;
this.inlineSqlUpdateLimit = true;
this.dbEncrypt = new MySqlDbEncrypt();
this.historySupport = new MySqlHistorySupport();
this.dbIdentity.setIdType(IdType.IDENTITY);
this.dbIdentity.setSupportsGetGeneratedKeys(true);
this.dbIdentity.setSupportsIdentity(true);
this.dbIdentity.setSupportsSequence(false);
this.dbDefaultValue.setNow("now(6)"); // must have same precision as TIMESTAMP
this.dbDefaultValue.setFalse("0");
this.dbDefaultValue.setTrue("1");
this.exceptionTranslator =
new SqlErrorCodes()
.addAcquireLock("1205")
.addDuplicateKey("1062", "1169")
.addDataIntegrity("630", "839", "840", "893", "1215", "1216", "1217", "1364", "1451", "1452", "1557")
.build();
this.openQuote = "`";
this.closeQuote = "`";
// use pipe for escaping as it depends if mysql runs in no_backslash_escapes or not.
this.likeClauseRaw = "like ? escape''";
this.likeClauseEscaped = "like ? escape'|'";
this.forwardOnlyHintOnFindIterate = true;
this.booleanDbType = Types.BIT;
dbTypeMap.put(DbType.BIT, new DbPlatformType("tinyint(1)"));
dbTypeMap.put(DbType.BOOLEAN, new DbPlatformType("tinyint(1)"));
dbTypeMap.put(DbType.TIMESTAMP, new DbPlatformType("datetime(6)"));
dbTypeMap.put(DbType.CLOB, new MySqlClob());
dbTypeMap.put(DbType.BLOB, new MySqlBlob());
dbTypeMap.put(DbType.BINARY, new DbPlatformType("binary", 255));
dbTypeMap.put(DbType.VARBINARY, new DbPlatformType("varbinary", 255));
dbTypeMap.put(DbType.JSON, new DbPlatformType("json", false));
dbTypeMap.put(DbType.JSONB, new DbPlatformType("json", false));
}
@Override
protected String withForUpdate(String sql, Query.ForUpdate forUpdateMode) {
// NOWAIT and SKIP LOCKED currently not supported with MySQL
return sql + " for update";
}
}
@@ -0,0 +1,14 @@
package io.ebean.config.dbplatform.mysql;
import io.ebean.annotation.Platform;
import io.ebean.config.dbplatform.DbPlatformType;
import io.ebean.config.dbplatform.DbType;
public class MySql55Platform extends BaseMySqlPlatform {
public MySql55Platform() {
super();
this.platform = Platform.MYSQL55;
dbTypeMap.put(DbType.TIMESTAMP, new DbPlatformType("datetime"));
}
}
@@ -1,75 +1,15 @@
package io.ebean.config.dbplatform.mysql;
import io.ebean.Query;
import io.ebean.annotation.Platform;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.config.dbplatform.DbPlatformType;
import io.ebean.config.dbplatform.DbType;
import io.ebean.config.dbplatform.IdType;
import io.ebean.config.dbplatform.SqlErrorCodes;
import java.sql.Types;
/**
* MySQL specific platform.
* <p>
* <ul>
* <li>supportsGetGeneratedKeys = true</li>
* <li>Uses LIMIT OFFSET clause</li>
* <li>Uses ` for quoted identifiers</li>
* </ul>
* </p>
*/
public class MySqlPlatform extends DatabasePlatform {
public class MySqlPlatform extends BaseMySqlPlatform {
public MySqlPlatform() {
super();
this.platform = Platform.MYSQL;
this.useExtraTransactionOnIterateSecondaryQueries = true;
this.selectCountWithAlias = true;
this.supportsSavepointId = false;
this.dbEncrypt = new MySqlDbEncrypt();
this.historySupport = new MySqlHistorySupport();
this.columnAliasPrefix = null;
this.dbIdentity.setIdType(IdType.IDENTITY);
this.dbIdentity.setSupportsGetGeneratedKeys(true);
this.dbIdentity.setSupportsIdentity(true);
this.dbIdentity.setSupportsSequence(false);
this.dbDefaultValue.setNow("now(6)"); // must have same precision as TIMESTAMP
this.dbDefaultValue.setFalse("0");
this.dbDefaultValue.setTrue("1");
this.exceptionTranslator =
new SqlErrorCodes()
.addAcquireLock("1205")
.addDuplicateKey("1062", "1169")
.addDataIntegrity("630", "839", "840", "893", "1215", "1216", "1217", "1364", "1451", "1452", "1557")
.build();
this.openQuote = "`";
this.closeQuote = "`";
// use pipe for escaping as it depends if mysql runs in no_backslash_escapes or not.
this.likeClauseRaw = "like ? escape ''";
this.likeClauseEscaped = "like ? escape '|'";
this.forwardOnlyHintOnFindIterate = true;
this.booleanDbType = Types.BIT;
dbTypeMap.put(DbType.BIT, new DbPlatformType("tinyint(1)"));
dbTypeMap.put(DbType.BOOLEAN, new DbPlatformType("tinyint(1)"));
dbTypeMap.put(DbType.TIMESTAMP, new DbPlatformType("datetime(6)"));
dbTypeMap.put(DbType.CLOB, new MySqlClob());
dbTypeMap.put(DbType.BLOB, new MySqlBlob());
dbTypeMap.put(DbType.BINARY, new DbPlatformType("binary", 255));
dbTypeMap.put(DbType.VARBINARY, new DbPlatformType("varbinary", 255));
}
@Override
protected String withForUpdate(String sql, Query.ForUpdate forUpdateMode) {
// NOWAIT and SKIP LOCKED currently not supported with MySQL
return sql + " for update";
}
}
@@ -23,7 +23,6 @@ public class NuoDbPlatform extends DatabasePlatform {
this.idInExpandedForm = true;
this.supportsResultSetConcurrencyModeUpdatable = false;
this.supportsDeleteTableAlias = true;
this.columnAliasPrefix = null;
this.likeClauseRaw = "like ?";
this.historySupport = new NuoDbHistorySupport();
//this.dbEncrypt = ...
@@ -37,6 +36,7 @@ public class NuoDbPlatform extends DatabasePlatform {
new SqlErrorCodes()
//.addAcquireLock("")
.addDuplicateKey("23000")
.addSerializableConflict("40002")
.build();
dbTypeMap.put(DbType.INTEGER, new DbPlatformType("integer", false));
@@ -0,0 +1,4 @@
/**
* NuoDB specific support.
*/
package io.ebean.config.dbplatform.nuodb;
@@ -0,0 +1,18 @@
package io.ebean.config.dbplatform.oracle;
import io.ebean.annotation.Platform;
import io.ebean.config.dbplatform.IdType;
/**
* Oracle 11 platform using rownum sql limiting.
*/
public class Oracle11Platform extends OraclePlatform {
public Oracle11Platform() {
super();
this.platform = Platform.ORACLE11;
this.columnAliasPrefix = "c";
this.sqlLimiter = new OracleRownumSqlLimiter();
dbIdentity.setIdType(IdType.SEQUENCE);
}
}
@@ -0,0 +1,34 @@
package io.ebean.config.dbplatform.oracle;
import io.ebean.config.dbplatform.SqlLimitRequest;
import io.ebean.config.dbplatform.SqlLimitResponse;
import io.ebean.config.dbplatform.SqlLimiter;
/**
* Use ANSI offset rows syntax.
*/
class OracleAnsiSqlRowsLimiter implements SqlLimiter {
@Override
public SqlLimitResponse limit(SqlLimitRequest request) {
String dbSql = request.getDbSql();
StringBuilder sb = new StringBuilder(50 + dbSql.length());
int firstRow = request.getFirstRow();
int maxRows = request.getMaxRows();
sb.append("select ");
if (request.isDistinct()) {
sb.append("distinct ");
}
sb.append(dbSql);
if (firstRow > 0) {
sb.append(" offset ").append(firstRow).append(" rows");
}
if (maxRows > 0) {
sb.append(" fetch next ").append(maxRows).append(" rows only");
}
return new SqlLimitResponse(sb.toString());
}
}
@@ -9,7 +9,6 @@ import io.ebean.config.dbplatform.DbPlatformType;
import io.ebean.config.dbplatform.DbType;
import io.ebean.config.dbplatform.IdType;
import io.ebean.config.dbplatform.PlatformIdGenerator;
import io.ebean.config.dbplatform.RownumSqlLimiter;
import io.ebean.config.dbplatform.SqlErrorCodes;
import javax.sql.DataSource;
@@ -27,11 +26,11 @@ public class OraclePlatform extends DatabasePlatform {
this.maxTableNameLength = 30;
this.maxConstraintNameLength = 30;
this.dbEncrypt = new OracleDbEncrypt();
this.sqlLimiter = new RownumSqlLimiter();
this.sqlLimiter = new OracleAnsiSqlRowsLimiter();
this.basicSqlLimiter = new BasicSqlAnsiLimiter();
this.historySupport = new OracleDbHistorySupport();
this.truncateTable = "truncate table %s cascade";
dbIdentity.setIdType(IdType.SEQUENCE);
dbIdentity.setIdType(IdType.IDENTITY);
dbIdentity.setSupportsSequence(true);
dbIdentity.setSupportsIdentity(true);
dbIdentity.setSupportsGetGeneratedKeys(true);
@@ -48,6 +47,7 @@ public class OraclePlatform extends DatabasePlatform {
//.addAcquireLock("")
.addDuplicateKey("1")
.addDataIntegrity("2291")
.addSerializableConflict("72000")
.build();
this.openQuote = "\"";
@@ -62,8 +62,7 @@ public class OraclePlatform extends DatabasePlatform {
dbTypeMap.put(DbType.DOUBLE, new DbPlatformType("number", 19, 4));
dbTypeMap.put(DbType.SMALLINT, new DbPlatformType("number", 5));
dbTypeMap.put(DbType.TINYINT, new DbPlatformType("number", 3));
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("number", 38));
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("number", 16, 3));
dbTypeMap.put(DbType.VARCHAR, new DbPlatformType("varchar2", 255));
dbTypeMap.put(DbType.LONGVARBINARY, new DbPlatformType("blob"));
@@ -0,0 +1,54 @@
package io.ebean.config.dbplatform.oracle;
import io.ebean.config.dbplatform.SqlLimitRequest;
import io.ebean.config.dbplatform.SqlLimitResponse;
import io.ebean.config.dbplatform.SqlLimiter;
/**
* Add ROWNUM column etc around SQL query to limit results.
*/
class OracleRownumSqlLimiter implements SqlLimiter {
@Override
public SqlLimitResponse limit(SqlLimitRequest request) {
// select *
// from ( select /*+ FIRST_ROWS(n) */ a.*, ROWNUM rnum
// from ( your_query_goes_here,
// with order by ) a
// where ROWNUM <=
// :MAX_ROW_TO_FETCH )
// where rnum >= :MIN_ROW_TO_FETCH;
String dbSql = request.getDbSql();
StringBuilder sb = new StringBuilder(60 + dbSql.length());
int firstRow = request.getFirstRow();
int lastRow = request.getMaxRows();
if (lastRow > 0) {
lastRow += firstRow;
}
sb.append("select * from (select ");
if (request.getMaxRows() > 0) {
sb.append("/*+ FIRST_ROWS(").append(request.getMaxRows()).append(") */ ");
}
sb.append("a.*, rownum rn_ from (select ");
if (request.isDistinct()) {
sb.append("distinct ");
}
sb.append(dbSql).append(") a ");
if (lastRow > 0) {
sb.append(" where rownum <= ").append(lastRow);
}
sb.append(") ");
if (firstRow > 0) {
sb.append(" where rn_ > ").append(firstRow);
}
String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
return new SqlLimitResponse(sql);
}
}
@@ -1,22 +0,0 @@
package io.ebean.config.dbplatform.postgres;
import io.ebean.config.dbplatform.IdType;
/**
* Postgres v8.3 specific platform.
* <p>
* No support for getGeneratedKeys.
* </p>
*/
public class Postgres8Platform extends PostgresPlatform {
public Postgres8Platform() {
super();
this.dbIdentity.setSupportsGetGeneratedKeys(false);
this.dbIdentity.setIdType(IdType.SEQUENCE);
this.dbIdentity.setSupportsSequence(true);
this.dbIdentity.setSupportsIdentity(true);
this.columnAliasPrefix = "as c";
}
}
@@ -0,0 +1,14 @@
package io.ebean.config.dbplatform.postgres;
import io.ebean.annotation.Platform;
/**
* Postgres9 platform - uses serial type for identity columns.
*/
public class Postgres9Platform extends PostgresPlatform {
public Postgres9Platform() {
super();
this.platform = Platform.POSTGRES9;
}
}
@@ -19,10 +19,9 @@ import java.sql.SQLException;
import java.sql.Types;
/**
* Postgres v9 specific platform.
* Postgres 10+ platform.
* <p>
* Uses serial types and getGeneratedKeys.
* </p>
* Defaults to use "generated by default as identity".
*/
public class PostgresPlatform extends DatabasePlatform {
@@ -35,7 +34,6 @@ public class PostgresPlatform extends DatabasePlatform {
this.blobDbType = Types.LONGVARBINARY;
this.clobDbType = Types.VARCHAR;
this.nativeUuidType = true;
this.columnAliasPrefix = null;
this.truncateTable = "truncate table %s cascade";
this.dbEncrypt = new PostgresDbEncrypt();
this.historySupport = new PostgresHistorySupport();
@@ -44,6 +42,7 @@ public class PostgresPlatform extends DatabasePlatform {
this.dbIdentity.setIdType(IdType.IDENTITY);
this.dbIdentity.setSupportsGetGeneratedKeys(true);
this.dbIdentity.setSupportsSequence(true);
this.dbIdentity.setSupportsIdentity(true);
this.dbDefaultValue.setNow("current_timestamp");
@@ -51,7 +50,8 @@ public class PostgresPlatform extends DatabasePlatform {
new SqlErrorCodes()
.addAcquireLock("55P03")
.addDuplicateKey("23505")
.addDataIntegrity("23000","23502","23503","23514")
.addDataIntegrity("23000", "23502", "23503", "23514")
.addSerializableConflict("40001")
.build();
this.openQuote = "\"";
@@ -62,6 +62,7 @@ public class PostgresPlatform extends DatabasePlatform {
dbTypeMap.put(DbType.UUID, new DbPlatformType("uuid", false));
dbTypeMap.put(DbType.INET, new DbPlatformType("inet", false));
dbTypeMap.put(DbType.CIDR, new DbPlatformType("cidr", false));
dbTypeMap.put(DbType.HSTORE, new DbPlatformType("hstore", false));
dbTypeMap.put(DbType.JSON, new DbPlatformType("json", false));
dbTypeMap.put(DbType.JSONB, new DbPlatformType("jsonb", false));
@@ -69,7 +70,6 @@ public class PostgresPlatform extends DatabasePlatform {
dbTypeMap.put(DbType.INTEGER, new DbPlatformType("integer", false));
dbTypeMap.put(DbType.DOUBLE, new DbPlatformType("float"));
dbTypeMap.put(DbType.TINYINT, new DbPlatformType("smallint"));
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("decimal", 38));
dbTypeMap.put(DbType.TIMESTAMP, new DbPlatformType("timestamptz"));
dbTypeMap.put(DbType.BINARY, dbBytea);
@@ -126,7 +126,6 @@ public class PostgresPlatform extends DatabasePlatform {
@Override
public boolean tablePartitionsExist(Connection connection, String table) throws SQLException {
try (PreparedStatement statement = connection.prepareStatement("select count(*) from pg_inherits i WHERE i.inhparent = ?::regclass")) {
statement.setString(1, table);
try (ResultSet resultSet = statement.executeQuery()) {
@@ -137,18 +136,15 @@ public class PostgresPlatform extends DatabasePlatform {
/**
* Return SQL using built in partition helper functions to create some initial partitions.
*
* <p>
* Only use this if extra-ddl doesn't have some initial partitions defined (which it should).
*/
@Override
public String tablePartitionInit(String tableName, PartitionMode mode, String property, String pkey) {
if (property == null) {
property = "";
}
if (pkey == null) {
pkey = "";
}
return "select partition('" + mode.name().toLowerCase() + "','" + tableName + "','" + pkey + "','" + property + "',1);";
// default partition required pg11 but this is only used for testing but bumped test docker container to pg11 by default
return
"create table " + tableName + "_default" + " partition of " + tableName + " default;\n" +
"select partition('" + mode.name().toLowerCase() + "','" + tableName + "',1);";
}
}
@@ -35,8 +35,7 @@ public class SqlAnywhereLimiter implements SqlLimiter {
sb.append(dbSql);
String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
return new SqlLimitResponse(sql, false);
return new SqlLimitResponse(sql);
}
}
@@ -32,8 +32,7 @@ public class SqlAnywherePlatform extends DatabasePlatform {
dbTypeMap.put(DbType.REAL, new DbPlatformType("float(16)"));
dbTypeMap.put(DbType.DOUBLE, new DbPlatformType("float(32)"));
dbTypeMap.put(DbType.TINYINT, new DbPlatformType("smallint"));
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("numeric", 28));
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("numeric", 16, 3));
dbTypeMap.put(DbType.BLOB, new DbPlatformType("binary(4500)"));
dbTypeMap.put(DbType.CLOB, new DbPlatformType("long varchar"));
dbTypeMap.put(DbType.LONGVARBINARY, new DbPlatformType("long binary"));
@@ -12,7 +12,6 @@ public class SqlServer17Platform extends SqlServerBasePlatform {
public SqlServer17Platform() {
super();
this.platform = Platform.SQLSERVER17;
this.columnAliasPrefix = null;
this.nativeUuidType = true;
this.dbTypeMap.put(DbType.UUID, new DbPlatformType("uniqueidentifier", false));
}
@@ -1,11 +0,0 @@
package io.ebean.config.dbplatform.sqlserver;
/**
* SQL Server platform using the older ROW_NUMBER() mechanism.
*/
public class SqlServer2005Platform extends SqlServer16Platform {
public SqlServer2005Platform() {
this.sqlLimiter = new SqlServer2005SqlLimiter();
}
}
@@ -1,79 +0,0 @@
package io.ebean.config.dbplatform.sqlserver;
import io.ebean.config.dbplatform.SqlLimitRequest;
import io.ebean.config.dbplatform.SqlLimitResponse;
import io.ebean.config.dbplatform.SqlLimiter;
/**
* Use top and row_number() function to limit sql results.
*/
public class SqlServer2005SqlLimiter implements SqlLimiter {
final String rowNumberWindowAlias;
/**
* Specify the name of the rowNumberWindowAlias.
*/
public SqlServer2005SqlLimiter(String rowNumberWindowAlias) {
this.rowNumberWindowAlias = rowNumberWindowAlias;
}
public SqlServer2005SqlLimiter() {
this("as limitresult");
}
@Override
public SqlLimitResponse limit(SqlLimitRequest request) {
StringBuilder sb = new StringBuilder(500);
int firstRow = request.getFirstRow();
int lastRow = request.getMaxRows();
if (lastRow > 0) {
lastRow += firstRow;
}
if (firstRow < 1) {
// just use top n
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);
}
/*
* SELECT * FROM (SELECT TOP 20 ROW_NUMBER() OVER (ORDER BY ...) AS rn, ...)
* AS limitresult WHERE rn >= 11 AND rn <= 20
*/
sb.append("select * ").append(NEW_LINE).append("from ( ");
sb.append("select ");
if (request.isDistinct()) {
sb.append("distinct ");
}
sb.append("top ").append(lastRow);
sb.append(" row_number() over (order by ");
sb.append(request.getDbOrderBy());
sb.append(") as rn, ");
sb.append(request.getDbSql());
sb.append(NEW_LINE).append(") ");
sb.append(rowNumberWindowAlias);
sb.append(" where ");
sb.append(" rn > ").append(firstRow);
if (lastRow > 0) {
sb.append(" and ");
sb.append(" rn <= ").append(lastRow);
}
String sql = request.getDbPlatform().completeSql(sb.toString(), request.getOrmQuery());
return new SqlLimitResponse(sql, true);
}
}
@@ -28,6 +28,7 @@ abstract class SqlServerBasePlatform extends DatabasePlatform {
this.persistBatchOnCascade = PersistBatch.NONE;
this.idInExpandedForm = true;
this.selectCountWithAlias = true;
this.selectCountWithColumnAlias = true;
this.sqlLimiter = new SqlServerSqlLimiter();
this.basicSqlLimiter = new SqlServerBasicSqlLimiter();
this.historySupport = new SqlServerHistorySupport();
@@ -61,9 +62,7 @@ abstract class SqlServerBasePlatform extends DatabasePlatform {
dbTypeMap.put(DbType.REAL, new DbPlatformType("float(16)"));
dbTypeMap.put(DbType.DOUBLE, new DbPlatformType("float(32)"));
dbTypeMap.put(DbType.TINYINT, new DbPlatformType("smallint"));
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("numeric", 28));
dbTypeMap.put(DbType.DECIMAL, new DbPlatformType("numeric", 16, 3));
dbTypeMap.put(DbType.DATE, new DbPlatformType("date"));
dbTypeMap.put(DbType.TIME, new DbPlatformType("time"));
dbTypeMap.put(DbType.TIMESTAMP, new DbPlatformType("datetime2"));
@@ -29,7 +29,7 @@ public class SqlServerSqlLimiter implements SqlLimiter {
}
sb.append("top ").append(maxRows).append(" ");
sb.append(dbSql);
return new SqlLimitResponse(sb.toString(), false);
return new SqlLimitResponse(sb.toString());
}
sb.append("select ");
@@ -43,8 +43,7 @@ public class SqlServerSqlLimiter implements SqlLimiter {
if (maxRows > 0) {
sb.append(" fetch next ").append(maxRows).append(" rows only");
}
String sql = sb.toString();
return new SqlLimitResponse(sql, false);
return new SqlLimitResponse(sb.toString());
}
}
@@ -1,106 +0,0 @@
package io.ebean.config.properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
/**
* Manages the underlying map of properties we are gathering.
*/
class LoadContext {
private static final Logger log = LoggerFactory.getLogger(LoadContext.class);
/**
* Map we are loading the properties into.
*/
private final Map<String, String> map = new LinkedHashMap<>();
/**
* Names of resources/files that were loaded.
*/
private final Set<String> loadedResources = new LinkedHashSet<>();
/**
* Return the input stream (maybe null) for the given source.
*/
InputStream resource(String resourcePath, Loader.Source source) {
InputStream is = null;
if (source == Loader.Source.RESOURCE) {
is = resourceStream(resourcePath);
if (is != null) {
loadedResources.add(resourcePath);
}
} else {
File file = new File(resourcePath);
if (file.exists()) {
try {
is = new FileInputStream(file);
loadedResources.add("file:" + resourcePath);
} catch (FileNotFoundException e) {
throw new IllegalStateException(e);
}
}
}
return is;
}
private InputStream resourceStream(String resourcePath) {
InputStream is = getClass().getResourceAsStream("/" + resourcePath);
if (is == null) {
// search the module path for top level resource
is = ClassLoader.getSystemResourceAsStream(resourcePath);
}
return is;
}
/**
* Add a property entry.
*/
void put(String key, String val) {
if (val != null) {
val = val.trim();
}
map.put(key, val);
}
/**
* Evaluate all the expressions and return as a Properties object.
*/
Properties eval() {
log.info("loaded properties from {}", loadedResources);
Properties properties = new Properties();
for (Map.Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String value = PropertyEval.eval(entry.getValue());
properties.setProperty(key, value);
}
return properties;
}
/**
* Read the special properties that can point to an external properties source.
*/
String indirectLocation() {
String indirectLocation = map.get("load.properties");
if (indirectLocation == null) {
indirectLocation = map.get("load.properties.override");
}
return indirectLocation;
}
}
@@ -1,181 +0,0 @@
package io.ebean.config.properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Properties;
/**
* Loads the configuration from known/expected locations.
* <p>
* Defines the loading order of resources and files.
* </p>
*/
class Loader {
private static final Logger log = LoggerFactory.getLogger(Loader.class);
enum Source {
RESOURCE,
FILE
}
private final LoadContext loadContext = new LoadContext();
private YamlLoader yamlLoader;
Loader() {
String skipYaml = System.getProperty("ebeanSkipYaml");
if (!"true".equals(skipYaml)) {
try {
Class<?> exists = Class.forName("org.yaml.snakeyaml.Yaml");
if (exists != null) {
yamlLoader = new YamlLoader(loadContext);
}
} catch (Exception e) {
// ignored
}
}
}
/**
* Load the configuration with the expected ordering.
*/
void load() {
loadMain(Source.RESOURCE);
// external file configuration overrides the resources configuration
loadMain(Source.FILE);
loadViaSystemProperty();
loadViaIndirection();
// test configuration (if found) overrides main configuration
// we should only find these resources when running tests
loadTest();
}
/**
* Load test configuration.
*/
private void loadTest() {
loadProperties("application-test.properties", Source.RESOURCE);
loadYaml("application-test.yaml", Source.RESOURCE);
loadYaml("application-test.yml", Source.RESOURCE);
loadProperties("test-ebean.properties", Source.RESOURCE);
}
/**
* Load configuration defined by a <em>load.properties</em> entry in properties file.
*/
private void loadViaIndirection() {
String location = loadContext.indirectLocation();
if (location != null) {
location = PropertyEval.eval(location);
loadWithExtensionCheck(location);
}
}
/**
* Load the main configuration for the given source.
*/
private void loadMain(Source source) {
loadYaml("application.yaml", source);
loadYaml("application.yml", source);
loadProperties("application.properties", source);
loadProperties("ebean.properties", source);
}
private void loadViaSystemProperty() {
String fileName = System.getenv("EBEAN_PROPS_FILE");
if (fileName == null) {
fileName = System.getProperty("ebean.props.file");
if (fileName != null) {
loadWithExtensionCheck(fileName);
}
} else {
loadWithExtensionCheck(fileName);
}
}
void loadWithExtensionCheck(String fileName) {
if (fileName.endsWith("yaml") || fileName.endsWith("yml")) {
loadYaml(fileName, Source.FILE);
} else if (fileName.endsWith("properties")) {
loadProperties(fileName, Source.FILE);
} else {
throw new IllegalArgumentException("Expecting only yml or properties file but got [" + fileName + "]");
}
}
/**
* Evaluate all the configuration entries and return as properties.
*/
Properties eval() {
return loadContext.eval();
}
void loadYaml(String resourcePath, Source source) {
if (yamlLoader != null) {
try {
try (InputStream is = resource(resourcePath, source)) {
yamlLoader.load(is);
}
} catch (Exception e) {
log.warn("Failed to read yml from:" + resourcePath, e);
}
}
}
void loadProperties(String resourcePath, Source source) {
try {
try (InputStream is = resource(resourcePath, source)) {
if (is != null) {
loadProperties(is);
}
}
} catch (Exception e) {
log.warn("Failed to read properties from:" + resourcePath, e);
}
}
private InputStream resource(String resourcePath, Source source) {
return loadContext.resource(resourcePath, source);
}
private void loadProperties(InputStream is) {
if (is != null) {
try {
Properties properties = new Properties();
properties.load(is);
put(properties);
} catch (IOException e) {
throw new RuntimeException("Failed to load properties?", e);
} finally {
close(is);
}
}
}
private void put(Properties properties) {
Enumeration<?> enumeration = properties.propertyNames();
while (enumeration.hasMoreElements()) {
String key = (String) enumeration.nextElement();
String property = properties.getProperty(key);
loadContext.put(key, property);
}
}
private void close(InputStream is) {
try {
is.close();
} catch (IOException e) {
log.warn("Error closing input stream for properties", e);
}
}
}
@@ -1,74 +0,0 @@
package io.ebean.config.properties;
import java.util.Enumeration;
import java.util.Properties;
/**
* Loads and evaluates properties and yml configuration.
*/
public class PropertiesLoader {
private static Properties properties;
/**
* Provides properties by reading known locations.
* <p>
* <h3>Main configuration</h3>
* <p>
* <p>Firstly loads from main resources</p>
* <pre>
* - application.properties
* - application.yaml
* - ebean.properties
* </pre>
* <p>
* <p>Then loads from local files</p>
* <pre>
* - application.properties
* - application.yaml
* - ebean.properties
* </pre>
* <p>
* <p>Then loads from environment variable <em>EBEAN_PROPS_FILE</em></p>
* <p>Then loads from system property <em>ebean.props.file</em></p>
* <p>Then loads from <em>load.properties</em></p>
* <p>
* <h3>Test configuration</h3>
* <p>
* Once the main configuration is read it will try to read common test configuration.
* This will only be successful if the test resources are available (i.e. running tests).
* </p>
* <p>Loads from test resources</p>
* <pre>
* - application-test.properties
* - application-test.yaml
* - test-ebean.properties
* </pre>
*/
public static synchronized Properties load() {
if (properties == null) {
Loader loader = new Loader();
loader.load();
properties = loader.eval();
}
return properties;
}
/**
* Return a copy of the properties with 'eval' run on all the values.
* This resolves expressions like ${HOME} etc.
*/
public static Properties eval(Properties properties) {
Properties evalCopy = new Properties();
Enumeration<?> names = properties.propertyNames();
while (names.hasMoreElements()) {
String name = (String)names.nextElement();
String value = PropertyEval.eval(properties.getProperty(name));
evalCopy.setProperty(name, value);
}
return evalCopy;
}
}
@@ -1,205 +0,0 @@
package io.ebean.config.properties;
import javax.naming.InitialContext;
import javax.naming.NamingException;
/**
* Helper used to evaluate expressions such as ${CATALINA_HOME}.
* <p>
* The expressions can contain environment variables, system properties or JNDI
* properties. JNDI expressions take the form ${jndi:propertyName} where you
* substitute propertyName with the name of the jndi property you wish to
* evaluate.
* </p>
*/
final class PropertyEval {
/**
* Prefix for looking up JNDI Environment variable.
*/
private static final String JAVA_COMP_ENV = "java:comp/env/";
/**
* Used to detect the start of an expression.
*/
private static final String START = "${";
/**
* Used to detect the end of an expression.
*/
private static final String END = "}";
/**
* Specify the PropertyHolder.
*/
private PropertyEval() {
}
/**
* Return the property value evaluating and replacing any expressions such as
* ${CATALINA_HOME}.
*/
static String eval(String val) {
if (val == null) {
return null;
}
int sp = val.indexOf(START);
if (sp > -1) {
int ep = val.indexOf(END, sp + 1);
if (ep > -1) {
return eval(val, sp, ep);
}
}
return val;
}
/**
* Convert the expression using JNDI, Environment variables, System Properties
* or existing an property in SystemProperties itself.
*/
private static String evaluateExpression(String exp) {
if (exp.isEmpty()) {
return null;
}
if (isJndiExpression(exp)) {
// JNDI property lookup...
String val = getJndiProperty(exp);
if (val != null) {
return val;
}
}
String val = System.getProperty(exp);
if (val == null) {
val = System.getenv(exp);
}
return val;
}
private static String eval(String val, int sp, int ep) {
return new EvalBuffer(val, sp, ep).process();
}
private static boolean isJndiExpression(String exp) {
return exp.startsWith("JNDI:") || exp.startsWith("jndi:");
}
/**
* Returns null if JNDI is not setup or if the property is not found.
*
* @param key the key of the JNDI Environment property including a JNDI: prefix.
*/
private static String getJndiProperty(String key) {
try {
// remove the JNDI: prefix
key = key.substring(5);
return (String) getJndiObject(key);
} catch (NamingException ex) {
return null;
}
}
/**
* Similar to getProperty but throws NamingException if JNDI is not setup or
* if the property is not found.
*/
private static Object getJndiObject(String key) throws NamingException {
InitialContext ctx = new InitialContext();
return ctx.lookup(JAVA_COMP_ENV + key);
}
private static class EvalBuffer {
private final StringBuilder buf = new StringBuilder();
private final String original;
private int position;
private int start;
private int end;
private String expression;
private String defaultValue;
EvalBuffer(String val, int start, int ep) {
this.original = val;
this.start = start;
this.end = ep;
this.position = 0;
moveToStart();
}
void moveToStart() {
if (start > position) {
buf.append(original.substring(position, start));
position = start;
}
}
void parseForDefault() {
int colonPos = original.lastIndexOf(':', end);
if (colonPos > start) {
expression = original.substring(start + START.length(), colonPos);
defaultValue = original.substring(colonPos + 1, end);
} else {
expression = original.substring(start + START.length(), end);
}
}
void evaluate() {
String eval = evaluateExpression(expression);
if (eval != null) {
buf.append(eval);
} else {
if (defaultValue != null) {
buf.append(defaultValue);
} else {
buf.append(START).append(expression).append(END);
}
}
}
String end() {
if (end < original.length() - 1) {
buf.append(original.substring(end + 1));
}
return buf.toString();
}
boolean next() {
if (end < original.length()) {
int startPos = original.indexOf(START, end + 1);
if (startPos > -1) {
int endPos = original.indexOf(END, startPos + 1);
if (endPos > -1) {
if (startPos > end + 1) {
buf.append(original.substring(end + 1, startPos));
}
this.start = startPos;
this.end = endPos;
return true;
}
}
}
return false;
}
private void evalNext() {
parseForDefault();
evaluate();
}
String process() {
evalNext();
while (next()) {
evalNext();
}
return end();
}
}
}
@@ -1,58 +0,0 @@
package io.ebean.config.properties;
import org.yaml.snakeyaml.Yaml;
import java.io.InputStream;
import java.util.Map;
/**
* Loads configuration from Yml into the load context.
* <p>
* Note that this ignores 'lists' so just reads 'maps' and scalar values.
* </p>
*/
class YamlLoader {
private final Yaml yaml = new Yaml();
private final LoadContext loadContext;
YamlLoader(LoadContext loadContext) {
this.loadContext = loadContext;
}
@SuppressWarnings("unchecked")
void load(InputStream is) {
if (is != null) {
for (Object map : yaml.loadAll(is)) {
loadMap((Map<String, Object>)map, null);
}
}
}
@SuppressWarnings("unchecked")
void loadMap(Map<String, Object> map, String path) {
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
if (path != null) {
key = path + "." + key;
}
Object val = entry.getValue();
if (val instanceof Map) {
loadMap((Map<String, Object>) val, key);
} else {
addScalar(key, val);
}
}
}
private void addScalar(String key, Object val) {
if (val instanceof String) {
loadContext.put(key, (String) val);
} else if (val instanceof Number || val instanceof Boolean) {
loadContext.put(key, val.toString());
}
}
}
@@ -1,6 +1,6 @@
package io.ebean.dbmigration;
import io.ebean.EbeanServer;
import io.ebean.Database;
import io.ebean.annotation.Platform;
import io.ebean.config.ServerConfig;
import io.ebean.config.dbplatform.DatabasePlatform;
@@ -62,11 +62,28 @@ public interface DbMigration {
*/
void setPathToResources(String pathToResources);
/**
* Set the path where migrations are generated to (which defaults to "dbmigration").
* <p>
* Normally we only use this when we use Ebean to generate the database migrations
* and then use some other tool like FlywayDB to run the migrations.
* <p>
* Example: with <code>setMigrationPath("db/migration")</code> ... the migrations
* are generated into <code>src/resources/db/migration</code>.
* <p>
* Note that if Ebean migration runner is used we should not use this method but
* instead set the migrationPath via a property such that both the migration generator
* and migration runner both use the same path.
*
* @param migrationPath The path that migrations are generated into.
*/
void setMigrationPath(String migrationPath);
/**
* Set the server to use to determine the current model.
* Typically this is not called explicitly.
*/
void setServer(EbeanServer ebeanServer);
void setServer(Database database);
/**
* Set the serverConfig to use. Typically this is not called explicitly.
@@ -76,7 +93,7 @@ public interface DbMigration {
/**
* Set the specific platform to generate DDL for.
* <p>
* If not set this defaults to the platform of the default server.
* If not set this defaults to the platform of the default database.
* </p>
*/
void setPlatform(Platform platform);
@@ -84,7 +101,7 @@ public interface DbMigration {
/**
* Set the specific platform to generate DDL for.
* <p>
* If not set this defaults to the platform of the default server.
* If not set this defaults to the platform of the default database.
* </p>
*/
void setPlatform(DatabasePlatform databasePlatform);
@@ -136,6 +153,23 @@ public interface DbMigration {
*/
void setGeneratePendingDrop(String generatePendingDrop);
/**
* Set to true if ALTER TABLE ADD FOREIGN KEY should be generated with an option to skip validation.
* <p>
* Currently this is only useful for Postgres DDL adding the <code>NOT VALID</code> option.
* </p>
*/
void setAddForeignKeySkipCheck(boolean addForeignKeySkipCheck);
/**
* Set the lock timeout to be included with the DDL generation.
* <p>
* Currently this is only useful for Postgres migrations adding a <code>set lock_timeout</code>
* statement to the generated database migration.
* </p>
*/
void setLockTimeout(int seconds);
/**
* Add an additional platform to write the migration DDL.
* <p>
@@ -198,6 +232,7 @@ public interface DbMigration {
* An "init" migration can only be executed and used on a database that has had no
* prior migrations run on it.
* </p>
*
* @return the version of the generated migration
*/
String generateInitMigration() throws IOException;

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