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
rob bygrave fea6dfd62b [maven-release-plugin] prepare release ebean-11.43.1 2019-08-16 00:00:31 +12:00
rob bygrave 464ed4322e #1794 - Also support "inRange" camelcase version of "inrange" in EQL 2019-08-15 23:58:58 +12:00
rob bygrave c3f556f0dc #1794 - Extend EQL to support inOrEmpty, eqOrNull, gtOrNull, ltOrNull 2019-08-15 23:40:19 +12:00
rob bygrave ba6810891e Bump to 11.43.1-SNAPSHOT 2019-08-15 22:20:09 +12:00
rob bygrave c530883e5e #1793 - ENH: Add filterMany() that takes expressions ... as a simpler option 2019-08-15 22:05:46 +12:00
rob bygrave 06542b031e Initial refactor to extract EqlWhereListener 2019-08-15 20:21:01 +12:00
rob bygrave 4b5365e708 #1792 - ENH: Support using Query beans for building FetchGroup (in a type safe manor) 2019-08-14 22:52:18 +12:00
Rob BygraveandGitHub 1d471fee92 #1768 - Initial refactor extracting CallOrigin interface (#1791) 2019-08-14 17:02:57 +12:00
rob bygrave 3825dea00a [maven-release-plugin] prepare for next development iteration 2019-08-12 21:12:45 +12:00
rob bygrave 3fd130ac4c [maven-release-plugin] prepare release ebean-11.42.3 2019-08-12 21:12:34 +12:00
rob bygrave 196645e7a2 #1789 - Add default constructor to EntityBeanIntercept for serialisation framework use only 2019-08-12 21:09:31 +12:00
rob bygrave f5459920e9 #1785 - Bean gets replaced on json deserialization with primitive 'null' id 2019-08-12 21:05:32 +12:00
rob bygrave ee6452cfb0 #1788 - ENH: Add support for NuoDB database platform 2019-08-12 20:41:45 +12:00
rob bygrave ad7e18561b #1788 - ENH: Add support for NuoDB database platform
Remove the extra truncate
2019-08-11 16:43:24 +12:00
rob bygrave c640524bfc #1788 - ENH: Add support for NuoDB database platform 2019-08-11 16:24:37 +12:00
rob bygrave fea840c859 #1782 - ENH: Add truncate(Class<?>... types) and truncate(String... tables)
Remove truncateTableBefore and truncateTableAfter for now
2019-08-10 21:44:48 +12:00
rob bygrave bb7df71391 #1782 - ENH: Add truncate(Class<?>... types) and truncate(String... tables) 2019-08-10 21:40:23 +12:00
rob bygrave cb6f0335b1 #1787 - Update CockroachDB support for DDL generation with autocommit and no history support 2019-08-08 23:22:58 +12:00
rob bygrave 762899ef10 [maven-release-plugin] prepare for next development iteration 2019-08-07 22:43:12 +12:00
rob bygrave 848d4f031e [maven-release-plugin] prepare release ebean-11.42.2 2019-08-07 22:42:59 +12:00
rob bygrave 481f828507 Bump provided scope jackson-databind version to 2.9.9.2 for security warning
This should have no effect as the dependency is scope provided.
2019-08-07 22:40:57 +12:00
rob bygrave b3d0c21a80 #1783 - Save bean with only *ToMany relations with user generated ID 2019-08-07 22:28:51 +12:00
rob bygrave a115cdf095 #1784 - Tests related to NPE with IDEA plugin and mockito 3.0.0 2019-08-07 21:38:52 +12:00
rob bygrave 410e9d475b [maven-release-plugin] prepare for next development iteration 2019-07-31 23:27:53 +12:00
rob bygrave 462385c7d0 [maven-release-plugin] prepare release ebean-11.42.1 2019-07-31 23:27:42 +12:00
rob bygrave 3655e2c6f8 #1778 - Bump jackson-core.version from 2.9.8 to 2.9.9 2019-07-31 23:25:30 +12:00
rob bygrave 318f6ae3f5 Bump to 11.42.1-SNAPSHOT 2019-07-31 23:21:01 +12:00
rob bygrave c63acad7e0 No effective change - updated review ddl 2019-07-29 23:45:20 +12:00
rob bygrave 6dba4a3d28 #1763 - Change such that db-create-all.sql and db-drop-all.sql generated files go into target (maven) or build (gradle) directories 2019-07-29 23:26:45 +12:00
rob bygrave ecf1e53616 [maven-release-plugin] prepare for next development iteration 2019-07-29 22:49:48 +12:00
rob bygrave 0ff9a00427 [maven-release-plugin] prepare release ebean-11.41.4 2019-07-29 22:49:36 +12:00
rob bygrave 725ff8dc58 git push origin masterMerge branch 'FOCONIS-bug-refresh-one-to-many' 2019-07-29 22:46:55 +12:00
rob bygrave a780dc133e #1776 Fix for - refresh does not work on oneToMany if property was not yet accessed 2019-07-29 22:46:39 +12:00
Roland Praml b111fcfecc refresh does not work on oneToMany if property was not yet accessed
(cherry picked from commit 446103e6e06d7583f8b2bb847907d7fc77a8be9f)
2019-07-26 12:14:30 +02:00
rob bygrave 114693b7cd #1774 - Change built in SQL Server I___create_procs DDL script to use GO (and not $$ delimiters)
Bump ebean-migration with handling for stored procedures delimited with GO and $$ etc
2019-07-25 21:46:35 +12:00
rob bygrave 5a39dcb39c #1775 - MySql 8 by default wants JDBC Date set and read with JVM Calendar (timezone) 2019-07-25 21:25:38 +12:00
rob bygrave b04f887bc3 Test only update generated resource - no effective change 2019-07-25 21:19:08 +12:00
rob bygrave 5c38561049 #1774 - Change built in SQL Server I___create_procs DDL script to use GO (and not $$ delimiters) 2019-07-24 23:36:36 +12:00
rob bygrave f40eb011c3 #1773 - Wrong link to timerbee.de in README.md 2019-07-24 21:57:47 +12:00
rob bygrave a08cf548e7 #1770 - Support use of Savepoints with MySql and MariaDB (that barf on savepoint.getSavepointId()) 2019-07-21 22:57:56 +12:00
rob bygrave f12f0d7f7a [maven-release-plugin] prepare for next development iteration 2019-07-21 16:50:02 +12:00
rob bygrave 0c53efcbbc [maven-release-plugin] prepare release ebean-11.41.3 2019-07-21 16:49:51 +12:00
rob bygrave 1aeed8ad12 Merge branch 'master' of github.com:ebean-orm/ebean 2019-07-19 10:44:07 +12:00
rob bygrave bcb136b692 #1765 - Wrong SQL generated on m2m and OrderBy (Regression of #1746) 2019-07-19 10:43:07 +12:00
rob bygrave 8b670fd615 Fix tests for sql server which doesn't support order by nulls last 2019-07-19 10:35:26 +12:00
rob bygrave 970bc8e973 Fix tests for sql server 2019-07-19 10:28:13 +12:00
Roland PramlandRob Bygrave 007b06e9db use local lookup instead of public lookup (#1764)
(cherry picked from commit dc0441aaea126efc23a9c2abc30a4dd67bac6752)
2019-07-19 09:12:07 +12:00
rob bygrave 4513dbf29d No effective change - whitespace change only to SqlTreeBuilder 2019-07-19 00:22:41 +12:00
rob bygrave 53bcc62a0c No effective change - whitespace change to test generated migration ddl 2019-07-19 00:21:04 +12:00
rob bygrave 858c55c978 No effective change - format only test code 2019-07-19 00:20:22 +12:00
rob bygrave cedba089e1 Merge branch 'cannot-access-referenced-prop' of https://github.com/FOCONIS/ebean into FOCONIS-cannot-access-referenced-prop 2019-07-18 23:48:47 +12:00
rob bygrave cbf7811f7c #1762 - Bump ebean-migration to 11.17.1 2019-07-18 23:37:25 +12:00
rob bygrave ea13b322ca Bump agent to 11.41.3 2019-07-18 23:34:28 +12:00
Alexander Wagner 486a8cf1c0 whitespaces 2019-07-18 12:15:44 +02:00
Alexander Wagner bfe46432da delete views from ddl 2019-07-18 12:14:38 +02:00
Alexander Wagner 272eae5f22 Do not use @View for Test 2019-07-18 11:19:43 +02:00
rob bygrave 502104eba8 [maven-release-plugin] prepare for next development iteration 2019-07-17 21:53:14 +12:00
rob bygrave fa45c79bd2 [maven-release-plugin] prepare release ebean-11.41.2 2019-07-17 21:53:01 +12:00
rob bygrave ee4d1bf866 #1760 #1759 - move make available via ebean-test-config 2019-07-17 15:48:11 +12:00
rob bygrave dcf7b60d37 #1760 #1759 - ENH: Add ForTests.rollbackAll(closure) and ForTests.createRollbackAll() 2019-07-17 14:44:52 +12:00
rob bygrave 0663a97941 No effective change - update test for TestTransientMap 2019-07-17 13:48:12 +12:00
rob bygrave f31ab4d6a8 #1758 - Error when using ebean 11.41.1 and ebean-spring-txn 11.10.4
Fix method visibility restoring those methods as public
2019-07-17 10:27:07 +12:00
André CamiloandRob Bygrave f77388738b ENH: backdoor to disable @Transactional during unit testing (#1756) 2019-07-16 23:09:04 +12:00
Roland PramlandRob Bygrave 945175c533 Throwing NotEnhancedException on _ebean_* method instead of enforce to implement them (#1755) 2019-07-16 23:07:40 +12:00
rob bygrave 7d37c6cfd8 #1753 - use selectId() for findCount() with Formula properties 2019-07-15 19:04:43 +12:00
rob bygrave 496672b394 #1753 - Tidy for Issue with using the Formula-Properties 2019-07-14 16:03:07 +12:00
rob bygrave 1ffe359573 Merge branch 'Tests-for-Queries-With-Formula-Properties' of https://github.com/FOCONIS/ebean into FOCONIS-Tests-for-Queries-With-Formula-Properties 2019-07-14 15:23:16 +12:00
rob bygrave 23cd9b6a93 Remove use of agent-loader
Enhancement always done via maven plugin or Ebean IDE plugin (javaagent)
2019-07-14 15:21:55 +12:00
rob bygrave 333ac8edd9 Bump agent to 11.41.2 2019-07-14 15:17:34 +12:00
Roland Praml 081cb20260 always add main ID property, if no foreign key (=noConstraint) is present
(cherry picked from commit ea562151a8e3043df13381abd0d076d592618340)
2019-07-12 14:23:50 +02:00
Roland Praml 53f1da32be Add testcase for @DbForeignKey(noconstraint = true) 2019-07-12 14:21:45 +02:00
Roland Praml 5544a2cc3e Possible fix 2019-07-12 12:59:19 +02:00
Thomas Fellner 84c3008db1 Add query tests for @Formula-Properties 2019-07-09 17:35:27 +02:00
rob bygrave d949d4d6a2 [maven-release-plugin] prepare for next development iteration 2019-07-03 00:12:09 +12:00
rob bygrave 03669dc307 [maven-release-plugin] prepare release ebean-11.41.1 2019-07-03 00:11:55 +12:00
rob bygrave 2a8fad7364 #1748 - Support older JPA API that doesn't have orphanRemoval() or joinColumn.foreignKey() 2019-07-03 00:08:50 +12:00
rob bygrave e62db11f01 #1747 - Refactor extract common code for SaveManyElementCollection preElementCollectionUpdate() 2019-07-02 23:41:01 +12:00
rob bygrave 8c8f2b95da #1747 - Refactor DeleteMeta and UpdateMeta to extract common appendWhere() code 2019-07-02 23:25:05 +12:00
rob bygrave 576eb01187 #1747 - Refactor remove unused SqlTreeProperties readOnly 2019-07-02 23:15:41 +12:00
rob bygrave 8b18b2a20e #1747 - Refactor io.ebeaninternal.server.query invert boolean methods 2019-07-02 23:10:21 +12:00
rob bygrave f5c12a916d #1747 - Refactor io.ebeaninternal.server.transaction access and remove unused 2019-07-02 22:58:31 +12:00
rob bygrave 2f8a99c304 #1747 - Refactor io.ebeaninternal.server.query access and remove unused 2019-07-02 22:37:35 +12:00
rob bygrave cd9a43c3ab Bump ebean-annotation to 4.11 2019-07-02 22:06:45 +12:00
rob bygrave f251ca5431 #1747 - Refactor ebeaninternal/server/persist remove unused part 3 2019-07-02 22:06:12 +12:00
rob bygrave 2c44c80f65 #1747 - Refactor ebeaninternal/server/persist remove unused part 2 2019-07-02 21:56:05 +12:00
rob bygrave d9efeac0a1 #1747 - Refactor ebeaninternal/server/persist remove unused emptyStringAsNull
- remove unused emptyStringAsNull
- tighten access
2019-07-02 21:47:53 +12:00
rob bygrave f4a7d0b6ad #1747 - Refactor ebeaninternal/server/persist access, switch 2019-07-02 21:39:07 +12:00
rob bygrave bc5db1e46a #1747 - Refactor remove unused methods 2019-07-02 21:26:24 +12:00
rob bygrave 8743148238 #1747 - Refactor BeanPropertyAssocOne.diff() next prefix 2019-07-02 21:25:42 +12:00
rob bygrave 68db6723d0 #1747 - Refactor tidy finals, local fields, switches, unused methods 2019-07-02 21:08:13 +12:00
rob bygrave 9b1fa43792 #1747 - Refactor tidy remove unused ParamTypeUtil 2019-07-02 20:48:19 +12:00
rob bygrave 5f2454831e #1747 - Refactor tidy tighten access on ebeaninternal/server/deploy
Adds PropertyAssocMany to ensure public access on BeanPropertyAssocMany helper methods for ebean-elastic integration.
2019-07-02 20:46:49 +12:00
rob bygrave 140178bb47 #1747 - Refactor tidy on AnnotationParser, DeployBeanInfo 2019-07-02 19:52:10 +12:00
rob bygrave f95b4b5c4b #1747 - Refactor tidy on AnnotationAssocOne, AnnotationAssocClass & Base 2019-07-02 19:48:24 +12:00
rob bygrave d3b3a79342 #1747 - Refactor tidy on DeployUtil and AnnotationAssocMany 2019-07-02 19:41:26 +12:00
rob bygrave 52398317bc #1746 - Wrong SQL generated when using setDistinct and order by on aggregated column 2019-07-01 22:50:44 +12:00
rob bygrave 7f2e4f54ff #1743 - Add hasForeignKeyConstraint()
Separate hasForeignKeyConstraint() for DDL use from hasForeignKey() used in query
2019-07-01 21:04:40 +12:00
rob bygrave 9f19ed5376 #1743 - When using @PrimaryKeyJoinColumn, FK constraint generation cannot be disabled 2019-07-01 00:07:14 +12:00
rob bygrave d49a7c415f Refactor tidy InheritInfo - no effective change 2019-06-30 21:53:59 +12:00
rob bygrave 8ffc9ede85 #1740 and #1744 Don't include the discriminator column on Inheritance query on a type that has no sub-types
Fix for #1740
2019-06-30 21:52:01 +12:00
rob bygrave eba521563a #1739 - Entity with just @Id and @OneToMany fields produces broken insert query 2019-06-30 19:37:49 +12:00
rob bygrave ed71e106df #1742 - Bump to ebean-agent 11.41.1 2019-06-30 19:00:42 +12:00
rob bygrave 050ae49f6b [maven-release-plugin] prepare for next development iteration 2019-06-29 00:44:16 +12:00
rob bygrave d5d9a897ae [maven-release-plugin] prepare release ebean-11.40.1 2019-06-29 00:44:05 +12:00
rob bygrave ddf200ffdd #1738 - Refactor toArray() plus various 2019-06-29 00:40:16 +12:00
rob bygrave 7fa5e2aa8c #1738 - Refactor add final, Object.equals, Integer.compare 2019-06-29 00:23:12 +12:00
rob bygrave 8bfae9deef #1738 - Refactor simplify switch and various 2019-06-28 23:48:03 +12:00
rob bygrave e6c9f151c1 #1738 - Refactor tidy suppressWarnings and access 2019-06-28 23:20:57 +12:00
rob bygrave 30a0935300 #1738 - Refactor tidy suppressWarnings 2019-06-28 23:04:20 +12:00
rob bygrave b4182d4519 #1738 - Refactor SqlTreeNodeBean tidy 2019-06-28 22:40:14 +12:00
rob bygrave 93cc0399f1 #1738 - Refactor SqlTreeNodeBean load method 2019-06-28 22:35:36 +12:00
rob bygrave 5404dab5a3 Bump to 11.40.1-SNAPSHOT 2019-06-28 21:35:02 +12:00
rob bygrave d70da1d805 #1738 - Refactor tidy internals - refactor move server.lib.Str 2019-06-28 21:32:15 +12:00
rob bygrave 2225d5b7e8 #1738 - Refactor tidy internals - refactor move DtoQueryRequest 2019-06-28 21:30:15 +12:00
rob bygrave 270369bd65 #1738 - Refactor tidy internals - DLoadContext 2019-06-28 21:20:42 +12:00
rob bygrave a932d61a94 #1737 - PersistenceException while using aggregate query on related entity
This part includes support for joins off an aggregation formula
on a ManyToOne.

e.g. We use min(customer) ... to 'query join' to customer
in the query below.

    List<Contact> contacts = Ebean.find(Contact.class)
      .select("lastName, min(customer)")
      .fetchQuery("customer", "name, status")
      .findList();
2019-06-28 21:03:14 +12:00
rob bygrave 24b08663af #1737 - PersistenceException while using aggregate query on related entity
Fix excluding the ability to additionally join (off the min(manyToOne))
2019-06-28 20:16:05 +12:00
rob bygrave bb6c9c84ba #1736 - Bump to ebean-agent 11.40.1 (with synthetic modifier on generated code) 2019-06-28 10:55:14 +12:00
rob bygrave a1e185b0f6 Refactor tidy internals - BatchedPstmtHolder, always true condition (no effective change)
Remove condition check on firstError == null ... as it is always true
2019-06-24 13:41:21 +12:00
Rob BygraveandGitHub e2a467ca5a Create FUNDING.yml 2019-06-19 23:49:00 +12:00
rob bygrave 4b28933298 [maven-release-plugin] prepare for next development iteration 2019-06-14 16:45:16 +12:00
rob bygrave 6077acf134 [maven-release-plugin] prepare release ebean-11.39.3 2019-06-14 16:45:05 +12:00
rob bygrave 8a4ffd21ab #1722 - Fix for - L2 cache throw exception when query with custom ManyToMany relation model 2019-06-14 16:38:58 +12:00
rob bygrave d1314124af #1722 - Failing test for - L2 cache throw exception when query with custom ManyToMany relation model 2019-06-14 16:38:43 +12:00
rob bygrave 36f018b6aa [maven-release-plugin] prepare for next development iteration 2019-06-13 23:38:28 +12:00
rob bygrave 87ccb6e333 [maven-release-plugin] prepare release ebean-11.39.2 2019-06-13 23:38:18 +12:00
rob bygrave 3432c365f6 Bump ebean-migration to 11.16.2 with fix for migration sql that ...
That includes semi-colon and new line in literal content
2019-06-13 00:14:20 +12:00
rob bygrave b7d5aa344f Fix test only - add missing assert on NoopExpressionTest 2019-06-13 00:11:34 +12:00
rob bygrave 7e768623e4 #1730 - Fix for wrong JDBC batch sorting / ordering
This is a bit of a refactor that simplifies the ordering of
batch execution (BatchedBeanHolder ordering). In short we
batch by bean type and depth (rather than just type).

This means that there are some cases we are not optimal
(where we could batch by bean type in different depths)
but that is expected to be rare and problematic for
hierarchies of the same type.
2019-06-12 23:41:48 +12:00
rob bygrave 73ab2ee1fe Merge branch 'FOCONIS-bug/wrong_batch_sorting' 2019-06-12 21:17:15 +12:00
rob bygrave 122fed448c Merge branch 'bug/wrong_batch_sorting' of https://github.com/FOCONIS/ebean into FOCONIS-bug/wrong_batch_sorting 2019-06-12 21:16:50 +12:00
rob bygrave 6e52bee91f #1723 - Fix for TestUpdateCircularSave.testCircularCascade() 2019-06-10 23:31:47 +12:00
rob bygrave cc26afad13 Merge branch 'tobias--circular_saves_bugs' 2019-06-10 21:04:17 +12:00
rob bygrave bf20449fb5 Merge branch 'circular_saves_bugs' of https://github.com/tobias-/ebean into tobias--circular_saves_bugs 2019-06-10 21:03:55 +12:00
Rob BygraveandGitHub 6af5fae8e9 #1727 - Refactor internals to use Instant for json parse on date time types (#1728) 2019-06-10 16:16:04 +12:00
rob bygrave e26a38ecaa #1727 - No effective change, simplify DefaultServer.createEntityBean() 2019-06-10 16:14:12 +12:00
rob bygrave 1cdf68f1c0 #1727 - No effective change, tests with static imports 2019-06-10 16:13:19 +12:00
jonasPoehlerandRob Bygrave 2923dd1d96 Bugfix/create entity bean unload (#1729)
* #1726 Add a testcase to reveal wrong behaviour of createEntityBean

* #1726 FIX: createEntityBean must not unload properties for "new" beans

(cherry picked from commit 270721bdb54373a83ef00b19a3c35da50f2a2bf5)
2019-06-10 16:09:12 +12:00
Jonas Pöhler (JPo) 9067508e1d Add testcase for wrong batch sorting 2019-06-07 13:42:31 +02:00
rob bygrave 385cc76e34 #1724 - Fix, UtilDateTimeParser - date time parsing with nanos precision 2019-06-04 22:20:28 +12:00
SnōwballandRob Bygrave c14cb4b85e Add (failing) java 11 to travis - date time parsing with nanos precision (#1724)
* Add (failing) java 11 to travis

* Extra test-case for date parser
2019-06-04 21:56:25 +12:00
Snōwball 52644647e4 Add another test case for circular dependencies 2019-05-27 11:14:48 +02:00
Snōwball 3bf9dd6743 Testcase for ebean with circular dependences
1. While the javax.persistance api discourages the use of bidirectional
   cascades, it does not prohibit them. They're very useful and natural
   if you think of the database as a graph instead of a tree.
   test case 1 (testCircularCascade) tests this.
2. Second test case fetches the child, but saves the parent. If used like
   that, the child will not have it's changes saved.
2019-05-23 16:38:55 +02:00
rob bygrave aececa2199 [maven-release-plugin] prepare for next development iteration 2019-05-22 22:23:33 +12:00
rob bygrave b4e22a4ca7 [maven-release-plugin] prepare release ebean-11.39.1 2019-05-22 22:23:19 +12:00
rob bygrave 9b8b4414c4 Bump agent and ebean-migration 2019-05-22 22:21:35 +12:00
rob bygrave b8fd2c7a02 Bump to 11.39.1-SNAPSHOT 2019-05-22 21:46:49 +12:00
rob bygrave a94f5d74ca No effective change - add test for select formula with positioned parameters 2019-05-21 16:59:39 +12:00
rob bygrave 3829613c37 #1717 #1721 - Fix for table touch with query cache clear 2019-05-21 09:17:07 +12:00
Roland PramlandRob Bygrave 0762eaf0ab changed test to detect issue #1717 (#1721) 2019-05-21 09:12:43 +12:00
Rob BygraveandGitHub 7fbdab6220 Refactor TableModState to use nanoTime refactor (#1720)
* #1719 - Refactor TableModState to use nanoTime

* Tests only - reduce logging
2019-05-21 00:42:17 +12:00
Roland PramlandRob Bygrave cf4d45befb refactor: unwrap invocationTargetException (#1718) 2019-05-21 00:37:03 +12:00
rob bygrave dcd81a857d #1717 - Add tests for Query Cache invalidation
Revert the prior change that added the extra calls to
changeSet.addInvalidate(desc); as they are not needed.
2019-05-20 21:14:47 +12:00
Roland PramlandRob Bygrave 0cac723eac Query Cache will not always be invalidated (#1717)
* provide failing test, that shows missing cache invalidation

* FIX: proper cache invalidation when dependent table will be modified
2019-05-20 20:25:18 +12:00
Rob BygraveandGitHub c6ba4d8155 Refactor DefaultTransactionThreadLocal, convert ThreadLocal to field (from map) (#1716)
* Refactor DefaultTransactionThreadLocal, convert ThreadLocal to field (from map)

* Add test for multiple database thread locals
2019-05-18 15:16:17 +12:00
Rob BygraveandGitHub 201958f38c Refactor tidy on DefaultTransactionThreadLocal (#1715)
- remove unused methods
- use clear() rather than set(null)
2019-05-18 12:32:17 +12:00
rob bygrave 9326c9c79e Adjustment on #1711, fix clearing of inactive transactions from thread local
Handles implicit transactions for update and delete queries plus delete
by id
2019-05-18 12:09:50 +12:00
rob bygrave 1042fdb280 Merge branch 'feature/1711-v2' 2019-05-18 11:43:51 +12:00
Roland PramlandRob Bygrave 197056dbc5 Refactor: Ebean uses the MigrationVersion from the ebean-migration artifact (#1713) 2019-05-18 11:32:17 +12:00
Roland PramlandRob Bygrave 895b5ee4ff The BaseTestCase ensures, that the threadLocal is cleared after each test. (#1712)
* The BaseTestCase ensures, that the threadLocal is cleared after each test.

* Change JdbcTransaction.toString to distingush between active and inactive transaction
2019-05-18 11:28:46 +12:00
rob bygrave c839fe6520 Adjustment on #1711, more explicit clearing of inactive transactions from thread local 2019-05-18 11:21:11 +12:00
Roland PramlandRob Bygrave 2678f85506 Fix memory leak in threadLocal on implicit transactions (#1711)
* refactor TestExecutionComplete

* Add more tests to discover missing threadScope cleanups

* FIX: clear threadScope on implicit created Jdbc transactions

* FIX: clear threadScope on completed JTA transactions

* Revert "FIX: clear threadScope on completed JTA transactions"

This reverts commit f844405542.
2019-05-18 10:00:34 +12:00
Rob BygraveandGitHub 2b1b4af7a2 Merge pull request #1710 from FOCONIS/sqlserver-platform-test
New test for SqlServerPlatform
2019-05-18 09:48:59 +12:00
Rob BygraveandGitHub 4218b8a2e8 Merge pull request #1708 from FOCONIS/refactor-tests-idtype
Refactor Tests: Check idType instead of assuming idType for a platform
2019-05-18 09:46:40 +12:00
Roland Praml fe7d73a4a4 New test for SqlServerPlatform 2019-05-17 18:07:24 +02:00
Roland Praml 81e86b07e3 Refactor Tests: Check idType instead of assuming idType for a platform 2019-05-17 16:38:25 +02:00
rob bygrave 910c04e373 Add sponsorship from timerbee.de 2019-05-17 21:08:44 +12:00
Rob BygraveandGitHub 205f1f5e89 Merge pull request #1704 from ebean-orm/feature/1701-v2
#1701 (v2) - Replace TransactionMap with HashMap in DefaultTransactionThreadLocal
2019-05-17 21:04:54 +12:00
rob bygrave a1a6d2b725 Fix test TestExecuteComplete 2019-05-17 14:56:35 +12:00
rob bygrave 30da589ea0 #1701 (v2) - Replace TransactionMap with HashMap in DefaultTransactionThreadLocal
- Use ThreadLocal.withInitial to always have a map.
- Remove the calls to local.remove(); when the map is empty (with the expectation that the thread local will GC with an empty map.
2019-05-17 12:01:28 +12:00
rob bygrave c66e9547e1 #1705 - SpiTransactionProxy depth(int diff) ... does not pass on depth to underlying transaction 2019-05-16 22:44:09 +12:00
rob bygrave 73990e3fb7 #1701 (v2) - Replace TransactionMap with HashMap in DefaultTransactionThreadLocal 2019-05-16 22:26:11 +12:00
rob bygrave f7920de3c2 #1698 No effective change - reformat 2019-05-16 20:27:16 +12:00
rob bygrave 3dd5069f5a #1698 FIX for IAE "key can't be empty" in System.getProperty()
That is, assertEquals("${}", PropertyEval.eval("${}"));
... for when we load properties that include the "${}" placeholder
2019-05-16 20:26:45 +12:00
rob bygrave 1d363776ec No effective change - refactor rename in test for StartMySql 2019-05-16 20:08:06 +12:00
rob bygrave c512eb564d #1702 - Format only change 2019-05-16 20:07:43 +12:00
Rob BygraveandGitHub 7f332e91ff Merge pull request #1702 from FOCONIS/fix-mig-default-value
Fix: Migration when dbdefault is involved
2019-05-16 20:00:34 +12:00
Rob BygraveandGitHub 8e9d644bc6 Merge pull request #1697 from ebean-orm/feature/1695-binary
#1695 - For MySql like remove the binary keyword + Add caseSensitiveCollation configuration option
2019-05-16 19:46:38 +12:00
rob bygrave fa5ce9cbba #1695 Add StartMyServer - docker mysql with collation options
- Adjust TestWhereLikeWithSlash ignoring slash escaping assert for mysql (due to dependency on no_backslash_escapes setting)
2019-05-16 16:55:05 +12:00
rob bygrave b7905daeb5 #1695 Fix case sensitive builtin sql server proc
- Update main.StartSqlServer to use updated ebean-test-docker with collation support
2019-05-16 15:36:22 +12:00
rob bygrave 9da7c9468e #1695 Add caseSensitiveCollation configuration option
This is really only to use with testing via
platform.isCaseSensitiveCollation() to determine
which asserts/tests apply (based on collation).
2019-05-15 16:19:12 +12:00
Roland Praml 9eee224e03 migration scripts 2019-05-14 20:05:24 +02:00
Roland Praml 906d5f04ad FIX: Migration when default value was changed 2019-05-14 20:02:55 +02:00
rob bygrave 654c3f7f67 #1695 - For SQL Server like remove the binary collation (Latin1_General_BIN) 2019-05-12 15:22:08 +12:00
rob bygrave c61e6b04a2 Update sql server testing 2019-05-12 11:41:24 +12:00
Rob BygraveandGitHub f893653090 Merge pull request #1699 from FOCONIS/fix-equals-modify-aware
Fix: equals() and hashCode() in ModifyAwareXXX
2019-05-11 13:43:40 +12:00
Roland Praml 579c1efcf6 Add tests and fixes in hashCode 2019-05-08 17:00:08 +02:00
Roland Praml 662f9cdeb3 fixed equals() method in ModifyAware collections. 2019-05-08 16:45:02 +02:00
rob bygrave b4782425f8 #1695 - For MySql like remove the binary keyword 2019-05-08 23:38:25 +12:00
rob bygrave 2648423930 #1696 - Refactor - trim unnecessary whitespace around IN clause bind parameters 2019-05-08 23:22:13 +12:00
rob bygrave b62cea5073 No effective change - add findNative tests with named params in select 2019-05-08 23:12:10 +12:00
rob bygrave c10ad11b8b No effective change - add example use of PathProperties 2019-05-08 22:50:37 +12:00
rob bygrave 4aa8a0dc63 #1694 - findList() with firstRows/maxRows adds "order by id" (even with orderById(false)) 2019-05-03 14:33:42 +12:00
rob bygrave e4569f9362 #1693 - Update ebean-migration 11.15.1 2019-05-03 12:45:03 +12:00
rob bygrave ed83bababc [maven-release-plugin] prepare for next development iteration 2019-05-01 00:39:58 +12:00
rob bygrave b746c83ed7 [maven-release-plugin] prepare release ebean-11.38.1 2019-05-01 00:39:44 +12:00
rob bygrave 8e45462c2c Bump ebean-annotation to 4.10 with @DbName 2019-04-30 23:43:52 +12:00
rob bygrave 9fdb375229 #1691 - Refactor io.ebean.Model to use a named database - support for use with non-default named database 2019-04-30 23:42:59 +12:00
Rob BygraveandGitHub 7e6d059ef1 Merge pull request #1690 from ebean-orm/feature/1686
#1686 - Change the default JSON format to ISO8601 for date and datetime types (from epoch millis)
2019-04-30 20:18:20 +12:00
rob bygrave 856a3a6fdd #1689 - ENH: Add query usingTransaction() and usingConnection() 2019-04-30 20:13:12 +12:00
rob bygrave f94c3e81e5 Merge branch 'master' of github.com:ebean-orm/ebean 2019-04-30 16:36:06 +12:00
rob bygrave 4bf9e2b18e Bump ebean-datasource to 4.5.2 2019-04-30 16:34:01 +12:00
Rob BygraveandGitHub 112de29964 Merge pull request #1688 from thibaultmeyer/bugfix/useless-comparison-test
Remove useless comparison test
2019-04-29 09:18:11 +12:00
Thibault Meyer c5d761076a Remove useless comparison test
The result of certain comparison tests can sometimes be inferred
from their context and the results of other comparisons. Inspect
the code to check whether the logic is correct, and consider
simplifying the logical expression.

Signed-off-by: Thibault Meyer <meyer.thibault@gmail.com>
2019-04-28 12:10:56 +02:00
rob bygrave 4bedefa494 Merge branch 'master' of github.com:ebean-orm/ebean 2019-04-28 09:51:08 +12:00
rob bygrave a5e3a70921 #1685 DefaultServerCache expose hit and miss count to assist testing
Expose these counters to assist the testing of duel caches where
 DefaultServerCache is used as the near cache.
2019-04-28 09:50:45 +12:00
Rob BygraveandGitHub f6f4368048 Merge pull request #1687 from thibaultmeyer/bugfix/implicit-conv-from-array-to-str
Fix implicit conversion from array to string
2019-04-28 00:38:23 +12:00
rob bygrave e700f1c83c #1685 Update ServerCacheFactory to support standard metrics collection 2019-04-27 23:22:26 +12:00
rob bygrave dc5ac02952 Bump to 11.38.1-SNAPSHOT 2019-04-27 23:06:09 +12:00
Thibault Meyer b89371acd1 Fix implicit conversion from array to string
When converting an array to a readable string, use Arrays.toString
for one-dimensional arrays. This function iterate over the contents
of the array and produce human-readable output.

Signed-off-by: Thibault Meyer <meyer.thibault@gmail.com>
2019-04-27 13:06:02 +02:00
rob bygrave 6c88325dad #1685 Update ServerCacheFactory to support standard metrics collection 2019-04-27 22:57:30 +12:00
rob bygrave ecec966a85 #1686 - Change the default JSON format to ISO8601 for date and datetime types (from epoch millis) 2019-04-27 11:20:21 +12:00
rob bygrave c46ac04c0a #1684 - Fix JSON marshalling on LocalDate, sql.Date etc - explicit UTC
Make explicit use of UTC
2019-04-27 10:33:17 +12:00
rob bygrave 25e6d05542 #1685 - Add support for MetaCounterMetrics and refactor DefaultServerCache to use them 2019-04-27 00:34:45 +12:00
rob bygrave d3ead5d2f9 #1684 - ENH: Support ISO date format for JSON marshalling on LocalDate, sql.Date etc 2019-04-26 19:01:16 +12:00
rob bygrave 28a70fa550 #1684 - ENH: Support ISO date format for JSON marshalling on LocalDate, sql.Date etc 2019-04-26 19:00:49 +12:00
rob bygrave cf31830cbc #1677 - No effective change - Add test but not failing etc 2019-04-26 13:21:19 +12:00
rob bygrave b4105ab5d0 #1683 - Refactor MetaQueryPlan and MetaOrmQueryMetric - rename getQueryPlanHash() to getSqlHash() 2019-04-26 12:55:40 +12:00
Rob BygraveandGitHub 1bb2b1318e Merge pull request #1682 from ebean-orm/feature/1679-region
Feature/1679 region
2019-04-26 12:03:11 +12:00
rob bygrave 65fa1c056b #1681 - Support hitting L2 bean cache via ... findList() with idsIn() expression 2019-04-26 12:01:16 +12:00
rob bygrave 242945aa18 #1681 - Update tests for TestCacheViaComplexNaturalKey 2019-04-26 11:54:52 +12:00
Rob BygraveandGitHub 5e77be6e6d Update sponsor image link for PayinTech 2019-04-26 09:16:40 +12:00
rob bygrave 8c0d6b1a72 #1679 - ENH: Support enabling/disabling L2 cache by "region" at runtime 2019-04-24 15:41:53 +12:00
rob bygrave 86436ac3ac #1679 - ENH: Support enabling/disabling L2 cache by "region" at runtime 2019-04-24 15:41:07 +12:00
rob bygrave ae228d6b0e #1679 - ENH: Support enabling/disabling L2 cache by "region" at runtime 2019-04-24 14:00:22 +12:00
rob bygrave 410d1a9b37 update sponsor logo for premium-minds 2019-04-12 20:53:35 +12:00
rob bygrave f667a73dc1 [maven-release-plugin] prepare for next development iteration 2019-04-12 13:38:53 +12:00
rob bygrave 4509c6b1ed [maven-release-plugin] prepare release ebean-11.37.1 2019-04-12 13:38:41 +12:00
rob bygrave d32559baf4 #1674 - For ProfileLocation use in constructors trim label <init> to init .... (for safe label) 2019-04-12 02:25:05 +12:00
rob bygrave 2639e799c5 #1673 - ENH: Support ProfileLocation on DtoQuery including via orm query.asDto() 2019-04-12 02:01:01 +12:00
rob bygrave 46c66b7169 #1672 - ENH: Add ebean.dumpMetricsOnShutdown=true ... for dumping metrics 2019-04-12 00:55:39 +12:00
rob bygrave 30ae435f33 #1672 - ENH: Add ebean.dumpMetricsOnShutdown=true ... for dumping metrics 2019-04-12 00:45:00 +12:00
rob bygrave 4f4743807c #1671 - Use table alias with delete query for Postgres, Oracle, MySql 2019-04-10 01:25:43 +12:00
rob bygrave 7b7a492241 Bump to 11.37.1 2019-04-09 23:04:34 +12:00
rob bygrave 4af8e53315 #1670 - Expose metrics as ServerMetrics interface (improvement over existing BasicMetricVisitor use) 2019-04-09 22:54:16 +12:00
rob bygrave 1c6fa575f2 #1669 - When deleting complex object graphs, entities are deleted multiple times
Fix by not unregistering the deleted bean hash in the transaction so that
the skip occurs on other root level bean traversals (the delete of the
2nd master bean)
2019-04-09 20:30:17 +12:00
rob bygrave 2430404e1f Merge branch 'FOCONIS-bug-delete-with-version' 2019-04-09 20:27:23 +12:00
rob bygrave d433e0ea46 Merge branch 'bug-delete-with-version' of https://github.com/FOCONIS/ebean into FOCONIS-bug-delete-with-version 2019-04-09 20:06:12 +12:00
rob bygrave 42591a5a87 No effective change - reformat line 2019-04-09 20:05:22 +12:00
Roland PramlandRob Bygrave 65a62bf683 Fix check constraint support for MariaDB >= 10.2.1 (#1668)
* fixed the check constraint support for mysql/mariadb

* update migration scripts
2019-04-09 19:38:57 +12:00
Roland Praml 3e3f3c35e7 add test case to show delete with version 2019-04-08 17:21:23 +02:00
Rob BygraveandGitHub f4db7ca0bb Update sponsors in README 2019-04-08 20:49:28 +12:00
rob bygrave b0e487cfbd Add sponsor payintech.com 2019-04-03 23:24:13 +13:00
rob bygrave 23fd29ddf1 #1659 - CVE-2018-12022 - Bump Jackson version from 2.9.5 to 2.9.8 2019-04-01 23:23:02 +13:00
rob bygrave f21cac5d4f [maven-release-plugin] prepare for next development iteration 2019-04-01 23:13:07 +13:00
rob bygrave c2e5619f70 [maven-release-plugin] prepare release ebean-11.36.4 2019-04-01 23:12:53 +13:00
rob bygrave 18e0ff7067 #1665 - Incorrect query execution metrics for ORM query converted to DTO query via asDto() 2019-04-01 23:11:16 +13:00
rob bygrave 4119c02f0d #1663 Additionally trim the OrmQueryDetail.asString() output removing extra whitespace 2019-04-01 23:09:58 +13:00
rob bygrave 8985d37aed Merge branch 'master' of github.com:ebean-orm/ebean 2019-04-01 22:25:24 +13:00
Rob BygraveandGitHub 23e035894f Add foconis.de as sponsor to readme 2019-04-01 22:24:50 +13:00
rob bygrave 32b8fd0e26 #1663 Additionally trim the OrmQueryDetail.asString() output removing extra whitespace 2019-03-29 00:43:32 +13:00
rob bygrave 4971db54c8 #1663 - AutoTune - merge profiling such that "select (orderDate) fetch customer (id)" instead merges to "select (orderDate,customer)" 2019-03-29 00:19:21 +13:00
rob bygrave e417b3cde2 #1661 - AutoTune - callstack filters _ebean_ methods 2019-03-28 20:47:34 +13:00
rob bygrave d23ca31e42 [maven-release-plugin] prepare for next development iteration 2019-03-27 16:44:00 +13:00
rob bygrave c9b71ae373 [maven-release-plugin] prepare release ebean-11.36.3 2019-03-27 16:43:47 +13:00
rob bygrave f06f21cf5e #1660 - Modify MetaOrmQueryMetric getQueryPlanHash to return hash of sql 2019-03-27 16:12:09 +13:00
rob bygrave f8b97ff397 #1658 - ENH: Add label to ProfileLocation and use as default query label
- Extend/propagate the label from the origin query to secondary queries
(appending the relative path).
2019-03-27 12:57:36 +13:00
rob bygrave fc032c632b #1658 - ENH: Add label to ProfileLocation and use as default query label 2019-03-27 09:37:35 +13:00
rob bygrave 54534ea7f3 #1657 - ERROR BeanDescriptorManager - Error in deployment java.lang.RuntimeException: Expecting [ ... ] to start with "select" 2019-03-21 22:30:27 +13:00
rob bygrave 812dcbb4bb #1653 - ENH: Add support for ClickHouse database
With array type conversion for primitive arrays
2019-03-20 23:13:50 +13:00
rob bygrave a3d4b57b94 Merge branch 'feature/1653-clickhouse' 2019-03-20 22:07:42 +13:00
rob bygrave 61479d365a Merge branch 'master' of github.com:ebean-orm/ebean 2019-03-20 22:05:54 +13:00
ooknightandRob Bygrave 3ba9a52b0e add server config : default enum type (#1655)
ENH: add server config : default enum type
2019-03-20 21:45:44 +13:00
rob bygrave 518ba37fb2 No effective change - Bump maven plugin version 2019-03-16 15:28:44 +13:00
rob bygrave fd6a7f64eb [maven-release-plugin] prepare for next development iteration 2019-03-14 21:17:03 +13:00
rob bygrave 8b073ef10a [maven-release-plugin] prepare release ebean-11.36.2 2019-03-14 21:16:47 +13:00
rob bygrave 6a7555055d No effective change - Update tests from Ebean -> DB 2019-03-14 21:11:59 +13:00
rob bygrave eb31f1bfce No effective change - Add more tests for LocalDate pre 1900 etc 2019-03-14 16:20:14 +13:00
rob bygrave 2e4f99318a No effective change - Ebean -> DB in tests 2019-03-14 16:15:47 +13:00
rob bygrave 409c1d06b2 #1652 - Conversion problem between org.joda.time.LocalDate and java.sql.Date field for dates before Jan 2 1900 2019-03-14 16:08:04 +13:00
rob bygrave 01f2881940 #1653 - ENH: Add support for ClickHouse database
With array type conversion etc
2019-03-14 14:44:30 +13:00
rob bygrave aef512a851 #1653 - ENH: Add support for ClickHouse database 2019-03-14 00:08:13 +13:00
rob bygrave 435e1f61fe #1651 - ENH: Support change to io.ebean.Model that supports named databases (other than default database) 2019-03-13 15:05:08 +13:00
rob bygrave 0230e3e253 Reduce logging for CI server 2019-03-12 15:06:26 +13:00
rob bygrave 770364fd1a [maven-release-plugin] prepare for next development iteration 2019-03-12 14:53:24 +13:00
rob bygrave fbc2d70967 [maven-release-plugin] prepare release ebean-11.36.1 2019-03-12 14:53:09 +13:00
rob bygrave 276e865f72 #1647 - Change ServerConfig.updateAllPropertiesInBatch to default to false 2019-03-12 14:49:00 +13:00
rob bygrave 9ded3890d7 #1649 - ENH: Add optional length() attribute to @DbEnumValue 2019-03-12 14:31:44 +13:00
rob bygrave bfeb0cd667 No effective change - update to using "Database" and DB 2019-03-12 14:29:28 +13:00
rob bygrave 119049b696 Javadoc update using "Database" vs "EbeanServer" 2019-03-07 16:53:13 +13:00
rob bygrave 33ff113585 #1648 - Change BeanFinder and BeanRepository to use Database rather than EbeanServer 2019-03-07 16:51:33 +13:00
rob bygrave 17e0953cad Javadoc update - reduce generated packages 2019-03-07 16:26:05 +13:00
rob bygrave e3ca5d2419 Javadoc update using "DB" and hide DB constructor 2019-03-07 12:01:05 +13:00
rob bygrave a5f435dbcf Javadoc update using "DB" 2019-03-07 11:25:34 +13:00
rob bygrave aa1e021501 Javadoc update using "DB" 2019-03-07 11:10:58 +13:00
rob bygrave 7ea6f16207 Javadoc update using "DB" vs "Ebean" 2019-03-07 10:56:56 +13:00
rob bygrave 197852857d #1646 - Ensure that java.sql.Array.free() is called 2019-03-07 09:25:48 +13:00
rob bygrave e7e6e00473 No effective change - Finder javadoc to use "Database" 2019-03-07 09:08:34 +13:00
rob bygrave 933c791d33 No effective change - Finder javadoc to use "Database" 2019-03-06 23:13:24 +13:00
rob bygrave 043c523c2a [maven-release-plugin] prepare for next development iteration 2019-03-05 23:06:29 +13:00
rob bygrave 82247fd4e4 [maven-release-plugin] prepare release ebean-11.35.3 2019-03-05 23:06:14 +13:00
rob bygrave 27f86548a6 #1645 - ENH: Add expression rawOrEmpty() ... as a convenience for conditionally added a raw expression 2019-03-05 23:03:22 +13:00
rob bygrave 7e8424328f [maven-release-plugin] prepare for next development iteration 2019-03-05 22:26:35 +13:00
rob bygrave 923828ce87 [maven-release-plugin] prepare release ebean-11.35.2 2019-03-05 22:26:19 +13:00
rob bygrave e195f20981 #1645 - ENH: Add expression rawOrEmpty() ... as a convenience for conditionally added a raw expression 2019-03-05 22:13:38 +13:00
rob bygrave 86d0216159 #1644 - ENH: Improve batch flush when multiple "top level" (unrelated) types are persisted 2019-03-04 12:42:08 +13:00
rob bygrave a4698ea1b6 #1643 - ENH: Add expression inOrEmpty() ... as a convenience for conditionally added a IN expression 2019-03-01 18:24:00 +13:00
rob bygrave 888384f7db No effective change (change to DB from Ebean for TestSubQuery) 2019-03-01 18:12:36 +13:00
rob bygrave 817c946eeb [maven-release-plugin] prepare for next development iteration 2019-02-24 16:20:36 +13:00
rob bygrave 1749c2cb4c [maven-release-plugin] prepare release ebean-11.35.1 2019-02-24 16:20:21 +13:00
rob bygrave 3afd3c4530 #1640 Additionally add expression eq and in support for Inet and Postgres any
Bump ebean-types to 1.3 with of() helper methods
2019-02-24 16:18:49 +13:00
rob bygrave e5f98f1b7a #1640 Additionally add expression eq and in support for Inet and Postgres any 2019-02-24 15:29:07 +13:00
rob bygrave 2e496c9e1e Bump pom to 11.35.1-SNAPSHOT 2019-02-21 22:15:49 +13:00
Rob BygraveandGitHub 5975694538 #1640 - For Postgres support mapping InetAddress to INET db column (#1641)
* #1640 - For Postgres support mapping InetAddress to INET db column

* #1640 - For Postgres support mapping InetAddress to INET db column

Support for Inet and Cdir types + offlineMigrationGeneration + PlatformConfig.databaseInetAddressVarchar for turning off InetAddress mapping on Postgres
2019-02-21 22:14:21 +13:00
rob bygrave 03a42f7f6e No effective change - update test DefaultProfileHandlerTest to output profiling files to target 2019-02-21 09:37:14 +13:00
rob bygrave 84f1e05eb4 [maven-release-plugin] prepare for next development iteration 2019-02-18 10:58:21 +13:00
rob bygrave da20ced1ed [maven-release-plugin] prepare release ebean-11.34.3 2019-02-18 10:58:08 +13:00
rob bygrave 1f1a6e2c04 #1642 - Bump to ebean-datasource 4.5.1 with offline/online support 2019-02-18 10:50:34 +13:00
Roland PramlandRob Bygrave 6b83800a83 FIX: Proper sort of migration versions (possible regression due #1577) (#1639) 2019-02-17 17:40:07 +13:00
rob bygrave c344551e4d [maven-release-plugin] prepare for next development iteration 2019-02-13 11:57:09 +13:00
rob bygrave 6b4aff7191 [maven-release-plugin] prepare release ebean-11.34.2 2019-02-13 11:56:55 +13:00
Roland PramlandRob Bygrave fc7fae35c9 FIX: When saving multiple m2m beans, only last m2m wins (Regression due #1630) (#1638)
* provide test case, that shows problem on multiple-m2m

* FIX: When saving multiple m2m beans, only last m2m wins (Regression due #1630)
2019-02-12 09:31:04 +13:00
rob bygrave 7929d8c0b8 Fix test data ordering 2019-02-11 23:17:54 +13:00
rob bygrave 058766dd92 No effective change - adjust test to use DB and try with resources 2019-02-11 23:13:57 +13:00
rob bygrave 4fdb8a77b4 Fix test data 2019-02-11 23:08:50 +13:00
Manuel PoloandRob Bygrave 56be1fc047 Fixed missing EBEAN_PROPS_FILE loading (#1635) 2019-02-11 23:02:10 +13:00
rob bygrave 192a946cf6 #1634 ENH: Add convenience expressions "equal to or null" eqOrNull() 2019-02-11 22:59:47 +13:00
rob bygrave aa7b15fd6e #1637 - build on jdk11 2019-02-11 22:48:10 +13:00
Roland PramlandRob Bygrave cb74ef01e0 build on jdk11 (#1637) 2019-02-11 22:42:05 +13:00
rob bygrave 829dfcb013 #1634 - ENH: Add convenience expressions "greater than or null" gtOrNull(), ltOrNull() and inRangeWith() 2019-02-09 00:30:55 +13:00
rob bygrave 25b6d2a5a0 [maven-release-plugin] prepare for next development iteration 2019-02-07 23:43:13 +13:00
rob bygrave 14fbc3a955 [maven-release-plugin] prepare release ebean-11.34.1 2019-02-07 23:42:57 +13:00
rob bygrave e41da2f995 #1632 - ENH: Add bind parameter expansion for SqlUpdate
Fix test with bind type.
2019-02-07 23:35:44 +13:00
rob bygrave ea60e42a4d #1633 - ENH: Add bind parameter expansion for raw() expressions 2019-02-07 23:29:42 +13:00
rob bygrave efce6b57e1 #1632 - ENH: Add bind parameter expansion for SqlUpdate 2019-02-07 23:19:00 +13:00
rob bygrave 988e4c7386 WIP Bind parameter expansion 2019-02-07 21:10:57 +13:00
rob bygrave 9e1d7ab722 #1631 - Change logging for SqlUpdate ... such that it is more consistent with other SQL logging wrt JDBC batch 2019-02-07 17:20:49 +13:00
rob bygrave 0c03a8b925 #1630 - ENH: Improve jdbc batch use when persisting ManyToMany intersection changes 2019-02-05 17:35:58 +13:00
rob bygrave 37a66f1ee2 Playing around with SqlUpdate and bind expansion for ?1 etc 2019-02-04 14:24:47 +13:00
rob bygrave a02673359d No effective change - tidy BindParams 2019-02-04 12:34:02 +13:00
rob bygrave f9d13cbba7 Merge branch 'master' of github.com:ebean-orm/ebean 2019-02-04 11:55:04 +13:00
rob bygrave f787483e30 #1629 - ENH: Add sqlQuery(sql) and sqlUpdate(sql) ... as alias for createSqlQuery(sql) and createSqlUpdate(sql) 2019-02-04 11:54:45 +13:00
rob bygrave 9e33f36808 #1629 - ENH: Add sqlQuery(sql) and sqlUpdate(sql) ... as alias for createSqlQuery(sql) and createSqlUpdate(sql) 2019-02-04 11:14:54 +13:00
Roland PramlandRob Bygrave 6a7e6caa66 Test fixes (#1628)
* FIX: mysql index sizes

* FIX: osolete whitespace in sqlserver tests

* Updated mssql-jdbc, this fixes problems in the batch insert (https://github.com/Microsoft/mssql-jdbc/pull/912)

* fix tablename  (reserved word in mariadb)

* ignored failing tests for sqlserver
2019-02-04 09:20:09 +13:00
rob bygrave 5a4a0e3886 Bump version to 11.34.1-SNAPSHOT 2019-02-03 22:39:23 +13:00
rob bygrave c3f586c461 Merge branch 'feature/1624-Database' 2019-02-03 22:21:36 +13:00
rob bygrave 99f7243d6c #1627 - Bump ebean-datasource to 4.3.4 2019-02-03 22:14:25 +13:00
rob bygrave 7026c00290 [maven-release-plugin] prepare for next development iteration 2019-02-02 22:29:02 +13:00
rob bygrave 448d94a335 [maven-release-plugin] prepare release ebean-11.33.3 2019-02-02 22:28:47 +13:00
rob bygrave 961a7ef7ea #1626 - ENH: Add SqlUpdate.setParams(Object ... ) and SqlQuery.setParams(Object ... ) ... as convenient alternative to many setParameter() calls 2019-02-02 22:17:07 +13:00
rob bygrave 5cef1ad017 #1625 - Populate UUID via database column default value / impossible to disable automatic generation for @Id fields of type UUID. 2019-02-02 20:16:05 +13:00
rob bygrave b814ca6e81 Bump ebean-migration to 11.14.1 with logging improvement 2019-02-02 17:37:21 +13:00
rob bygrave a24e6b6064 #1623 - DbOrderByTrim doesn't remove asc/desc if you're sorting by a function called on a column
This fix removes the word boundary check prior to the blank space for asc and desc (allowing the preceeding char to be a brace or anything)
2019-02-02 00:40:56 +13:00
rob bygrave b751823abb #1624 - ENH: Create io.ebean.DB as alias for Ebean and io.ebean.Database as alias for EbeanServer
Adjust Model and Finder to use DB and Database
2019-02-01 23:20:53 +13:00
rob bygrave f3cb7e2cfd #1624 - ENH: Create io.ebean.DB as alias for Ebean and io.ebean.Database as alias for EbeanServer 2019-02-01 22:53:41 +13:00
rob bygrave 31d7c6fed8 #1622 - ENH: Bump ebean-datasource to 4.3.3 with improved DataSourceInitialiseException 2019-01-30 12:10:16 +13:00
rob bygrave c5fb1dbe23 [maven-release-plugin] prepare for next development iteration 2019-01-29 15:59:24 +13:00
rob bygrave b7770a9617 [maven-release-plugin] prepare release ebean-11.33.2 2019-01-29 15:59:11 +13:00
rob bygrave 41abf34ef6 #1621 - Consider clean up white space in generated SQL (as in remove unneeded extra spaces) 2019-01-25 01:52:23 +13:00
rob bygrave 89beaee0f6 #1621 - Consider clean up white space in generated SQL (as in remove unneeded extra spaces) 2019-01-25 01:47:21 +13:00
rob bygrave 5052afbd07 #1620 - Support case statement in order by clause 2019-01-23 22:28:53 +13:00
rob bygrave d89a58482c no effective change - tidy test order by parse 2019-01-23 21:48:49 +13:00
rob bygrave eb1bca805e #1619 - Support aggregation formula on fetch clause e.g. query.fetch("machineUsage", "sum(totalKms)") 2019-01-23 16:45:47 +13:00
rob bygrave 9cb66b112f [maven-release-plugin] prepare for next development iteration 2019-01-23 00:31:34 +13:00
rob bygrave 210901ee2d [maven-release-plugin] prepare release ebean-11.33.1 2019-01-23 00:31:18 +13:00
rob bygrave 396fb49acd #1618 - ENH: Add @Sum ... as short hand for @Aggregation("sum(<property name>)") 2019-01-23 00:29:51 +13:00
rob bygrave a83896f1ff #1617 - save() on a reference bean causes insert to occur ... results in duplicate key exception
Fix
2019-01-22 21:59:17 +13:00
rob bygrave 3483372ae3 #1617 - save() on a reference bean causes insert to occur ... results in duplicate key exception
Tests broken by fix as the test inserts only included id value in the insert
2019-01-22 21:59:04 +13:00
rob bygrave 4e1f817ade #1617 - save() on a reference bean causes insert to occur ... results in duplicate key exception
Tests that reproduce the issue (supplied by Andre - thanks for that)
2019-01-22 21:54:03 +13:00
rob bygrave d4139aa8ef #1616 - Enhance EQL grammer 1) Allow select without ( and ) 2) support aggregate functions min,max,sum,count,avg 3) support quoting fetch paths (that are keywords)
Fix test for Postgres any()
2019-01-22 21:23:16 +13:00
rob bygrave a6cfed7c44 #1616 - Enhance EQL grammer 1) Allow select without ( and ) 2) support aggregate functions min,max,sum,count,avg 3) support quoting fetch paths (that are keywords) 2019-01-22 21:12:18 +13:00
rob bygrave cc17ea8911 No effective change - improve tests for TestAggregationTopLevel 2019-01-22 20:26:50 +13:00
rob bygrave 141f0a8b16 Testing out concept - aggregation formula on fetch clause 2019-01-22 15:56:20 +13:00
rob bygrave 9dbd903a73 No effective change - Update tests for aggregation queries 2019-01-22 15:53:47 +13:00
rob bygrave b8105190d1 #1615 - findNative() with List/array named parameter throws error ... query plan key doesn't take bind count into account 2019-01-22 01:56:58 +13:00
rob bygrave ef3d911e19 #1614 - Refactor DbMigration.generateMigration() to use System out to log key messages and throw UnknownResourcePathException 2019-01-22 01:08:15 +13:00
rob bygrave 31fd0b7ed5 Bump version to 11.33.1-SNAPSHOT 2019-01-22 01:04:25 +13:00
rob bygrave 26d1288757 #1613 - When using transaction.setPersistCascade(false) ... a Delete query should not cascade 2019-01-22 00:05:19 +13:00
rob bygrave 1d49e5b341 #1613 - When using transaction.setPersistCascade(false) ... a Delete query should not cascade 2019-01-21 22:09:15 +13:00
rob bygrave 4a0806e453 #1612 - query.setMapKey("customer.id") throws NullPointerException (ie. mapKey is a path rather than local property) 2019-01-21 21:57:30 +13:00
rob bygrave ab48f796c6 #1611 - ENH: Add inRange expression (as half open expression) ... (property >= lowerValue and property < upperValue)
Bump antlr4-runtime from 4.7.1 to 4.7.2
2019-01-21 20:30:39 +13:00
rob bygrave 0cb8bb0415 #1611 - ENH: Add inRange expression (as half open expression) ... (property >= lowerValue and property < upperValue)
Add inrange to EQL grammer
2019-01-21 20:28:38 +13:00
rob bygrave 471691c747 #1611 - ENH: Add inRange expression (as half open expression) ... (property >= lowerValue and property < upperValue) 2019-01-21 20:01:57 +13:00
rob bygrave c86e6b3cf9 #1610 - Refactor: Change SQL logging such that jdbc batch use is more obvious 2019-01-21 19:31:28 +13:00
rob bygrave b399713a85 No effective change - update readme 2019-01-17 17:19:35 +13:00
rob bygrave f8d4ad7f33 No effective change - update on Transaction 2019-01-16 15:44:45 +13:00
rob bygrave 7984a9ccd1 No effective change - update test to use try with resources 2019-01-16 11:13:43 +13:00
rob bygrave 27cda09523 Merge branch 'master' of github.com:ebean-orm/ebean 2019-01-15 22:16:15 +13:00
rob bygrave 20fc23c19c No effective change - improve javadoc for ExpressionList 2019-01-15 22:16:03 +13:00
André CamiloandRob Bygrave bac53a5d75 FIX: insert in batch OneToOne relationship (#1609) 2019-01-15 11:56:52 +13:00
rob bygrave 2e0690efa9 No effective change - improve javadoc for Transaction and EbeanServer 2019-01-14 23:10:56 +13:00
rob bygrave fdd9b1905c No effective change - improve javadoc for query.exists() and query.setBaseTable() 2019-01-10 14:52:55 +13:00
rob bygrave fc966618a6 No effective change - improve javadoc for Query.setInheritType() 2019-01-10 14:42:55 +13:00
rob bygrave 669ba7837a [maven-release-plugin] prepare for next development iteration 2019-01-10 03:44:59 +13:00
rob bygrave 0edf90056c [maven-release-plugin] prepare release ebean-11.32.1 2019-01-10 03:44:44 +13:00
Rob BygraveandGitHub 6b27a9d280 Support @ManyToOne inside @Embeddables - fix for #52 (#1608)
* #52 - @ManyToOne support inside @Embeddables

Initial test and work

* #52 - @ManyToOne support inside @Embeddables

Initial test and work

* #52 - @ManyToOne support inside @Embeddables

Initial test and work

* #52 - @ManyToOne support inside @Embeddables

Initial test and work

* #52 - @ManyToOne support inside @Embeddables

Initial test and work

* #52 - @ManyToOne support inside @Embeddables

Initial test and work

* #52 - @ManyToOne support inside @Embeddables

Update test with sql capture

* #52 - @ManyToOne support inside @Embeddables

Update test with cache clearing before hand (such that we hit DB on lazy load)
2019-01-10 03:40:02 +13:00
rob bygrave 2b0669c2ae #1594 - Support loading of beans with invalid JSON content
Adjust to be per query via query.setAllowLoadErrors() rather than a
global config via ServerConfig.
2019-01-09 20:03:26 +13:00
rob bygrave 9fc10e8e04 Merge branch 'FOCONIS-feature/load-error' 2019-01-09 19:26:13 +13:00
rob bygrave fb5eb0cdd2 Merge branch 'feature/load-error' of https://github.com/FOCONIS/ebean into FOCONIS-feature/load-error 2019-01-09 19:25:50 +13:00
rob bygrave 3351882915 #1602 - Adjust test adding sql checking for discriminator 2019-01-09 19:20:05 +13:00
Roland PramlandRob Bygrave 31c6d16e73 A query on inherited beans can be restricted to the subtype of one of its children (#1602)
ENH: A query on inherited beans can be restricted to the subtype of one of its children
2019-01-09 19:15:04 +13:00
rob bygrave cd8c12a9a8 #1566 - ENH: Support query.setBaseTable() ... to query against dynamic table (ala manual table partitioning) 2019-01-09 19:13:35 +13:00
rob bygrave 3207ae1f08 No effective change - tidy test 2019-01-09 19:05:16 +13:00
Roland PramlandRob Bygrave 5fe532c393 Refactor: relpaced system-property "ebean.ignoreExtraDdl" with serverConfig flag (#1597) 2019-01-09 16:17:11 +13:00
rob bygrave 93b9cbf9ac bump to 11.32.1-SNAPSHOT 2019-01-09 14:01:25 +13:00
rob bygrave 8a34d6050b #1607 - ENH: Add query.exists() query ... as a convenience for "does a row exist" check 2019-01-09 13:59:53 +13:00
rob bygrave ab3e6ccbf7 [maven-release-plugin] prepare for next development iteration 2019-01-09 12:43:01 +13:00
rob bygrave cc58fc8195 [maven-release-plugin] prepare release ebean-11.31.3 2019-01-09 12:42:48 +13:00
rob bygrave 1c34c09f3c #1606 - Bean with Inheritance and OneToMany with JoinTable and cascade ... doesn't cascade save on all bean types 2019-01-09 12:37:13 +13:00
rob bygrave 8544712448 #1606 - Bean with Inheritance and OneToMany with JoinTable and cascade ... doesn't cascade save on all bean types 2019-01-09 12:29:28 +13:00
rob bygrave 5e22079366 [maven-release-plugin] prepare for next development iteration 2019-01-08 23:04:14 +13:00
rob bygrave 903b0a3929 [maven-release-plugin] prepare release ebean-11.31.2 2019-01-08 23:03:59 +13:00
Roland PramlandRob Bygrave b18bc82b8a FIX: possible NPE in DeleteUnloadedForeignKeys.deleteCascade and in initPostTarget (#1601) 2019-01-08 22:41:43 +13:00
Roland PramlandRob Bygrave 50de32af29 Fixed tests, if SqlServer has "Latin1_General_100_BIN2" collation. (#1600)
This means, all names are interpreted case sensitive by the db
2019-01-08 22:40:14 +13:00
Roland PramlandRob Bygrave 0b18189e62 exposed the schedule methods in BackgroundExecutor (#1599) 2019-01-08 22:39:08 +13:00
Roland PramlandRob Bygrave 0b6e73d729 FIX: create uuid-state file in user's home directory (#1598) 2019-01-08 22:37:42 +13:00
Roland PramlandRob Bygrave 3108076953 SqlServer queryplan captured in transaction & fix of possible NPE (#1592)
* SqlServer queryplan captured in transaction & fix of possible NPE

* rolled back transaction earlier
2019-01-08 22:15:31 +13:00
Roland PramlandRob Bygrave 7ed4435ccc Fix some testcases fof MySql/SqlServer (#1591)
* FIX testcases for MariaDB+utf8mb4  (Failure was: "Specified key was too long; max key length is 767 bytes")

* Excluded tests that won't work on SqlServers generated ids
2019-01-08 22:13:55 +13:00
rob bygrave 7aef4ff1bd #1605 - RuntimeException: Nothing in batch? ... when lazy loading on partially populated L2 bean cache 2019-01-08 21:44:18 +13:00
rob bygrave 5bcad17ae1 No effective change - add a test for filterMany with isNotEmpty() 2019-01-08 16:50:28 +13:00
rob bygrave b1beb0b787 #1596 - NullPointerException at findOne() with filterMany() 2019-01-07 22:21:54 +13:00
rob bygrave 585eb2b57b #1604 - Open URL resources without caching 2019-01-07 22:10:17 +13:00
rob bygrave 2653ec50aa #1604 - Open URL resources without caching 2019-01-07 21:52:55 +13:00
rob bygrave cb4432a588 No effective change - Bump agent to 11.27.1 2019-01-07 21:46:14 +13:00
Roland Praml 4d93b70bf9 Supports loading of corrupt beans 2019-01-03 11:43:50 +01:00
rob bygrave 0b299edf0d [maven-release-plugin] prepare for next development iteration 2018-12-21 20:56:41 +13:00
rob bygrave cf10246783 [maven-release-plugin] prepare release ebean-11.31.1 2018-12-21 20:56:26 +13:00
rob bygrave babba914a0 No effective change - add toString() for ServerCacheNotification 2018-12-21 17:14:29 +13:00
rob bygrave 0397140e0b #1589 - Refactor internals move SqlQuery sqlDistinct ... to SqlTreeNodeRoot (query plan) 2018-12-21 15:57:07 +13:00
rob bygrave 82def2710e No effective change - adjust test to have at least 1 column on insert 2018-12-21 15:51:09 +13:00
rob bygrave 60ad417e1b No effective change - adjust test to have at least 1 column on insert 2018-12-21 15:21:01 +13:00
rob bygrave 3af1b574fd #1588 -Fix query plan capture excluding update and delete queries from query plan capture 2018-12-21 14:31:49 +13:00
rob bygrave 60c8683914 No effective change - test assert to contains rather than containsExactly 2018-12-21 14:29:50 +13:00
rob bygrave 72263c0af0 No effective change - test assert to contains rather than containsExactly 2018-12-21 13:57:00 +13:00
rob bygrave f66316138d #1584 - Fix for - Query cache bug, which produces wrong results 2018-12-21 13:53:05 +13:00
Roland PramlandRob Bygrave b403942491 Query cache bug, which produces wrong results (#1584) 2018-12-21 11:55:07 +13:00
rob bygrave baa3909c63 #1586 - ENH: Add TimedMetric.addSinceNanos() ... as a helper when using start nanos 2018-12-21 02:28:23 +13:00
rob bygrave 81f42f8e95 #1587 - Fix for propagation of @Cache(nearCache=true) 2018-12-21 02:19:21 +13:00
rob bygrave 0377e3ec5c #1586 - ENH: Add TimedMetric.addSinceNanos() ... as a helper when using start nanos 2018-12-21 02:10:16 +13:00
rob bygrave 58f6c67d78 #1585 - Change the L2 bean cache keys to be String based 2018-12-21 01:54:46 +13:00
rob bygrave 84f7fc5d81 No effective change - javadoc for ServerConfig getServiceObject 2018-12-19 21:20:37 +13:00
rob bygrave ea02bebc6f [maven-release-plugin] prepare for next development iteration 2018-12-19 21:16:42 +13:00
rob bygrave da874d84a8 [maven-release-plugin] prepare release ebean-11.30.1 2018-12-19 21:16:27 +13:00
rob bygrave 049cacad1c #1583 - ENH: Add type safe ServerConfig getServiceObject(Class<P> cls) and putServiceObject() 2018-12-19 21:14:25 +13:00
rob bygrave ced8c79458 #1582 - ENH: Pass @Cache nearCache option to ServerCacheOptions (for L2 plugins like Redis) 2018-12-19 20:57:45 +13:00
rob bygrave a66edf8077 #1477 Query plan capture - use explain analyze for Postgres
... so that we also get DB side timing
2018-12-19 16:55:24 +13:00
Rob BygraveandGitHub 94591954b3 1476 - Query plan capture, initial wip capturing bind params (#1477)
* 1476 - Query plan capture, initial wip capturing bind params

* No effective change - Reset test default db to H2

* #1476 - Query plan capture, initial wip capturing bind params #1477

Update with consumer

* #1476 - Query plan capture, initial wip capturing bind params #1477

Update with query plan request

* #1476 - Query plan capture, initial wip capturing bind params #1477

Extract interface

* #1476 - Query plan capture, initial wip capturing bind params #1477

Extract interface
2018-12-19 16:04:28 +13:00
rob bygrave e611353163 No effective change - update javadoc for QueryIterator to use try with resources 2018-12-19 15:22:32 +13:00
rob bygrave e7811910e9 No effective change - update javadoc 2018-12-19 15:15:38 +13:00
rob bygrave 138b587ff7 #1581 - ENH: Add query.asUpdate() ... to convert a query into an UpdateQuery (typically with query beans) 2018-12-19 14:45:33 +13:00
rob bygrave 8fc6c4c648 #1580 - Refactor move io.ebeaninternal.metric to public package of io.ebean.metric (such that it can be used by plugins like redis l2 cache plugin) 2018-12-19 14:16:36 +13:00
rob bygrave ebdc28e1cd #1579 - ENH: for UpdateQuery add setLabel() and update() as top level methods 2018-12-19 13:58:28 +13:00
rob bygrave 51f79e769c [maven-release-plugin] prepare for next development iteration 2018-12-17 23:39:34 +13:00
rob bygrave c2a69714ca [maven-release-plugin] prepare release ebean-11.29.1 2018-12-17 23:39:18 +13:00
rob bygrave f3213e7b90 Bump to 11.29.1-SNAPSHOT 2018-12-17 23:19:43 +13:00
rob bygrave 55de997297 #1578 - Remove unmaintained META-INF/ebean-version.mf manifest file ... use EbeanVersion.getVersion() instead 2018-12-17 23:18:29 +13:00
rob bygrave 65890f9777 No effective change - remove unused resources from test resources 2018-12-17 23:14:51 +13:00
rob bygrave 41c1e7260c #1577 - ENH: Add support for "dbinit" migrations (Sort of "checkpoint" or "fast forward" migrations) 2018-12-17 23:11:13 +13:00
rob bygrave 7d35789db4 #1573 - Incorrect CamelCase conversion when number proceeds uppercase letter 2018-12-16 16:12:34 +13:00
rob bygrave d266d6d440 #1574 - "NullPointerException" in query.copy().findList() but not in query.findList() 2018-12-16 00:29:18 +13:00
rob bygrave 6d5374e66a #1576 - ClusterManager creates ClusterBroadcast even when config is not active 2018-12-15 23:17:00 +13:00
rob bygrave 8410de8831 #1573 - Incorrect CamelCase conversion when number proceeds uppercase letter 2018-12-13 00:19:40 +13:00
rob bygrave 4b0230e862 Refactor - reduce visibility on DefaultDbMigration 2018-12-11 21:03:45 +13:00
rob bygrave fa96f81f8c [maven-release-plugin] prepare for next development iteration 2018-12-06 00:19:14 +13:00
rob bygrave a5fea5e9be [maven-release-plugin] prepare release ebean-11.28.3 2018-12-06 00:18:53 +13:00
rob bygrave bafba0babf #1572 - Support query.select("customer.id").findSingleAttributeList() ... in addition to the expected and working select("customer").findSingleAttributeList() 2018-12-06 00:15:06 +13:00
rob bygrave e4088c5fbe #1571 - NPE in cacheable bean with embeddedid on delete 2018-12-05 23:03:15 +13:00
RienandRob Bygrave 0405ceb96c NPE in cacheable bean with embeddedid on delete (#1570) 2018-12-05 21:49:27 +13:00
rob bygrave ebf96c87bf [maven-release-plugin] prepare for next development iteration 2018-12-03 22:14:59 +13:00
rob bygrave fcaf11f262 [maven-release-plugin] prepare release ebean-11.28.2 2018-12-03 22:14:46 +13:00
rob bygrave 05df47c0d7 #1569 - Ebean generates wrong ddl (datetime(6) vs timestamp) for H2 with @History annotation 2018-12-03 22:11:47 +13:00
rob bygrave a8892292fb #1569 - Ebean generates wrong ddl (datetime(6) vs timestamp) for H2 with @History annotation 2018-12-03 22:05:18 +13:00
rob bygrave e876ef8d87 #1559 - @Lob with @ElementCollection 2018-12-03 21:07:33 +13:00
rob bygrave 315b39813b #1568 - @OneToMany with orphanRemoval=true ... with @Cache (and not a @ManyToOne) doesn't remove orphans after cache hit 2018-11-30 23:46:11 +13:00
rob bygrave 6d5e0c4766 Add test only - Add test for L2 cache with orphanRemoval 2018-11-30 23:41:23 +13:00
rob bygrave a2ce17aec0 Add test only - Add test for L2 cache with orphanRemoval 2018-11-30 22:42:36 +13:00
rob bygrave fcffa92c55 #1567 - SqlUpdate addBatch() ... with named parameters errors with PersistenceException: No batched statement found for key 2018-11-30 21:47:23 +13:00
rob bygrave 7fda8079c2 [maven-release-plugin] prepare for next development iteration 2018-11-30 09:55:20 +13:00
rob bygrave cca9bb4427 [maven-release-plugin] prepare release ebean-11.28.1 2018-11-30 09:55:06 +13:00
rob bygrave f45089240a #1565 - Bump to ebean-datasource 4.3.1 ... with option for owner database credentials and InitDatabase 2018-11-30 09:44:07 +13:00
rob bygrave 8252a51545 #1565 - Bump to ebean-datasource 4.3.1 ... with option for owner database credentials and InitDatabase 2018-11-29 10:16:48 +13:00
rob bygrave c440c768cf #1564 - Remove deprecated io.ebeaninternal.server.core.ServletContextListener - migrate to io.ebean.event.ServletContextListener 2018-11-29 10:01:56 +13:00
rob bygrave c6ae501354 #1563 - Remove deprecated noop method ServerConfig.loadTestProperties() - migrate to loadProperties() 2018-11-29 09:59:16 +13:00
rob bygrave 70e2b1c2ae #1562 - Query cache use incorrect with RawExpression - incorrect bind hash 2018-11-29 09:54:24 +13:00
rob bygrave 211f28eea3 [maven-release-plugin] prepare for next development iteration 2018-11-27 14:58:40 +13:00
1591 changed files with 69636 additions and 26402 deletions
+3
View File
@@ -0,0 +1,3 @@
# These are supported funding model platforms
custom: https://ebean.io/sponsors
+3 -3
View File
@@ -1,14 +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
+33 -4
View File
@@ -1,8 +1,39 @@
[![Build Status](https://travis-ci.org/ebean-orm/ebean.svg?branch=master)](https://travis-ci.org/ebean-orm/ebean)
[![Maven Central : ebean](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean)
# Sponsors
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="https://www.foconis.de/" target="_blank">
<img width="222px" src="https://www.foconis.de/templates/yootheme/cache/foconis_logo_322-709da1de.png">
</a>
</td>
<td align="center" valign="middle">
<a href="https://www.payintech.com/" target="_blank">
<img width="222px" src="https://ebean.io/images/sponsor_PayinTech-logo-noir.png">
</a>
</td>
<td align="center" valign="middle">
<a href="https://www.premium-minds.com" target="_blank">
<img width="222px" src="https://ebean.io/images/logo-med-principal.png">
</a>
</td>
<td align="center" valign="middle">
<a href="https://timerbee.de" target="_blank">
<img width="222px" src="https://ebean.io/images/logo-timerbee.png">
</a>
</td>
</tr>
</tbody>
</table>
# Need help?
Post questions or issues to the Ebean google group - https://groups.google.com/forum/#!forum/ebean
# Documentation
Goto [https://ebean-orm.github.io/](http://ebean-orm.github.io/ "Ebean ORM's Website")
Goto [https://ebean.io/docs/](https://ebean.io/docs/)
## Maven cental links:
@@ -10,8 +41,6 @@ Goto [https://ebean-orm.github.io/](http://ebean-orm.github.io/ "Ebean ORM's Web
[Maven central - all related projects](http://search.maven.org/#search%7Cga%7C1%7Cebean "maven central all related projects")
## Current versions
* [![Maven Central : ebean](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.ebean/ebean) - ebean
## 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
+84 -107
View File
@@ -3,56 +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.27.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.5</jackson-core.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.27.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:
@@ -88,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>
<!--
@@ -102,46 +72,46 @@
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.1</version>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-annotation</artifactId>
<version>4.3</version>
<version>6.13</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-types</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-datasource</artifactId>
<version>4.2.2</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.11.1</version>
<version>12.1.4</version>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>4.7.1</version>
<version>4.7.2</version>
</dependency>
<!-- Jackson core used internally by Ebean -->
@@ -155,7 +125,7 @@
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-core.version}</version>
<version>${jackson-databind.version}</version>
<scope>provided</scope>
</dependency>
@@ -188,27 +158,49 @@
<scope>provided</scope>
</dependency>
<!-- Provided scope to compile with java 11 -->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
<scope>provided</scope>
</dependency>
<!-- Provided scope for Postgres JSON/JSONB support -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.2</version>
<version>42.2.10</version>
<scope>provided</scope>
</dependency>
<!-- Test scope -->
<!--<dependency>-->
<!--<groupId>oracle</groupId>-->
<!--<artifactId>oracle-jdbc</artifactId>-->
<!--<version>7.0</version>-->
<!--<scope>test</scope>-->
<!--</dependency>-->
<dependency>
<groupId>com.nuodb.jdbc</groupId>
<artifactId>nuodb-jdbc</artifactId>
<version>20.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-docker-run</artifactId>
<version>1.5.1</version>
<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>3.1.5</version>
<scope>test</scope>
</dependency>
@@ -219,26 +211,12 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.avaje</groupId>
<artifactId>avaje-agentloader</artifactId>
<version>2.1.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-agent</artifactId>
<version>11.25.1</version>
<scope>test</scope>
</dependency>
<!-- Provided scope so that the H2HistoryTrigger can live in Ebean core
and not require a separate module for it -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.196</version>
<version>1.4.199</version>
<scope>provided</scope>
</dependency>
@@ -259,15 +237,21 @@
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>6.4.0.jre8</version>
<version>7.2.2.jre8</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<!-- Do not upgrade to 6.0.6: https://bugs.mysql.com/bug.php?id=82896 -->
<version>5.1.43</version>
<version>8.0.17</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>2.6.0</version>
<scope>test</scope>
</dependency>
@@ -278,12 +262,18 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>
<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>
@@ -294,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>
@@ -309,13 +299,13 @@
<plugin>
<groupId>io.ebean</groupId>
<artifactId>ebean-maven-plugin</artifactId>
<version>11.25.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>
@@ -327,9 +317,10 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
<version>3.0.0-M4</version>
<configuration>
<useSystemClassLoader>false</useSystemClassLoader>
<trimStackTrace>false</trimStackTrace>
<failIfNoTests>false</failIfNoTests>
<includes>
<include>**/Test*.java</include>
@@ -365,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.*:com.avaje.ebean.util</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>
<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>
<linksource>true</linksource>
<overview>src/main/java/com/avaje/ebean/overview.html</overview>
</configuration>
+24 -2
View File
@@ -1,6 +1,8 @@
package io.ebean;
import java.util.concurrent.Callable;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
/**
@@ -29,12 +31,32 @@ 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.
*
* @return a ScheduledFuture representing pending completion of the task and
* whose get() method will return null upon completion
*/
ScheduledFuture<?> schedule(Runnable r, long delay, TimeUnit unit);
/**
* Schedules a Callable for one-shot action that becomes enabled after the given delay.
*
* @return a ScheduledFuture that can be used to extract result or cancel
*/
<V> ScheduledFuture<V> schedule(Callable<V> c, long delay, TimeUnit unit);
}
+16 -21
View File
@@ -15,8 +15,8 @@ import java.util.Optional;
* public class CustomerFinder extends BeanFinder<Long,Customer> {
*
* @Inject
* public CustomerFinder(EbeanServer server) {
* super(Customer.class, server);
* public CustomerFinder(Database database) {
* super(Customer.class, database);
* }
*
* // ... add customer specific finders
@@ -29,25 +29,25 @@ import java.util.Optional;
*/
public abstract class BeanFinder<I,T> {
protected final EbeanServer server;
protected final Database server;
protected final Class<T> type;
/**
* Create with the given bean type and EbeanServer instance.
* Create with the given bean type and Database instance.
*
* @param type The bean type
* @param server The EbeanServer instance typically created via Spring factory or equivalent.
* @param server The Database instance typically created via Spring factory or equivalent.
*/
protected BeanFinder(Class<T> type, EbeanServer server) {
protected BeanFinder(Class<T> type, Database server) {
this.type = type;
this.server = server;
}
/**
* Return the EbeanServer to use.
* Return the Database to use.
*/
public EbeanServer db() {
public Database db() {
return server;
}
@@ -66,21 +66,20 @@ public abstract class BeanFinder<I,T> {
}
/**
* Return typically a different EbeanServer to the default.
* Return typically a different Database to the default.
* <p>
* This is equivalent to {@link Ebean#getServer(String)}
* This is equivalent to {@link DB#byName(String)}
*
* @param server The name of the EbeanServer. If this is null then the default EbeanServer is
* returned.
* @param server The name of the Database. If this is null then the default Database is returned.
*/
public EbeanServer db(String server) {
return Ebean.getServer(server);
public Database db(String server) {
return DB.byName(server);
}
/**
* Creates an entity reference for this ID.
* <p>
* Equivalent to {@link EbeanServer#getReference(Class, Object)}
* Equivalent to {@link Database#getReference(Class, Object)}
*/
@Nonnull
public T ref(I id) {
@@ -89,8 +88,6 @@ public abstract class BeanFinder<I,T> {
/**
* Retrieves an entity by ID.
* <p>
* Equivalent to {@link EbeanServer#find(Class, Object)}
*/
@Nullable
public T findById(I id) {
@@ -107,8 +104,6 @@ public abstract class BeanFinder<I,T> {
/**
* Delete a bean by Id.
* <p>
* Equivalent to {@link EbeanServer#delete(Class, Object)}
*/
public void deleteById(I id) {
db().delete(type, id);
@@ -138,7 +133,7 @@ public abstract class BeanFinder<I,T> {
* }</pre>
*
* <p>
* Equivalent to {@link EbeanServer#update(Class)}
* Equivalent to {@link Database#update(Class)}
*/
protected UpdateQuery<T> updateQuery() {
return db().update(type);
@@ -147,7 +142,7 @@ public abstract class BeanFinder<I,T> {
/**
* Creates a query.
* <p>
* Equivalent to {@link EbeanServer#find(Class)}
* Equivalent to {@link Database#find(Class)}
*/
protected Query<T> query() {
return db().find(type);
+14 -14
View File
@@ -13,7 +13,7 @@ import java.util.Collection;
* public class CustomerRepository extends BeanRepository<Long,Customer> {
*
* @Inject
* public CustomerRepository(EbeanServer server) {
* public CustomerRepository(Database server) {
* super(Customer.class, server);
* }
*
@@ -34,23 +34,23 @@ import java.util.Collection;
public abstract class BeanRepository<I, T> extends BeanFinder<I, T> {
/**
* Create with the given bean type and EbeanServer instance.
* Create with the given bean type and Database instance.
* <p>
* Typically users would extend BeanRepository rather than BeanFinder.
* </p>
* <pre>{@code
*
* @Inject
* public CustomerRepository(EbeanServer server) {
* public CustomerRepository(Database server) {
* super(Customer.class, server);
* }
*
* }</pre>
*
* @param type The bean type
* @param server The EbeanServer instance typically created via Spring factory or equivalent
* @param server The Database instance typically created via Spring factory or equivalent
*/
protected BeanRepository(Class<T> type, EbeanServer server) {
protected BeanRepository(Class<T> type, Database server) {
super(type, server);
}
@@ -75,7 +75,7 @@ public abstract class BeanRepository<I, T> extends BeanFinder<I, T> {
*
* }</pre>
*
* @see EbeanServer#markAsDirty(Object)
* @see Database#markAsDirty(Object)
*/
public void markAsDirty(T bean) {
db().markAsDirty(bean);
@@ -111,7 +111,7 @@ public abstract class BeanRepository<I, T> extends BeanFinder<I, T> {
* Ebean will detect if this is a new bean or a previously fetched bean and perform either an
* insert or an update based on that.
*
* @see EbeanServer#save(Object)
* @see Database#save(Object)
*/
public void save(T bean) {
db().save(bean);
@@ -127,7 +127,7 @@ public abstract class BeanRepository<I, T> extends BeanFinder<I, T> {
/**
* Update this entity.
*
* @see EbeanServer#update(Object)
* @see Database#update(Object)
*/
public void update(T bean) {
db().update(bean);
@@ -136,7 +136,7 @@ public abstract class BeanRepository<I, T> extends BeanFinder<I, T> {
/**
* Insert this entity.
*
* @see EbeanServer#insert(Object)
* @see Database#insert(Object)
*/
public void insert(T bean) {
db().insert(bean);
@@ -157,7 +157,7 @@ public abstract class BeanRepository<I, T> extends BeanFinder<I, T> {
* deleted. Note that, if JDBC batch mode is used then this always returns true.
* </p>
*
* @see EbeanServer#delete(Object)
* @see Database#delete(Object)
*/
public boolean delete(T bean) {
return db().delete(bean);
@@ -177,7 +177,7 @@ public abstract class BeanRepository<I, T> extends BeanFinder<I, T> {
* want to perform a hard/permanent delete.
* </p>
*
* @see EbeanServer#deletePermanent(Object)
* @see Database#deletePermanent(Object)
*/
public boolean deletePermanent(T bean) {
return db().deletePermanent(bean);
@@ -189,7 +189,7 @@ public abstract class BeanRepository<I, T> extends BeanFinder<I, T> {
* Ebean will detect if this is a new bean or a previously fetched bean and perform either an
* insert or an update based on that.
*
* @see EbeanServer#merge(Object)
* @see Database#merge(Object)
*/
public void merge(T bean) {
db().merge(bean);
@@ -201,7 +201,7 @@ public abstract class BeanRepository<I, T> extends BeanFinder<I, T> {
* Ebean will detect if this is a new bean or a previously fetched bean and perform either an
* insert or an update based on that.
*
* @see EbeanServer#merge(Object, MergeOptions)
* @see Database#merge(Object, MergeOptions)
*/
public void merge(T bean, MergeOptions options) {
db().merge(bean, options);
@@ -210,7 +210,7 @@ public abstract class BeanRepository<I, T> extends BeanFinder<I, T> {
/**
* Refreshes this entity from the database.
*
* @see EbeanServer#refresh(Object)
* @see Database#refresh(Object)
*/
public void refresh(T bean) {
db().refresh(bean);
+9 -2
View File
@@ -1,5 +1,6 @@
package io.ebean;
import javax.annotation.Nullable;
import java.util.Map;
import java.util.Set;
@@ -56,7 +57,7 @@ public interface BeanState {
*
* // set loaded state on the email property to false so that
* // the email property is not included in a stateless update
* Ebean.getBeanState(user).setPropertyLoaded("email", false);
* DB.getBeanState(user).setPropertyLoaded("email", false);
*
* user.update();
*
@@ -101,7 +102,7 @@ public interface BeanState {
/**
* Advanced - Used to programmatically build a partially or fully loaded
* entity bean. First create an entity bean via
* {@link EbeanServer#createEntityBean(Class)}, then populate its properties
* {@link Database#createEntityBean(Class)}, then populate its properties
* and then call this method specifying which properties where loaded or null
* for a fully loaded entity bean.
*/
@@ -111,4 +112,10 @@ public interface BeanState {
* Reset the bean putting it into NEW state such that a save() results in an insert.
*/
void resetForInsert();
/**
* Returns a map with load erros.
*/
@Nullable
Map<String, Exception> getLoadErrors();
}
+2 -2
View File
@@ -69,8 +69,8 @@ public enum CacheMode {
*/
GET(true, false);
private boolean get;
private boolean put;
private final boolean get;
private final boolean put;
CacheMode(boolean get, boolean put) {
this.get = get;
+16 -18
View File
@@ -17,11 +17,11 @@ import java.sql.SQLException;
*
* String sql = "{call sp_order_mod(?,?)}";
*
* CallableSql cs = Ebean.createCallableSql(sql);
* CallableSql cs = DB.createCallableSql(sql);
* cs.setParameter(1, "turbo");
* cs.registerOut(2, Types.INTEGER);
*
* Ebean.execute(cs);
* DB.execute(cs);
*
* // read the out parameter
* Integer returnValue = (Integer) cs.getObject(2);
@@ -38,7 +38,7 @@ import java.sql.SQLException;
*
* String sql = "{call sp_insert_order(?,?)}";
*
* CallableSql cs = Ebean.createCallableSql(sql);
* CallableSql cs = DB.createCallableSql(sql);
*
* // Inform Ebean this stored procedure inserts into the
* // oe_order table and inserts + updates the oe_order_detail table.
@@ -46,35 +46,33 @@ import java.sql.SQLException;
* cs.addModification("oe_order", true, false, false);
* cs.addModification("oe_order_detail", true, true, false);
*
* Transaction t = Ebean.startTransaction();
*
* // execute using JDBC batching 10 statements at a time
* t.setBatchMode(true);
* t.setBatchSize(10);
* try {
* try (Transaction t = DB.beginTransaction()) {
*
* // execute using JDBC batching 10 statements at a time
* t.setBatchMode(true);
* t.setBatchSize(10);
*
* cs.setParameter(1, "Was");
* cs.setParameter(2, "Banana");
* Ebean.execute(cs);
* DB.execute(cs);
*
* cs.setParameter(1, "Here");
* cs.setParameter(2, "Kumera");
* Ebean.execute(cs);
* DB.execute(cs);
*
* cs.setParameter(1, "More");
* cs.setParameter(2, "Apple");
* Ebean.execute(cs);
* DB.execute(cs);
*
* // Ebean.externalModification("oe_order",true,false,false);
* // Ebean.externalModification("oe_order_detail",true,true,false);
* Ebean.commitTransaction();
* // DB.externalModification("oe_order",true,false,false);
* // DB.externalModification("oe_order_detail",true,true,false);
* t.commit();
*
* } finally {
* Ebean.endTransaction();
* }
* }</pre>
*
* @see SqlUpdate
* @see Ebean#execute(CallableSql)
*/
public interface CallableSql {
@@ -173,7 +171,7 @@ public interface CallableSql {
* Add table modification information to the TransactionEvent.
* <p>
* This would be similar to using the
* <code>Ebean.externalModification()</code> method. It may be easier and make
* <code>DB.externalModification()</code> method. It may be easier and make
* more sense to set it here with the CallableSql.
* </p>
* <p>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,67 @@
package io.ebean;
import io.ebean.config.ContainerConfig;
import io.ebean.config.DatabaseConfig;
/**
* Creates Database instances.
* <p>
* This uses either DatabaseConfig or properties in the application.properties file to
* configure and create a Database instance.
* </p>
* <p>
* The Database instance can either be registered with the DB singleton or
* not. The DB singleton effectively holds a map of Database by a name.
* If the Database is registered with the DB singleton you can retrieve it
* later via {@link DB#byName(String)}.
* </p>
* <p>
* One Database can be nominated as the 'default/primary' Database. Many
* methods on the DB singleton such as {@link DB#find(Class)} are just a
* convenient way of using the 'default/primary' Database.
* </p>
*/
public class DatabaseFactory {
/**
* Initialise the container with clustering configuration.
* <p>
* Call this prior to creating any Database instances or alternatively set the
* ContainerConfig on the ServerConfig when creating the first Database instance.
*/
public static synchronized void initialiseContainer(ContainerConfig containerConfig) {
EbeanServerFactory.initialiseContainer(containerConfig);
}
/**
* 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 database.
*/
public static synchronized Database create(DatabaseConfig config) {
return EbeanServerFactory.create(config);
}
/**
* Create using the ServerConfig additionally specifying a classLoader to use as the context class loader.
*/
public static synchronized Database createWithContextClassLoader(DatabaseConfig config, ClassLoader classLoader) {
return EbeanServerFactory.createWithContextClassLoader(config, classLoader);
}
/**
* Shutdown gracefully all Database instances cleaning up any resources as required.
* <p>
* This is typically invoked via JVM shutdown hook and not explicitly called.
* </p>
*/
public static synchronized void shutdown() {
EbeanServerFactory.shutdown();
}
}
+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")
+30 -3
View File
@@ -30,7 +30,7 @@ import java.util.function.Predicate;
* String sql = "select id, name from customer where name like :name and status_code = :status";
*
* List<CustomerDto> beans =
* Ebean.findDto(CustomrDto.class, sql)
* DB.findDto(CustomerDto.class, sql)
* .setParameter("name", "Acme%")
* .setParameter("status", "ACTIVE")
* .findList();
@@ -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);
@@ -109,6 +126,12 @@ public interface DtoQuery<T> {
*/
DtoQuery<T> setLabel(String label);
/**
* 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.
*/
DtoQuery<T> setProfileLocation(ProfileLocation profileLocation);
/**
* Set a timeout on this query.
* <p>
@@ -130,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);
}
+35 -118
View File
@@ -24,113 +24,29 @@ import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
/**
* This Ebean object is effectively a singleton that holds a map of registered
* {@link EbeanServer}s. It additionally provides a convenient way to use the
* 'default' EbeanServer.
* Deprecated - please migrate to use <code>io.ebean.DB</code>.
* <p>
* If you are using a Dependency Injection framework such as
* <strong>Spring</strong> or <strong>Guice</strong> you will probably
* <strong>NOT</strong> use this Ebean singleton object. Instead you will
* configure and construct EbeanServer instances using {@link ServerConfig} and
* {@link EbeanServerFactory} and inject those EbeanServer instances into your
* data access objects.
* </p>
* Ebean is a registry of {@link Database} by name. Ebean has now been renamed to {@link DB}.
* <p>
* In documentation "Ebean singleton" refers to this object.
* </p>
* <ul>
* <li>There is one EbeanServer per Database (javax.sql.DataSource).</li>
* <li>EbeanServers can be 'registered' with the Ebean singleton (put into its
* map). Registered EbeanServer's can later be retrieved via
* {@link #getServer(String)}.</li>
* <li>One EbeanServer can be referred to as the 'default' EbeanServer. For
* convenience, the Ebean singleton (this object) provides methods such as
* {@link #find(Class)} that proxy through to the 'default' EbeanServer. This
* can be useful for applications that use a single database.</li>
* </ul>
* Ebean is effectively this is an alias for {@link DB} which is the new and improved name for Ebean.
* <p>
* For developer convenience Ebean has static methods that proxy through to the
* methods on the <em>'default'</em> EbeanServer. These methods are provided for
* developers who are mostly using a single database. Many developers will be
* able to use the methods on Ebean rather than get a EbeanServer.
* </p>
* <p>
* EbeanServers can be created and used without ever needing or using the Ebean
* singleton. Refer to {@link ServerConfig#setRegister(boolean)}.
* </p>
* <p>
* You can either programmatically create/register EbeanServers via
* {@link EbeanServerFactory} or they can automatically be created and
* registered when you first use the Ebean singleton. When EbeanServers are
* created automatically they are configured using information in the
* ebean.properties file.
* </p>
* <pre>{@code
*
* // fetch shipped orders (and also their customer)
* List<Order> list = Ebean.find(Order.class)
* .fetch("customer")
* .where()
* .eq("status.code", Order.Status.SHIPPED)
* .findList();
*
* // read/use the order list ...
* for (Order order : list) {
* Customer customer = order.getCustomer();
* ...
* }
*
* }</pre>
* <pre>{@code
*
* // fetch order 10, modify and save
* Order order = Ebean.find(Order.class, 10);
*
* OrderStatus shipped = Ebean.getReference(OrderStatus.class,"SHIPPED");
* order.setStatus(shipped);
* order.setShippedDate(shippedDate);
* ...
*
* // implicitly creates a transaction and commits
* Ebean.save(order);
*
* }</pre>
* <p>
* When you have multiple databases and need access to a specific one the
* {@link #getServer(String)} method provides access to the EbeanServer for that
* specific database.
* </p>
* <pre>{@code
*
* // Get access to the Human Resources EbeanServer/Database
* EbeanServer hrDb = Ebean.getServer("hr");
*
* // fetch contact 3 from the HR database
* Contact contact = hrDb.find(Contact.class, 3);
*
* contact.setName("I'm going to change");
* ...
*
* // save the contact back to the HR database
* hrDb.save(contact);
*
* }</pre>
* 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);
static {
EbeanVersion.getVersion(); // initalizes the version class and logs the version.
EbeanVersion.getVersion(); // initialises the version class and logs the version.
}
/**
* Manages creation and cache of EbeanServers.
* Manages creation and cache of Databases.
*/
private static final Ebean.ServerManager serverMgr = new Ebean.ServerManager();
/**
* Helper class for managing fast and safe access and creation of
* EbeanServers.
* Helper class for managing fast and safe access and creation of Databases.
*/
private static final class ServerManager {
@@ -147,7 +63,7 @@ public final class Ebean {
private final Object monitor = new Object();
/**
* The 'default' EbeanServer.
* The 'default' Database.
*/
private EbeanServer defaultServer;
@@ -166,20 +82,20 @@ public final class Ebean {
throw e;
} catch (DataSourceConfigurationException e) {
String msg = "Configuration error creating DataSource for the default EbeanServer." +
" This typically means a missing application-test.yaml or missing ebean-test-config dependency." +
String msg = "Configuration error creating DataSource for the default Database." +
" 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);
} catch (Throwable e) {
logger.error("Error trying to create the default EbeanServer", e);
logger.error("Error trying to create the default Database", e);
throw new RuntimeException(e);
}
}
private EbeanServer getDefaultServer() {
if (defaultServer == null) {
String msg = "The default EbeanServer has not been defined?";
String msg = "The default Database has not been defined?";
msg += " This is normally set via the ebean.datasource.default property.";
msg += " Otherwise it should be registered programmatically via registerServer()";
throw new PersistenceException(msg);
@@ -201,7 +117,7 @@ public final class Ebean {
}
/**
* Synchronized read, create and put of EbeanServers.
* Synchronized read, create and put of Databases.
*/
private EbeanServer getWithCreate(String name) {
@@ -240,7 +156,7 @@ public final class Ebean {
}
/**
* Get the EbeanServer for a given DataSource. If name is null this will
* Get the Database for a given DataSource. If name is null this will
* return the 'default' EbeanServer.
* <p>
* This is provided to access EbeanServer for databases other than the
@@ -272,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
@@ -294,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;
@@ -549,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;
* ...
* }
@@ -631,12 +547,10 @@ public final class Ebean {
* Customer customer = new Customer();
* customer.setId(7);
* customer.setName("ModifiedNameNoOCC");
* ebeanServer.update(customer);
*
* DB.update(customer);
*
* }</pre>
*
* @see ServerConfig#setUpdatesDeleteMissingChildren(boolean)
* @see ServerConfig#setUpdateChangesOnly(boolean)
*/
public static void update(Object bean) throws OptimisticLockException {
serverMgr.getDefaultServer().update(bean);
@@ -883,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
@@ -954,6 +868,8 @@ public final class Ebean {
}
/**
* Deprecated - migrate to DB.sqlQuery().
* <p>
* Create a SqlQuery for executing native sql
* query statements.
* <p>
@@ -961,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);
}
/**
@@ -1131,10 +1049,9 @@ public final class Ebean {
*
* String sql = "select c.id, c.name from customer c where c.name like ? order by c.name";
*
* Query<Customer> query = ebeanServer.findNative(Customer.class, sql);
* query.setParameter(1, "Rob%");
*
* List<Customer> customers = query.findList();
* List<Customer> customers = DB.findNative(Customer.class, sql)
* .setParameter(1, "Rob%")
* .findList()
*
* }</pre>
*
@@ -1283,7 +1200,7 @@ public final class Ebean {
* public void run() {
* User u1 = Ebean.find(User.class, 1);
* ...
* }
* }
* });
*
* }</pre>
@@ -1335,7 +1252,7 @@ public final class Ebean {
* User u1 = Ebean.find(User.class, 1);
* ...
* return u1.getEmail();
* }
* }
* });
*
* }</pre>
File diff suppressed because it is too large Load Diff
@@ -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 "";
}
}
@@ -22,8 +22,8 @@ package io.ebean;
* example.setName("Rob%");
* example.setNotes("%something%");
*
* List&lt;Customer&gt; list =
* Ebean.find(Customer.class)
* List<Customer> list =
* DB.find(Customer.class)
* .where()
* // pass the bean into the where() clause
* .exampleLike(example)
@@ -46,7 +46,7 @@ package io.ebean;
* .includeZeros();
*
* List<Customer> list =
* Ebean.find(Customer.class)
* DB.find(Customer.class)
* .where()
* .add(qbe)
* .findList();
+87 -54
View File
@@ -13,27 +13,15 @@ import java.util.Map;
* {@link Query#where()}.
* </p>
* <p>
* This provides a convenient way to create expressions for the 'Default'
* server. It is actually a short cut for using the ExpressionFactory of the
* 'default' EbeanServer.
* This provides a convenient way to create expressions for the default
* database.
* <p>
* See also {@link Ebean#getExpressionFactory()}
* See also {@link DB#getExpressionFactory()}
* </p>
* <p>
* Creates standard common expressions for using in a Query Where or Having
* clause.
* </p>
* <pre>{@code
*
* // Example: Using an Expr.or() method
* Query<Order> query = Ebean.createQuery(Order.class);
* query.where(
* Expr.or(Expr.eq("status", Order.NEW),
* Expr.gt("orderDate", lastWeek));
*
* List<Order> list = query.findList();
* ...
* }</pre>
*
* @see Query#where()
*/
@@ -46,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);
}
/**
@@ -61,30 +49,38 @@ 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);
}
/**
* In Range - property >= value1 and property < value2.
* <p>
* Unlike Between inRange is "half open" and usually more useful for use with dates or timestamps.
* </p>
*/
public static Expression inRange(String propertyName, Object value1, Object 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);
}
/**
@@ -92,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);
}
/**
@@ -135,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);
}
/**
@@ -150,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);
}
/**
@@ -159,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);
}
/**
@@ -174,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);
}
/**
@@ -189,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);
}
/**
@@ -204,49 +200,86 @@ 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);
}
/**
* In where null or empty values means that no predicate is added to the query.
* <p>
* That is, only add the IN predicate if the values are not null or empty.
* <p>
* Without this we typically need to code an <code>if</code> block to only add
* the IN predicate if the collection is not empty like:
* </p>
*
* <h3>Without inOrEmpty()</h3>
* <pre>{@code
*
* query.where() // add some predicates
* .eq("status", Status.NEW);
*
* if (ids != null && !ids.isEmpty()) {
* query.where().in("customer.id", ids);
* }
*
* query.findList();
*
* }</pre>
*
* <h3>Using inOrEmpty()</h3>
* <pre>{@code
*
* query.where()
* .eq("status", Status.NEW)
* .inOrEmpty("customer.id", ids)
* .findList();
*
* }</pre>
*/
public static Expression inOrEmpty(String propertyName, Collection<?> 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);
}
/**
@@ -259,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);
}
/**
@@ -270,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);
}
/**
@@ -281,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);
}
/**
@@ -296,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);
}
/**
@@ -304,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);
}
/**
@@ -312,7 +345,7 @@ public class Expr {
*/
public static Expression not(Expression exp) {
return Ebean.getExpressionFactory().not(exp);
return DB.getExpressionFactory().not(exp);
}
/**
@@ -320,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);
}
/**
@@ -328,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);
}
}
+94 -3
View File
@@ -30,9 +30,9 @@ import java.util.Map;
* Expr.or(Expr.eq("status", Order.Status.NEW),
* Expr.gt("orderDate", lastWeek));
*
* Query<Order> query = Ebean.createQuery(Order.class);
* query.where().add(newOrLastWeek);
* List<Order> list = query.findList();
* List<Order> list = DB.find(Order.class)
* .where().add(newOrLastWeek)
* .findList();
* ...
* }</pre>
*
@@ -122,6 +122,11 @@ public interface ExpressionFactory {
*/
Expression eq(String propertyName, Object value);
/**
* Equal To or Null - property equal to the given value or null.
*/
Expression eqOrNull(String propertyName, Object value);
/**
* Not Equal To - property not equal to the given value.
*/
@@ -149,6 +154,33 @@ public interface ExpressionFactory {
*/
Expression ineObject(String propertyName, Object value);
/**
* In Range - property >= value1 and property < value2.
* <p>
* Unlike Between inRange is "half open" and usually more useful for use with dates or timestamps.
* </p>
*/
Expression inRange(String propertyName, Object value1, Object value2);
/**
* Value in Range between 2 properties.
*
* <pre>{@code
*
* .startDate.inRangeWith(endDate, now)
*
* // which equates to
* startDate <= now and (endDate > now or endDate is null)
*
* }</pre>
*
* <p>
* This is a convenience expression combining a number of simple expressions.
* The most common use of this could be called "effective dating" where 2 date or
* timestamp columns represent the date range in which
*/
Expression inRangeWith(String lowProperty, String highProperty, Object value);
/**
* Between - property between the two given values.
*/
@@ -159,6 +191,14 @@ public interface ExpressionFactory {
*/
Expression betweenProperties(String lowProperty, String highProperty, Object value);
/**
* Greater Than Or Null - property greater than the given value or null.
* <p>
* A convenient expression combining GT and Is Null. Most often useful for range
* expressions where the top range value is nullable.
*/
Expression gtOrNull(String propertyName, Object value);
/**
* Greater Than - property greater than the given value.
*/
@@ -170,6 +210,14 @@ public interface ExpressionFactory {
*/
Expression ge(String propertyName, Object value);
/**
* Less Than or Null - property less than the given value or null.
* <p>
* A convenient expression combining LT and Is Null. Most often useful for range
* expressions where the bottom range value is nullable.
*/
Expression ltOrNull(String propertyName, Object value);
/**
* Less Than - property less than the given value.
*/
@@ -277,6 +325,41 @@ public interface ExpressionFactory {
*/
Expression in(String propertyName, Collection<?> values);
/**
* In where null or empty values means that no predicate is added to the query.
* <p>
* That is, only add the IN predicate if the values are not null or empty.
* <p>
* Without this we typically need to code an <code>if</code> block to only add
* the IN predicate if the collection is not empty like:
* </p>
*
* <h3>Without inOrEmpty()</h3>
* <pre>{@code
*
* query.where() // add some predicates
* .eq("status", Status.NEW);
*
* if (ids != null && !ids.isEmpty()) {
* query.where().in("customer.id", ids);
* }
*
* query.findList();
*
* }</pre>
*
* <h3>Using inOrEmpty()</h3>
* <pre>{@code
*
* query.where()
* .eq("status", Status.NEW)
* .inOrEmpty("customer.id", ids)
* .findList();
*
* }</pre>
*/
Expression inOrEmpty(String propertyName, Collection<?> values);
/**
* Not In - property has a value in the array of values.
*/
@@ -453,4 +536,12 @@ public interface ExpressionFactory {
*/
<T> Junction<T> junction(Junction.Type type, Query<T> query, ExpressionList<T> parent);
/**
* Add the expressions to the given expression list.
*
* @param where The expression list to add the expressions to
* @param expressions The expressions that are parsed
* @param params Bind parameters to match ? or ?1 bind positions.
*/
<T> void where(ExpressionList<T> where, String expressions, Object[] params);
}
+344 -87
View File
@@ -9,6 +9,7 @@ import io.ebean.search.TextSimple;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.persistence.NonUniqueResultException;
import java.sql.Connection;
import java.sql.Timestamp;
import java.util.Collection;
import java.util.List;
@@ -29,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
@@ -51,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.
@@ -58,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
@@ -71,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();
@@ -81,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);
/**
@@ -128,6 +137,38 @@ public interface ExpressionList<T> {
*/
<D> DtoQuery<D> asDto(Class<D> dtoClass);
/**
* Return the underlying query as an UpdateQuery.
* <p>
* Typically this is used with query beans to covert a query bean
* query into an UpdateQuery like the examples below.
* </p>
*
* <pre>{@code
*
* int rowsUpdated = new QCustomer()
* .name.startsWith("Rob")
* .asUpdate()
* .set("active", false)
* .update();;
*
* }</pre>
*
* <pre>{@code
*
* int rowsUpdated = new QContact()
* .notes.note.startsWith("Make Inactive")
* .email.endsWith("@foo.com")
* .customer.id.equalTo(42)
* .asUpdate()
* .set("inactive", true)
* .setRaw("email = lower(email)")
* .update();
*
* }</pre>
*/
UpdateQuery<T> asUpdate();
/**
* Execute using "for update" clause which results in the DB locking the record.
*/
@@ -154,6 +195,16 @@ public interface ExpressionList<T> {
*/
Query<T> setIncludeSoftDeletes();
/**
* Execute the query using the given transaction.
*/
Query<T> usingTransaction(Transaction transaction);
/**
* Execute the query using the given connection.
*/
Query<T> usingConnection(Connection connection);
/**
* Execute as a delete query deleting the 'root level' beans that match the predicates
* in the query.
@@ -194,6 +245,32 @@ public interface ExpressionList<T> {
*/
int update(Transaction transaction);
/**
* Execute the query returning true if a row is found.
* <p>
* The query is executed using max rows of 1 and will only select the id property.
* This method is really just a convenient way to optimise a query to perform a
* 'does a row exist in the db' check.
* </p>
*
* <h2>Example:</h2>
* <pre>{@code
*
* boolean userExists = query().where().eq("email", "rob@foo.com").exists();
*
* }</pre>
*
* <h2>Example using a query bean:</h2>
* <pre>{@code
*
* boolean userExists = new QContact().email.equalTo("rob@foo.com").exists();
*
* }</pre>
*
* @return True if the query finds a matching row in the database
*/
boolean exists();
/**
* Execute the query iterating over the results.
*
@@ -258,27 +335,27 @@ public interface ExpressionList<T> {
/**
* Execute the query returning a list of values for a single property.
* <p>
*
* <h3>Example 1:</h3>
* <pre>{@code
*
* List<String> names =
* Ebean.find(Customer.class)
* DB.find(Customer.class)
* .select("name")
* .orderBy().asc("name")
* .order().asc("name")
* .findSingleAttributeList();
*
* }</pre>
* <p>
*
* <h3>Example 2:</h3>
* <pre>{@code
*
* List<String> names =
* Ebean.find(Customer.class)
* DB.find(Customer.class)
* .setDistinct(true)
* .select("name")
* .where().eq("status", Customer.Status.NEW)
* .orderBy().asc("name")
* .order().asc("name")
* .setMaxRows(100)
* .findSingleAttributeList();
*
@@ -291,11 +368,10 @@ public interface ExpressionList<T> {
/**
* Execute a query returning a single value of a single property/column.
* <p>
* <pre>{@code
*
* String name =
* Ebean.find(Customer.class)
* DB.find(Customer.class)
* .select("name")
* .where().eq("id", 42)
* .findSingleAttribute();
@@ -376,10 +452,9 @@ public interface ExpressionList<T> {
* If maxRows is not set on the query prior to calling findPagedList() then a
* PersistenceException is thrown.
* </p>
* <p>
* <pre>{@code
*
* PagedList<Order> pagedList = Ebean.find(Order.class)
* PagedList<Order> pagedList = DB.find(Order.class)
* .setFirstRow(50)
* .setMaxRows(20)
* .findPagedList();
@@ -422,7 +497,26 @@ public interface ExpressionList<T> {
* Add some filter predicate expressions to the many property.
*/
@Nonnull
ExpressionList<T> filterMany(String prop);
ExpressionList<T> filterMany(String manyProperty);
/**
* Add filter expressions to the many property.
*
* <pre>{@code
*
* DB.find(Customer.class)
* .where()
* .eq("name", "Rob")
* .filterMany("orders", "status = ?", Status.NEW)
* .findList();
*
* }</pre>
*
* @param manyProperty The many property
* @param expressions Filter expressions with and, or and ? or ?1 type bind parameters
* @param params Bind parameters used in the expressions
*/
ExpressionList<T> filterMany(String manyProperty, String expressions, Object... params);
/**
* Specify specific properties to fetch on the main/root bean (aka partial
@@ -446,7 +540,7 @@ public interface ExpressionList<T> {
* <pre>{@code
*
* List<Customer> customers =
* Ebean.find(Customer.class)
* DB.find(Customer.class)
* .setDistinct(true)
* .select("name") // only select the customer name
* .findList();
@@ -473,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.
@@ -515,12 +609,11 @@ public interface ExpressionList<T> {
/**
* Extended version for setDistinct in conjunction with "findSingleAttributeList";
* <p>
* <pre>{@code
*
* List<CountedValue<Order.Status>> orderStatusCount =
*
* Ebean.find(Order.class)
* DB.find(Order.class)
* .select("status")
* .where()
* .gt("orderDate", LocalDate.now().minusMonths(3))
@@ -597,6 +690,14 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> where();
/**
* Add the expressions to this expression list.
*
* @param expressions The expressions that are parsed and added to this expression list
* @param params Bind parameters to match ? or ?1 bind positions.
*/
ExpressionList<T> where(String expressions, Object... params);
/**
* Path exists - for the given path in a JSON document.
* <pre>{@code
@@ -625,7 +726,6 @@ public interface ExpressionList<T> {
/**
* Equal to expression for the value at the given path in the JSON document.
* <p>
* <pre>{@code
*
* where().jsonEqualTo("content", "path.other", 34)
@@ -640,7 +740,6 @@ public interface ExpressionList<T> {
/**
* Not Equal to - for the given path in a JSON document.
* <p>
* <pre>{@code
*
* where().jsonNotEqualTo("content", "path.other", 34)
@@ -655,7 +754,6 @@ public interface ExpressionList<T> {
/**
* Greater than - for the given path in a JSON document.
* <p>
* <pre>{@code
*
* where().jsonGreaterThan("content", "path.other", 34)
@@ -666,7 +764,6 @@ public interface ExpressionList<T> {
/**
* Greater than or equal to - for the given path in a JSON document.
* <p>
* <pre>{@code
*
* where().jsonGreaterOrEqual("content", "path.other", 34)
@@ -677,7 +774,6 @@ public interface ExpressionList<T> {
/**
* Less than - for the given path in a JSON document.
* <p>
* <pre>{@code
*
* where().jsonLessThan("content", "path.other", 34)
@@ -688,7 +784,6 @@ public interface ExpressionList<T> {
/**
* Less than or equal to - for the given path in a JSON document.
* <p>
* <pre>{@code
*
* where().jsonLessOrEqualTo("content", "path.other", 34)
@@ -699,7 +794,6 @@ public interface ExpressionList<T> {
/**
* Between - for the given path in a JSON document.
* <p>
* <pre>{@code
*
* where().jsonBetween("content", "orderDate", lowerDateTime, upperDateTime)
@@ -710,21 +804,6 @@ public interface ExpressionList<T> {
/**
* Add an Expression to the list.
* <p>
* This returns the list so that add() can be chained.
* </p>
* <p>
* <pre>{@code
*
* Query<Customer> query = Ebean.find(Customer.class);
* query.where()
* .like("name","Rob%")
* .eq("status", Customer.ACTIVE);
*
* List<Customer> list = query.findList();
* ...
*
* }</pre>
*/
ExpressionList<T> add(Expression expr);
@@ -738,6 +817,11 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> eq(String propertyName, Object value);
/**
* Equal To or Null - property is equal to a given value or null.
*/
ExpressionList<T> eqOrNull(String propertyName, Object value);
/**
* Not Equal To - property not equal to the given value.
*/
@@ -755,6 +839,33 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> ine(String propertyName, String value);
/**
* Value in Range between 2 properties.
*
* <pre>{@code
*
* .startDate.inRangeWith(endDate, now)
*
* // which equates to
* startDate <= now and (endDate > now or endDate is null)
*
* }</pre>
*
* <p>
* This is a convenience expression combining a number of simple expressions.
* The most common use of this could be called "effective dating" where 2 date or
* timestamp columns represent the date range in which
*/
ExpressionList<T> inRangeWith(String lowProperty, String highProperty, Object value);
/**
* In Range - property >= value1 and property < value2.
* <p>
* Unlike Between inRange is "half open" and usually more useful for use with dates or timestamps.
* </p>
*/
ExpressionList<T> inRange(String propertyName, Object value1, Object value2);
/**
* Between - property between the two given values.
*/
@@ -770,6 +881,11 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> gt(String propertyName, Object value);
/**
* Greater Than or Null - property greater than the given value or null.
*/
ExpressionList<T> gtOrNull(String propertyName, Object value);
/**
* Greater Than or Equal to - property greater than or equal to the given
* value.
@@ -781,6 +897,11 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> lt(String propertyName, Object value);
/**
* Less Than or Null - property less than the given value or null.
*/
ExpressionList<T> ltOrNull(String propertyName, Object value);
/**
* Less Than or Equal to - property less than or equal to the given value.
*/
@@ -810,7 +931,6 @@ public interface ExpressionList<T> {
* To get control over the options you can create an ExampleExpression and set
* those options such as case insensitive etc.
* </p>
* <p>
* <pre>{@code
*
* // create an example bean and set the properties
@@ -819,16 +939,15 @@ public interface ExpressionList<T> {
* example.setName("Rob%");
* example.setNotes("%something%");
*
* List&lt;Customer&gt; list = Ebean.find(Customer.class).where()
* // pass the bean into the where() clause
* .exampleLike(example)
* // you can add other expressions to the same query
* .gt("id", 2).findList();
* List<Customer> list =
* DB.find(Customer.class)
* .where().exampleLike(example)
* .findList();
*
* }</pre>
* <p>
* Similarly you can create an ExampleExpression
* <p>
* </p>
* <pre>{@code
*
* Customer example = new Customer();
@@ -838,7 +957,7 @@ public interface ExpressionList<T> {
* // create a ExampleExpression with more control
* ExampleExpression qbe = new ExampleExpression(example, true, LikeType.EQUAL_TO).includeZeros();
*
* List<Customer> list = Ebean.find(Customer.class).where().add(qbe).findList();
* List<Customer> list = DB.find(Customer.class).where().add(qbe).findList();
*
* }</pre>
*/
@@ -915,6 +1034,41 @@ public interface ExpressionList<T> {
*/
ExpressionList<T> in(String propertyName, Collection<?> values);
/**
* In where null or empty values means that no predicate is added to the query.
* <p>
* That is, only add the IN predicate if the values are not null or empty.
* <p>
* Without this we typically need to code an <code>if</code> block to only add
* the IN predicate if the collection is not empty like:
* </p>
*
* <h3>Without inOrEmpty()</h3>
* <pre>{@code
*
* query.where() // add some predicates
* .eq("status", Status.NEW);
*
* if (ids != null && !ids.isEmpty()) {
* query.where().in("customer.id", ids);
* }
*
* query.findList();
*
* }</pre>
*
* <h3>Using inOrEmpty()</h3>
* <pre>{@code
*
* query.where()
* .eq("status", Status.NEW)
* .inOrEmpty("customer.id", ids)
* .findList();
*
* }</pre>
*/
ExpressionList<T> inOrEmpty(String propertyName, Collection<?> values);
/**
* In - using a subQuery.
* <p>
@@ -1050,7 +1204,6 @@ public interface ExpressionList<T> {
/**
* Add expression for ALL of the given bit flags to be set.
* <p>
* <pre>{@code
*
* where().bitwiseAll("flags", BwFlags.HAS_BULK + BwFlags.HAS_COLOUR)
@@ -1064,7 +1217,6 @@ public interface ExpressionList<T> {
/**
* Add expression for the given bit flags to be NOT set.
* <p>
* <pre>{@code
*
* where().bitwiseNot("flags", BwFlags.HAS_COLOUR)
@@ -1099,21 +1251,39 @@ 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 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>
*/
ExpressionList<T> raw(String raw, Object value);
@@ -1121,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);
@@ -1139,15 +1320,83 @@ public interface ExpressionList<T> {
* then they are not translated. logical property name names (not fully
* qualified) will still be translated to their physical name.
* </p>
* <p>
* <pre>{@code
*
* raw("orderQty < shipQty")
*
* }</pre>
*
* <h4>Subquery example:</h4>
* <pre>{@code
*
* .raw("t0.customer_id in (select customer_id from customer_group where group_id = any(?::uuid[]))", groupIds)
*
* }</pre>
*/
ExpressionList<T> raw(String raw);
/**
* Only add the raw expression if the values is not null or empty.
* <p>
* This is a pure convenience expression to make it nicer to deal with the pattern where we use
* raw() expression with a subquery and only want to add the subquery predicate when the collection
* of values is not empty.
* </p>
* <h3>Without inOrEmpty()</h3>
* <pre>{@code
*
* query.where() // add some predicates
* .eq("status", Status.NEW);
*
* // common pattern - we can use rawOrEmpty() instead
* if (orderIds != null && !orderIds.isEmpty()) {
* query.where().raw("t0.customer_id in (select o.customer_id from orders o where o.id in (?1))", orderIds);
* }
*
* query.findList();
*
* }</pre>
*
* <h3>Using rawOrEmpty()</h3>
* Note that in the example below we use the <code>?1</code> bind parameter to get "parameter expansion"
* for each element in the collection.
*
* <pre>{@code
*
* query.where()
* .eq("status", Status.NEW)
* // only add the expression if orderIds is not empty
* .rawOrEmpty("t0.customer_id in (select o.customer_id from orders o where o.id in (?1))", orderIds);
* .findList();
*
* }</pre>
*
* <h3>Postgres ANY</h3>
* With Postgres we would often use the SQL <code>ANY</code> expression and array parameter binding
* rather than <code>IN</code>.
*
* <pre>{@code
*
* query.where()
* .eq("status", Status.NEW)
* .rawOrEmpty("t0.customer_id in (select o.customer_id from orders o where o.id = any(?))", orderIds);
* .findList();
*
* }</pre>
* <p>
* Note that we need to cast the Postgres array for UUID types like:
* </p>
* <pre>{@code
*
* " ... = any(?::uuid[])"
*
* }</pre>
*
* @param raw The raw expression that is typically a subquery
* @param values The values which is typically a list or set of id values.
*/
ExpressionList<T> rawOrEmpty(String raw, Collection<?> values);
/**
* Add a match expression.
*
@@ -1218,12 +1467,10 @@ public interface ExpressionList<T> {
* typically you only explicitly need to use the and() junction
* when it is nested inside an or() or not() junction.
* </p>
* <p>
* <pre>{@code
*
* // Example: Nested and()
*
* Ebean.find(Customer.class)
* .where()
* .or()
* .and() // nested and
@@ -1234,7 +1481,7 @@ public interface ExpressionList<T> {
* .eq("status", Customer.Status.ACTIVE)
* .gt("id", 0)
* .endAnd()
* .orderBy().asc("name")
* .order().asc("name")
* .findList();
* }</pre>
*/
@@ -1244,16 +1491,27 @@ public interface ExpressionList<T> {
* Return a list of expressions that will be joined by OR's.
* This is exactly the same as disjunction();
* <p>
* <p>
* Use endOr() or endJunction() to end the OR junction.
* </p>
* <p>
*
* <pre>{@code
*
* // Example: (status active OR anniversary is null)
*
* .where()
* .or()
* .eq("status", Customer.Status.ACTIVE)
* .isNull("anniversary")
* .order().asc("name")
* .findList();
*
* }</pre>
*
* <pre>{@code
*
* // Example: Use or() to join
* // two nested and() expressions
*
* Ebean.find(Customer.class)
* .where()
* .or()
* .and()
@@ -1264,7 +1522,7 @@ public interface ExpressionList<T> {
* .eq("status", Customer.Status.ACTIVE)
* .gt("id", 0)
* .endAnd()
* .orderBy().asc("name")
* .order().asc("name")
* .findList();
*
* }</pre>
@@ -1277,8 +1535,8 @@ public interface ExpressionList<T> {
* Use endNot() or endJunction() to end expressions being added to the
* NOT expression list.
* </p>
* <p>
* <pre>@{code
*
* <pre>{@code
*
* .where()
* .not()
@@ -1287,19 +1545,18 @@ public interface ExpressionList<T> {
* .endNot()
*
* }</pre>
* <p>
* <pre>@{code
*
* <pre>{@code
*
* // Example: nested not()
*
* Ebean.find(Customer.class)
* .where()
* .eq("status", Customer.Status.ACTIVE)
* .not()
* .gt("id", 1)
* .eq("anniversary", onAfter)
* .endNot()
* .orderBy()
* .order()
* .asc("name")
* .findList();
*
+65 -16
View File
@@ -10,9 +10,10 @@ 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 EbeanServer.
* The extended API for Database.
* <p>
* This provides the finder methods that take an explicit transaction rather than obtaining
* the transaction from the usual mechanism (which is ThreadLocal based).
@@ -23,7 +24,7 @@ import java.util.function.Predicate;
* the transaction to use.
* </p>
* <p>
* Note that in all cases the transaction supplied can be null and in this case the EbeanServer
* Note that in all cases the transaction supplied can be null and in this case the Database
* will use the normal mechanism to obtain the transaction to use.
* </p>
*/
@@ -42,6 +43,32 @@ public interface ExtendedServer {
*/
void setClock(Clock clock);
/**
* Execute the query returning true if a row is found.
* <p>
* The query is executed using max rows of 1 and will only select the id property.
* This method is really just a convenient way to optimise a query to perform a
* 'does a row exist in the db' check.
* </p>
*
* <h2>Example:</h2>
* <pre>{@code
*
* boolean userExists = query().where().eq("email", "rob@foo.com").exists();
*
* }</pre>
*
* <h2>Example using a query bean:</h2>
* <pre>{@code
*
* boolean userExists = new QContact().email.equalTo("rob@foo.com").exists();
*
* }</pre>
*
* @return True if the query finds a matching row in the database
*/
<T> boolean exists(Query<?> ormQuery, Transaction transaction);
/**
* Return the number of 'top level' or 'root' entities this query should return.
*
@@ -65,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)
@@ -78,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>
@@ -92,7 +143,7 @@ public interface ExtendedServer {
* <p>
* <pre>{@code
*
* ebeanServer.find(Order.class)
* DB.find(Order.class)
* .where().eq("status", Order.Status.NEW)
* .order().asc("id")
* .findEach((Order order) -> {
@@ -126,7 +177,7 @@ public interface ExtendedServer {
* <p>
* <pre>{@code
*
* ebeanServer.find(Order.class)
* DB.find(Order.class)
* .where().eq("status", Order.Status.NEW)
* .order().asc("id")
* .findEachWhile((Order order) -> {
@@ -165,8 +216,7 @@ public interface ExtendedServer {
* <p>
* <pre>{@code
*
* List<Customer> customers =
* ebeanServer.find(Customer.class)
* List<Customer> customers = DB.find(Customer.class)
* .where().ilike("name", "rob%")
* .findList();
*
@@ -243,7 +293,7 @@ public interface ExtendedServer {
* <p>
* <pre>{@code
*
* PagedList<Order> pagedList = Ebean.find(Order.class)
* PagedList<Order> pagedList = DB.find(Order.class)
* .setFirstRow(50)
* .setMaxRows(20)
* .findPagedList();
@@ -272,8 +322,7 @@ public interface ExtendedServer {
* <p>
* <pre>{@code
*
* Set<Customer> customers =
* ebeanServer.find(Customer.class)
* Set<Customer> customers = DB.find(Customer.class)
* .where().ilike("name", "rob%")
* .findSet();
*
@@ -312,9 +361,9 @@ public interface ExtendedServer {
* <pre>{@code
*
* List<String> names =
* Ebean.find(Customer.class)
* DB.find(Customer.class)
* .select("name")
* .orderBy().asc("name")
* .order().asc("name")
* .findSingleAttributeList();
*
* }</pre>
@@ -322,11 +371,11 @@ public interface ExtendedServer {
* <pre>{@code
*
* List<String> names =
* Ebean.find(Customer.class)
* DB.find(Customer.class)
* .setDistinct(true)
* .select("name")
* .where().eq("status", Customer.Status.NEW)
* .orderBy().asc("name")
* .order().asc("name")
* .setMaxRows(100)
* .findSingleAttributeList();
*
@@ -384,7 +433,7 @@ public interface ExtendedServer {
/**
* Execute the update query returning the number of rows updated.
* <p>
* The update query must be created using {@link EbeanServer#update(Class)}.
* The update query must be created using {@link Database#update(Class)}.
* </p>
*
* @param query the update query to execute
+28 -6
View File
@@ -24,7 +24,7 @@ import java.io.Serializable;
* <p>
* <pre>{@code
* // Normal fetch join results in a single SQL query
* List<Order> list = Ebean.find(Order.class).fetch("details").findList();
* List<Order> list = DB.find(Order.class).fetch("details").findList();
*
* // Find Orders join details using a single SQL query
* }</pre>
@@ -36,7 +36,7 @@ import java.io.Serializable;
*
* // This will use 2 SQL queries to build this object graph
* List<Order> list =
* Ebean.find(Order.class)
* DB.find(Order.class)
* .fetch("details", new FetchConfig().query())
* .findList();
*
@@ -52,7 +52,7 @@ import java.io.Serializable;
*
* // This will use 3 SQL queries to build this object graph
* List<Order> list =
* Ebean.find(Order.class)
* DB.find(Order.class)
* .fetch("details", new FetchConfig().query())
* .fetch("customer", new FetchConfig().queryFirst(5))
* .findList();
@@ -70,7 +70,7 @@ import java.io.Serializable;
* <pre>{@code
* // This will use 3 SQL queries to build this object graph
* List<Order> list =
* Ebean.find(Order.class)
* DB.find(Order.class)
* .select("status, shipDate")
* .fetch("details", "quantity, price", new FetchConfig().query())
* .fetch("details.product", "sku, name")
@@ -100,7 +100,7 @@ import java.io.Serializable;
* <pre>{@code
*
* List<Order> list =
* Ebean.find(Order.class)
* DB.find(Order.class)
* .fetch("customer", new FetchConfig().query(10).lazy(5))
* .findList();
*
@@ -121,7 +121,7 @@ import java.io.Serializable;
* <p>
* <pre>{@code
*
* List<Order> list = Ebean.find(Order.class)
* List<Order> list = DB.find(Order.class)
* .fetch("customer","name", new FetchConfig().lazy(5))
* .fetch("customer.contacts","contactName, phone, email")
* .fetch("customer.shippingAddress")
@@ -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;
}
}
+9
View File
@@ -1,5 +1,7 @@
package io.ebean;
import io.ebean.service.SpiFetchGroupQuery;
import javax.annotation.Nonnull;
/**
@@ -111,4 +113,11 @@ public interface FetchGroup<T> {
return XServiceProvider.fetchGroupOf(cls);
}
/**
* Return a query to be used by query beans for constructing FetchGroup.
*/
static <T> SpiFetchGroupQuery<T> queryFor(Class<T> beanType) {
return XServiceProvider.fetchGroupQueryFor(beanType);
}
}
@@ -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.
*/
+5 -5
View File
@@ -25,14 +25,14 @@ import java.util.Set;
* // get a list of entities (query execution statistics in this case)
*
* List<MetaQueryStatistic> list =
* Ebean.find(MetaQueryStatistic.class).findList();
* DB.find(MetaQueryStatistic.class).findList();
*
* long nowMinus24Hrs = System.currentTimeMillis() - 24 * (1000 * 60 * 60);
*
* // sort and filter the list returning a filtered list...
*
* List<MetaQueryStatistic> filteredList =
* Ebean.filter(MetaQueryStatistic.class)
* DB.filter(MetaQueryStatistic.class)
* .sort("avgTimeMicros desc")
* .gt("executionCount", 0)
* .gt("lastQueryTime", nowMinus24Hrs)
@@ -63,12 +63,12 @@ import java.util.Set;
* // get a list of entities (query execution statistics)
*
* List<Order> orders =
* Ebean.find(Order.class).findList();
* DB.find(Order.class).findList();
*
* // Apply a filter...
*
* List<Order> filteredOrders =
* Ebean.filter(Order.class)
* DB.filter(Order.class)
* .startsWith("customer.name", "Rob")
* .eq("customer.shippingAddress.city", "Auckland")
* .filter(orders);
@@ -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);
+31 -27
View File
@@ -2,7 +2,6 @@ package io.ebean;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
/**
@@ -14,8 +13,7 @@ import java.util.List;
* </p>
* <h3>Testing</h3>
* <p>
* For testing the mocki-ebean project has the ability to replace the finder implementation
* <p>
* For testing the mocki-ebean project has the ability to replace the finder implementation.
* </p>
* <pre>{@code
*
@@ -25,7 +23,7 @@ import java.util.List;
* super(Customer.class);
* }
*
* // Add your customer finder methods ...
* // Add finder methods ...
*
* public Customer byName(String name) {
* return query().eq("name", name).findOne();
@@ -34,7 +32,7 @@ import java.util.List;
* public List<Customer> findNew() {
* return query().where()
* .eq("status", Customer.Status.NEW)
* .orderBy("name")
* .order("name")
* .findList()
* }
* }
@@ -46,6 +44,15 @@ import java.util.List;
* ...
*
* }</pre>
* <p>
* When the Finder is registered as a field on Customer it can then be used like:
* </p>
* <pre>{@code
*
* Customer rob = Customer.find.byName("Rob");
*
* }</pre>
*
*/
public class Finder<I, T> {
@@ -55,9 +62,9 @@ public class Finder<I, T> {
private final Class<T> type;
/**
* The name of the EbeanServer, null for the default server.
* The name of the database this finder will use, null for the default database.
*/
private final String serverName;
private final String _$dbName;
/**
* Create with the type of the entity bean.
@@ -82,15 +89,15 @@ public class Finder<I, T> {
*/
public Finder(Class<T> type) {
this.type = type;
this.serverName = null;
this._$dbName = null;
}
/**
* Create with the type of the entity bean and specific server name.
* Create with the type of the entity bean and specific database name.
*/
public Finder(Class<T> type, String serverName) {
public Finder(Class<T> type, String databaseName) {
this.type = type;
this.serverName = serverName;
this._$dbName = databaseName;
}
/**
@@ -108,30 +115,27 @@ public class Finder<I, T> {
}
/**
* Return the underlying 'default' EbeanServer.
* <p>
* This provides full access to the API such as explicit transaction demarcation etc.
* Return the Database this finder will use.
*/
public EbeanServer db() {
return Ebean.getServer(serverName);
public Database db() {
return DB.byName(_$dbName);
}
/**
* Return typically a different EbeanServer to the default.
* Return typically a different Database to the default.
* <p>
* This is equivalent to {@link Ebean#getServer(String)}
* This is equivalent to {@link DB#byName(String)}
*
* @param server The name of the EbeanServer. If this is null then the default EbeanServer is
* returned.
* @param databaseName The name of the Database. If this is null then the default database is returned.
*/
public EbeanServer db(String server) {
return Ebean.getServer(server);
public Database db(String databaseName) {
return DB.byName(databaseName);
}
/**
* Creates an entity reference for this ID.
* <p>
* Equivalent to {@link EbeanServer#getReference(Class, Object)}
* Equivalent to {@link Database#getReference(Class, Object)}
*/
@Nonnull
public T ref(I id) {
@@ -141,7 +145,7 @@ public class Finder<I, T> {
/**
* Retrieves an entity by ID.
* <p>
* Equivalent to {@link EbeanServer#find(Class, Object)}
* Equivalent to {@link Database#find(Class, Object)}
*/
@Nullable
public T byId(I id) {
@@ -151,7 +155,7 @@ public class Finder<I, T> {
/**
* Delete a bean by Id.
* <p>
* Equivalent to {@link EbeanServer#delete(Class, Object)}
* Equivalent to {@link Database#delete(Class, Object)}
*/
public void deleteById(I id) {
db().delete(type, id);
@@ -181,7 +185,7 @@ public class Finder<I, T> {
* }</pre>
*
* <p>
* Equivalent to {@link EbeanServer#update(Class)}
* Equivalent to {@link Database#update(Class)}
*/
public UpdateQuery<T> update() {
return db().update(type);
@@ -190,7 +194,7 @@ public class Finder<I, T> {
/**
* Creates a query.
* <p>
* Equivalent to {@link EbeanServer#find(Class)}
* Equivalent to {@link Database#find(Class)}
*/
public Query<T> query() {
return db().find(type);
+1 -1
View File
@@ -20,7 +20,7 @@ import java.util.concurrent.TimeoutException;
* <pre>{@code
*
* // create a query to find all orders
* Query<Order> query = Ebean.find(Order.class);
* Query<Order> query = DB.find(Order.class);
*
* // execute the query in a background thread
* // immediately returning the futureList
+3 -3
View File
@@ -11,7 +11,7 @@ package io.ebean;
* </p>
* <pre>{@code
* Query q =
* Ebean.find(Person.class)
* DB.find(Person.class)
* .where()
* .or()
* .like("name", "Rob%")
@@ -30,7 +30,7 @@ package io.ebean;
* <pre>{@code
*
* Query q =
* Ebean.find(Person.class)
* DB.find(Person.class)
* .where()
* .or()
* .like("name", "Rob%")
@@ -50,7 +50,7 @@ package io.ebean;
* </p>
* <pre>{@code
* Query<Customer> q =
* Ebean.find(Customer.class)
* DB.find(Customer.class)
* .where()
* .or()
* .and()
+65 -47
View File
@@ -11,15 +11,15 @@ import io.ebean.bean.EntityBean;
* Ebean users.
* <p>
* Note that there is a ebean-mocker project that enables you to use Mockito or similar
* tools to still mock out the underlying 'default EbeanServer' for testing purposes.
* tools to still mock out the underlying 'default Database' for testing purposes.
* <p>
* You may choose not use this Model mapped superclass if you don't like the 'Active Record' style
* or if you believe it 'pollutes' your entity beans.
* <p>
* You can use Dependency Injection like Guice or Spring to construct and wire a EbeanServer instance
* You can use Dependency Injection like Guice or Spring to construct and wire a Database instance
* and have that same instance used with this Model and Finder. The way that works is that when the
* DI container creates the EbeanServer instance it can be registered with the Ebean singleton. In this
* way the EbeanServer instance can be injected as per normal Guice / Spring dependency injection and
* DI container creates the Database instance it can be registered with DB. In this
* way the Database instance can be injected as per normal Guice / Spring dependency injection and
* that same instance also used to support the Model and Finder active record style.
* <p>
* If you choose to use the Model mapped superclass you will probably also chose to additionally add
@@ -76,15 +76,33 @@ import io.ebean.bean.EntityBean;
public abstract class Model {
/**
* Return the underlying 'default' EbeanServer.
* The name of the database this entity will use, null for the default database.
*/
private final String _$dbName;
/**
* Create using the default database.
*/
public Model() {
this._$dbName = null;
}
/**
* Create with a named database (typically not the default database).
*/
public Model(String dbName) {
this._$dbName = dbName;
}
/**
* Return the underlying 'default' Database.
* <p>
* This provides full access to the API such as explicit transaction demarcation etc.
* <p>
* Example:
* <pre>{@code
*
* Transaction transaction = Customer.db().beginTransaction();
* try {
* try (Transaction transaction = Customer.db().beginTransaction()) {
*
* // turn off cascade persist for this transaction
* transaction.setPersistCascade(false);
@@ -104,26 +122,12 @@ public abstract class Model {
*
* transaction.commit();
*
* } finally {
* transaction.end();
* }
*
* }</pre>
*/
public static EbeanServer db() {
return Ebean.getDefaultServer();
}
/**
* Return a named EbeanServer that is typically different to the default server.
* <p>
* If you are using multiple databases then each database has a name and maps to a single
* EbeanServer. You can use this method to get an EbeanServer for another database.
*
* @param server The name of the EbeanServer. If this is null then the default EbeanServer is returned.
*/
public static EbeanServer db(String server) {
return Ebean.getServer(server);
public Database db() {
return DB.byName(_$dbName);
}
/**
@@ -146,7 +150,7 @@ public abstract class Model {
*
* }</pre>
*
* @see EbeanServer#markAsDirty(Object)
* @see Database#markAsDirty(Object)
*/
public void markAsDirty() {
db().markAsDirty(this);
@@ -182,12 +186,19 @@ public abstract class Model {
* Ebean will detect if this is a new bean or a previously fetched bean and perform either an
* insert or an update based on that.
*
* @see EbeanServer#save(Object)
* @see Database#save(Object)
*/
public void save() {
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>
@@ -202,21 +213,35 @@ public abstract class Model {
/**
* Update this entity.
*
* @see EbeanServer#update(Object)
* @see Database#update(Object)
*/
public void update() {
db().update(this);
}
/**
* Update this entity with an explicit transaction.
*/
public void update(Transaction transaction) {
db().update(this, transaction);
}
/**
* Insert this entity.
*
* @see EbeanServer#insert(Object)
* @see Database#insert(Object)
*/
public void insert() {
db().insert(this);
}
/**
* Insert with an explicit transaction.
*/
public void insert(Transaction transaction) {
db().insert(this, transaction);
}
/**
* Delete this bean.
* <p>
@@ -232,12 +257,19 @@ public abstract class Model {
* deleted. Note that, if JDBC batch mode is used then this always returns true.
* </p>
*
* @see EbeanServer#delete(Object)
* @see Database#delete(Object)
*/
public boolean delete() {
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>
@@ -245,37 +277,23 @@ public abstract class Model {
* want to perform a hard/permanent delete.
* </p>
*
* @see EbeanServer#deletePermanent(Object)
* @see Database#deletePermanent(Object)
*/
public boolean deletePermanent() {
return db().deletePermanent(this);
}
/**
* Perform an update using this entity against the specified server.
* Delete a bean permanently without soft delete using an explicit transaction.
*/
public void update(String server) {
db(server).update(this);
}
/**
* Perform an insert using this entity against the specified server.
*/
public void insert(String server) {
db(server).insert(this);
}
/**
* Perform a delete using this entity against the specified server.
*/
public boolean delete(String server) {
return db(server).delete(this);
public boolean deletePermanent(Transaction transaction) {
return db().deletePermanent(this, transaction);
}
/**
* Refreshes this entity from the database.
*
* @see EbeanServer#refresh(Object)
* @see Database#refresh(Object)
*/
public void refresh() {
db().refresh(this);
+24 -13
View File
@@ -4,7 +4,6 @@ import io.ebean.util.StringHelper;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@@ -81,7 +80,6 @@ public final class OrderBy<T> implements Serializable {
* Add a property with ascending order to this OrderBy.
*/
public Query<T> asc(String propertyName, String collation) {
list.add(new Property(propertyName, true, collation));
return query;
}
@@ -90,7 +88,6 @@ public final class OrderBy<T> implements Serializable {
* Add a property with descending order to this OrderBy.
*/
public Query<T> desc(String propertyName) {
list.add(new Property(propertyName, false));
return query;
}
@@ -99,7 +96,6 @@ public final class OrderBy<T> implements Serializable {
* Add a property with descending order to this OrderBy.
*/
public Query<T> desc(String propertyName, String collation) {
list.add(new Property(propertyName, false, collation));
return query;
}
@@ -109,7 +105,6 @@ public final class OrderBy<T> implements Serializable {
* Return true if the property is known to be contained in the order by clause.
*/
public boolean containsProperty(String propertyName) {
for (Property aList : list) {
if (propertyName.equals(aList.getProperty())) {
return true;
@@ -162,10 +157,9 @@ public final class OrderBy<T> implements Serializable {
* Return a copy of the OrderBy.
*/
public OrderBy<T> copy() {
OrderBy<T> copy = new OrderBy<>();
for (Property aList : list) {
copy.add(aList.copy());
for (Property property : list) {
copy.add(property.copy());
}
return copy;
}
@@ -242,6 +236,18 @@ public final class OrderBy<T> implements Serializable {
return this;
}
/**
* Return true if this order by can be used in select clause.
*/
public boolean supportsSelect() {
for (Property property : list) {
if (!property.supportsSelect()) {
return false;
}
}
return true;
}
/**
* A property and its ascending descending order.
*/
@@ -402,6 +408,12 @@ public final class OrderBy<T> implements Serializable {
this.ascending = ascending;
}
/**
* Support use in select clause if no collation or nulls ordering.
*/
boolean supportsSelect() {
return nulls == null;
}
}
private void parse(String orderByClause) {
@@ -412,15 +424,15 @@ public final class OrderBy<T> implements Serializable {
String[] chunks = orderByClause.split(",");
for (String chunk : chunks) {
String[] pairs = chunk.split(" ");
Property p = parseProperty(pairs);
Property p = parseProperty(chunk);
if (p != null) {
list.add(p);
}
}
}
private Property parseProperty(String[] pairs) {
private Property parseProperty(String chunk) {
String[] pairs = chunk.split(" ");
if (pairs.length == 0) {
return null;
}
@@ -446,8 +458,7 @@ public final class OrderBy<T> implements Serializable {
boolean asc = isAscending(wordList.get(1));
return new Property(wordList.get(0), asc, wordList.get(2), wordList.get(3));
}
String m = "Expecting a 1, 2 or 4 words in [" + Arrays.toString(pairs) + "] but got " + wordList;
throw new RuntimeException(m);
return new Property(chunk.trim(), true);
}
private boolean isAscending(String s) {
+8 -2
View File
@@ -24,8 +24,7 @@ import java.util.concurrent.Future;
* // We want to find the first 50 new orders
* // ... so we don't really need setFirstRow(0)
*
* PagedList<Order> pagedList
* = ebeanServer.find(Order.class)
* PagedList<Order> pagedList = DB.find(Order.class)
* .where().eq("status", Order.Status.NEW)
* .order().asc("id")
* .setFirstRow(0)
@@ -61,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
+2 -2
View File
@@ -26,11 +26,11 @@ import java.util.List;
* pairs.add("sj2", 1001);
* pairs.add("pf3", 1000);
*
* List<OCachedNatKeyBean3> list = Ebean.find(OCachedNatKeyBean3.class)
* List<OCachedNatKeyBean3> list = DB.find(OCachedNatKeyBean3.class)
* .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) {
+23 -3
View File
@@ -31,17 +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);
}
+274 -127
View File
@@ -3,6 +3,7 @@ package io.ebean;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.persistence.NonUniqueResultException;
import java.sql.Connection;
import java.sql.Timestamp;
import java.util.List;
import java.util.Map;
@@ -10,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.
@@ -19,14 +21,11 @@ import java.util.function.Predicate;
* <p>
* <pre>{@code
*
* List<Order> orderList =
* ebeanServer.find(Order.class)
* .fetch("customer")
* .fetch("details")
* List<Order> orderList = DB.find(Order.class)
* .where()
* .like("customer.name","rob%")
* .gt("orderDate",lastWeek)
* .orderBy("customer.id, id desc")
* .order("customer.id, id desc")
* .setMaxRows(50)
* .findList();
*
@@ -38,29 +37,14 @@ import java.util.function.Predicate;
* <pre>{@code
*
* String oql =
* +" fetch customer "
* +" fetch details "
* +" where customer.name like :custName and orderDate > :minOrderDate "
* +" order by customer.id, id desc "
* +" limit 50 ";
*
* Query<Order> query = ebeanServer.createQuery(Order.class, oql);
* query.setParameter("custName", "Rob%");
* query.setParameter("minOrderDate", lastWeek);
*
* List<Order> orderList = query.findList();
* ...
* }</pre>
* <p>
* Example: Using a named query called "with.cust.and.details"
* </p>
* <pre>{@code
*
* Query<Order> query = ebeanServer.createNamedQuery(Order.class,"with.cust.and.details");
* query.setParameter("custName", "Rob%");
* query.setParameter("minOrderDate", lastWeek);
*
* List<Order> orderList = query.findList();
* List<Order> orderList = DB.createQuery(Order.class, oql)
* .setParameter("custName", "Rob%")
* .setParameter("minOrderDate", lastWeek)
* .findList();
* ...
* }</pre>
* <h3>AutoTune</h3>
@@ -244,6 +228,38 @@ public interface Query<T> {
*/
<D> DtoQuery<D> asDto(Class<D> dtoClass);
/**
* Convert the query to a UpdateQuery.
* <p>
* Typically this is used with query beans to covert a query bean
* query into an UpdateQuery like the examples below.
* </p>
*
* <pre>{@code
*
* int rowsUpdated = new QCustomer()
* .name.startsWith("Rob")
* .asUpdate()
* .set("active", false)
* .update();;
*
* }</pre>
*
* <pre>{@code
*
* int rowsUpdated = new QContact()
* .notes.note.startsWith("Make Inactive")
* .email.endsWith("@foo.com")
* .customer.id.equalTo(42)
* .asUpdate()
* .set("inactive", true)
* .setRaw("email = lower(email)")
* .update();
*
* }</pre>
*/
UpdateQuery<T> asUpdate();
/**
* Cancel the query execution if supported by the underlying database and
* driver.
@@ -340,6 +356,27 @@ public interface Query<T> {
*/
Query<T> setAutoTune(boolean autoTune);
/**
* Execute the query allowing properties with invalid JSON to be collected and not fail the query.
* <pre>{@code
*
* // fetch a bean with JSON content
* EBasicJsonList bean= DB.find(EBasicJsonList.class)
* .setId(42)
* .setAllowLoadErrors() // collect errors into bean state if we have invalid JSON
* .findOne();
*
*
* // get the invalid JSON errors from the bean state
* Map<String, Exception> errors = server().getBeanState(bean).getLoadErrors();
*
* // If this map is not empty tell we have invalid JSON
* // and should try and fix the JSON content or inform the user
*
* }</pre>
*/
Query<T> setAllowLoadErrors();
/**
* Set the default lazy loading batch size to use.
* <p>
@@ -383,8 +420,7 @@ public interface Query<T> {
* </p>
* <pre>{@code
*
* List<Customer> customers =
* ebeanServer.find(Customer.class)
* List<Customer> customers = DB.find(Customer.class)
* // Only fetch the customer id, name and status.
* // This is described as a "Partial Object"
* .select("name, status")
@@ -412,8 +448,7 @@ public interface Query<T> {
* <pre>{@code
*
* // query orders...
* List<Order> orders =
* ebeanServer.find(Order.class)
* List<Order> orders = DB.find(Order.class)
* // fetch the customer...
* // ... getting the customers name and phone number
* .fetch("customer", "name, phoneNumber")
@@ -428,8 +463,7 @@ public interface Query<T> {
* <pre>{@code
*
* // fetch customers (their id, name and status)
* List<Customer> customers =
* ebeanServer.find(Customer.class)
* List<Customer> customers = DB.find(Customer.class)
* .select("name, status")
* .fetch("contacts", "firstName,lastName,email")
* .findList();
@@ -468,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>
@@ -498,8 +540,7 @@ public interface Query<T> {
* <pre>{@code
*
* // fetch customers (their id, name and status)
* List<Customer> customers =
* ebeanServer.find(Customer.class)
* List<Customer> customers = DB.find(Customer.class)
* .select("name, status")
* .fetch("contacts", "firstName,lastName,email", new FetchConfig().lazy(10))
* .findList();
@@ -520,8 +561,7 @@ public interface Query<T> {
* <pre>{@code
*
* // fetch customers (their id, name and status)
* List<Customer> customers =
* ebeanServer.find(Customer.class)
* List<Customer> customers = DB.find(Customer.class)
* // eager fetch the contacts
* .fetch("contacts")
* .findList();
@@ -556,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>
@@ -584,8 +629,7 @@ public interface Query<T> {
* <pre>{@code
*
* // fetch customers (their id, name and status)
* List<Customer> customers =
* ebeanServer.find(Customer.class)
* List<Customer> customers = DB.find(Customer.class)
* // lazy fetch contacts with a batch size of 100
* .fetch("contacts", new FetchConfig().lazy(100))
* .findList();
@@ -602,10 +646,25 @@ public interface Query<T> {
*/
Query<T> apply(FetchPath fetchPath);
/**
* Execute the query using the given transaction.
*/
Query<T> usingTransaction(Transaction transaction);
/**
* Execute the query using the given connection.
*/
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>
* This query will execute against the EbeanServer that was used to create it.
* This query will execute against the Database that was used to create it.
* </p>
*/
@Nonnull
@@ -627,24 +686,21 @@ public interface Query<T> {
* the jdbc statement and resultSet are closed at the end of the iteration.
* </p>
* <p>
* This query will execute against the EbeanServer that was used to create it.
* This query will execute against the Database that was used to create it.
* </p>
* <pre>{@code
*
* Query<Customer> query =
* ebeanServer.find(Customer.class)
* Query<Customer> query = DB.find(Customer.class)
* .where().eq("status", Status.NEW)
* .order().asc("id");
*
* QueryIterator<Customer> it = query.findIterate();
* try {
* // use try with resources to ensure QueryIterator is closed
*
* try (QueryIterator<Customer> it = query.findIterate()) {
* while (it.hasNext()) {
* Customer customer = it.next();
* // do something with customer ...
* }
* } finally {
* // close the underlying resources
* it.close();
* }
*
* }</pre>
@@ -652,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>
@@ -681,7 +783,7 @@ public interface Query<T> {
* </p>
* <pre>{@code
*
* ebeanServer.find(Customer.class)
* DB.find(Customer.class)
* .where().eq("status", Status.NEW)
* .order().asc("id")
* .findEach((Customer customer) -> {
@@ -710,7 +812,7 @@ public interface Query<T> {
* </p>
* <pre>{@code
*
* ebeanServer.find(Customer.class)
* DB.find(Customer.class)
* .fetch("contacts", new FetchConfig().query(2))
* .where().eq("status", Status.NEW)
* .order().asc("id")
@@ -733,12 +835,11 @@ public interface Query<T> {
/**
* Execute the query returning the list of objects.
* <p>
* This query will execute against the EbeanServer that was used to create it.
* This query will execute against the Database that was used to create it.
* </p>
* <pre>{@code
*
* List<Customer> customers =
* ebeanServer.find(Customer.class)
* List<Customer> customers = DB.find(Customer.class)
* .where().ilike("name", "rob%")
* .findList();
*
@@ -750,12 +851,11 @@ public interface Query<T> {
/**
* Execute the query returning the set of objects.
* <p>
* This query will execute against the EbeanServer that was used to create it.
* This query will execute against the Database that was used to create it.
* </p>
* <pre>{@code
*
* Set<Customer> customers =
* ebeanServer.find(Customer.class)
* Set<Customer> customers = DB.find(Customer.class)
* .where().ilike("name", "rob%")
* .findSet();
*
@@ -767,7 +867,7 @@ public interface Query<T> {
/**
* Execute the query returning a map of the objects.
* <p>
* This query will execute against the EbeanServer that was used to create it.
* This query will execute against the Database that was used to create it.
* </p>
* <p>
* You can use setMapKey() so specify the property values to be used as keys
@@ -775,8 +875,7 @@ public interface Query<T> {
* </p>
* <pre>{@code
*
* Map<String, Product> map =
* ebeanServer.find(Product.class)
* Map<String, Product> map = DB.find(Product.class)
* .setMapKey("sku")
* .findMap();
*
@@ -792,9 +891,9 @@ public interface Query<T> {
* <pre>{@code
*
* List<String> names =
* Ebean.find(Customer.class)
* DB.find(Customer.class)
* .select("name")
* .orderBy().asc("name")
* .order().asc("name")
* .findSingleAttributeList();
*
* }</pre>
@@ -803,11 +902,11 @@ public interface Query<T> {
* <pre>{@code
*
* List<String> names =
* Ebean.find(Customer.class)
* DB.find(Customer.class)
* .setDistinct(true)
* .select("name")
* .where().eq("status", Customer.Status.NEW)
* .orderBy().asc("name")
* .order().asc("name")
* .setMaxRows(100)
* .findSingleAttributeList();
*
@@ -824,7 +923,7 @@ public interface Query<T> {
* <pre>{@code
*
* String name =
* Ebean.find(Customer.class)
* DB.find(Customer.class)
* .select("name")
* .where().eq("id", 42)
* .findSingleAttribute();
@@ -838,6 +937,37 @@ public interface Query<T> {
*/
boolean isCountDistinct();
/**
* Execute the query returning true if a row is found.
* <p>
* The query is executed using max rows of 1 and will only select the id property.
* This method is really just a convenient way to optimise a query to perform a
* 'does a row exist in the db' check.
* </p>
*
* <h2>Example using a query bean:</h2>
* <pre>{@code
*
* boolean userExists =
* new QContact()
* .email.equalTo("rob@foo.com")
* .exists();
*
* }</pre>
*
* <h2>Example:</h2>
* <pre>{@code
*
* boolean userExists = query()
* .where().eq("email", "rob@foo.com")
* .exists();
*
* }</pre>
*
* @return True if the query finds a matching row in the database
*/
boolean exists();
/**
* Execute the query returning either a single bean or null (if no matching
* bean is found).
@@ -852,8 +982,7 @@ public interface Query<T> {
* <pre>{@code
*
* // assuming the sku of products is unique...
* Product product =
* ebeanServer.find(Product.class)
* Product product = DB.find(Product.class)
* .where().eq("sku", "aa113")
* .findOne();
* ...
@@ -865,8 +994,7 @@ public interface Query<T> {
* <pre>{@code
*
* // Fetch order 1 and additionally fetch join its order details...
* Order order =
* ebeanServer.find(Order.class)
* Order order = DB.find(Order.class)
* .setId(1)
* .fetch("details")
* .findOne();
@@ -1007,7 +1135,7 @@ public interface Query<T> {
* </p>
* <pre>{@code
*
* PagedList<Order> pagedList = Ebean.find(Order.class)
* PagedList<Order> pagedList = DB.find(Order.class)
* .setFirstRow(50)
* .setMaxRows(20)
* .findPagedList();
@@ -1032,11 +1160,9 @@ public interface Query<T> {
* // a query with a named parameter
* String oql = "find order where status = :orderStatus";
*
* Query<Order> query = ebeanServer.find(Order.class, oql);
*
* // bind the named parameter
* query.bind("orderStatus", OrderStatus.NEW);
* List<Order> list = query.findList();
* List<Order> list = DB.find(Order.class, oql)
* .setParameter("orderStatus", OrderStatus.NEW)
* .findList();
*
* }</pre>
*
@@ -1054,12 +1180,9 @@ public interface Query<T> {
* // a query with a positioned parameter
* String oql = "where status = ? order by id desc";
*
* Query<Order> query = ebeanServer.createQuery(Order.class, oql);
*
* // bind the parameter
* query.setParameter(1, OrderStatus.NEW);
*
* List<Order> list = query.findList();
* List<Order> list = DB.createQuery(Order.class, oql)
* .setParameter(1, OrderStatus.NEW)
* .findList();
*
* }</pre>
*
@@ -1068,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>
@@ -1076,8 +1223,7 @@ public interface Query<T> {
* </p>
* <pre>{@code
*
* Order order =
* ebeanServer.find(Order.class)
* Order order = DB.find(Order.class)
* .setId(1)
* .fetch("details")
* .findOne();
@@ -1098,8 +1244,7 @@ public interface Query<T> {
* Add a single Expression to the where clause returning the query.
* <pre>{@code
*
* List<Order> newOrders =
* ebeanServer.find(Order.class)
* List<Order> newOrders = DB.find(Order.class)
* .where().eq("status", Order.NEW)
* .findList();
* ...
@@ -1114,8 +1259,7 @@ public interface Query<T> {
* where clause.
* <pre>{@code
*
* List<Order> orders =
* ebeanServer.find(Order.class)
* List<Order> orders = DB.find(Order.class)
* .where()
* .eq("status", Order.NEW)
* .ilike("customer.name","rob%")
@@ -1161,10 +1305,7 @@ public interface Query<T> {
* </p>
* <pre>{@code
*
* List<Customer> list =
* ebeanServer.find(Customer.class)
* // .fetch("orders", new FetchConfig().lazy())
* // .fetch("orders", new FetchConfig().query())
* List<Customer> list = DB.find(Customer.class)
* .fetch("orders")
* .where().ilike("name", "rob%")
* .filterMany("orders").eq("status", Order.Status.NEW).gt("orderDate", lastWeek)
@@ -1178,8 +1319,7 @@ public interface Query<T> {
* </p>
*
* @param propertyName the name of the many property that you want to have a filter on.
* @return the expression list that you add filter expressions for the many
* to.
* @return the expression list that you add filter expressions for the many to.
*/
ExpressionList<T> filterMany(String propertyName);
@@ -1221,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);
@@ -1235,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);
@@ -1248,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();
@@ -1261,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);
@@ -1293,7 +1415,7 @@ public interface Query<T> {
* <pre>{@code
*
* List<Customer> customers =
* Ebean.find(Customer.class)
* DB.find(Customer.class)
* .setDistinct(true)
* .select("name")
* .findList();
@@ -1309,7 +1431,7 @@ public interface Query<T> {
*
* List<CountedValue<Order.Status>> orderStatusCount =
*
* Ebean.find(Order.class)
* DB.find(Order.class)
* .select("status")
* .where()
* .gt("orderDate", LocalDate.now().minusMonths(3))
@@ -1329,7 +1451,6 @@ public interface Query<T> {
* count:1 orderStatus:COMPLETE
*
* }</pre>
*
*/
Query<T> setCountDistinct(CountDistinctOrder orderBy);
@@ -1366,10 +1487,8 @@ public interface Query<T> {
*
* // Assuming sku is unique for products...
*
* Map<String,Product> productMap =
* ebeanServer.find(Product.class)
* // use sku for keys...
* .setMapKey("sku")
* Map<String,Product> productMap = DB.find(Product.class)
* .setMapKey("sku") // sku map keys...
* .findMap();
*
* }</pre>
@@ -1419,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.
@@ -1541,11 +1649,50 @@ public interface Query<T> {
*/
Query<T> alias(String alias);
/**
* Set the base table to use for this query.
* <p>
* Typically this is used when a table has partitioning and we wish to specify a specific
* partition/table to query against.
* </p>
* <pre>{@code
*
* QOrder()
* .setBaseTable("order_2019_05")
* .status.equalTo(Status.NEW)
* .findList();
*
* }</pre>
*/
Query<T> setBaseTable(String baseTable);
/**
* Return the type of beans being queried.
*/
Class<T> getBeanType();
/**
* Restrict the query to only return subtypes of the given inherit type.
*
* <pre>{@code
*
* List<Animal> animals =
* new QAnimal()
* .name.startsWith("Fluffy")
* .setInheritType(Cat.class)
* .findList();
*
* }</pre>
*
* @param type An inheritance subtype of the
*/
Query<T> setInheritType(Class<? extends T> type);
/**
* Returns the inherit type. This is normally the same as getBeanType() returns as long as no other type is set.
*/
Class<? extends T> getInheritType();
/**
* Return the type of query being executed.
*/
+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 -3
View File
@@ -87,7 +87,7 @@ package io.ebean;
* // .columnMapping("sum(d.order_qty*d.unit_price)", "totalAmount")
* .create();
*
* List<OrderAggregate> list = Ebean.find(OrderAggregate.class)
* List<OrderAggregate> list = DB.find(OrderAggregate.class)
* .setRawSql(rawSql)
* .where().gt("order.id", 0)
* .having().gt("totalAmount", 20)
@@ -114,7 +114,7 @@ package io.ebean;
* .columnMappingIgnore("'ignoreMe'")
* .create();
*
* List<OrderAggregate> orders = Ebean.find(OrderAggregate.class)
* List<OrderAggregate> orders = DB.find(OrderAggregate.class)
* .setRawSql(rawSql)
* .fetch("order", "status,orderDate", new FetchConfig().query())
* .fetch("order.customer", "name")
@@ -146,7 +146,7 @@ package io.ebean;
* .tableAliasMapping("p", "details.product")
* .create();
*
* List<Order> ordersFromRaw = Ebean.find(Order.class)
* List<Order> ordersFromRaw = DB.find(Order.class)
* .setRawSql(rawSql)
* .setParameter("maxOrderId", 2)
* .setParameter("productId", 1)
+1 -1
View File
@@ -13,7 +13,7 @@ import java.sql.SQLException;
*
* String sql = "select id, name, status from o_customer order by name desc";
*
* Ebean.createSqlQuery(sql)
* DB.sqlQuery(sql)
* .findEachRow((resultSet, rowNum) -> {
*
* // read directly from ResultSet
+4 -3
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> {
*
@@ -40,9 +40,10 @@ import java.sql.SQLException;
*
* String sql = "select id, name, status from o_customer where name = ?";
*
* CustomerDto rob = Ebean.createSqlQuery(sql)
* CustomerDto rob = DB.sqlQuery(sql)
* .setParameter(1, "Rob")
* .findOne(CUSTOMER_MAPPER);
* .mapTo(CUSTOMER_MAPPER)
* .findOne();
*
*
* }</pre>
+13 -16
View File
@@ -13,20 +13,8 @@ import java.util.Map;
* <h3>Example of simple use</h3>
* <pre>{@code
*
* EbeanServer server = Ebean.getDefaultServer();
* server.script().run("/scripts/test-script.sql");
*
* }</pre>
*
*
* <h3>Example using place holders in the script</h3>
* <pre>{@code
*
* Map<String,String> placeholders = new HashMap<>();
* placeholders.put("tableName", "e_basic");
*
* EbeanServer server = Ebean.getDefaultServer();
* server.script().run("/scripts/test-script.sql");
* Database database = DB.getDefault();
* database.script().run("/scripts/test-script.sql");
*
* }</pre>
*/
@@ -45,8 +33,8 @@ public interface ScriptRunner {
* Map<String,String> placeholders = new HashMap<>();
* placeholders.put("tableName", "e_basic");
*
* EbeanServer server = Ebean.getDefaultServer();
* server.script().run("/scripts/test-script.sql");
* Database database = DB.getDefault();
* database.script().run("/scripts/test-script.sql", placeholders);
*
* }</pre>
*/
@@ -62,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);
}
}
+197 -67
View File
@@ -10,34 +10,30 @@ import java.util.function.Consumer;
import java.util.function.Predicate;
/**
* Query object for performing native SQL queries that return SqlRow's.
* <p>
* Firstly note that you can use your own sql queries with <em>entity beans</em>
* by using the SqlSelect annotation. This should be your first approach when
* wanting to use your own SQL queries.
* </p>
* <p>
* If ORM Mapping is too tight and constraining for your problem then SqlQuery
* could be a good approach.
* </p>
* Query object for performing native SQL queries that return SqlRow or directly read
* ResultSet using a RowMapper.
* <p>
* The returned SqlRow objects are similar to a LinkedHashMap with some type
* conversion support added.
* </p>
* <p>
* Refer to {@link DtoQuery} for native sql queries returning DTO beans.
* </p>
* <p>
* Refer to {@link Database#findNative(Class, String)} for native sql queries returning entity beans.
* </p>
*
* <pre>{@code
*
* // its typically a good idea to use a named query
* // and put the sql in the orm.xml instead of in your code
* // example using named parameters
*
* String sql = "select id, name from customer where name like :name and status_code = :status";
*
* SqlQuery sqlQuery = Ebean.createSqlQuery(sql);
* sqlQuery.setParameter("name", "Acme%");
* sqlQuery.setParameter("status", "ACTIVE");
*
* // execute the query returning a List of MapBean objects
* List<SqlRow> list = sqlQuery.findList();
* List<SqlRow> list =
* DB.sqlQuery(sql)
* .setParameter("name", "Acme%")
* .setParameter("status", "ACTIVE")
* .findList();
*
* }</pre>
*/
@@ -79,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);
/**
@@ -104,7 +98,7 @@ public interface SqlQuery extends Serializable {
*
* String sql = "select id, name, status from customer order by name desc";
*
* Ebean.createSqlQuery(sql)
* DB.sqlQuery(sql)
* .findEachRow((resultSet, rowNum) -> {
*
* // read directly from ResultSet
@@ -129,77 +123,158 @@ 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 = Ebean.createSqlQuery(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
*
* .mapToScalar(Long.class)
* .findList();
* }
*/
@Deprecated
<T> List<T> findSingleAttributeList(Class<T> attributeType);
/**
* Set one of more positioned parameters.
* <p>
* This is a convenient alternative to multiple calls to {@link #setParameter(Object)}.
*
* <pre>{@code
*
* String sql =
* " select (unit_price * order_qty) " +
* " from o_order_detail " +
* " where unit_price > ? " +
* " order by (unit_price * order_qty) desc";
* String sql = "select id, name from customer where name like ? and status = ?";
*
* //
* List<BigDecimal> lineAmounts = Ebean.createSqlQuery(sql)
* .setParameter(1, 3)
* .findSingleAttributeList(BigDecimal.class);
* List<SqlRow> list =
* DB.sqlQuery(sql)
* .setParameters("Rob", Status.NEW)
* .findList();
*
*
* // effectively the same as ...
*
* .setParameter("Rob")
* .setParameter("Status.NEW)
*
* // and ...
*
* .setParameter(1, "Rob")
* .setParameter(2, "Status.NEW)
*
* }</pre>
*/
SqlQuery setParameters(Object... values);
/**
* Deprecated migrate to setParameters(Object... values)
*/
@Deprecated
SqlQuery setParams(Object... values);
/**
* 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>
* The attributeType can be any scalar type that Ebean supports (includes javax time types, Joda types etc).
* When binding a collection of values into a IN expression we should use
* indexed parameters like ?1, ?2, ?3 etc rather than just ?.
* </p>
*
* @param attributeType The type of the returned value
* <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
*/
<T> List<T> findSingleAttributeList(Class<T> attributeType);
SqlQuery setParameter(Object value);
/**
* The same as bind for named parameters.
*/
SqlQuery setParameter(String name, Object value);
/**
* The same as bind for positioned parameters.
* 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.
*/
@@ -236,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();
}
}
+118 -38
View File
@@ -5,56 +5,92 @@ 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>
* <p>
*
* <h2>Positioned parameter example</h2>
* <pre>{@code
*
* // example that uses 'named' parameters
* // example using 'positioned' parameters
*
* String s = "UPDATE f_topic set post_count = :count where id = :id";
* String sql = "insert into audit_log (group, title, description) values (?, ?, ?);
*
* SqlUpdate update = Ebean.createSqlUpdate(s);
* update.setParameter("id", 1);
* update.setParameter("count", 50);
*
* int modifiedCount = update.execute();
*
* String msg = "There were " + modifiedCount + " rows updated";
* int rows =
* DB.sqlUpdate(sql)
* .setParams("login", "new user", "user rob was created")
* .executeNow();
*
* }</pre>
*
* <h2>Named parameter example</h2>
* <pre>{@code
*
* // example using 'named' parameters
*
* String sql = "update topic set post_count = :count where id = :id";
*
* int rows =
* DB.sqlUpdate(sql)
* .setParameter("id", 1)
* .setParameter("count", 50)
* .execute();
*
* 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 (?,?,?)";
* SqlUpdate insert = Ebean.createSqlUpdate(sql);
*
* try (Transaction txn = Ebean.beginTransaction()) {
* SqlUpdate insert = DB.sqlUpdate(sql);
*
* 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();
@@ -65,21 +101,21 @@ package io.ebean;
* </p>
* <pre>{@code
*
* try (Transaction txn = Ebean.beginTransaction()) {
* 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();
@@ -112,8 +148,6 @@ public interface SqlUpdate {
* {@link Transaction#setBatchMode(boolean)} and
* {@link Transaction#setBatchSize(int)}.
* </p>
*
* @see Ebean#execute(SqlUpdate)
*/
int execute();
@@ -218,10 +252,56 @@ public interface SqlUpdate {
SqlUpdate setTimeout(int secs);
/**
* Set the next positioned parameter.
* Set one of more positioned parameters.
* <p>
* This is a convenient alternative to multiple setParameter() calls.
*
* <pre>{@code
*
* String sql = "insert into audit_log (id, name, version) values (?,?,?)";
*
* DB.sqlUpdate(sql)
* .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 bind parameter by position.
*
* @param value The value to bind
*/
SqlUpdate setParameter(Object value);
/**
* Deprecated migrate to setParameter(value).
*/
@Deprecated
SqlUpdate setNextParameter(Object value);
/**
+105 -49
View File
@@ -14,21 +14,20 @@ import java.sql.Connection;
public interface Transaction extends AutoCloseable {
/**
* Return the current transaction (of the default server) or null if there is
* Return the current transaction (of the default database) or null if there is
* no current transaction in scope.
* <p>
* This is the same as <code>Ebean.currentTransaction()</code>
* This is the same as <code>DB.currentTransaction()</code>
* </p>
* <p>
* This returns the current transaction for the 'default server'. If you are using
* multiple EbeanServer's then use {@link EbeanServer#currentTransaction()}.
* This returns the current transaction for the default database.
* </p>
*
* @see Ebean#currentTransaction()
* @see EbeanServer#currentTransaction()
* @see DB#currentTransaction()
* @see Database#currentTransaction()
*/
static Transaction current() {
return Ebean.currentTransaction();
return DB.currentTransaction();
}
/**
@@ -244,8 +243,7 @@ public interface Transaction extends AutoCloseable {
*
* // assume Customer has L2 bean caching enabled ...
*
* Transaction transaction = Ebean.beginTransaction();
* try {
* try (Transaction transaction = DB.beginTransaction()) {
*
* // this uses L2 bean cache as the transaction
* // ... is considered "query only" at this point
@@ -253,7 +251,7 @@ public interface Transaction extends AutoCloseable {
*
* // transaction no longer "query only" once
* // ... a bean has been saved etc
* Ebean.save(someBean);
* someBean.save();
*
* // will NOT use L2 bean cache as the transaction
* // ... is no longer considered "query only"
@@ -273,8 +271,7 @@ public interface Transaction extends AutoCloseable {
* Customer.find.byId(99); // skips l2 bean cache
*
*
* } finally {
* transaction.end();
* transaction.commit();
* }
*
* }</pre>
@@ -290,36 +287,66 @@ public interface Transaction extends AutoCloseable {
boolean isSkipCache();
/**
* Turn on or off statement batching. Statement batching can be transparent
* for drivers and databases that support getGeneratedKeys. Otherwise you may
* wish to specifically control when batching is used via this method.
* <p>
* Refer to <code>java.sql.PreparedStatement.addBatch();</code>
* <p>
* Note that you may also wish to use the setPersistCascade method to stop
* save and delete cascade behaviour. You may do this to have full control
* over the order of execution rather than the normal cascading fashion.
* </p>
* <p>
* Note that the <em>execution order</em> in batch mode may be different from
* non batch mode execution order. Also note that <em>insert behaviour</em>
* may be different depending on the JDBC driver and its support for
* getGeneratedKeys. That is, for JDBC drivers that do not support
* getGeneratedKeys you may not get back the generated IDs (used for inserting
* associated detail beans etc).
* </p>
* Turn on or off use of JDBC statement batching.
* <p>
* Calls to save(), delete(), insert() and execute() all support batch
* processing. This includes normal beans, MapBean, CallableSql and UpdateSql.
* processing. This includes normal beans, CallableSql and UpdateSql.
* </p>
*
* <pre>{@code
*
* try (Transaction transaction = database.beginTransaction()) {
*
* // turn on JDBC batch
* transaction.setBatchMode(true);
*
* // tune the batch size
* transaction.setBatchSize(50);
*
* ...
*
* transaction.commit();
* }
*
* }</pre>
*
* <h3>getGeneratedKeys</h3>
* <p>
* The flushing of the batched statements is automatic but you can call
* batchFlush when you like. Note that flushing occurs when a query is
* executed or when you mix UpdateSql and CallableSql with save and delete of
* Often with large batch inserts we want to turn off getGeneratedKeys. We do
* 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 = database.beginTransaction()) {
*
* transaction.setBatchMode(true);
* transaction.setBatchSize(100);
* // insert but don't bother getting back the generated keys
* transaction.setBatchGetGeneratedKeys(false);
*
*
* // perform lots of inserts ...
* ...
*
* transaction.commit();
* }
*
* }</pre>
*
* <h3>Flush</h3>
* <p>
* The batch is automatically flushed when it hits the batch size and also when we
* execute queries or when we mix UpdateSql and CallableSql with save and delete of
* beans.
* </p>
* <p>
* Example: batch processing executing every 3 rows
* We use {@link #flush()} to explicitly flush the batch and we can use
* {@link #setFlushOnQuery(boolean)} and {@link #setFlushOnMixed(boolean)}
* to control the automatic flushing behaviour.
* </p>
* <p>
* Example: batch processing of CallableSql executing every 10 rows
* </p>
*
* <pre>{@code
@@ -334,24 +361,21 @@ public interface Transaction extends AutoCloseable {
* CallableSql cs = new CallableSql(sql);
* cs.registerOut(2, Types.INTEGER);
*
* // (optional) inform eBean this stored procedure
* // (optional) inform Ebean this stored procedure
* // inserts into a table called sp_test
* cs.addModification("sp_test", true, false, false);
*
* Transaction txn = ebeanServer.beginTransaction();
* txn.setBatchMode(true);
* txn.setBatchSize(3);
* try {
* try (Transaction txn = DB.beginTransaction()) {
* txn.setBatchMode(true);
* txn.setBatchSize(10);
*
* for (int i = 0; i < da.length;) {
* cs.setParameter(1, da[i]);
* ebeanServer.execute(cs);
* DB.execute(cs);
* }
*
* // NB: commit implicitly flushes
* // Note: commit implicitly flushes
* txn.commit();
*
* } finally {
* txn.end();
* }
*
* }</pre>
@@ -408,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
@@ -425,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
@@ -435,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)
@@ -444,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 {
+1 -1
View File
@@ -41,7 +41,7 @@ package io.ebean;
* <p>
* <pre>{@code
*
* Update<Topic> update = Ebean.createUpdate(Topic.class, "incrementPostCount");
* Update<Topic> update = DB.createUpdate(Topic.class, "incrementPostCount");
* update.setParameter("id", 1);
* int rows = update.execute();
*
+16 -12
View File
@@ -12,8 +12,7 @@ package io.ebean;
* <p>
* <pre>{@code
*
* int rows = ebeanServer
* .update(Customer.class)
* int rows = DB.update(Customer.class)
* .set("status", Customer.Status.ACTIVE)
* .set("updtime", new Timestamp(System.currentTimeMillis()))
* .where()
@@ -39,8 +38,7 @@ package io.ebean;
* <p>
* <pre>{@code
*
* int rows = ebeanServer
* .update(Customer.class)
* int rows = DB.update(Customer.class)
* .set("status", Customer.Status.ACTIVE)
* .set("updtime", new Timestamp(System.currentTimeMillis()))
* .where()
@@ -73,8 +71,7 @@ public interface UpdateQuery<T> {
* <p>
* <pre>{@code
*
* int rows = ebeanServer
* .update(Customer.class)
* int rows = DB.update(Customer.class)
* .set("status", Customer.Status.ACTIVE)
* .set("updtime", new Timestamp(System.currentTimeMillis()))
* .where()
@@ -93,8 +90,7 @@ public interface UpdateQuery<T> {
* <p>
* <pre>{@code
*
* int rows = ebeanServer
* .update(Customer.class)
* int rows = DB.update(Customer.class)
* .setNull("notes")
* .where()
* .gt("id", 1000)
@@ -114,8 +110,7 @@ public interface UpdateQuery<T> {
* <p>
* <pre>{@code
*
* int rows = ebeanServer
* .update(Customer.class)
* int rows = DB.update(Customer.class)
* .setRaw("status = coalesce(status, 'A')")
* .where()
* .gt("id", 1000)
@@ -134,8 +129,7 @@ public interface UpdateQuery<T> {
* </p>
* <pre>{@code
*
* int rows = ebeanServer
* .update(Customer.class)
* int rows = DB.update(Customer.class)
* .setRaw("status = coalesce(status, ?)", Customer.Status.ACTIVE)
* .where()
* .gt("id", 1000)
@@ -154,9 +148,19 @@ public interface UpdateQuery<T> {
*/
UpdateQuery<T> setProfileLocation(ProfileLocation profileLocation);
/**
* Set the label on the update query.
*/
UpdateQuery<T> setLabel(String label);
/**
* Return the query expression list to add predicates to.
*/
ExpressionList<T> where();
/**
* Execute the update returning the number of rows updated.
*/
int update();
}
+15 -13
View File
@@ -1,5 +1,6 @@
package io.ebean;
import io.ebean.service.SpiFetchGroupQuery;
import io.ebean.service.SpiFetchGroupService;
import io.ebean.service.SpiProfileLocationFactory;
import io.ebean.service.SpiRawSqlService;
@@ -19,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);
}
/**
@@ -71,4 +66,11 @@ class XServiceProvider {
static <T> FetchGroupBuilder<T> fetchGroupOf(Class<T> cls) {
return fetchGroupService.of(cls);
}
/**
* Return the FetchGroup Query for building fetch groups via query beans.
*/
static <T> SpiFetchGroupQuery<T> fetchGroupQueryFor(Class<T> cls) {
return fetchGroupService.queryFor(cls);
}
}
@@ -9,7 +9,7 @@ package io.ebean.bean;
public interface BeanCollectionLoader {
/**
* Return the name of the associated EbeanServer.
* Return the name of the associated Database.
*/
String getName();
+1 -1
View File
@@ -9,7 +9,7 @@ package io.ebean.bean;
public interface BeanLoader {
/**
* Return the name of the associated EbeanServer.
* Return the name of the associated Database.
*/
String getName();
@@ -0,0 +1,22 @@
package io.ebean.bean;
/**
* A call origin for query execution profiling to collect graph use (for query tuning).
*/
public interface CallOrigin {
/**
* Return the top element. Typically the top stack element with class and line.
*/
String getTopElement();
/**
* Return the full description of the call origin.
*/
String getFullDescription();
/**
* Compute and return an origin key based on the query hash.
*/
String getOriginKey(int queryHash);
}
+22 -59
View File
@@ -3,6 +3,8 @@ package io.ebean.bean;
import java.io.Serializable;
import java.util.Arrays;
import static io.ebean.util.EncodeB64.enc;
/**
* Represent the call stack (stack trace elements).
* <p>
@@ -17,15 +19,15 @@ import java.util.Arrays;
* Note the call stack is trimmed to remove the common ebean internal elements.
* </p>
*/
public final class CallStack implements Serializable {
public final class CallStack implements Serializable, CallOrigin {
private static final long serialVersionUID = -8590644046907438579L;
private static final String NEWLINE = "\n";
private final String zeroHash;
private final String pathHash;
private final StackTraceElement[] callStack;
private final int hc;
public CallStack(StackTraceElement[] callStack, int zeroHash, int pathHash) {
@@ -37,12 +39,17 @@ public final class CallStack implements Serializable {
private int computeHashCode() {
int hc = 0;
for (StackTraceElement aCallStack : callStack) {
hc = 92821 * hc + aCallStack.hashCode();
for (StackTraceElement element : callStack) {
hc = 92821 * hc + element.hashCode();
}
return hc;
}
@Override
public String toString() {
return zeroHash + ":" + pathHash + ":" + callStack[0];
}
@Override
public int hashCode() {
return hc;
@@ -63,73 +70,29 @@ public final class CallStack implements Serializable {
/**
* Return the first element of the call stack.
*/
public StackTraceElement getFirstStackTraceElement() {
return callStack[0];
}
/**
* Return the call stack.
*/
public StackTraceElement[] getCallStack() {
return callStack;
}
/**
* Return the hash for the first stack element.
*/
public String getZeroHash() {
return zeroHash;
}
/**
* Return the hash for the stack elements (excluding first stack element).
*/
public String getPathHash() {
return pathHash;
}
@Override
public String toString() {
return zeroHash + ":" + pathHash + ":" + callStack[0];
public String getTopElement() {
return callStack[0].toString();
}
/**
* Return the call stack lines appended with the given newLine string.
*/
public String description(String newLine) {
@Override
public String getFullDescription() {
StringBuilder sb = new StringBuilder(400);
for (StackTraceElement aCallStack : callStack) {
sb.append(aCallStack.toString()).append(newLine);
for (int i = 0; i < callStack.length; i++) {
if (i > 0) {
sb.append(NEWLINE);
}
sb.append(callStack[i].toString());
}
return sb.toString();
}
@Override
public String getOriginKey(int queryHash) {
return enc(queryHash) + "." + zeroHash + "." + pathHash;
}
private static final int radix = 1 << 6;
private static final int mask = radix - 1;
/**
* Convert the integer to unsigned base 64.
*/
public static String enc(int i) {
char[] buf = new char[32];
int charPos = 32;
do {
buf[--charPos] = intToBase64[i & mask];
i >>>= 6;
} while (i != 0);
return new String(buf, charPos, (32 - charPos));
}
private static final char intToBase64[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
};
}
+36 -12
View File
@@ -16,12 +16,16 @@ public interface EntityBean extends Serializable {
/**
* Return all the property names in defined order.
*/
String[] _ebean_getPropertyNames();
default String[] _ebean_getPropertyNames() {
throw new NotEnhancedException();
}
/**
* Return the property name at the given position.
*/
String _ebean_getPropertyName(int pos);
default String _ebean_getPropertyName(int pos) {
throw new NotEnhancedException();
}
/**
* Return the enhancement marker value.
@@ -30,28 +34,38 @@ public interface EntityBean extends Serializable {
* entity classes are enhanced (specifically not just a super class).
* </p>
*/
String _ebean_getMarker();
default String _ebean_getMarker() {
throw new NotEnhancedException();
}
/**
* Create and return a new entity bean instance.
*/
Object _ebean_newInstance();
default Object _ebean_newInstance() {
throw new NotEnhancedException();
}
/**
* Generated method that sets the loaded state on all the embedded beans on
* this entity bean by using EntityBeanIntercept.setEmbeddedLoaded(Object o);
*/
void _ebean_setEmbeddedLoaded();
default void _ebean_setEmbeddedLoaded() {
throw new NotEnhancedException();
}
/**
* Return true if any embedded beans are new or dirty.
*/
boolean _ebean_isEmbeddedNewOrDirty();
default boolean _ebean_isEmbeddedNewOrDirty() {
throw new NotEnhancedException();
}
/**
* Return the intercept for this object.
*/
EntityBeanIntercept _ebean_getIntercept();
default EntityBeanIntercept _ebean_getIntercept() {
throw new NotEnhancedException();
}
/**
* Similar to _ebean_getIntercept() except it checks to see if the intercept
@@ -66,7 +80,9 @@ public interface EntityBean extends Serializable {
* frameworks that can't take into account our ebean fields.
* </p>
*/
EntityBeanIntercept _ebean_intercept();
default EntityBeanIntercept _ebean_intercept() {
throw new NotEnhancedException();
}
/**
* Set the value of a field of an entity bean of this type.
@@ -75,12 +91,16 @@ public interface EntityBean extends Serializable {
* on entity beans. That means lazy loading and oldValues creation.
* </p>
*/
void _ebean_setField(int fieldIndex, Object value);
default void _ebean_setField(int fieldIndex, Object value) {
throw new NotEnhancedException();
}
/**
* Set the field value with interception.
*/
void _ebean_setFieldIntercept(int fieldIndex, Object value);
default void _ebean_setFieldIntercept(int fieldIndex, Object value) {
throw new NotEnhancedException();
}
/**
* Return the value of a field from an entity bean of this type.
@@ -89,11 +109,15 @@ public interface EntityBean extends Serializable {
* on entity beans. That means lazy loading.
* </p>
*/
Object _ebean_getField(int fieldIndex);
default Object _ebean_getField(int fieldIndex) {
throw new NotEnhancedException();
}
/**
* Return the field value with interception.
*/
Object _ebean_getFieldIntercept(int fieldIndex);
default Object _ebean_getFieldIntercept(int fieldIndex) {
throw new NotEnhancedException();
}
}
@@ -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,25 +98,29 @@ 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;
this.flags = new byte[owner._ebean_getPropertyNames().length];
}
/**
* EXPERIMENTAL - Constructor only for use by serialization frameworks.
*/
public EntityBeanIntercept() {
this.owner = null;
this.flags = null;
}
/**
* Return the 'owning' entity bean.
*/
@@ -301,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.
@@ -348,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;
@@ -368,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;
@@ -400,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;
@@ -422,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
@@ -430,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;
@@ -448,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();
@@ -472,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;
@@ -494,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;
@@ -582,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;
@@ -637,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);
@@ -651,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;
}
@@ -689,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);
@@ -711,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);
@@ -735,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) {
@@ -770,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;
}
@@ -795,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')
@@ -821,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
}
@@ -856,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);
}
/**
@@ -892,6 +888,7 @@ public final class EntityBeanIntercept implements Serializable {
}
private void preGetterCallback(int propertyIndex) {
PreGetterCallback preGetterCallback = this.preGetterCallback;
if (preGetterCallback != null) {
preGetterCallback.preGetterTrigger(propertyIndex);
}
@@ -921,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();
@@ -964,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);
}
}
@@ -977,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) {
@@ -989,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) {
@@ -1001,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) {
@@ -1013,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) {
@@ -1025,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) {
@@ -1037,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) {
@@ -1049,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) {
@@ -1061,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) {
@@ -1073,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)) {
@@ -1085,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)) {
@@ -1115,4 +1096,47 @@ public final class EntityBeanIntercept implements Serializable {
public void setSortOrder(int sortOrder) {
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.
*/
public void setLoadError(int propertyIndex, Exception t) {
if (loadErrors == null) {
loadErrors = new Exception[owner._ebean_getPropertyNames().length];
}
loadErrors[propertyIndex] = t;
flags[propertyIndex] |= FLAG_LOADED_PROP;
}
/**
* Returns the loadErrors.
*/
public Map<String, Exception> getLoadErrors() {
if (loadErrors == null) {
return null;
}
Map<String, Exception> ret = null;
int len = getPropertyLength();
for (int i = 0; i < len; i++) {
Exception loadError = loadErrors[i];
if (loadError != null) {
if (ret == null) {
ret = new LinkedHashMap<>();
}
ret.put(getProperty(i), loadError);
}
}
return ret;
}
}
@@ -0,0 +1,12 @@
package io.ebean.bean;
/**
* This exception is thrown, when the default implementation of EntityBean is not or not properly overwritten by enhancer.
*
* @author Roland Praml, FOCONIS AG
*
*/
public class NotEnhancedException extends RuntimeException {
private static final long serialVersionUID = 1L;
}
@@ -1,6 +1,7 @@
package io.ebean.bean;
import java.io.Serializable;
import java.util.Objects;
/**
* Identifies a unique node of an object graph.
@@ -85,8 +86,7 @@ public final class ObjectGraphNode implements Serializable {
}
ObjectGraphNode e = (ObjectGraphNode) obj;
//noinspection StringEquality
return ((e.path == path) || (e.path != null && e.path.equals(path)))
return (Objects.equals(e.path, path))
&& e.originQueryPoint.equals(originQueryPoint);
}
}
@@ -16,7 +16,7 @@ public final class ObjectGraphOrigin implements Serializable {
private static final long serialVersionUID = 410937765287968708L;
private final CallStack callStack;
private final CallOrigin callOrigin;
private final String beanType;
@@ -24,11 +24,11 @@ public final class ObjectGraphOrigin implements Serializable {
private final String key;
public ObjectGraphOrigin(int queryHash, CallStack callStack, String beanType) {
this.callStack = callStack;
public ObjectGraphOrigin(int queryHash, CallOrigin callOrigin, String beanType) {
this.callOrigin = callOrigin;
this.beanType = beanType;
this.queryHash = queryHash;
this.key = callStack.getOriginKey(queryHash);
this.key = callOrigin.getOriginKey(queryHash);
}
/**
@@ -49,22 +49,22 @@ public final class ObjectGraphOrigin implements Serializable {
/**
* The call stack involved.
*/
public CallStack getCallStack() {
return callStack;
public CallOrigin getCallOrigin() {
return callOrigin;
}
public String getFirstStackElement() {
return callStack.getFirstStackTraceElement().toString();
public String getTopElement() {
return callOrigin.getTopElement();
}
@Override
public String toString() {
return "key[" + key + "] type[" + beanType + "] " + callStack.getFirstStackTraceElement() + " ";
return "key[" + key + "] type[" + beanType + "] " + callOrigin.getTopElement();
}
@Override
public int hashCode() {
int hc = 92821 * callStack.hashCode();
int hc = 92821 * callOrigin.hashCode();
hc = 92821 * hc + beanType.hashCode();
hc = 92821 * hc + queryHash;
return hc;
@@ -82,6 +82,6 @@ public final class ObjectGraphOrigin implements Serializable {
ObjectGraphOrigin e = (ObjectGraphOrigin) obj;
return e.queryHash == queryHash
&& e.beanType.equals(beanType)
&& e.callStack.equals(callStack);
&& e.callOrigin.equals(callOrigin);
}
}
@@ -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);
}
}
}
+9
View File
@@ -1,5 +1,7 @@
package io.ebean.cache;
import io.ebean.meta.MetricVisitor;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
@@ -79,4 +81,11 @@ public interface ServerCache {
* @param reset if true the statistics are reset.
*/
ServerCacheStatistics getStatistics(boolean reset);
/**
* Visit the metrics for the cache.
*/
default void visit(MetricVisitor visitor) {
// do nothing by default
}
}
+10 -1
View File
@@ -9,13 +9,15 @@ public class ServerCacheConfig {
private final ServerCacheType type;
private final String cacheKey;
private final String shortName;
private final ServerCacheOptions cacheOptions;
private final CurrentTenantProvider tenantProvider;
private final QueryCacheEntryValidate queryCacheEntryValidate;
public ServerCacheConfig(ServerCacheType type, String cacheKey, ServerCacheOptions cacheOptions, CurrentTenantProvider tenantProvider, QueryCacheEntryValidate queryCacheEntryValidate) {
public ServerCacheConfig(ServerCacheType type, String cacheKey, String shortName, ServerCacheOptions cacheOptions, CurrentTenantProvider tenantProvider, QueryCacheEntryValidate queryCacheEntryValidate) {
this.type = type;
this.cacheKey = cacheKey;
this.shortName = shortName;
this.cacheOptions = cacheOptions;
this.tenantProvider = tenantProvider;
this.queryCacheEntryValidate = queryCacheEntryValidate;
@@ -35,6 +37,13 @@ public class ServerCacheConfig {
return cacheKey;
}
/**
* Return the short name for the cache.
*/
public String getShortName() {
return shortName;
}
/**
* Return the tuning options.
*/
+9
View File
@@ -1,10 +1,19 @@
package io.ebean.cache;
import io.ebean.meta.MetricVisitor;
/**
* Defines method for constructing caches for beans and queries.
*/
public interface ServerCacheFactory {
/**
* Visit the metrics for the cache.
*/
default void visit(MetricVisitor visitor) {
// do nothing by default
}
/**
* Create the cache for the given type with options.
*/
+36 -2
View File
@@ -1,10 +1,19 @@
package io.ebean.cache;
import io.ebean.meta.MetricVisitor;
import java.util.List;
/**
* The cache service for server side caching of beans and query results.
*/
public interface ServerCacheManager {
/**
* Visit the metrics for all the server caches.
*/
void visitMetrics(MetricVisitor visitor);
/**
* Return true if the L2 caching is local.
* <p>
@@ -14,6 +23,31 @@ public interface ServerCacheManager {
*/
boolean isLocalL2Caching();
/**
* Return all the cache regions.
*/
List<ServerCacheRegion> allRegions();
/**
* Set the regions that are enabled.
* <p>
* Typically this is set on startup and at runtime (via dynamic configuration).
* </p>
*
* @param regions A region name or comma delimited list of region names.
*/
void setEnabledRegions(String regions);
/**
* Enable or disable all the cache regions.
*/
void setAllRegionsEnabled(boolean enabled);
/**
* Return the cache region by name. Typically to enable or disable the region.
*/
ServerCacheRegion getRegion(String name);
/**
* Return the cache for mapping natural keys to id values.
*/
@@ -46,7 +80,7 @@ public interface ServerCacheManager {
/**
* Clear all the local caches.
*
* <p>
* This is used when the L2 Cache is based on clustered near-caches (Like Ebean-K8s-L2Cache).
* It is not used when the L2 cache is a distributed cache such as HazelCast or Ignite etc.
*/
@@ -54,7 +88,7 @@ public interface ServerCacheManager {
/**
* Clear the local caches for this bean type.
*
* <p>
* This is used when the L2 Cache is based on clustered near-caches (Like Ebean-K8s-L2Cache).
* It is not used when the L2 cache is a distributed cache such as HazelCast or Ignite etc.
*/
+4 -6
View File
@@ -10,17 +10,15 @@ import java.util.Set;
*/
public class ServerCacheNotification {
private final long modifyTimestamp;
private final Set<String> dependentTables;
public ServerCacheNotification(long modifyTimestamp, Set<String> dependentTables) {
this.modifyTimestamp = modifyTimestamp;
public ServerCacheNotification(Set<String> dependentTables) {
this.dependentTables = dependentTables;
}
public long getModifyTimestamp() {
return modifyTimestamp;
@Override
public String toString() {
return "tables:" + dependentTables;
}
public Set<String> getDependentTables() {
+33
View File
@@ -12,6 +12,7 @@ public class ServerCacheOptions {
private int maxIdleSecs;
private int maxSecsToLive;
private int trimFrequency;
private boolean nearCache;
/**
* Construct with no set options.
@@ -40,6 +41,14 @@ public class ServerCacheOptions {
this.trimFrequency = cacheTuning.trimFrequency();
}
/**
* Create with nearCache option.
*/
public ServerCacheOptions(boolean nearCache, CacheBeanTuning tuning) {
this(tuning);
this.nearCache = nearCache;
}
/**
* Apply any settings from the default settings that have not already been
* specifically set.
@@ -70,9 +79,33 @@ public class ServerCacheOptions {
copy.maxIdleSecs = maxIdleSecs;
copy.maxSecsToLive = maxSecsToLive;
copy.trimFrequency = trimFrequency;
copy.nearCache = this.nearCache;
return copy;
}
/**
* Return a copy of this object with nearCache option.
*/
public ServerCacheOptions copy(boolean nearCache) {
ServerCacheOptions copy = copy();
copy.nearCache = nearCache;
return copy;
}
/**
* Return true if nearCache was explicitly turned on.
*/
public boolean isNearCache() {
return nearCache;
}
/**
* Turn on nearCache option.
*/
public void setNearCache(boolean nearCache) {
this.nearCache = nearCache;
}
/**
* Return the maximum cache size.
*/
+23
View File
@@ -0,0 +1,23 @@
package io.ebean.cache;
/**
* Cache region can be enabled independently.
*/
public interface ServerCacheRegion {
/**
* Return the region name.
*/
String getName();
/**
* Return true if the cache region is enabled.
*/
boolean isEnabled();
/**
* Set to true to enable the cache region.
*/
void setEnabled(boolean enabled);
}
+12 -96
View File
@@ -21,23 +21,13 @@ public class ServerCacheStatistics {
protected long missCount;
protected long insertCount;
protected long updateCount;
protected long putCount;
protected long removeCount;
protected long clearCount;
protected long evictionRunCount;
protected long evictionRunMicros;
protected long evictByIdle;
protected long evictByTTL;
protected long evictByLRU;
protected long evictCount;
@Override
public String toString() {
@@ -49,15 +39,10 @@ public class ServerCacheStatistics {
sb.append(" hitRatio:").append(getHitRatio());
sb.append(" hit:").append(hitCount);
sb.append(" miss:").append(missCount);
sb.append(" insert:").append(insertCount);
sb.append(" update:").append(updateCount);
sb.append(" put:").append(putCount);
sb.append(" remove:").append(removeCount);
sb.append(" clear:").append(clearCount);
sb.append(" evictByIdle:").append(evictByIdle);
sb.append(" evictByTTL:").append(evictByTTL);
sb.append(" evictByLRU:").append(evictByLRU);
sb.append(" evictionRunCount:").append(evictionRunCount);
sb.append(" evictionRunMicros:").append(evictionRunMicros);
sb.append(" evict:").append(evictCount);
return sb.toString();
}
@@ -153,29 +138,15 @@ public class ServerCacheStatistics {
/**
* Set the put insert count.
*/
public void setInsertCount(long insertCount) {
this.insertCount = insertCount;
public void setPutCount(long putCount) {
this.putCount = putCount;
}
/**
* Return the put insert count.
*/
public long getInsertCount() {
return insertCount;
}
/**
* Set the put update count.
*/
public void setUpdateCount(long updateCount) {
this.updateCount = updateCount;
}
/**
* Return the put update count.
*/
public long getUpdateCount() {
return updateCount;
public long getPutCount() {
return putCount;
}
/**
@@ -206,73 +177,18 @@ public class ServerCacheStatistics {
return clearCount;
}
/**
* Set the eviction run count.
*/
public void setEvictionRunCount(long evictCount) {
this.evictionRunCount = evictCount;
}
/**
* Return the eviction run count.
*/
public long getEvictionRunCount() {
return evictionRunCount;
}
/**
* Set the eviction run time in micros.
*/
public void setEvictionRunMicros(long evictionRunMicros) {
this.evictionRunMicros = evictionRunMicros;
}
/**
* Return the eviction run time in micros.
*/
public long getEvictionRunMicros() {
return evictionRunMicros;
}
/**
* Set the count of entries evicted due to idle time.
*/
public void setEvictByIdle(long evictByIdle) {
this.evictByIdle = evictByIdle;
public void setEvictCount(long evictCount) {
this.evictCount = evictCount;
}
/**
* Return the count of entries evicted due to idle time.
*/
public long getEvictByIdle() {
return evictByIdle;
public long getEvictCount() {
return evictCount;
}
/**
* Set the count of entries evicted due to time to live.
*/
public void setEvictByTTL(long evictByTTL) {
this.evictByTTL = evictByTTL;
}
/**
* Return the count of entries evicted due to time to live.
*/
public long getEvictByTTL() {
return evictByTTL;
}
/**
* Set the count of entries evicted due to time least recently used.
*/
public void setEvictByLRU(long evictByLRU) {
this.evictByLRU = evictByLRU;
}
/**
* Return the count of entries evicted due to time least recently used.
*/
public long getEvictByLRU() {
return evictByLRU;
}
}
+1 -1
View File
@@ -25,7 +25,7 @@ public enum ServerCacheType {
*/
QUERY("_Q");
private String code;
private final String code;
ServerCacheType(String code) {
this.code = code;
@@ -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;
@@ -20,7 +20,7 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
protected boolean disableLazyLoad;
/**
* The EbeanServer this is associated with. (used for lazy fetch).
* The Database this is associated with. (used for lazy fetch).
*/
protected transient BeanCollectionLoader loader;
@@ -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();
@@ -219,7 +219,6 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
/**
* Copies all relevant properties for a clone. See {@link #getShallowCopy()}
* @param other
*/
protected void setFromOriginal(AbstractBeanCollection<E> other) {
this.disableLazyLoad = other.disableLazyLoad;
+1 -1
View File
@@ -237,7 +237,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
}
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
@SuppressWarnings({"unchecked"})
public Set<Entry<K, E>> entrySet() {
init();
if (isReadOnly()) {
@@ -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;
}
@@ -1,7 +1,7 @@
package io.ebean.config;
/**
* Used to provide some automatic configuration early in the creation of an EbeanServer.
* Used to provide some automatic configuration early in the creation of a Database.
*/
public interface AutoConfigure {
@@ -1,11 +1,11 @@
package io.ebean.config;
/**
* Defines the AutoTune behaviour for a EbeanServer.
* Defines the AutoTune behaviour for a Database.
*/
public class AutoTuneConfig {
private AutoTuneMode mode = AutoTuneMode.DEFAULT_ON;
private AutoTuneMode mode = AutoTuneMode.DEFAULT_OFF;
private String queryTuningFile = "ebean-autotune.xml";
@@ -3,7 +3,7 @@ package io.ebean.config;
import java.util.Properties;
/**
* Configuration for the container that holds the EbeanServer instances.
* Configuration for the container that holds the Database instances.
* <p>
* Provides configuration for cluster communication (if clustering is used). The cluster communication is
* used to invalidate appropriate parts of the L2 cache across the cluster.
@@ -0,0 +1,44 @@
package io.ebean.config;
import io.ebean.DatabaseFactory;
/**
* The configuration used for creating a Database.
* <p>
* Used to programmatically construct an Database and optionally register it
* with the DB singleton.
* </p>
* <p>
* If you just use DB thout this programmatic configuration Ebean will read
* the application.properties file and take the configuration from there. This usually
* includes searching the class path and automatically registering any entity
* classes and listeners etc.
* </p>
* <pre>{@code
*
* DatabaseConfig config = new DatabaseConfig();
*
* // read the ebean.properties and load
* // those settings into this serverConfig object
* config.loadFromProperties();
*
* // explicitly register the entity beans to avoid classpath scanning
* config.addClass(Customer.class);
* config.addClass(User.class);
*
* Database db = DatabaseFactory.create(config);
*
* }</pre>
*
* <p>
* Note that ServerConfigProvider provides a standard Java ServiceLoader mechanism that can
* be used to apply configuration to the DatabaseConfig.
* </p>
*
* @author emcgreal
* @author rbygrave
* @see DatabaseFactory
*/
public class DatabaseConfig extends ServerConfig {
}
@@ -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.
*/
@@ -5,7 +5,6 @@ import io.ebean.annotation.Platform;
import io.ebean.migration.MigrationConfig;
import io.ebean.migration.MigrationRunner;
import io.ebean.util.StringHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,6 +32,8 @@ public class DbMigrationConfig {
*/
protected String migrationPath = "dbmigration";
protected String migrationInitPath = "dbinit";
/**
* Subdirectory the model xml files go into.
*/
@@ -118,6 +119,15 @@ public class DbMigrationConfig {
this.platform = platform;
}
/**
* Return the path for normal migrations or dbinit migrations.
*
* @param dbinitMigration When true return the path for dbinit migrations.
*/
public String getMigrationPath(boolean dbinitMigration) {
return dbinitMigration ? migrationInitPath : migrationPath;
}
/**
* Return the resource path for db migrations.
*/
@@ -130,7 +140,7 @@ public class DbMigrationConfig {
* <p>
* The default of "dbmigration" is reasonable in most cases. You may look to set this
* to be something like "dbmigration/myapp" where myapp gives it a unique resource path
* in the case there are multiple EbeanServer applications in the single classpath.
* in the case there are multiple Database applications in the single classpath.
* </p>
*/
public void setMigrationPath(String migrationPath) {
@@ -419,6 +429,7 @@ public class DbMigrationConfig {
public void loadSettings(PropertiesWrapper properties, String serverName) {
migrationPath = properties.get("migration.migrationPath", migrationPath);
migrationInitPath = properties.get("migration.migrationInitPath", migrationInitPath);
modelPath = properties.get("migration.modelPath", modelPath);
applyPrefix = properties.get("migration.applyPrefix", applyPrefix);
applySuffix = properties.get("migration.applySuffix", applySuffix);
@@ -472,6 +483,7 @@ public class DbMigrationConfig {
runnerConfig.setMetaTable(metaTable);
runnerConfig.setApplySuffix(applySuffix);
runnerConfig.setMigrationPath(migrationPath);
runnerConfig.setMigrationInitPath(migrationInitPath);
runnerConfig.setRunPlaceholderMap(runPlaceholderMap);
runnerConfig.setRunPlaceholders(runPlaceholders);
runnerConfig.setDbUsername(getDbUsername());
@@ -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
*/
@@ -5,6 +5,22 @@ package io.ebean.config;
*/
public abstract class JsonConfig {
/**
* Defined the format used for Date types.
*/
public enum Date {
/**
* Format as epoch millis.
*/
MILLIS,
/**
* Format as ISO-8601 date format.
*/
ISO8601
}
/**
* Defined the format used for DateTime types.
*/
@@ -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).
*/
@@ -47,6 +54,13 @@ public class PlatformConfig {
*/
private DbUuid dbUuid = DbUuid.AUTO_VARCHAR;
/**
* Set to true to force InetAddress to map to Varchar (for Postgres rather than INET)
*/
private boolean databaseInetAddressVarchar;
private boolean caseSensitiveCollation = true;
/**
* Modify the default mapping of standard types such as default precision for DECIMAL etc.
*/
@@ -56,7 +70,7 @@ public class PlatformConfig {
* Construct with defaults.
*/
public PlatformConfig() {
this.constraintNaming = new DbConstraintNaming();
}
/**
@@ -69,6 +83,23 @@ public class PlatformConfig {
this.idType = platformConfig.idType;
this.geometrySRID = platformConfig.geometrySRID;
this.dbUuid = platformConfig.dbUuid;
this.caseSensitiveCollation = platformConfig.caseSensitiveCollation;
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;
}
/**
@@ -83,6 +114,23 @@ public class PlatformConfig {
*/
public void setAllQuotedIdentifiers(boolean allQuotedIdentifiers) {
this.allQuotedIdentifiers = allQuotedIdentifiers;
if (!customConstraintNaming) {
this.constraintNaming = new DbConstraintNaming(!allQuotedIdentifiers);
}
}
/**
* Return true if the collation is case sensitive.
*/
public boolean isCaseSensitiveCollation() {
return caseSensitiveCollation;
}
/**
* Set to false to indicate that the collation is case insensitive.
*/
public void setCaseSensitiveCollation(boolean caseSensitiveCollation) {
this.caseSensitiveCollation = caseSensitiveCollation;
}
/**
@@ -181,6 +229,20 @@ public class PlatformConfig {
this.idType = idType;
}
/**
* Return true if InetAddress should map to varchar column (rather than Postgres INET).
*/
public boolean isDatabaseInetAddressVarchar() {
return databaseInetAddressVarchar;
}
/**
* Set to true to force InetAddress to map to varchar column.
*/
public void setDatabaseInetAddressVarchar(boolean databaseInetAddressVarchar) {
this.databaseInetAddressVarchar = databaseInetAddressVarchar;
}
/**
* Add a custom type mapping.
* <p>
@@ -235,6 +297,8 @@ public class PlatformConfig {
databaseSequenceBatchSize = p.getInt("databaseSequenceBatchSize", databaseSequenceBatchSize);
databaseBooleanTrue = p.get("databaseBooleanTrue", databaseBooleanTrue);
databaseBooleanFalse = p.get("databaseBooleanFalse", databaseBooleanFalse);
databaseInetAddressVarchar = p.getBoolean("databaseInetAddressVarchar", databaseInetAddressVarchar);
caseSensitiveCollation = p.getBoolean("caseSensitiveCollation", caseSensitiveCollation);
DbUuid dbUuid = p.getEnum(DbUuid.class, "dbuuid", null);
if (dbUuid != null) {
+306 -235
View File
@@ -1,7 +1,8 @@
package io.ebean.config;
import com.fasterxml.jackson.core.JsonFactory;
import io.ebean.EbeanServerFactory;
import io.avaje.config.Config;
import io.ebean.DatabaseFactory;
import io.ebean.PersistenceContextScope;
import io.ebean.Query;
import io.ebean.Transaction;
@@ -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,10 +28,10 @@ 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;
import javax.persistence.EnumType;
import javax.sql.DataSource;
import java.time.Clock;
import java.util.ArrayList;
@@ -44,30 +44,32 @@ import java.util.Properties;
import java.util.ServiceLoader;
/**
* The configuration used for creating a EbeanServer.
* Deprecated - please migrate to <code>io.ebean.DatabaseConfig</code>.
*
* The configuration used for creating a Database.
* <p>
* Used to programmatically construct an EbeanServer and optionally register it
* with the Ebean singleton.
* Used to programmatically construct a Database and optionally register it
* with the DB singleton.
* </p>
* <p>
* If you just use Ebean without this programmatic configuration Ebean will read
* the ebean.properties file and take the configuration from there. This usually
* If you just use DB without this programmatic configuration DB will read
* the application.properties file and take the configuration from there. This usually
* includes searching the class path and automatically registering any entity
* classes and listeners etc.
* </p>
* <pre>{@code
*
* ServerConfig c = new ServerConfig();
* ServerConfig config = new ServerConfig();
*
* // read the ebean.properties and load
* // those settings into this serverConfig object
* c.loadFromProperties();
* config.loadFromProperties();
*
* // explicitly register the entity beans to avoid classpath scanning
* c.addClass(Customer.class);
* c.addClass(User.class);
* config.addClass(Customer.class);
* config.addClass(User.class);
*
* EbeanServer server = EbeanServerFactory.create(c);
* Database database = DatabaseFactory.create(config);
*
* }</pre>
*
@@ -78,12 +80,13 @@ import java.util.ServiceLoader;
*
* @author emcgreal
* @author rbygrave
* @see EbeanServerFactory
* @see DatabaseFactory
*/
@Deprecated
public class ServerConfig {
/**
* The EbeanServer name.
* The Database name.
*/
private String name = "db";
@@ -106,12 +109,12 @@ public class ServerConfig {
private String resourceDirectory;
/**
* Set to true to register this EbeanServer with the Ebean singleton.
* Set to true to register this Database with the DB singleton.
*/
private boolean register = true;
/**
* Set to true if this is the default/primary server.
* Set to true if this is the default/primary database.
*/
private boolean defaultServer = true;
@@ -132,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.
@@ -150,7 +162,7 @@ public class ServerConfig {
private DocStoreConfig docStoreConfig = new DocStoreConfig();
/**
* Set to true when the EbeanServer only uses Document store.
* Set to true when the Database only uses Document store.
*/
private boolean docStoreOnly;
@@ -168,7 +180,12 @@ public class ServerConfig {
/**
* The JSON format used for DateTime types. Default to millis.
*/
private JsonConfig.DateTime jsonDateTime = JsonConfig.DateTime.MILLIS;
private JsonConfig.DateTime jsonDateTime = JsonConfig.DateTime.ISO8601;
/**
* The JSON format used for Date types. Default to millis.
*/
private JsonConfig.Date jsonDate = JsonConfig.Date.ISO8601;
/**
* For writing JSON specify if null values or empty collections should be exluded.
@@ -229,6 +246,8 @@ public class ServerConfig {
private int persistBatchSize = 20;
private EnumType defaultEnumType = EnumType.ORDINAL;
private boolean disableLazyLoading;
/**
@@ -252,6 +271,8 @@ public class ServerConfig {
private boolean ddlRun;
private boolean ddlExtra = true;
private boolean ddlCreateOnly;
private String ddlInitSql;
@@ -313,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.
*/
@@ -335,25 +344,10 @@ public class ServerConfig {
*/
private NamingConvention namingConvention = new UnderscoreNamingConvention();
/**
* Naming convention used in DDL generation for primary keys, foreign keys etc.
*/
private DbConstraintNaming constraintNaming = new DbConstraintNaming();
/**
* Behaviour of update to include on the change properties.
*/
private boolean updateChangesOnly = true;
/**
* Behaviour of updates in JDBC batch to by default include all properties.
*/
private boolean updateAllPropertiesInBatch = true;
/**
* Default behaviour for updates when cascade save on a O2M or M2M to delete any missing children.
*/
private boolean updatesDeleteMissingChildren = true;
private boolean updateAllPropertiesInBatch;
/**
* Database platform configuration.
@@ -366,9 +360,10 @@ public class ServerConfig {
private UuidVersion uuidVersion = UuidVersion.VERSION4;
/**
* The UUID state file (for Version 1 UUIDs).
* The UUID state file (for Version 1 UUIDs). By default, the file is created in
* ${HOME}/.ebean/${servername}-uuid.state
*/
private String uuidStateFile = "ebean-uuid.state";
private String uuidStateFile;
/**
* The clock used for setting the timestamps (e.g. @UpdatedTimestamp) on objects.
@@ -414,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.
*/
@@ -473,6 +464,12 @@ public class ServerConfig {
*/
private boolean disableL2Cache;
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.
@@ -486,6 +483,16 @@ public class ServerConfig {
*/
private boolean notifyL2CacheInForeground;
/**
* Set to true to support query plan capture.
*/
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.
*/
@@ -501,7 +508,7 @@ public class ServerConfig {
/**
* Controls the default order by id setting of queries. See {@link Query#orderById(boolean)}
*/
private boolean defaultOrderById = false;
private boolean defaultOrderById;
/**
* The mappingLocations for searching xml mapping.
@@ -513,8 +520,12 @@ public class ServerConfig {
*/
private boolean idGeneratorAutomatic = true;
private boolean dumpMetricsOnShutdown;
private String dumpMetricsOptions;
/**
* Construct a Server Configuration for programmatically creating an EbeanServer.
* Construct a Database Configuration for programmatically creating an Database.
*/
public ServerConfig() {
@@ -564,8 +575,9 @@ public class ServerConfig {
/**
* Sets the default orderById setting for queries.
* Deprecated - look to have explicit order by. Sets the default orderById setting for queries.
*/
@Deprecated
public void setDefaultOrderById(boolean defaultOrderById) {
this.defaultOrderById = defaultOrderById;
}
@@ -594,6 +606,48 @@ public class ServerConfig {
return serviceObject.get(key);
}
/**
* Put a service object into configuration such that it can be passed to a plugin.
*
* <pre>{@code
*
* JedisPool jedisPool = ..
*
* serverConfig.putServiceObject(jedisPool);
*
* }</pre>
*/
public void putServiceObject(Object configObject) {
String key = serviceObjectKey(configObject);
serviceObject.put(key, configObject);
}
private String serviceObjectKey(Object configObject) {
return serviceObjectKey(configObject.getClass());
}
private String serviceObjectKey(Class<?> cls) {
String simpleName = cls.getSimpleName();
return Character.toLowerCase(simpleName.charAt(0)) + simpleName.substring(1);
}
/**
* Used by plugins to obtain service objects.
*
* <pre>{@code
*
* JedisPool jedisPool = serverConfig.getServiceObject(JedisPool.class);
*
* }</pre>
*
* @param cls The type of the service object to obtain
* @return The service object given the class type
*/
@SuppressWarnings("unchecked")
public <P> P getServiceObject(Class<P> cls) {
return (P) serviceObject.get(serviceObjectKey(cls));
}
/**
* Return the Jackson JsonFactory to use.
* <p>
@@ -626,6 +680,20 @@ public class ServerConfig {
this.jsonDateTime = jsonDateTime;
}
/**
* Return the JSON format used for Date types.
*/
public JsonConfig.Date getJsonDate() {
return jsonDate;
}
/**
* Set the JSON format to use for Date types.
*/
public void setJsonDate(JsonConfig.Date jsonDate) {
this.jsonDate = jsonDate;
}
/**
* Return the JSON include mode used when writing JSON.
*/
@@ -644,14 +712,14 @@ public class ServerConfig {
}
/**
* Return the name of the EbeanServer.
* Return the name of the Database.
*/
public String getName() {
return name;
}
/**
* Set the name of the EbeanServer.
* Set the name of the Database.
*/
public void setName(String name) {
this.name = name;
@@ -660,8 +728,8 @@ public class ServerConfig {
/**
* Return the container / clustering configuration.
* <p/>
* The container holds all the EbeanServer instances and provides clustering communication
* services to all the EbeanServer instances.
* The container holds all the Database instances and provides clustering communication
* services to all the Database instances.
*/
public ContainerConfig getContainerConfig() {
return containerConfig;
@@ -670,8 +738,8 @@ public class ServerConfig {
/**
* Set the container / clustering configuration.
* <p/>
* The container holds all the EbeanServer instances and provides clustering communication
* services to all the EbeanServer instances.
* The container holds all the Database instances and provides clustering communication
* services to all the Database instances.
*/
public void setContainerConfig(ContainerConfig containerConfig) {
this.containerConfig = containerConfig;
@@ -711,8 +779,8 @@ public class ServerConfig {
}
/**
* Set false if you do not want this EbeanServer to be registered as the "default" server
* with the Ebean singleton.
* Set false if you do not want this Database to be registered as the "default" database
* with the DB singleton.
* <p>
* This is only used when {@link #setRegister(boolean)} is also true.
* </p>
@@ -929,6 +997,14 @@ public class ServerConfig {
this.queryBatchSize = queryBatchSize;
}
public EnumType getDefaultEnumType() {
return defaultEnumType;
}
public void setDefaultEnumType(EnumType defaultEnumType) {
this.defaultEnumType = defaultEnumType;
}
/**
* Return true if lazy loading is disabled on queries by default.
*/
@@ -1498,14 +1574,14 @@ public class ServerConfig {
}
/**
* Return true if this EbeanServer is a Document store only instance (has no JDBC DB).
* Return true if this Database is a Document store only instance (has no JDBC DB).
*/
public boolean isDocStoreOnly() {
return docStoreOnly;
}
/**
* Set to true if this EbeanServer is Document store only instance (has no JDBC DB).
* Set to true if this Database is Document store only instance (has no JDBC DB).
*/
public void setDocStoreOnly(boolean docStoreOnly) {
this.docStoreOnly = docStoreOnly;
@@ -1529,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);
}
/**
@@ -1660,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>
@@ -1806,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;
@@ -1905,16 +1945,16 @@ public class ServerConfig {
}
/**
* Return true if the EbeanServer instance should be created in offline mode.
* Return true if the Database instance should be created in offline mode.
*/
public boolean isDbOffline() {
return dbOffline;
}
/**
* Set to true if the EbeanServer instance should be created in offline mode.
* Set to true if the Database instance should be created in offline mode.
* <p>
* Typically used to create an EbeanServer instance for DDL Migration generation
* Typically used to create an Database instance for DDL Migration generation
* without requiring a real DataSource / Database to connect to.
* </p>
*/
@@ -2069,6 +2109,16 @@ public class ServerConfig {
this.ddlRun = ddlRun;
}
/**
* Set to false if you not want to run the extra-ddl.xml scripts. (default = true)
* <p>
* Typically we want this on when we are running tests.
*/
public void setDdlExtra(boolean ddlExtra) {
this.ddlExtra = ddlExtra;
}
/**
* Return true if the "drop all ddl" should be skipped.
* <p>
@@ -2139,6 +2189,13 @@ public class ServerConfig {
return ddlRun;
}
/**
* Return true, if extra-ddl.xml should be executed.
*/
public boolean isDdlExtra() {
return ddlExtra;
}
/**
* Return true if the class path search should be disabled.
*/
@@ -2148,7 +2205,7 @@ public class ServerConfig {
/**
* Set to true to disable the class path search even for the case where no entity bean classes
* have been registered. This can be used to start an EbeanServer instance just to use the
* have been registered. This can be used to start an Database instance just to use the
* SQL functions such as SqlQuery, SqlUpdate etc.
*/
public void setDisableClasspathSearch(boolean disableClasspathSearch) {
@@ -2185,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>
@@ -2201,9 +2264,6 @@ public class ServerConfig {
* </p>
*/
public void addPackage(String packageName) {
if (packages == null) {
packages = new ArrayList<>();
}
packages.add(packageName);
}
@@ -2229,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.
@@ -2243,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() {
@@ -2262,8 +2322,7 @@ public class ServerConfig {
*
* // assume Customer has L2 bean caching enabled ...
*
* Transaction transaction = Ebean.beginTransaction();
* try {
* try (Transaction transaction = DB.beginTransaction()) {
*
* // this uses L2 bean cache as the transaction
* // ... is considered "query only" at this point
@@ -2271,7 +2330,7 @@ public class ServerConfig {
*
* // transaction no longer "query only" once
* // ... a bean has been saved etc
* Ebean.save(someBean);
* DB.save(someBean);
*
* // will NOT use L2 bean cache as the transaction
* // ... is no longer considered "query only"
@@ -2290,9 +2349,6 @@ public class ServerConfig {
* transaction.setSkipCache(true);
* Customer.find.byId(99); // skips l2 bean cache
*
*
* } finally {
* transaction.end();
* }
*
* }</pre>
@@ -2310,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.
*/
@@ -2343,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 the ebeanServer should collection query statistics 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.
*/
@@ -2726,7 +2706,7 @@ public class ServerConfig {
* Load settings from ebean.properties.
*/
public void loadFromProperties() {
this.properties = PropertiesLoader.load();
this.properties = Config.asProperties();
configureFromProperties();
}
@@ -2735,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();
}
@@ -2763,20 +2743,6 @@ public class ServerConfig {
return list;
}
/**
* Deprecated - this does nothing now, we always try to read test configuration.
* <p>
* Load settings from test-ebean.properties and do nothing if the properties is not found.
* <p>
* This is typically used when test-ebean.properties is put into the test class path and used
* to configure Ebean for running tests.
* </p>
*/
@Deprecated
public void loadTestProperties() {
// do nothing now ... as we always try to read test configuration and that should only
}
/**
* Return the properties that we used for configuration and were set via a call to loadFromProperties().
*/
@@ -2793,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");
}
/**
@@ -2844,13 +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);
@@ -2871,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'");
@@ -2914,20 +2879,18 @@ public class ServerConfig {
localTimeWithNanos = p.getBoolean("localTimeWithNanos", localTimeWithNanos);
jodaLocalTimeMode = p.get("jodaLocalTimeMode", jodaLocalTimeMode);
defaultEnumType = p.getEnum(EnumType.class, "defaultEnumType", defaultEnumType);
disableLazyLoading = p.getBoolean("disableLazyLoading", disableLazyLoading);
lazyLoadBatchSize = p.getInt("lazyLoadBatchSize", lazyLoadBatchSize);
queryBatchSize = p.getInt("queryBatchSize", queryBatchSize);
jsonInclude = p.getEnum(JsonConfig.Include.class, "jsonInclude", jsonInclude);
String jsonDateTimeFormat = p.get("jsonDateTime", null);
if (jsonDateTimeFormat != null) {
jsonDateTime = JsonConfig.DateTime.valueOf(jsonDateTimeFormat);
} else {
jsonDateTime = JsonConfig.DateTime.MILLIS;
}
jsonDateTime = p.getEnum(JsonConfig.DateTime.class, "jsonDateTime", jsonDateTime);
jsonDate = p.getEnum(JsonConfig.Date.class, "jsonDate", jsonDate);
ddlGenerate = p.getBoolean("ddl.generate", ddlGenerate);
ddlRun = p.getBoolean("ddl.run", ddlRun);
ddlExtra = p.getBoolean("ddl.extra", ddlExtra);
ddlCreateOnly = p.getBoolean("ddl.createOnly", ddlCreateOnly);
ddlInitSql = p.get("ddl.initSql", ddlInitSql);
ddlSeedSql = p.get("ddl.seedSql", ddlSeedSql);
@@ -2972,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) {
@@ -3068,6 +3031,20 @@ public class ServerConfig {
this.expressionNativeIlike = expressionNativeIlike;
}
/**
* Return the enabled L2 cache regions.
*/
public String getEnabledL2Regions() {
return enabledL2Regions;
}
/**
* Set the enabled L2 cache regions (comma delimited).
*/
public void setEnabledL2Regions(String enabledL2Regions) {
this.enabledL2Regions = enabledL2Regions;
}
/**
* Return true if L2 cache is disabled.
*/
@@ -3082,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
*/
@@ -3211,6 +3202,86 @@ public class ServerConfig {
this.idGeneratorAutomatic = idGeneratorAutomatic;
}
/**
* Return true if query plan capture is enabled.
*/
public boolean isCollectQueryPlans() {
return collectQueryPlans;
}
/**
* Set to true to enable query plan capture.
*/
public void setCollectQueryPlans(boolean collectQueryPlans) {
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.
*/
public boolean isDumpMetricsOnShutdown() {
return dumpMetricsOnShutdown;
}
/**
* Set to true if metrics should be dumped when the server is shutdown.
*/
public void setDumpMetricsOnShutdown(boolean dumpMetricsOnShutdown) {
this.dumpMetricsOnShutdown = dumpMetricsOnShutdown;
}
/**
* Return the options for dumping metrics.
*/
public String getDumpMetricsOptions() {
return dumpMetricsOptions;
}
/**
* Include 'sql' or 'hash' in options such that they are included in the output.
*
* @param dumpMetricsOptions Example "sql,hash", "sql"
*/
public void setDumpMetricsOptions(String dumpMetricsOptions) {
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,
@@ -35,9 +35,9 @@ public enum TenantMode {
* (that holds configuration e.g.)
*/
DB_WITH_MASTER(true, true);
boolean dynamicDataSource;
boolean ddlEnabled;
final boolean dynamicDataSource;
final boolean ddlEnabled;
TenantMode(boolean dynamicDataSource, boolean ddlEnabled) {
this.dynamicDataSource = dynamicDataSource;
@@ -50,12 +50,12 @@ public enum TenantMode {
public boolean isDynamicDataSource() {
return dynamicDataSource;
}
/**
* Returns true, if DDL is enabled.
*/
public boolean isDdlEnabled() {
return ddlEnabled;
}
}
@@ -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
}
@@ -49,6 +49,10 @@ public class DatabasePlatform {
*/
protected boolean useExtraTransactionOnIterateSecondaryQueries;
protected boolean supportsDeleteTableAlias;
protected boolean supportsSavepointId = true;
/**
* The behaviour used when ending a read only transaction at read committed isolation level.
*/
@@ -69,6 +73,13 @@ public class DatabasePlatform {
*/
protected boolean allQuotedIdentifiers;
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.
*/
@@ -133,9 +144,9 @@ public class DatabasePlatform {
*/
protected Platform platform = Platform.GENERIC;
protected String columnAliasPrefix = "c";
protected String truncateTable = "truncate table %s";
protected String tableAliasPlaceHolder = "${ta}";
protected String columnAliasPrefix;
/**
* Use a BackTick ` at the beginning and end of table or column names that you
@@ -163,23 +174,24 @@ 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
* findIterate() and findVisit().
*/
protected boolean forwardOnlyHintOnFindIterate;
/**
* If set then use the CONCUR_UPDATABLE hint when creating ResultSets.
*
* <p>
* This is {@code false} for HANA
*/
protected boolean supportsResultSetConcurrencyModeUpdatable = true;
@@ -224,6 +236,7 @@ public class DatabasePlatform {
*/
public void configure(PlatformConfig config) {
this.sequenceBatchSize = config.getDatabaseSequenceBatchSize();
this.caseSensitiveCollation = config.isCaseSensitiveCollation();
configureIdType(config.getIdType());
configure(config, config.isAllQuotedIdentifiers());
}
@@ -265,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;
}
/**
@@ -306,6 +319,37 @@ public class DatabasePlatform {
return supportsNativeIlike;
}
/**
* Return true if the platform supports delete statements with table alias.
*/
public boolean isSupportsDeleteTableAlias() {
return supportsDeleteTableAlias;
}
/**
* Return true if the collation is case sensitive.
* <p>
* This is expected to be used for testing only.
* </p>
*/
public boolean isCaseSensitiveCollation() {
return caseSensitiveCollation;
}
/**
* Return true if the platform supports SavepointId values.
*/
public boolean isSupportsSavepointId() {
return supportsSavepointId;
}
/**
* Return true if the platform supports LIMIT with sql update.
*/
public boolean isInlineSqlUpdateLimit() {
return inlineSqlUpdateLimit;
}
/**
* Return the maximum table name length.
* <p>
@@ -337,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;
@@ -433,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.
*/
@@ -524,7 +554,7 @@ public class DatabasePlatform {
public void setForwardOnlyHintOnFindIterate(boolean forwardOnlyHintOnFindIterate) {
this.forwardOnlyHintOnFindIterate = forwardOnlyHintOnFindIterate;
}
/**
* Return true if the ResultSet CONCUR_UPDATABLE Hint should be used on
* createNativeSqlTree() PreparedStatements.
@@ -535,7 +565,7 @@ public class DatabasePlatform {
public boolean isSupportsResultSetConcurrencyModeUpdatable() {
return supportsResultSetConcurrencyModeUpdatable;
}
/**
* Set to true if the ResultSet CONCUR_UPDATABLE Hint should be used by default on createNativeSqlTree() PreparedStatements.
*/
@@ -546,7 +576,7 @@ public class DatabasePlatform {
/**
* Normally not needed - overridden in CockroachPlatform.
*/
public boolean isDdlCommitOnCreateIndex() {
public boolean isDdlAutoCommit() {
return false;
}
@@ -626,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;
@@ -639,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());
@@ -677,6 +715,13 @@ public class DatabasePlatform {
return persistBatchOnCascade;
}
/**
* Return a statement to truncate a table.
*/
public String truncateStatement(String table) {
return String.format(truncateTable, table);
}
/**
* Create the DB schema if it does not exist.
*/
@@ -746,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));
@@ -27,15 +27,13 @@ public class DbDefaultValue {
* The key for the NOW / current timestamp.
*/
public static final String NOW = "now";
/**
* The 'null' literal.
*/
public static final String NULL = "null";
protected Map<String, String> map = new LinkedHashMap<>();
protected final Map<String, String> map = new LinkedHashMap<>();
/**
* Set the DB now function.
@@ -82,10 +80,9 @@ public class DbDefaultValue {
return val != null ? val : dbDefaultLiteral;
}
/**
* This method checks & convert the {@link DbDefault#value()} to a valid SQL literal.
*
*
* This is mainly to quote string literals and verify integer/dates for correctness.
* <p>
* Note: There are some special cases:
@@ -98,24 +95,24 @@ public class DbDefaultValue {
* If you need really the String "null", you have to specify <code>@DbDefault("'null'")</code>
* which gives you the <code>default 'null'</code> statement.</li>
* <li>Any statement, that begins and ends with single quote will not be checked or get quoted again.</li>
* <li>A statement that begins with "$RAW:", e.g <code>@DbDefault("$RAW:N'SANDNES'")</code> will lead to
* <li>A statement that begins with "$RAW:", e.g <code>@DbDefault("$RAW:N'SANDNES'")</code> will lead to
* a <code>default N'SANDNES'</code> in DDL. Note that this is platform specific!</li>
* </ul>
*/
public static String toSqlLiteral(String defaultValue, Class<?> propertyType, int sqlType) {
if (propertyType == null
|| defaultValue == null
|| defaultValue == null
|| NULL.equals(defaultValue)
|| (defaultValue.startsWith("'") && defaultValue.endsWith("'"))
|| (defaultValue.startsWith("$RAW:"))) {
|| (defaultValue.startsWith("$RAW:"))) {
return defaultValue;
}
if (Boolean.class.isAssignableFrom(propertyType) || Boolean.TYPE.isAssignableFrom(propertyType)) {
return toBooleanLiteral(defaultValue);
}
if (Number.class.isAssignableFrom(propertyType)
if (Number.class.isAssignableFrom(propertyType)
|| Byte.TYPE.equals(propertyType)
|| Short.TYPE.equals(propertyType)
|| Integer.TYPE.equals(propertyType)
@@ -126,7 +123,7 @@ public class DbDefaultValue {
Double.valueOf(defaultValue); // verify if it is a number
return defaultValue;
}
// check if it is a date/time - in all other cases return quoted defaultValue
switch (sqlType) {
// date
@@ -155,7 +152,7 @@ public class DbDefaultValue {
}
throw new IllegalArgumentException("'" + value + "' is not a valid value for boolean");
}
/**
* This adds single qoutes around the <code>value</code> and doubles single quotes.
* "User's home" will return "'User''s home'"
@@ -175,7 +172,7 @@ public class DbDefaultValue {
return sb.toString();
}
private static String toDateLiteral(String value) {
if (NOW.equals(value)) {
return value; // this will get translated later
@@ -191,7 +188,7 @@ public class DbDefaultValue {
DatatypeConverter.parseTime(value); // verify
return toTextLiteral(value);
}
private static String toDateTimeLiteral(String value) {
if (NOW.equals(value)) {
return value; // this will get translated later
@@ -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();
@@ -11,12 +11,12 @@ class DbPlatformTypeLookup {
/**
* A map to lookup the type by name.
*/
private Map<String, DbType> nameLookup = new HashMap<>();
private final Map<String, DbType> nameLookup = new HashMap<>();
/**
* A map to lookup the type by JDBC int value.
*/
private Map<Integer, DbType> idLookup = new HashMap<>();
private final Map<Integer, DbType> idLookup = new HashMap<>();
DbPlatformTypeLookup() {
addAll();
@@ -23,10 +23,15 @@ public class DbPlatformTypeMapping {
}
}
private static DbPlatformTypeLookup lookup = new DbPlatformTypeLookup();
private static final DbPlatformTypeLookup lookup = new DbPlatformTypeLookup();
private static final DbPlatformType BOOLEAN_LOGICAL = new BooleanLogicalType();
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")
private static final DbPlatformType UUID_PLACEHOLDER = new DbPlatformType("uuidPlaceholder");
@@ -106,10 +111,12 @@ public class DbPlatformTypeMapping {
put(DbType.JSONBLOB, new DbPlatformType("jsonblob"));
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));
@@ -121,6 +128,8 @@ public class DbPlatformTypeMapping {
put(DbType.JSONVARCHAR, JSON_VARCHAR_PLACEHOLDER);
// default to native UUID and override on platform configure()
put(DbType.UUID, UUID_NATIVE);
put(DbType.INET, INET_VARCHAR);
put(DbType.CIDR, CIDR_VARCHAR);
}
}
@@ -35,6 +35,8 @@ public enum DbType {
ARRAY(Types.ARRAY),
UUID(ExtraDbTypes.UUID),
INET(ExtraDbTypes.INET),
CIDR(ExtraDbTypes.CIDR),
POINT(ExtraDbTypes.POINT),
POLYGON(ExtraDbTypes.POLYGON),
@@ -40,6 +40,9 @@ public interface ExtraDbTypes {
*/
int JSONBlob = 5005;
int INET = 5020;
int CIDR = 5021;
/**
* Geo Point
*/

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