Compare commits

...
119 Commits
Author SHA1 Message Date
Rob Bygrave e2731a99be [maven-release-plugin] prepare release ebean-9.4.1 2016-12-06 23:44:26 +13:00
Rob Bygrave 7d56df3b23 Bump pom to 9.4.1-SNAPSHOT 2016-12-06 23:43:37 +13:00
Rob Bygrave bebef48332 Update test ebean.properties 2016-12-03 22:03:55 +13:00
Rob Bygrave f66ea12fbf #912 - Refactor - move platform specfic code into subpackages 2016-12-03 15:39:24 +13:00
Rob Bygrave b08f1580f9 #910 - SQL Server update - Add ANSI based row limiter (2012+) and make as default platform 2016-12-03 15:10:11 +13:00
Rob Bygrave 707912f7ad No effective change - add some wait into history test (TestHistoryInsert) 2016-12-03 13:55:45 +13:00
Rob Bygrave 5ce31b16d4 #910 - SQL Server update - refactor rename platform to SqlServerPlatform 2016-12-03 13:30:17 +13:00
Rob Bygrave a5945b1d5d #911 - SQL Server - remove old MsSqlServer2000Platform (expecting users migrated to SQL Server 2005+) 2016-12-03 13:24:52 +13:00
Rob Bygrave b8577ae6d0 #910 - SQL Server update - tidy whitespace for MsSqlServer2005SqlLimiter 2016-12-03 13:19:15 +13:00
Rob Bygrave 14dedb7b9a #910 - SQL Server update 2016-12-03 13:18:33 +13:00
Rob Bygrave 2dbd543127 #909 - @Lob with @Size ... produces incorrect DDL for Postgres 2016-12-03 08:42:46 +13:00
Rob Bygrave cc989af1c6 #908 - Remove support for Immutable Compound Values 2016-12-02 22:49:00 +13:00
Rob Bygrave 0aad285f35 #907 - Remove Model.Finder ... migrate to Finder 2016-12-02 21:47:30 +13:00
Rob Bygrave a3754e31f2 #906 - Add NamingConvention Support for JoinColumn (OneToMany, ManyToOne) - was PR #887 2016-12-02 21:21:19 +13:00
Rob Bygrave 1dd0f3f609 [maven-release-plugin] prepare for next development iteration 2016-12-01 21:04:18 +13:00
Rob Bygrave f9b381b10a [maven-release-plugin] prepare release ebean-9.3.1 2016-12-01 21:04:09 +13:00
Rob Bygrave 6e2d7a89f8 #493 - ENH: Multi-tenant support - update bootup DataSource check 2016-12-01 21:02:52 +13:00
Rob Bygrave dfa336239f #493 - ENH: Multi-tenant support - update bootup DataSource check 2016-12-01 20:43:47 +13:00
Rob Bygrave 3a28dd0d55 #493 - ENH: Multi-tenant support - nice error when explicit DatabasePlatform not set, turn off DDL run automatically 2016-12-01 20:23:42 +13:00
Rob Bygrave 502e9daaf2 #493 - ENH: Multi-tenant support - cache tidy up 2016-12-01 00:27:32 +13:00
Rob Bygrave b7c92aec3d No effective change - rename var 2016-11-30 23:09:31 +13:00
Rob Bygrave c0341458c3 #493 - ENH: Multi-tenant support 2016-11-29 01:34:45 +13:00
Rob Bygrave aecac211d9 pom bump ebean-annotation to 1.4 2016-11-28 22:55:57 +13:00
Rob Bygrave c46b235eff #904 - ENH: Add @PreSoftDelete @PostSoftDelete ... such that methods on beans can be used for these callbacks 2016-11-28 22:24:17 +13:00
Rob Bygrave a585447dc9 #903 - Refactor: Internals, BeanPropertyAccess getter and setter methods can be cached and don't need constructor 2016-11-28 22:02:45 +13:00
Rob Bygrave 85bb05d90e Bump ebean-annotation to 1.4-SNAPSHOT 2016-11-28 21:51:37 +13:00
Rob Bygrave 027dd1eba9 #899 - @Unmapped JSON, handle wildcard use (Kotlin Any) 2016-11-28 21:29:16 +13:00
Rob Bygrave 588d5c5cfa #902 - EJsonWriter.write(Object object, Writer writer) ... closes the writer but should not 2016-11-28 21:27:14 +13:00
Rob Bygrave 7ba86f7cf2 #901 - ENH: Use "db" as default EbeanServer name 2016-11-26 00:54:11 +13:00
Rob Bygrave 609dc233a8 #899 - ENH: Add @UnmappedJson support ... (mostly for document store only use / ElasticSearch) 2016-11-25 23:58:55 +13:00
Rob Bygrave 5d7c287821 Bump pom to 9.3.1-SNAPSHOT 2016-11-25 21:18:35 +13:00
Rob Bygrave ff325057c4 #882 - ENH: Support document store only - Add Query.setDocIndexName() 2016-11-25 21:18:16 +13:00
Rob Bygrave cc6469851b #897 - Remove @EmbeddedColumns ... replace with @Embedded(prefix="...") 2016-11-24 22:05:27 +13:00
Rob Bygrave 7f31104439 #827 - ENH: Add support for AttributeConverter from JPA 2.1 2016-11-24 20:21:48 +13:00
Rob Bygrave 2ab98a922d #896 - Bump persistence API 2.1.2 with @Repeatable annotations (most notably, @AttributeOverride and @JoinColumn) 2016-11-24 19:47:08 +13:00
Rob Bygrave 063c1825ca #895 - Refactor: Remove unnecessary coalesce on soft delete (as predicate on left join etc) 2016-11-24 17:19:46 +13:00
Rob Bygrave d0e9c6a218 No effective change - explicit import required 2016-11-24 02:22:23 +13:00
Rob Bygrave 81d829f74e #894 - ENH: Add support for @OneToMany orphanRemoval = true (which is the same as @PrivateOwned) 2016-11-24 02:21:54 +13:00
Rob Bygrave b4a0d9f5ea #893 - Move to persistence API version 2.1.1 2016-11-24 02:17:54 +13:00
Rob Bygrave f0044aba91 #892 - Refactor: Replace Ebean's QueryEachWhileConsumer with java.util.function.Predicate 2016-11-24 00:19:16 +13:00
Rob Bygrave 6f322dcfb2 #891 - Refactor: Replace Ebean's QueryEachConsumer with java.util.function.Consumer 2016-11-24 00:02:23 +13:00
Rob Bygrave a391a25b7f No effective change - update Javadoc on QueryIterator with try with resources 2016-11-23 23:44:54 +13:00
Rob Bygrave 4af350bd14 No effective change - modify one of the QueryIterator tests to use try with resources 2016-11-23 23:40:57 +13:00
Rob Bygrave cdb319f0ef #885 - DbMigrationConfig.loadSettings config has wrong 2016-11-23 23:30:23 +13:00
Rob Bygrave 60ed64cb37 #883 Soft-delete when using fetch (not including soft deleted children) 2016-11-23 23:12:37 +13:00
Rob Bygrave 79efe006ec #888 - Move annotations - remove types that are now in ebean-annotation 2016-11-23 22:05:05 +13:00
Rob Bygrave 70f929949d #888 - Move annotations - bump dependency to ebean-annotation 1.1 (released) 2016-11-23 21:58:17 +13:00
Rob Bygrave d7916eb3ee #888 - Move Ebean annotations into a separate module (initial remove) 2016-11-23 20:36:00 +13:00
Rob Bygrave f724982776 #889 - Refactor: Change @Where @Formula to use Platform (enum) rather than DatabasePlatform (class) 2016-11-23 20:33:35 +13:00
Rob Bygrave 182a47697e #882 - ENH: Support document store only use (ie. Use @DocStore without @Entity and persist, fetch only against ElasticSearch with no SQL DB) 2016-11-21 00:17:28 +13:00
Rob Bygrave d6b37bdf83 No effective change - format only 2016-11-21 00:00:00 +13:00
Rob BygraveandGitHub 0bc2dc7d4c Merge pull request #847 from FOCONIS/feature/platform-dependent-annotations
platform dependent @Formula and @Where annotations
2016-11-20 20:56:27 +13:00
Roland Praml 1263f0f049 Merge remote-tracking branch 'ebean/master' into feature/platform-dependent-annotations
# Conflicts:
#	src/main/java/com/avaje/ebean/annotation/Formula.java
#	src/main/java/com/avaje/ebeaninternal/server/deploy/parse/AnnotationParser.java
2016-11-17 13:31:22 +01:00
Rob Bygrave f4b32e89f5 [maven-release-plugin] prepare for next development iteration 2016-11-17 23:55:50 +13:00
Rob Bygrave 54711a96d3 [maven-release-plugin] prepare release ebean-9.2.1 2016-11-17 23:55:41 +13:00
Rob Bygrave 6ca5ec986c #881 - Split DocPropertyType.STRING into KEYWORD and TEXT ... for ElasticSearch 5.x support 2016-11-17 23:31:43 +13:00
Rob Bygrave 40029edca8 Bump pom to 9.2.1-SNAPSHOT (for doc type split from String to Keyword & Text 2016-11-17 23:01:31 +13:00
Rob Bygrave 4159af9002 No effective change - logback-test.xml 2016-11-17 23:00:14 +13:00
Rob Bygrave b0dae02c42 #881 - Split DocPropertyType.STRING into KEYWORD and TEXT ... for ElasticSearch 5.x support 2016-11-17 22:59:50 +13:00
Rob Bygrave 0322b37ae7 no effective change - format test code 2016-11-17 20:17:46 +13:00
Rob Bygrave 58760fe001 no effective change - format test code 2016-11-17 20:17:21 +13:00
Rob Bygrave 99f3bc8c54 no effective change - format and javadoc 2016-11-17 20:14:35 +13:00
Rob Bygrave d3bf219129 no effective change - format 2016-11-17 20:06:58 +13:00
Rob Bygrave 57813179b2 no effective change - format 2016-11-17 20:05:04 +13:00
Rob Bygrave c410700433 no effective change - format 2016-11-17 20:00:01 +13:00
Rob Bygrave 697e4dd0da no effective change - format and javadoc 2016-11-17 19:58:37 +13:00
Rob Bygrave 60dfe6308e no effective change - format and javadoc 2016-11-17 19:54:54 +13:00
Rob Bygrave 002d7d9f27 no effective change - format only 2016-11-17 19:24:38 +13:00
Rob Bygrave 2dceccfa78 no effective change - format only 2016-11-17 19:22:58 +13:00
Rob Bygrave 5cf9d14237 no effective change - format only 2016-11-17 19:21:17 +13:00
Rob Bygrave bdd4370fe3 no effective change - format only 2016-11-17 19:17:34 +13:00
Rob Bygrave 63b08af3d2 no effective change - format only 2016-11-17 19:14:02 +13:00
Rob Bygrave 983306ed86 no effective change - format only 2016-11-17 19:11:28 +13:00
Rob Bygrave 15973c8992 no effective change - format only 2016-11-17 19:10:02 +13:00
Rob Bygrave b49a52057a no effective change - format only 2016-11-17 19:07:23 +13:00
Rob Bygrave 82151872fd no effective change - format only 2016-11-17 19:06:26 +13:00
Rob Bygrave 709d4151f2 no effective change - format only 2016-11-17 17:21:25 +13:00
Rob Bygrave d8e3f127c0 no effective change - reduce access to AbstractBeanCollection 2016-11-17 17:20:27 +13:00
Rob Bygrave f4e422a239 no effective change - formatting only 2016-11-17 17:15:49 +13:00
Rob Bygrave 442f24124c #879 - Ebean not fetching complete list of attribute beans when equals(Object o) is implemented 2016-11-17 17:15:14 +13:00
Rob Bygrave 259814f4d9 #849 - AbstractNamingConvention.getTableName inheritance logic differs from InheritInfo 2016-11-16 21:57:38 +13:00
Rob BygraveandGitHub 41a860ebb9 Merge pull request #874 from FOCONIS/feature/inheritance
Feature/inheritance
2016-11-16 21:14:41 +13:00
Rob Bygrave 2584fe9b7b [maven-release-plugin] prepare for next development iteration 2016-11-16 00:24:54 +13:00
Rob Bygrave f815415eb0 [maven-release-plugin] prepare release ebean-9.1.2 2016-11-16 00:24:44 +13:00
Rob Bygrave cf81d1699b Modify scm in pom 2016-11-16 00:23:54 +13:00
Roland Praml 0f3f79ab2c ADD @OrderBy to fix Postgres-tests 2016-11-15 12:03:25 +01:00
Rob Bygrave de9576835c #872 - test models for DDL check constraint issue (not reproduced) 2016-11-15 23:27:08 +13:00
Roland Praml 7e7951df09 ADD @OrderBy to fix Postgres-tests 2016-11-15 11:15:54 +01:00
Rob Bygrave 632cf10096 #878 - @AttributeOverride (not wrapped in @AttributeOverrides) is not applied 2016-11-15 22:48:36 +13:00
Rob Bygrave d2b6d06da5 Merge branch 'master' of github.com:ebean-orm/ebean 2016-11-15 22:13:09 +13:00
Rob Bygrave b41f3e9d1f #877 - DBMigration Generates wrong ddl for UUID type 2016-11-15 22:12:54 +13:00
Rob BygraveandGitHub 8357d9c7e7 Merge pull request #876 from ksperling/batching-exception-safety
Batching exception safety: Fix test
2016-11-14 15:28:36 +13:00
Karsten Sperling 97f1834c4d Batching exception safety: Update test to reflect real world scenario more closely (and actually fail before the change) 2016-11-14 12:48:58 +13:00
Rob Bygrave 01f551a951 #875 - Changes to support ElasticSearch 5.x 2016-11-12 01:05:13 +13:00
Rob Bygrave 482d454fc3 #875 - Changes to support ElasticSearch 5.x 2016-11-11 23:43:13 +13:00
Roland Praml 7341f742de ADD missing join in test 2016-11-11 10:08:08 +01:00
Roland Praml ffb2d6a10c Merge remote-tracking branch 'ebean/master' into feature/inheritance 2016-11-11 09:57:50 +01:00
Roland Praml 56c96923c4 extended the test cases 2016-11-11 09:57:13 +01:00
Roland Praml e4e850717d FIX: @Formula: support for discriminator & joins added 2016-11-11 09:57:02 +01:00
Rob Bygrave 2953418683 No effective change - add .editorconfig 2016-11-11 17:14:12 +13:00
Rob Bygrave 5c142a61f6 No effective change - add javadoc 2016-11-11 17:11:15 +13:00
Rob BygraveandGitHub 74626184b2 Merge pull request #873 from ksperling/batching-exception-safety
Batching exception safety
2016-11-11 17:06:29 +13:00
Roland Praml 019fdd3a12 fix test 2016-11-09 16:31:26 +01:00
Roland Praml 119edbdb9d FIX: Missing comma in bindlog 2016-11-09 16:16:53 +01:00
Roland Praml e8237cc04f ENH: Support for @Formula in combination with @ManyToOne 2016-11-09 16:15:59 +01:00
Roland Praml 95ee163d8b extended test cases 2016-11-09 15:56:55 +01:00
Roland Praml 9a22f9735a no ebean code change: extended test case to use a bean in @Formula and return ID 2016-11-09 10:26:37 +01:00
Roland Praml 29dbd5ac5d No effective code change - add unit test to demonstrate inheritance use case 2016-11-09 10:11:00 +01:00
Karsten Sperling 8661e1fd3f Reset batch on rollback 2016-11-09 10:58:57 +13:00
Karsten Sperling 9569b1b0d5 Added test for exception safety when using batchOnCascade 2016-11-09 10:58:57 +13:00
Rob BygraveandGitHub 3eb9bc1d16 Merge pull request #870 from 0xbaadf00d/feature/use-foreach
Replace "for" with "foreach"
2016-11-08 23:42:12 +13:00
Thibault Meyer ec6a8f5ea2 Replace "for" with "foreach" 2016-11-08 09:06:13 +01:00
Rob Bygrave d6ba567763 [maven-release-plugin] prepare for next development iteration 2016-11-08 00:32:47 +13:00
Roland Praml 4fa9f739d4 Merge remote-tracking branch 'ebean/master' into feature/platform-dependent-annotations
# Conflicts:
#	pom.xml
2016-11-04 09:42:37 +01:00
Roland Praml ba0509dadc Merge remote-tracking branch 'ebean/master' into feature/platform-dependent-annotations 2016-11-02 14:22:24 +01:00
Roland Praml 64c67e3755 removed debug code and completed documentation 2016-11-01 00:43:17 +01:00
Roland Praml 6142dd34f4 No effective code change - removed unused imports 2016-11-01 00:27:12 +01:00
Roland Praml 06e265ec47 Provide test case 2016-11-01 00:02:44 +01:00
Roland Praml 7b19973836 Better support for repeatable annotations (needs Java 8) 2016-10-31 23:36:43 +01:00
1346 changed files with 25355 additions and 27748 deletions
+12
View File
@@ -0,0 +1,12 @@
# editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
spaces_around_operators = true
+13 -7
View File
@@ -9,7 +9,7 @@
<groupId>org.avaje.ebean</groupId>
<artifactId>ebean</artifactId>
<version>9.1.1</version>
<version>9.4.1</version>
<packaging>jar</packaging>
<name>ebean</name>
@@ -20,8 +20,8 @@
</properties>
<scm>
<developerConnection>scm:git:https://github.com/ebean-orm/ebean.git</developerConnection>
<tag>ebean-9.1.1</tag>
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
<tag>ebean-9.4.1</tag>
</scm>
<dependencies>
@@ -33,9 +33,15 @@
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<groupId>org.avaje.ebean</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>org.avaje.ebean</groupId>
<artifactId>ebean-annotation</artifactId>
<version>1.4</version>
</dependency>
<dependency>
@@ -170,7 +176,7 @@
<version>1.4.192</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
@@ -310,5 +316,5 @@
</plugins>
</build>
</project>
@@ -15,7 +15,7 @@ import java.util.concurrent.TimeUnit;
* code if you want. It can be useful for some server caching implementations
* (background population and trimming of the cache etc).
* </p>
*
*
* @author rbygrave
*/
public interface BackgroundExecutor {
+7 -10
View File
@@ -45,13 +45,11 @@ public interface BeanState {
/**
* Set the loaded state of the property given it's name.
*
* <p>
* Typically this would be used to set the loaded state of a property
* to false to ensure that the specific property is excluded from a
* stateless update.
* Typically this would be used to set the loaded state of a property
* to false to ensure that the specific property is excluded from a
* stateless update.
* </p>
*
* <pre>{@code
*
* // populate a bean via say JSON
@@ -64,8 +62,7 @@ public interface BeanState {
* user.update();
*
* }</pre>
*
*
* <p>
* This will throw an IllegalArgumentException if the property is unknown.
*/
void setPropertyLoaded(String propertyName, boolean loaded);
@@ -87,8 +84,8 @@ public interface BeanState {
/**
* Return a map of the updated properties and their new and old values.
*/
Map<String,ValuePair> getDirtyValues();
Map<String, ValuePair> getDirtyValues();
/**
* Return true if the bean is readOnly.
* <p>
@@ -125,4 +122,4 @@ public interface BeanState {
* Reset the bean putting it into NEW state such that a save() results in an insert.
*/
void resetForInsert();
}
}
+43 -49
View File
@@ -13,65 +13,66 @@ import java.sql.SQLException;
* <p>
* Example 1:
* </p>
*
* <pre class="code">
* String sql = &quot;{call sp_order_mod(?,?)}&quot;;
*
* <pre>{@code
*
* String sql = "{call sp_order_mod(?,?)}";
*
* CallableSql cs = Ebean.createCallableSql(sql);
* cs.setParameter(1, &quot;turbo&quot;);
* cs.setParameter(1, "turbo");
* cs.registerOut(2, Types.INTEGER);
*
*
* Ebean.execute(cs);
*
*
* // read the out parameter
* Integer returnValue = (Integer) cs.getObject(2);
* </pre>
*
*
* }</pre>
* <p>
* Example 2:<br>
* Includes batch mode, table modification information and label. Note that the
* label is really only to help people reading the transaction logs to identify
* the procedure called etc.
* </p>
*
* <pre class="code">
* String sql = &quot;{call sp_insert_order(?,?)}&quot;;
*
*
* <pre>{@code
*
* String sql = "{call sp_insert_order(?,?)}";
*
* CallableSql cs = Ebean.createCallableSql(sql);
*
*
* // Inform Ebean this stored procedure inserts into the
* // oe_order table and inserts + updates the oe_order_detail table.
* // this is used to invalidate objects in the cache
* cs.addModification(&quot;oe_order&quot;, true, false, false);
* cs.addModification(&quot;oe_order_detail&quot;, true, true, false);
*
* 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 {
* cs.setParameter(1, &quot;Was&quot;);
* cs.setParameter(2, &quot;Banana&quot;);
* cs.setParameter(1, "Was");
* cs.setParameter(2, "Banana");
* Ebean.execute(cs);
*
* cs.setParameter(1, &quot;Here&quot;);
* cs.setParameter(2, &quot;Kumera&quot;);
*
* cs.setParameter(1, "Here");
* cs.setParameter(2, "Kumera");
* Ebean.execute(cs);
*
* cs.setParameter(1, &quot;More&quot;);
* cs.setParameter(2, &quot;Apple&quot;);
*
* cs.setParameter(1, "More");
* cs.setParameter(2, "Apple");
* Ebean.execute(cs);
*
* // Ebean.externalModification(&quot;oe_order&quot;,true,false,false);
* // Ebean.externalModification(&quot;oe_order_detail&quot;,true,true,false);
*
* // Ebean.externalModification("oe_order",true,false,false);
* // Ebean.externalModification("oe_order_detail",true,true,false);
* Ebean.commitTransaction();
*
*
* } finally {
* Ebean.endTransaction();
* }
* </pre>
*
* }</pre>
*
* @see com.avaje.ebean.SqlUpdate
* @see com.avaje.ebean.Ebean#execute(CallableSql)
*/
@@ -119,21 +120,17 @@ public interface CallableSql {
* This is designed so that you do not need to set params in index order. You
* can set/register param 2 before param 1 etc.
* </p>
*
* @param position
* the index position of the parameter.
* @param value
* the value of the parameter.
*
* @param position the index position of the parameter.
* @param value the value of the parameter.
*/
CallableSql bind(int position, Object value);
/**
* Bind a positioned parameter (same as bind method).
*
* @param position
* the index position of the parameter.
* @param value
* the value of the parameter.
*
* @param position the index position of the parameter.
* @param value the value of the parameter.
*/
CallableSql setParameter(int position, Object value);
@@ -147,11 +144,9 @@ public interface CallableSql {
* This is designed so that you do not need to register params in index order.
* You can set/register param 2 before param 1 etc.
* </p>
*
* @param position
* the index position of the parameter (starts with 1).
* @param type
* the jdbc type of the OUT parameter that will be read.
*
* @param position the index position of the parameter (starts with 1).
* @param type the jdbc type of the OUT parameter that will be read.
*/
CallableSql registerOut(int position, int type);
@@ -168,7 +163,6 @@ public interface CallableSql {
Object getObject(int position);
/**
*
* You can extend this object and override this method for more advanced
* stored procedure calls. This would be the case when ResultSets are returned
* etc.
@@ -190,4 +184,4 @@ public interface CallableSql {
*/
CallableSql addModification(String tableName, boolean inserts, boolean updates, boolean deletes);
}
}
@@ -1,10 +1,9 @@
package com.avaje.ebean;
import java.util.ArrayList;
import com.avaje.ebean.RawSql.ColumnMapping;
import javax.persistence.PersistenceException;
import com.avaje.ebean.RawSql.ColumnMapping;
import java.util.ArrayList;
/**
* Parses columnMapping (select clause) mapping columns to bean properties.
@@ -48,9 +47,9 @@ final class DRawSqlColumnsParser {
String[] split = colInfo.split("\\s(?=[^\\)]*(?:\\(|$))");
if (split.length > 1) {
ArrayList<String> tmp = new ArrayList<>(split.length);
for (int i = 0; i < split.length; i++) {
if (!split[i].trim().isEmpty()) {
tmp.add(split[i].trim());
for (String aSplit : split) {
if (!aSplit.trim().isEmpty()) {
tmp.add(aSplit.trim());
}
}
split = tmp.toArray(new String[tmp.size()]);
@@ -66,15 +65,15 @@ final class DRawSqlColumnsParser {
if (split.length == 2) {
return new ColumnMapping.Column(indexPos++, split[0], split[1]);
}
// Ok, we now expect/require the AS keyword and it should be the
// second to last word in the colInfo content
// Ok, we now expect/require the AS keyword and it should be the
// second to last word in the colInfo content
if (!split[split.length - 2].equalsIgnoreCase("as")) {
throw new PersistenceException("Expecting AS keyword as second to last word when parsing column " + colInfo);
}
// build back the 'column formula' that precedes the AS keyword
StringBuilder sb = new StringBuilder();
sb.append(split[0]);
for (int i = 1; i < split.length-2; i++) {
for (int i = 1; i < split.length - 2; i++) {
sb.append(" ").append(split[i]);
}
return new ColumnMapping.Column(indexPos++, sb.toString(), split[split.length - 1]);
@@ -47,7 +47,7 @@ class DRawSqlParser {
private DRawSqlParser(String sqlString) {
sqlString = sqlString.trim();
sqlString = sqlString.replace('\n',' ');
sqlString = sqlString.replace('\n', ' ');
this.sql = sqlString;
this.hasPlaceHolders = findAndRemovePlaceHolders();
this.textParser = new SimpleTextParser(sqlString);
@@ -39,13 +39,13 @@ public final class DocStoreQueueEntry {
}
}
final Action type;
private final Action type;
final String queueId;
private final String queueId;
final String path;
private final String path;
final Object beanId;
private final Object beanId;
/**
* Construct for an INDEX or DELETE action.
@@ -6,6 +6,8 @@ import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
* Document storage operations.
@@ -93,7 +95,6 @@ public interface DocumentStore {
* <p>
* Typically this is called indirectly by findPagedList() on the query that has setUseDocStore(true).
* </p>
*
* <pre>{@code
*
* PagedList<Customer> newCustomers =
@@ -104,7 +105,6 @@ public interface DocumentStore {
* .findPagedList();
*
* }</pre>
*
*/
<T> PagedList<T> findPagedList(DocQueryRequest<T> request);
@@ -117,7 +117,6 @@ public interface DocumentStore {
* <p>
* Typically this is called indirectly by findEach() on the query that has setUseDocStore(true).
* </p>
*
* <pre>{@code
*
* server.find(Order.class)
@@ -132,7 +131,7 @@ public interface DocumentStore {
*
* }</pre>
*/
<T> void findEach(DocQueryRequest<T> query, QueryEachConsumer<T> consumer);
<T> void findEach(DocQueryRequest<T> query, Consumer<T> consumer);
/**
* Execute the query against the document store with the expectation of a large set of results
@@ -146,8 +145,6 @@ public interface DocumentStore {
* <p>
* Typically this is called indirectly by findEachWhile() on the query that has setUseDocStore(true).
* </p>
*
*
* <pre>{@code
*
* server.find(Order.class)
@@ -166,7 +163,7 @@ public interface DocumentStore {
*
* }</pre>
*/
<T> void findEachWhile(DocQueryRequest<T> query, QueryEachWhileConsumer<T> consumer);
<T> void findEachWhile(DocQueryRequest<T> query, Predicate<T> consumer);
/**
* Process the queue entries sending updates to the document store or queuing them for later processing.
@@ -175,7 +172,6 @@ public interface DocumentStore {
/**
* Drop the index from the document store (similar to DDL drop table).
*
* <pre>{@code
*
* DocumentStore documentStore = server.docStore();
@@ -183,13 +179,11 @@ public interface DocumentStore {
* documentStore.dropIndex("product_copy");
*
* }</pre>
*
*/
void dropIndex(String indexName);
/**
* Create an index given a mapping file as a resource in the classPath (similar to DDL create table).
*
* <pre>{@code
*
* DocumentStore documentStore = server.docStore();
@@ -201,8 +195,8 @@ public interface DocumentStore {
*
* }</pre>
*
* @param indexName the name of the new index
* @param alias the alias of the index
* @param indexName the name of the new index
* @param alias the alias of the index
*/
void createIndex(String indexName, String alias);
@@ -222,7 +216,6 @@ public interface DocumentStore {
* documentStore.indexSettings("product", settings);
*
* }</pre>
*
* <pre>{@code
*
* // refresh_interval 1s ... restore after bulk loading
@@ -244,7 +237,6 @@ public interface DocumentStore {
* <p>
* This copy process does not use the database but instead will copy from the source index to a destination index.
* </p>
*
* <pre>{@code
*
* long copyCount = documentStore.copyIndex(Product.class, "product_copy");
@@ -263,7 +255,6 @@ public interface DocumentStore {
* <p>
* To support this the document needs to have a <code>@WhenModified</code> property.
* </p>
*
* <pre>{@code
*
* long copyCount = documentStore.copyIndex(Product.class, "product_copy", sinceMillis);
@@ -279,7 +270,6 @@ public interface DocumentStore {
/**
* Copy from a source index to a new index taking only the documents
* matching the given query.
*
* <pre>{@code
*
* // predicates to select the source documents to copy
+80 -133
View File
@@ -41,7 +41,6 @@ import java.util.concurrent.ConcurrentHashMap;
* {@link #find(Class)} that proxy through to the 'default' EbeanServer. This
* can be useful for applications that use a single database.</li>
* </ul>
*
* <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
@@ -59,7 +58,6 @@ import java.util.concurrent.ConcurrentHashMap;
* created automatically they are configured using information in the
* ebean.properties file.
* </p>
*
* <pre>{@code
*
* // fetch shipped orders (and also their customer)
@@ -76,40 +74,36 @@ import java.util.concurrent.ConcurrentHashMap;
* }
*
* }</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);
*
@@ -217,7 +211,7 @@ public final class Ebean {
private void register(EbeanServer server, boolean isDefaultServer) {
registerWithName(server.getName(), server, isDefaultServer);
}
private void registerWithName(String name, EbeanServer server, boolean isDefaultServer) {
synchronized (monitor) {
concMap.put(name, server);
@@ -242,16 +236,14 @@ public final class Ebean {
* transactions and the ability to use transactions created externally to
* Ebean.
* </p>
*
* <pre>{@code
* // use the "hr" database
* EbeanServer hrDatabase = Ebean.getServer("hr");
*
*
* Person person = hrDatabase.find(Person.class, 10);
* }</pre>
*
* @param name
* the name of the server, can use null for the 'default server'
*
* @param name the name of the server, can use null for the 'default server'
*/
public static EbeanServer getServer(String name) {
return serverMgr.get(name);
@@ -304,7 +296,7 @@ public final class Ebean {
serverMgr.registerWithName(name, server, defaultServer);
return originalPrimaryServer;
}
/**
* Return the next identity value for a given bean type.
* <p>
@@ -336,7 +328,6 @@ public final class Ebean {
* Example of using a transaction to span multiple calls to find(), save()
* etc.
* </p>
*
* <pre>{@code
*
* // start a transaction (stored in a ThreadLocal)
@@ -345,9 +336,9 @@ public final class Ebean {
* Order order = Ebean.find(Order.class,10); ...
*
* Ebean.save(order);
*
*
* Ebean.commitTransaction();
*
*
* } finally {
* // rollback if we didn't commit
* // i.e. an exception occurred before commitTransaction().
@@ -355,7 +346,6 @@ public final class Ebean {
* }
*
* }</pre>
*
* <p>
* If you want to externalise the transaction management then you should be
* able to do this via EbeanServer. Specifically with EbeanServer you can pass
@@ -371,10 +361,8 @@ public final class Ebean {
/**
* Start a transaction additionally specifying the isolation level.
*
* @param isolation
* the Transaction isolation level
*
*
* @param isolation the Transaction isolation level
*/
public static Transaction beginTransaction(TxIsolation isolation) {
return serverMgr.getDefaultServer().beginTransaction(isolation);
@@ -382,12 +370,10 @@ public final class Ebean {
/**
* Start a transaction typically specifying REQUIRES_NEW or REQUIRED semantics.
*
* <p>
* Note that this provides an try finally alternative to using {@link #execute(TxScope, TxCallable)} or
* {@link #execute(TxScope, TxRunnable)}.
* </p>
*
* <h3>REQUIRES_NEW example:</h3>
* <pre>{@code
* // Start a new transaction. If there is a current transaction
@@ -408,7 +394,6 @@ public final class Ebean {
* }
*
* }</pre>
*
* <h3>REQUIRED example:</h3>
* <pre>{@code
*
@@ -431,7 +416,7 @@ public final class Ebean {
*
* }</pre>
*/
public static Transaction beginTransaction(TxScope scope){
public static Transaction beginTransaction(TxScope scope) {
return serverMgr.getDefaultServer().beginTransaction(scope);
}
@@ -449,7 +434,6 @@ public final class Ebean {
* If there is no currently active transaction then a PersistenceException is thrown.
*
* @param transactionCallback the transaction callback to be registered with the current transaction
*
* @throws PersistenceException if there is no currently active transaction
*/
public static void register(TransactionCallback transactionCallback) throws PersistenceException {
@@ -480,7 +464,6 @@ public final class Ebean {
* <p>
* Code example:
* </p>
*
* <pre>{@code
* Ebean.beginTransaction();
* try {
@@ -488,7 +471,7 @@ public final class Ebean {
*
* // commit at the end
* Ebean.commitTransaction();
*
*
* } finally {
* // if commit didn't occur then rollback the transaction
* Ebean.endTransaction();
@@ -532,16 +515,14 @@ public final class Ebean {
* In this example below the details property has a CascadeType.ALL set so
* saving an order will also save all its details.
* </p>
*
* <pre>{@code
* public class Order { ...
*
*
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
* List<OrderDetail> details;
* ...
* }
* }</pre>
*
* <p>
* When a save cascades via a OneToMany or ManyToMany Ebean will automatically
* set the 'parent' object to the 'detail' object. In the example below in
@@ -576,16 +557,15 @@ public final class Ebean {
* <p>
* An unmodified bean that is saved or updated is normally skipped and this marks the bean as
* dirty so that it is not skipped.
*
* <pre>{@code
*
*
* Customer customer = Ebean.find(Customer, id);
*
*
* // mark the bean as dirty so that a save() or update() will
* // increment the version property
* Ebean.markAsDirty(customer);
* Ebean.save(customer);
*
*
* }</pre>
*/
public static void markAsDirty(Object bean) throws OptimisticLockException {
@@ -614,17 +594,16 @@ public final class Ebean {
* controls if only the changed properties are included in the update or if all the loaded
* properties are included instead.
* </p>
*
* <pre>{@code
*
*
* // A 'stateless update' example
* Customer customer = new Customer();
* customer.setId(7);
* customer.setName("ModifiedNameNoOCC");
* ebeanServer.update(customer);
*
*
* }</pre>
*
*
* @see ServerConfig#setUpdatesDeleteMissingChildren(boolean)
* @see ServerConfig#setUpdateChangesOnly(boolean)
*/
@@ -731,7 +710,6 @@ public final class Ebean {
/**
* Refresh a 'many' property of a bean.
*
* <pre>{@code
*
* Order order = ...;
@@ -740,11 +718,9 @@ public final class Ebean {
* Ebean.refreshMany(order, "details");
*
* }</pre>
*
* @param bean
* the entity bean containing the List Set or Map to refresh.
* @param manyPropertyName
* the property name of the List Set or Map to refresh.
*
* @param bean the entity bean containing the List Set or Map to refresh.
* @param manyPropertyName the property name of the List Set or Map to refresh.
*/
public static void refreshMany(Object bean, String manyPropertyName) {
serverMgr.getDefaultServer().refreshMany(bean, manyPropertyName);
@@ -755,24 +731,21 @@ public final class Ebean {
* <p>
* This is sometimes described as a proxy (with lazy loading).
* </p>
*
* <pre>{@code
*
* Product product = Ebean.getReference(Product.class, 1);
*
*
* // You can get the id without causing a fetch/lazy load
* Integer productId = product.getId();
*
*
* // If you try to get any other property a fetch/lazy loading will occur
* // This will cause a query to execute...
* String name = product.getName();
*
* }</pre>
*
* @param beanType
* the type of entity bean
* @param id
* the id value
*
* @param beanType the type of entity bean
* @param id the id value
*/
public static <T> T getReference(Class<T> beanType, Object id) {
return serverMgr.getDefaultServer().getReference(beanType, id);
@@ -796,29 +769,26 @@ public final class Ebean {
* Note that the sorting uses a Comparator and Collections.sort(); and does
* not invoke a DB query.
* </p>
*
* <pre>{@code
*
*
* // find orders and their customers
* List<Order> list = Ebean.find(Order.class)
* .fetch("customer")
* .orderBy("id")
* .findList();
*
*
* // sort by customer name ascending, then by order shipDate
* // ... then by the order status descending
* Ebean.sort(list, "customer.name, shipDate, status desc");
*
*
* // sort by customer name descending (with nulls low)
* // ... then by the order id
* Ebean.sort(list, "customer.name desc nullsLow, id");
*
*
* }</pre>
*
* @param list
* the list of entity beans
* @param sortByClause
* the properties to sort the list by
*
* @param list the list of entity beans
* @param sortByClause the properties to sort the list by
*/
public static <T> void sort(List<T> list, String sortByClause) {
serverMgr.getDefaultServer().sort(list, sortByClause);
@@ -826,35 +796,35 @@ public final class Ebean {
/**
* Find a bean using its unique id. This will not use caching.
*
* <pre>{@code
*
* // Fetch order 1
* Order order = Ebean.find(Order.class, 1);
*
* }</pre>
*
* <p>
* If you want more control over the query then you can use createQuery() and
* Query.findUnique();
* </p>
*
* <pre>{@code
*
* // ... additionally fetching customer, customer shipping address,
* // order details, and the product associated with each order detail.
* // note: only product id and name is fetch (its a "partial object").
* // note: all other objects use "*" and have all their properties fetched.
*
*
* Query<Order> query = Ebean.find(Order.class)
* .setId(1)
* .fetch("customer")
* .fetch("customer.shippingAddress")
* .fetch("details")
* .query();
*
*
* // fetch associated products but only fetch their product id and name
* query.fetch("details.product", "name");
*
*
* // traverse the object graph...
*
*
* Order order = query.findUnique();
* Customer customer = order.getCustomer();
* Address shippingAddress = customer.getShippingAddress();
@@ -864,11 +834,9 @@ public final class Ebean {
* String productName = product.getName();
*
* }</pre>
*
* @param beanType
* the type of entity bean to fetch
* @param id
* the id value
*
* @param beanType the type of entity bean to fetch
* @param id the id value
*/
@Nullable
public static <T> T find(Class<T> beanType, Object id) {
@@ -903,7 +871,7 @@ public final class Ebean {
/**
* Create a CallableSql to execute a given stored procedure.
*
*
* @see CallableSql
*/
public static CallableSql createCallableSql(String sql) {
@@ -921,19 +889,18 @@ public final class Ebean {
* <p>
* An example:
* </p>
*
* <pre>{@code
*
*
* // The bean name and properties - "topic","postCount" and "id"
*
*
* // will be converted into their associated table and column names
* String updStatement = "update topic set postCount = :pc where id = :id";
*
*
* Update<Topic> update = Ebean.createUpdate(Topic.class, updStatement);
*
*
* update.set("pc", 9);
* update.set("id", 3);
*
*
* int rows = update.execute();
* System.out.println("rows updated:" + rows);
*
@@ -983,8 +950,7 @@ public final class Ebean {
* which is was created.
* </p>
*
* @param beanType
* the class of entity to be fetched
* @param beanType the class of entity to be fetched
* @return A ORM Query object for this beanType
*/
public static <T> Query<T> createQuery(Class<T> beanType) {
@@ -996,12 +962,10 @@ public final class Ebean {
* Parse the Ebean query language statement returning the query which can then
* be modified (add expressions, change order by clause, change maxRows, change
* fetch and select paths etc).
*
* <p>
* <h3>Example</h3>
*
* <pre>{@code
*
*
* // Find order additionally fetching the customer, details and details.product name.
*
* String eql = "fetch customer fetch details fetch details.product (name) where id = :orderId ";
@@ -1023,9 +987,8 @@ public final class Ebean {
* }</pre>
*
* @param beanType The type of bean to fetch
* @param eql The Ebean query
* @param <T> The type of the entity bean
*
* @param eql The Ebean query
* @param <T> The type of the entity bean
* @return The query with expressions defined as per the parsed query statement
*/
public static <T> Query<T> createQuery(Class<T> beanType, String eql) {
@@ -1040,9 +1003,8 @@ public final class Ebean {
* exists is that people used to JPA will probably be looking for a
* createQuery method (the same as entityManager).
* </p>
*
* @param beanType
* the type of entity bean to find
*
* @param beanType the type of entity bean to find
* @return A ORM Query object for this beanType
*/
public static <T> Query<T> find(Class<T> beanType) {
@@ -1103,28 +1065,24 @@ public final class Ebean {
* <p>
* Example:
* </p>
*
* <pre>{@code
*
* // example that uses 'named' parameters
* String s = "UPDATE f_topic set post_count = :count where id = :id"
*
*
* SqlUpdate update = Ebean.createSqlUpdate(s);
*
*
* update.setParameter("id", 1);
* update.setParameter("count", 50);
*
*
* int modifiedCount = Ebean.execute(update);
*
*
* String msg = "There where " + modifiedCount + "rows updated";
*
* }</pre>
*
* @param sqlUpdate
* the update sql potentially with bind values
*
*
* @param sqlUpdate the update sql potentially with bind values
* @return the number of rows updated or deleted. -1 if executed in batch.
*
* @see SqlUpdate
* @see CallableSql
* @see Ebean#execute(CallableSql)
@@ -1138,23 +1096,22 @@ public final class Ebean {
* <p>
* Example:
* </p>
*
* <pre>{@code
*
* String sql = "{call sp_order_modify(?,?,?)}";
*
*
* CallableSql cs = Ebean.createCallableSql(sql);
* cs.setParameter(1, 27);
* cs.setParameter(2, "SHIPPED");
* cs.registerOut(3, Types.INTEGER);
*
*
* Ebean.execute(cs);
*
*
* // read the out parameter
* Integer returnValue = (Integer) cs.getObject(3);
*
* }</pre>
*
*
* @see CallableSql
* @see Ebean#execute(SqlUpdate)
*/
@@ -1168,7 +1125,6 @@ public final class Ebean {
* The scope can control the transaction type, isolation and rollback
* semantics.
* </p>
*
* <pre>{@code
*
* // set specific transactional scope settings
@@ -1193,17 +1149,16 @@ public final class Ebean {
* The default scope runs with REQUIRED and by default will rollback on any
* exception (checked or runtime).
* </p>
*
* <pre>{@code
*
* Ebean.execute(new TxRunnable() {
* public void run() {
* User u1 = Ebean.find(User.class, 1);
* User u2 = Ebean.find(User.class, 2);
*
*
* u1.setName("u1 mod");
* u2.setName("u2 mod");
*
*
* Ebean.save(u1);
* Ebean.save(u2);
* }
@@ -1221,7 +1176,6 @@ public final class Ebean {
* The scope can control the transaction type, isolation and rollback
* semantics.
* </p>
*
* <pre>{@code
*
* // set specific transactional scope settings
@@ -1236,7 +1190,6 @@ public final class Ebean {
* });
*
* }</pre>
*
*/
public static <T> T execute(TxScope scope, TxCallable<T> c) {
return serverMgr.getDefaultServer().execute(scope, c);
@@ -1252,20 +1205,19 @@ public final class Ebean {
* This is basically the same as TxRunnable except that it returns an Object
* (and you specify the return type via generics).
* </p>
*
* <pre>{@code
*
* Ebean.execute(new TxCallable<String>() {
* public String call() {
* User u1 = Ebean.find(User.class, 1);
* User u2 = Ebean.find(User.class, 2);
*
*
* u1.setName("u1 mod");
* u2.setName("u2 mod");
*
*
* Ebean.save(u1);
* Ebean.save(u2);
*
*
* return u1.getEmail();
* }
* });
@@ -1300,15 +1252,11 @@ public final class Ebean {
* If there is NO current transaction when you call this method then this
* information is registered immediately (with the transaction manager).
* </p>
*
* @param tableName
* the name of the table that was modified
* @param inserts
* true if rows where inserted into the table
* @param updates
* true if rows on the table where updated
* @param deletes
* true if rows on the table where deleted
*
* @param tableName the name of the table that was modified
* @param inserts true if rows where inserted into the table
* @param updates true if rows on the table where updated
* @param deletes true if rows on the table where deleted
*/
public static void externalModification(String tableName, boolean inserts, boolean updates, boolean deletes) {
@@ -1327,7 +1275,6 @@ public final class Ebean {
/**
* Return the manager of the server cache ("L2" cache).
*
*/
public static ServerCacheManager getServerCacheManager() {
return serverMgr.getDefaultServer().getServerCacheManager();
+19 -21
View File
@@ -15,6 +15,8 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
* Provides the API for fetching and saving beans to a particular DataSource.
@@ -169,7 +171,7 @@ public interface EbeanServer {
* <p>
* Useful if you use BeanPostConstructListeners or &#64;PostConstruct Annotations.
* In this case you should not use "new Bean...()". Making all bean construtors protected
* could be a good idea here.
* could be a good idea here.
* </p>
*/
<T> T createEntityBean(Class<T> type);
@@ -224,9 +226,8 @@ public interface EbeanServer {
* Parse the Ebean query language statement returning the query which can then
* be modified (add expressions, change order by clause, change maxRows, change
* fetch and select paths etc).
*
* <p>
* <h3>Example</h3>
*
* <pre>{@code
*
* // Find order additionally fetching the customer, details and details.product name.
@@ -250,9 +251,8 @@ public interface EbeanServer {
* }</pre>
*
* @param beanType The type of bean to fetch
* @param eql The Ebean query
* @param <T> The type of the entity bean
*
* @param eql The Ebean query
* @param <T> The type of the entity bean
* @return The query with expressions defined as per the parsed query statement
*/
<T> Query<T> createQuery(Class<T> beanType, String eql);
@@ -757,8 +757,8 @@ public interface EbeanServer {
/**
* Return a QueryIterator for the query.
* <p>
* Generally using {@link #findEach(Query, QueryEachConsumer, Transaction)} or
* {@link #findEachWhile(Query, QueryEachWhileConsumer, Transaction)} is preferred
* Generally using {@link #findEach(Query, Consumer, Transaction)} or
* {@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>
@@ -768,8 +768,8 @@ public interface EbeanServer {
* </p>
*
* @see Query#findIterate()
* @see Query#findEach(QueryEachConsumer)
* @see Query#findEachWhile(QueryEachWhileConsumer)
* @see Query#findEach(Consumer)
* @see Query#findEachWhile(Predicate)
*/
<T> QueryIterator<T> findIterate(Query<T> query, Transaction transaction);
@@ -798,10 +798,10 @@ public interface EbeanServer {
*
* }</pre>
*
* @see Query#findEach(QueryEachConsumer)
* @see Query#findEachWhile(QueryEachWhileConsumer)
* @see Query#findEach(Consumer)
* @see Query#findEachWhile(Predicate)
*/
<T> void findEach(Query<T> query, QueryEachConsumer<T> consumer, Transaction transaction);
<T> void findEach(Query<T> query, Consumer<T> consumer, Transaction transaction);
/**
* Execute the query visiting the each bean one at a time.
@@ -835,10 +835,10 @@ public interface EbeanServer {
*
* }</pre>
*
* @see Query#findEach(QueryEachConsumer)
* @see Query#findEachWhile(QueryEachWhileConsumer)
* @see Query#findEach(Consumer)
* @see Query#findEachWhile(Predicate)
*/
<T> void findEachWhile(Query<T> query, QueryEachWhileConsumer<T> consumer, Transaction transaction);
<T> void findEachWhile(Query<T> query, Predicate<T> consumer, Transaction transaction);
/**
* Return versions of a @History entity bean.
@@ -994,7 +994,7 @@ public interface EbeanServer {
/**
* Execute the query returning a list of values for a single property.
*
* <p>
* <h3>Example 1:</h3>
* <pre>{@code
*
@@ -1005,7 +1005,6 @@ public interface EbeanServer {
* .findSingleAttributeList();
*
* }</pre>
*
* <h3>Example 2:</h3>
* <pre>{@code
*
@@ -1021,7 +1020,6 @@ public interface EbeanServer {
* }</pre>
*
* @return the list of values for the selected property
*
* @see Query#findSingleAttributeList()
*/
<A, T> List<A> findSingleAttributeList(Query<T> query, Transaction transaction);
@@ -1097,7 +1095,7 @@ public interface EbeanServer {
* This streaming type query is useful for large query execution as only 1 row needs to be held in memory.
* </p>
*/
void findEach(SqlQuery query, QueryEachConsumer<SqlRow> consumer, Transaction transaction);
void findEach(SqlQuery query, Consumer<SqlRow> consumer, Transaction transaction);
/**
* Execute the SqlQuery iterating a row at a time with the ability to stop consuming part way through.
@@ -1108,7 +1106,7 @@ public interface EbeanServer {
* This streaming type query is useful for large query execution as only 1 row needs to be held in memory.
* </p>
*/
void findEachWhile(SqlQuery query, QueryEachWhileConsumer<SqlRow> consumer, Transaction transaction);
void findEachWhile(SqlQuery query, Predicate<SqlRow> consumer, Transaction transaction);
/**
* Execute the sql query returning a single MapBean or null.
@@ -36,7 +36,7 @@ public class EbeanServerFactory {
/**
* Initialise the container with clustering configuration.
*
* <p>
* Call this prior to creating any EbeanServer instances or alternatively set the
* ContainerConfig on the ServerConfig when creating the first EbeanServer instance.
*/
@@ -14,44 +14,44 @@ package com.avaje.ebean;
* To get control over the options you can create an ExampleExpression and set
* those options such as case insensitive etc.
* </p>
*
* <pre class="code">
*
* <pre>{@code
* // create an example bean and set the properties
* // with the query parameters you want
* Customer example = new Customer();
* example.setName(&quot;Rob%&quot;);
* example.setNotes(&quot;%something%&quot;);
*
* 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(&quot;id&quot;, 2)
* .gt("id", 2)
* .findList();
*
* </pre>
*
*
* }</pre>
*
* Similarly you can create an ExampleExpression
*
* <pre>
*
* <pre>{@code
*
* Customer example = new Customer();
* example.setName(&quot;Rob%&quot;);
* example.setNotes(&quot;%something%&quot;);
*
* example.setName("Rob%");
* example.setNotes("%something%");
*
* // create a ExampleExpression with more control
* ExampleExpression qbe = new ExampleExpression(example, true, LikeType.EQUAL_TO)
* .includeZeros();
*
* List&lt;Customer&gt; list =
*
* List<Customer> list =
* Ebean.find(Customer.class)
* .where()
* .add(qbe)
* .findList();
* </pre>
*
* @author Rob Bygrave
*
* }</pre>
*/
public interface ExampleExpression extends Expression {
@@ -90,4 +90,4 @@ public interface ExampleExpression extends Expression {
*/
ExampleExpression useEqualTo();
}
}
+16 -19
View File
@@ -23,20 +23,19 @@ import java.util.Map;
* Creates standard common expressions for using in a Query Where or Having
* clause.
* </p>
*
* <pre class="code">
* // Example: Using an Expr.or() method
* Query&lt;Order&gt; query = Ebean.createQuery(Order.class);
* query.where(
* Expr.or(Expr.eq(&quot;status&quot;, Order.NEW),
* Expr.gt(&quot;orderDate&quot;, lastWeek));
*
* List&lt;Order&gt; list = query.findList();
* <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>
*
* }</pre>
*
* @see Query#where()
* @author Rob Bygrave
*/
public class Expr {
@@ -77,10 +76,10 @@ public class Expr {
* Between - value between two given properties.
*/
public static Expression between(String lowProperty, String highProperty, Object value) {
return Ebean.getExpressionFactory().betweenProperties(lowProperty, highProperty, value);
}
/**
* Greater Than - property greater than the given value.
*/
@@ -142,8 +141,7 @@ public class Expr {
/**
* Create the query by Example expression specifying more options.
*/
public static ExampleExpression exampleLike(Object example, boolean caseInsensitive,
LikeType likeType) {
public static ExampleExpression exampleLike(Object example, boolean caseInsensitive, LikeType likeType) {
return Ebean.getExpressionFactory().exampleLike(example, caseInsensitive, likeType);
}
@@ -257,9 +255,8 @@ public class Expr {
* Expression where all the property names in the map are equal to the
* corresponding value.
* </p>
*
* @param propertyMap
* a map keyed by property names.
*
* @param propertyMap a map keyed by property names.
*/
public static Expression allEq(Map<String, Object> propertyMap) {
return Ebean.getExpressionFactory().allEq(propertyMap);
@@ -24,20 +24,19 @@ import java.util.Map;
* <p>
* The ExpressionList is returned from {@link Query#where()}.
* </p>
*
* <pre class="code">
* // Example: fetch orders where status equals new or orderDate > lastWeek.
*
* Expression newOrLastWeek =
* Expr.or(Expr.eq(&quot;status&quot;, Order.Status.NEW),
* Expr.gt(&quot;orderDate&quot;, lastWeek));
*
* Query&lt;Order&gt; query = Ebean.createQuery(Order.class);
* <pre>{@code
* // Example: fetch orders where status equals new or orderDate > lastWeek.
*
* Expression newOrLastWeek =
* Expr.or(Expr.eq("status", Order.Status.NEW),
* Expr.gt("orderDate", lastWeek));
*
* Query<Order> query = Ebean.createQuery(Order.class);
* query.where().add(newOrLastWeek);
* List&lt;Order&gt; list = query.findList();
* List<Order> list = query.findList();
* ...
* </pre>
*
* }</pre>
*
* @see Query#where()
*/
public interface ExpressionFactory {
@@ -282,7 +281,7 @@ public interface ExpressionFactory {
* Exists expression
*/
Expression exists(Query<?> subQuery);
/**
* Not exists expression
*/
@@ -319,9 +318,8 @@ public interface ExpressionFactory {
* Expression where all the property names in the map are equal to the
* corresponding value.
* </p>
*
* @param propertyMap
* a map keyed by property names.
*
* @param propertyMap a map keyed by property names.
*/
Expression allEq(Map<String, Object> propertyMap);
@@ -13,6 +13,8 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
* List of Expressions that make up a where or having clause.
@@ -104,7 +106,7 @@ public interface ExpressionList<T> {
* Perform an 'As of' query using history tables to return the object graph
* as of a time in the past.
* <p>
* To perform this query the DB must have underlying history tables.
* To perform this query the DB must have underlying history tables.
* </p>
*
* @param asOf the date time in the past at which you want to view the data
@@ -151,17 +153,17 @@ public interface ExpressionList<T> {
/**
* Execute the query process the beans one at a time.
*
* @see Query#findEach(QueryEachConsumer)
* @see Query#findEach(Consumer)
*/
void findEach(QueryEachConsumer<T> consumer);
void findEach(Consumer<T> consumer);
/**
* Execute the query processing the beans one at a time with the ability to
* stop processing before reading all the beans.
*
* @see Query#findEachWhile(QueryEachWhileConsumer)
* @see Query#findEachWhile(Predicate)
*/
void findEachWhile(QueryEachWhileConsumer<T> consumer);
void findEachWhile(Predicate<T> consumer);
/**
* Execute the query returning a list.
@@ -201,7 +203,7 @@ public interface ExpressionList<T> {
/**
* Execute the query returning a list of values for a single property.
*
* <p>
* <h3>Example 1:</h3>
* <pre>{@code
*
@@ -212,7 +214,7 @@ public interface ExpressionList<T> {
* .findSingleAttributeList();
*
* }</pre>
*
* <p>
* <h3>Example 2:</h3>
* <pre>{@code
*
@@ -240,7 +242,6 @@ public interface ExpressionList<T> {
* </p>
*
* @throws NonUniqueResultException if more than one result was found
*
* @see Query#findUnique()
*/
@Nullable
@@ -292,7 +293,7 @@ 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)
@@ -309,7 +310,6 @@ public interface ExpressionList<T> {
* }</pre>
*
* @return The PagedList
*
* @see Query#findPagedList()
*/
PagedList<T> findPagedList();
@@ -317,8 +317,8 @@ public interface ExpressionList<T> {
/**
* Return versions of a @History entity bean.
* <p>
* Generally this query is expected to be a find by id or unique predicates query.
* It will execute the query against the history returning the versions of the bean.
* Generally this query is expected to be a find by id or unique predicates query.
* It will execute the query against the history returning the versions of the bean.
* </p>
*/
List<Version<T>> findVersions();
@@ -326,8 +326,8 @@ public interface ExpressionList<T> {
/**
* Return versions of a @History entity bean between the 2 timestamps.
* <p>
* Generally this query is expected to be a find by id or unique predicates query.
* It will execute the query against the history returning the versions of the bean.
* Generally this query is expected to be a find by id or unique predicates query.
* It will execute the query against the history returning the versions of the bean.
* </p>
*/
List<Version<T>> findVersionsBetween(Timestamp start, Timestamp end);
@@ -363,6 +363,19 @@ public interface ExpressionList<T> {
*/
Query<T> setDistinct(boolean distinct);
/**
* Set the index(es) to search for a document store which uses partitions.
* <p>
* For example, when executing a query against ElasticSearch with daily indexes we can
* explicitly specify the indexes to search against.
* </p>
*
* @param indexName The index or indexes to search against
* @return This query
* @see Query#setDocIndexName(String)
*/
Query<T> setDocIndexName(String indexName);
/**
* Set the first row to fetch.
*
@@ -440,7 +453,6 @@ public interface ExpressionList<T> {
/**
* Path exists - for the given path in a JSON document.
*
* <pre>{@code
*
* where().jsonExists("content", "path.other")
@@ -448,13 +460,12 @@ public interface ExpressionList<T> {
* }</pre>
*
* @param propertyName the property that holds a JSON document
* @param path the nested path in the JSON document in dot notation
* @param path the nested path in the JSON document in dot notation
*/
ExpressionList<T> jsonExists(String propertyName, String path);
/**
* Path does not exist - for the given path in a JSON document.
*
* <pre>{@code
*
* where().jsonNotExists("content", "path.other")
@@ -462,13 +473,13 @@ public interface ExpressionList<T> {
* }</pre>
*
* @param propertyName the property that holds a JSON document
* @param path the nested path in the JSON document in dot notation
* @param path the nested path in the JSON document in dot notation
*/
ExpressionList<T> jsonNotExists(String propertyName, String path);
/**
* Equal to expression for the value at the given path in the JSON document.
*
* <p>
* <pre>{@code
*
* where().jsonEqualTo("content", "path.other", 34)
@@ -476,14 +487,14 @@ public interface ExpressionList<T> {
* }</pre>
*
* @param propertyName the property that holds a JSON document
* @param path the nested path in the JSON document in dot notation
* @param value the value used to test against the document path's value
* @param path the nested path in the JSON document in dot notation
* @param value the value used to test against the document path's value
*/
ExpressionList<T> jsonEqualTo(String propertyName, String path, Object value);
/**
* Not Equal to - for the given path in a JSON document.
*
* <p>
* <pre>{@code
*
* where().jsonNotEqualTo("content", "path.other", 34)
@@ -491,14 +502,14 @@ public interface ExpressionList<T> {
* }</pre>
*
* @param propertyName the property that holds a JSON document
* @param path the nested path in the JSON document in dot notation
* @param value the value used to test against the document path's value
* @param path the nested path in the JSON document in dot notation
* @param value the value used to test against the document path's value
*/
ExpressionList<T> jsonNotEqualTo(String propertyName, String path, Object value);
/**
* Greater than - for the given path in a JSON document.
*
* <p>
* <pre>{@code
*
* where().jsonGreaterThan("content", "path.other", 34)
@@ -509,7 +520,7 @@ 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)
@@ -520,7 +531,7 @@ public interface ExpressionList<T> {
/**
* Less than - for the given path in a JSON document.
*
* <p>
* <pre>{@code
*
* where().jsonLessThan("content", "path.other", 34)
@@ -531,7 +542,7 @@ 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)
@@ -542,7 +553,7 @@ public interface ExpressionList<T> {
/**
* Between - for the given path in a JSON document.
*
* <p>
* <pre>{@code
*
* where().jsonBetween("content", "orderDate", lowerDateTime, upperDateTime)
@@ -556,7 +567,7 @@ public interface ExpressionList<T> {
* <p>
* This returns the list so that add() can be chained.
* </p>
*
* <p>
* <pre>{@code
*
* Query<Customer> query = Ebean.find(Customer.class);
@@ -647,7 +658,7 @@ 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
@@ -663,9 +674,9 @@ public interface ExpressionList<T> {
* .gt("id", 2).findList();
*
* }</pre>
*
* <p>
* Similarly you can create an ExampleExpression
*
* <p>
* <pre>{@code
*
* Customer example = new Customer();
@@ -804,8 +815,7 @@ public interface ExpressionList<T> {
* corresponding value.
* </p>
*
* @param propertyMap
* a map keyed by property names.
* @param propertyMap a map keyed by property names.
*/
ExpressionList<T> allEq(Map<String, Object> propertyMap);
@@ -849,7 +859,7 @@ 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>
* <h4>Example:</h4>
* <pre>{@code
*
@@ -881,7 +891,7 @@ 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")
@@ -894,7 +904,7 @@ public interface ExpressionList<T> {
* Add a match expression.
*
* @param propertyName The property name for the match
* @param search The search value
* @param search The search value
*/
ExpressionList<T> match(String propertyName, String search);
@@ -902,14 +912,14 @@ public interface ExpressionList<T> {
* Add a match expression with options.
*
* @param propertyName The property name for the match
* @param search The search value
* @param search The search value
*/
ExpressionList<T> match(String propertyName, String search, Match options);
/**
* Add a multi-match expression.
*/
ExpressionList<T> multiMatch(String search, String... properties);
ExpressionList<T> multiMatch(String search, String... properties);
/**
* Add a multi-match expression using options.
@@ -960,7 +970,7 @@ 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()
@@ -985,11 +995,11 @@ public interface ExpressionList<T> {
/**
* Return a list of expressions that will be joined by OR's.
* This is exactly the same as disjunction();
*
* <p>
* Use endOr() or endJunction() to end the OR junction.
* <p>
* Use endOr() or endJunction() to end the OR junction.
* </p>
*
* <p>
* <pre>{@code
*
* // Example: Use or() to join
@@ -1016,10 +1026,10 @@ public interface ExpressionList<T> {
/**
* Return a list of expressions that will be wrapped by NOT.
* <p>
* Use endNot() or endJunction() to end expressions being added to the
* NOT expression list.
* Use endNot() or endJunction() to end expressions being added to the
* NOT expression list.
* </p>
*
* <p>
* <pre>@{code
*
* .where()
@@ -1029,7 +1039,7 @@ public interface ExpressionList<T> {
* .endNot()
*
* }</pre>
*
* <p>
* <pre>@{code
*
* // Example: nested not()
+33 -29
View File
@@ -21,47 +21,52 @@ import java.io.Serializable;
* is high (a lot of "Many" beans per "One" bean) then this can be more
* efficient loaded as 2 SQL queries.
* </p>
*
* <p>
* <pre>{@code
* // Normal fetch join results in a single SQL query
* List<Order> list = Ebean.find(Order.class).fetch("details").findList();
*
*
* // Find Orders join details using a single SQL query
* }</pre>
* <p>
* Example: Using a "query join" instead of a "fetch join" we instead use 2 SQL queries
* </p>
*
* <p>
* <pre>{@code
*
* // This will use 2 SQL queries to build this object graph
* List<Order> list =
* Ebean.find(Order.class)
* .fetch("details", new FetchConfig().query())
* .findList();
*
*
* // query 1) find order
* // query 2) find orderDetails where order.id in (?,?...) // first 100 order id's
*
* }</pre>
* <p>
* Example: Using 2 "query joins"
* </p>
*
* <p>
* <pre>{@code
*
* // This will use 3 SQL queries to build this object graph
* List<Order> list =
* Ebean.find(Order.class)
* .fetch("details", new FetchConfig().query())
* .fetch("customer", new FetchConfig().queryFirst(5))
* .findList();
*
*
* // query 1) find order
* // query 2) find orderDetails where order.id in (?,?...) // first 100 order id's
* // query 3) find customer where id in (?,?,?,?,?) // first 5 customers
*
* }</pre>
* <p>
* Example: Using "query joins" and partial objects
* </p>
*
* <p>
*
* <pre>{@code
* // This will use 3 SQL queries to build this object graph
* List<Order> list =
@@ -73,13 +78,13 @@ import java.io.Serializable;
* .fetch("customer.contacts")
* .fetch("customer.shippingAddress")
* .findList();
*
*
* // query 1) find order (status, shipDate)
* // query 2) find orderDetail (quantity, price) fetch product (sku, name) where
* // order.id in (?,? ...)
* // query 3) find customer (name) fetch contacts (*) fetch shippingAddress (*)
* // where id in (?,?,?,?,?)
*
*
* // Note: the fetch of "details.product" is automatically included into the
* // fetch of "details"
* //
@@ -91,20 +96,21 @@ import java.io.Serializable;
* immediately and the lazy defines the batch size to use for further lazy
* loading (if lazy loading is invoked).
* </p>
*
* <p>
* <pre>{@code
*
* List<Order> list =
* Ebean.find(Order.class)
* .fetch("customer", new FetchConfig().query(10).lazy(5))
* .findList();
*
*
* // query 1) find order
* // query 2) find customer where id in (?,?,?,?,?,?,?,?,?,?) // first 10 customers
* // .. then if lazy loading of customers is invoked
* // .. use a batch size of 5 to load the customers
*
*
* }</pre>
*
* <p>
* <p>
* Example of controlling the lazy loading query:
* </p>
@@ -112,22 +118,23 @@ import java.io.Serializable;
* This gives us the ability to optimise the lazy loading query for a given use
* case.
* </p>
*
* <p>
* <pre>{@code
*
* List<Order> list = Ebean.find(Order.class)
* .fetch("customer","name", new FetchConfig().lazy(5))
* .fetch("customer.contacts","contactName, phone, email")
* .fetch("customer.shippingAddress")
* .where().eq("status",Order.Status.NEW)
* .findList();
*
*
* // query 1) find order where status = Order.Status.NEW
* //
* // .. if lazy loading of customers is invoked
* //
* // .. if lazy loading of customers is invoked
* // .. use a batch size of 5 to load the customers
*
*
* }</pre>
*
*
* @author mario
* @author rbygrave
*/
@@ -159,9 +166,8 @@ public class FetchConfig implements Serializable {
/**
* Specify that this path should be lazy loaded with a specified batch size.
*
* @param lazyBatchSize
* the batch size for lazy loading
*
* @param lazyBatchSize the batch size for lazy loading
*/
public FetchConfig lazy(int lazyBatchSize) {
this.lazyBatchSize = lazyBatchSize;
@@ -193,9 +199,8 @@ public class FetchConfig implements Serializable {
* This will load all beans on this path eagerly unless a {@link #lazy(int)}
* is also used.
* </p>
*
* @param queryBatchSize
* the batch size used to load beans on this path
*
* @param queryBatchSize the batch size used to load beans on this path
*/
public FetchConfig query(int queryBatchSize) {
this.queryBatchSize = queryBatchSize;
@@ -211,9 +216,8 @@ public class FetchConfig implements Serializable {
* If there are more parent beans than the batch size then they will not be
* loaded eagerly but instead use lazy loading.
* </p>
*
* @param queryBatchSize
* the number of parent beans this path is populated for
*
* @param queryBatchSize the number of parent beans this path is populated for
*/
public FetchConfig queryFirst(int queryBatchSize) {
this.queryBatchSize = queryBatchSize;
@@ -227,7 +231,7 @@ public class FetchConfig implements Serializable {
public int getLazyBatchSize() {
return lazyBatchSize;
}
/**
* Return the batch size for separate query load.
*/
+38 -39
View File
@@ -19,64 +19,63 @@ import java.util.Set;
* The result of the filter method will leave the original list unmodified and
* return a new List instance.
* </p>
*
* <pre class="code">
*
* <p>
* <pre>{@code
*
* // get a list of entities (query execution statistics in this case)
*
* List&lt;MetaQueryStatistic&gt; list =
*
* List<MetaQueryStatistic> list =
* Ebean.find(MetaQueryStatistic.class).findList();
*
*
* long nowMinus24Hrs = System.currentTimeMillis() - 24 * (1000 * 60 * 60);
*
*
* // sort and filter the list returning a filtered list...
*
* List&lt;MetaQueryStatistic&gt; filteredList =
*
* List<MetaQueryStatistic> filteredList =
* Ebean.filter(MetaQueryStatistic.class)
* .sort(&quot;avgTimeMicros desc&quot;)
* .gt(&quot;executionCount&quot;, 0)
* .gt(&quot;lastQueryTime&quot;, nowMinus24Hrs)
* .eq(&quot;autoTuned&quot;, true)
* .sort("avgTimeMicros desc")
* .gt("executionCount", 0)
* .gt("lastQueryTime", nowMinus24Hrs)
* .eq("autoTuned", true)
* .maxRows(10)
* .filter(list);
*
* </pre>
*
* }</pre>
* <p>
* The propertyNames can traverse the object graph (e.g. customer.name) by using
* dot notation. If any point during the object graph traversal to get a
* property value is null then null is returned.
* </p>
*
* <pre>
* // examples of property names that
* <p>
* <pre>{@code
*
* // examples of property names that
* // ... will traverse the object graph
* // ... where customer is a property of our bean
*
*
* customer.name
* customer.shippingAddress.city
* </pre>
*
* </p>
*
* <pre class="code">
*
*
* }</pre>
* <p>
* <pre>{@code
*
* // get a list of entities (query execution statistics)
*
* List&lt;Order&gt; orders =
*
* List<Order> orders =
* Ebean.find(Order.class).findList();
*
*
* // Apply a filter...
*
* List&lt;Order&gt; filteredOrders =
*
* List<Order> filteredOrders =
* Ebean.filter(Order.class)
* .startsWith(&quot;customer.name&quot;, &quot;Rob&quot;)
* .eq(&quot;customer.shippingAddress.city&quot;, &quot;Auckland&quot;)
* .startsWith("customer.name", "Rob")
* .eq("customer.shippingAddress.city", "Auckland")
* .filter(orders);
*
* </pre>
*
* @param <T>
* the entity bean type
*
* }</pre>
*
* @param <T> the entity bean type
*/
public interface Filter<T> {
@@ -189,9 +188,9 @@ public interface Filter<T> {
* <p>
* The sourceList will remain unmodified.
* </p>
*
*
* @return Returns a new list with the sorting and filters applied.
*/
List<T> filter(List<T> sourceList);
}
}
+4 -11
View File
@@ -11,11 +11,10 @@ import java.util.List;
* These 'finders' are a place to organise all the finder methods for that bean type
* and specific finder methods are expected to be added (find by unique properties etc).
* </p>
*
* <h3>Testing</h3>
* <p>
* For testing the mocki-ebean project has the ability to replace the finder implementation
*
* For testing the mocki-ebean project has the ability to replace the finder implementation
* <p>
* </p>
* <pre>{@code
*
@@ -61,7 +60,6 @@ public class Finder<I, T> {
/**
* Create with the type of the entity bean.
*
* <pre>{@code
*
* public class CustomerFinder extends Finder<Customer> {
@@ -96,10 +94,8 @@ public class Finder<I, T> {
/**
* Return the underlying 'default' EbeanServer.
*
* <p>
* This provides full access to the API such as explicit transaction demarcation etc.
*
*/
public EbeanServer db() {
return Ebean.getServer(serverName);
@@ -110,9 +106,8 @@ public class Finder<I, T> {
* <p>
* This is equivalent to {@link Ebean#getServer(String)}
*
* @param server
* The name of the EbeanServer. If this is null then the default EbeanServer is
* returned.
* @param server The name of the EbeanServer. If this is null then the default EbeanServer is
* returned.
*/
public EbeanServer db(String server) {
return Ebean.getServer(server);
@@ -120,7 +115,6 @@ public class Finder<I, T> {
/**
* Creates an entity reference for this ID.
*
* <p>
* Equivalent to {@link EbeanServer#getReference(Class, Object)}
*/
@@ -130,7 +124,6 @@ public class Finder<I, T> {
/**
* Retrieves an entity by ID.
*
* <p>
* Equivalent to {@link EbeanServer#find(Class, Object)}
*/
+8 -11
View File
@@ -17,31 +17,30 @@ import java.util.concurrent.TimeoutException;
* <p>
* A simple example:
* </p>
*
* <pre>{@code
*
* // create a query to find all orders
* Query<Order> query = Ebean.find(Order.class);
*
*
* // execute the query in a background thread
* // immediately returning the futureList
* FutureList<Order> futureList = query.findFutureList();
*
* // do something else ...
*
*
* // do something else ...
*
* if (!futureList.isDone()){
* // we can cancel the query execution. This will cancel
* // the underlying query if that is supported by the JDBC
* // driver and database
* futureList.cancel(true);
* }
*
*
*
* if (!futureList.isCancelled()){
* // wait for the query to finish and return the list
* List<Order> list = futureList.get();
* ...
* }
*
*
* }</pre>
*/
public interface FutureList<T> extends Future<List<T>> {
@@ -56,7 +55,6 @@ public interface FutureList<T> extends Future<List<T>> {
* unchecked PersistenceException.
*
* @return The query list result
*
* @throws PersistenceException when a InterruptedException or ExecutionException occurs.
*/
List<T> getUnchecked();
@@ -66,8 +64,7 @@ public interface FutureList<T> extends Future<List<T>> {
* and ExecutionException in the unchecked PersistenceException.
*
* @return The query list result
*
* @throws TimeoutException if the wait timed out
* @throws TimeoutException if the wait timed out
* @throws PersistenceException if a InterruptedException or ExecutionException occurs.
*/
List<T> getUnchecked(long timeout, TimeUnit unit) throws TimeoutException;
@@ -8,8 +8,8 @@ import java.util.concurrent.Future;
* <p>
* It extends the java.util.concurrent.Future.
* </p>
*
* @param <T> the BeanType
*
* @param <T> the BeanType
* @author rbygrave
*/
public interface FutureRowCount<T> extends Future<Integer> {
+7 -5
View File
@@ -9,7 +9,6 @@ package com.avaje.ebean;
* <p>
* Note: where() always takes you to the top level WHERE expression list.
* </p>
*
* <pre>{@code
* Query q =
* Ebean.find(Person.class)
@@ -23,13 +22,13 @@ package com.avaje.ebean;
*
* // read as...
* // where ( ((name like Rob%) or (status = NEW)) AND (id &gt; 10) )
* }</pre>
*
* }</pre>
* <p>
* Note: endJunction() takes you to the parent expression list
* </p>
*
* <pre>{@code
*
* Query q =
* Ebean.find(Person.class)
* .where()
@@ -46,11 +45,9 @@ package com.avaje.ebean;
* // read as...
* // where ( ((name like Rob%) or (status = NEW)) AND (id > 10) )
* }</pre>
*
* <p>
* Example of a nested disjunction.
* </p>
*
* <pre>{@code
* Query<Customer> q =
* Ebean.find(Customer.class)
@@ -96,6 +93,11 @@ public interface Junction<T> extends Expression, ExpressionList<T> {
*/
NOT(" and ", "not ", false),
/**
* FILTER group (for internal use only).
*/
FILTER("filter", "", true),
/**
* Text search AND group.
*/
+24 -647
View File
@@ -1,43 +1,32 @@
package com.avaje.ebean;
import com.avaje.ebean.bean.EntityBean;
import com.avaje.ebean.util.ClassUtil;
import org.jetbrains.annotations.Nullable;
import javax.persistence.MappedSuperclass;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
/**
* A MappedSuperclass base class that provides convenience methods for inserting, updating and
* deleting beans.
*
* <p>
* By having your entity beans extend this it provides a 'Active Record' style programming model for
* Ebean users.
*
* <p>
* Note that there is a avaje-ebeanorm-mocker project that enables you to use Mockito or similar
* 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.
*
* <p>
* You may choose not use this Model mapped superclass if you don't like the 'Active Record' style
* or if you believe it 'pollutes' your entity beans.
*
* <p>
* You can use Dependency Injection like Guice or Spring to construct and wire a EbeanServer instance
* and have that same instance used with this Model and Finder. The way that works is that when the
* DI container creates the EbeanServer instance it can be registered with the Ebean singleton. In this
* way the EbeanServer instance can be injected as per normal Guice / Spring dependency injection and
* that same instance also used to support the Model and Finder active record style.
*
* <p>
* If you choose to use the Model mapped superclass you will probably also chose to additionally add
* a {@link Find} as a public static field to complete the active record pattern and provide a
* a {@link Finder} as a public static field to complete the active record pattern and provide a
* relatively nice clean way to write queries.
*
* <p>
* <h3>Typical common @MappedSuperclass</h3>
* <pre>{@code
*
@@ -51,34 +40,28 @@ import java.util.UUID;
*
* @Version Long version;
*
* @CreatedTimestamp Timestamp whenCreated;
* @WhenCreated Timestamp whenCreated;
*
* @UpdatedTimestamp Timestamp whenUpdated;
* @WhenUpdated Timestamp whenUpdated;
*
* ...
*
* }</pre>
*
* <p>
* <h3>Extend the Model</h3>
* <pre>{@code
*
* // Extend the mappedSuperclass
*
* @Entity @Table(name="oto_account")
* @Entity @Table(name="o_account")
* public class Customer extends BaseModel {
*
* // Add a static Find
* // ... with Long being the type of our @Id property.
* // ... Note the {} at the end as Find is an abstract class.
*
* public static final Find<Long,Account> find = new Find<Long,Account>(){};
*
* String name;
* ...
* }
*
* }</pre>
*
* <p>
* <h3>Modal: save()</h3>
* <pre>{@code
*
@@ -90,64 +73,43 @@ import java.util.UUID;
* customer.save();
*
* }</pre>
*
* <h3>Find byId</h3>
* <pre>{@code
*
* // find byId
* Customer customer = Customer.find.byId(42);
*
* }</pre>
*
* <h3>Find where</h3>
* <pre>{@code
*
* // find where ...
* List<Customer> customers =
* Customer.find
* .where().gt("startDate", lastMonth)
* .findList();
*
* }</pre>
*/
@MappedSuperclass
public abstract class Model {
/**
* Return the underlying 'default' EbeanServer.
*
* <p>
* This provides full access to the API such as explicit transaction demarcation etc.
*
* <p>
* Example:
* <pre>{@code
*
* Transaction transaction = Customer.db().beginTransaction();
* try {
*
*
* // turn off cascade persist for this transaction
* transaction.setPersistCascade(false);
*
*
* // extra control over jdbc batching for this transaction
* transaction.setBatchGetGeneratedKeys(false);
* transaction.setBatchMode(true);
* transaction.setBatchSize(20);
*
*
* Customer customer = new Customer();
* customer.setName(&quot;Roberto&quot;);
* customer.save();
*
*
* Customer otherCustomer = new Customer();
* otherCustomer.setName("Franko");
* otherCustomer.save();
*
*
* transaction.commit();
*
*
* } finally {
* transaction.end();
* }
*
*
* }</pre>
*/
public static EbeanServer db() {
@@ -156,13 +118,11 @@ public abstract class Model {
/**
* 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.
*
* @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);
@@ -176,16 +136,16 @@ public abstract class Model {
* <p>
* An unmodified bean that is saved or updated is normally skipped and this marks the bean as
* dirty so that it is not skipped.
*
* <p>
* <pre>{@code
*
*
* Customer customer = Customer.find.byId(id);
*
*
* // mark the bean as dirty so that a save() or update() will
* // increment the version property
* customer.markAsDirty();
* customer.save();
*
*
* }</pre>
*
* @see EbeanServer#markAsDirty(Object)
@@ -197,7 +157,7 @@ public abstract class Model {
/**
* Mark the property as unset or 'not loaded'.
* <p>
* This would be used to specify a property that we did not wish to include in a stateless update.
* This would be used to specify a property that we did not wish to include in a stateless update.
* </p>
* <pre>{@code
*
@@ -215,12 +175,11 @@ public abstract class Model {
* @param propertyName the name of the property on the bean to be marked as 'unset'
*/
public void markPropertyUnset(String propertyName) {
((EntityBean)this)._ebean_getIntercept().setPropertyLoaded(propertyName, false);
((EntityBean) this)._ebean_getIntercept().setPropertyLoaded(propertyName, false);
}
/**
* Insert or update this entity depending on its state.
*
* <p>
* Ebean will detect if this is a new bean or a previously fetched bean and perform either an
* insert or an update based on that.
@@ -313,586 +272,4 @@ public abstract class Model {
db().refresh(this);
}
/**
* A concrete implementation of Find.
* <p>
* It should be preferred to use {@link Find} instead of Finder as that can use reflection to determine the class
* literal type of the entity bean.
* </p>
* @param <I> type of the Id property
* @param <T> type of the entity bean
*/
public static class Finder<I, T> extends Find<I, T> {
/**
* Create with the type of the entity bean.
*
* <pre>{@code
*
* @Entity
* public class Customer extends BaseModel {
*
* public static final Finder<Long,Customer> find = new Finder<Long,Customer>(Customer.class);
* ...
*
* }</pre>
*
* <p/>
* The preferred approach is to instead use <code>Find</code> as below. This approach is more DRY in that it does
* not require the class literal Customer.class to be passed into the constructor.
*
* <pre>{@code
*
* @Entity
* public class Customer extends BaseModel {
*
* public static final Find<Long,Customer> find = new Find<Long,Customer>(){};
* ...
*
* }</pre>
*/
public Finder(Class<T> type) {
super(null, type);
}
/**
* Create with the type of the entity bean and specific server name.
*/
public Finder(String serverName, Class<T> type) {
super(serverName, type);
}
}
/**
* Helper object for performing queries.
*
* <p>
* Typically a Find instance is defined as a public static field on an entity bean class to provide a
* nice way to write queries.
*
* <h3>Example use:</h3>
*
* <pre>{@code
*
* @Entity
* public class Customer extends BaseModel {
*
* public static final Find<Long,Customer> find = new Find<Long,Customer>(){};
*
* ...
*
* }</pre>
* <p/>
* This enables you to write code like:
* <pre>{@code
*
* Customer customer = Customer.find.byId(42L);
*
* List<Customer> customers =
* Customer.find
* .select("name, dateOfBirth")
* .findList();
*
* }</pre>
*
* <h3>Kotlin</h3>
* In Kotlin you would typically create Find as a companion object.
* <pre>{@code
*
* // kotlin
* companion object : Model.Find<Long, Product>() {}
*
* }</pre>
* @param <I>
* The Id type. This is most often a {@link Long} but is also often a {@link UUID} or
* {@link String}.
*
* @param <T>
* The entity bean type
*/
public static abstract class Find<I, T> {
/**
* The entity bean type.
*/
private final Class<T> type;
/**
* The name of the EbeanServer, null for the default server.
*/
private final String serverName;
/**
* Creates a finder for entity of type <code>T</code> with ID of type <code>I</code>.
* <p/>
* Typically you create Find as a public static field on each entity bean as the example below.
*
* <p/>
* Note that Find is an abstract class and hence <code>{}</code> is required. This is done so
* that the type (class literal) of the entity bean can be derived from the generics parameter.
*
* <pre>{@code
*
* @Entity
* public class Customer extends BaseModel {
*
* // Note the trailing {} as Find is an abstract class.
* // We do this so that we can derive the type literal Customer.class
* // via reflection
* public static final Find<Long,Customer> find = new Find<Long,Customer>(){};
* ...
*
* }</pre>
* <p/>
* This enables you to write code like:
* <pre>{@code
*
* Customer customer = Customer.find.byId(42L);
*
* List<Customer> customers =
* Customer.find
* .select("name, email, dateOfBirth")
* .findList();
*
* }</pre>
*
* <h3>Kotlin</h3>
* In Kotlin you would typically create it as a companion object.
*
* <pre>{@code
*
* // kotlin
* companion object : Model.Find<Long, Product>() {}
*
* }</pre>
*/
@SuppressWarnings("unchecked")
public Find() {
this.serverName = null;
this.type = (Class<T>)ClassUtil.getSecondArgumentType(getClass());
}
/**
* Construct passing the class literal type of the entity type.
*/
protected Find(String serverName, Class<T> type) {
this.serverName = serverName;
this.type = type;
}
/**
* Return the underlying 'default' EbeanServer.
*
* <p>
* This provides full access to the API such as explicit transaction demarcation etc.
*
*/
public EbeanServer db() {
return Ebean.getServer(serverName);
}
/**
* Return typically a different EbeanServer to the default.
* <p>
* This is equivalent to {@link Ebean#getServer(String)}
*
* @param server
* The name of the EbeanServer. If this is null then the default EbeanServer is
* returned.
*/
public EbeanServer db(String server) {
return Ebean.getServer(server);
}
/**
* Creates a Finder for the named EbeanServer.
*
* <p>
* Create and return a new Finder for a different server.
*/
public Finder<I, T> on(String server) {
return new Finder<>(server, type);
}
/**
* Delete a bean by Id.
* <p>
* Equivalent to {@link EbeanServer#delete(Class, Object)}
*/
public void deleteById(I id) {
db().delete(type, id);
}
/**
* Retrieves all entities of the given type.
*
* <p>
* This is the same as (synonym for) {@link #findList()}
*/
public List<T> all() {
return findList();
}
/**
* Retrieves an entity by ID.
*
* <p>
* Equivalent to {@link EbeanServer#find(Class, Object)}
*/
@Nullable
public T byId(I id) {
return db().find(type, id);
}
/**
* Creates an entity reference for this ID.
*
* <p>
* Equivalent to {@link EbeanServer#getReference(Class, Object)}
*/
public T ref(I id) {
return db().getReference(type, id);
}
/**
* Creates a filter for sorting and filtering lists of entities locally without going back to
* the database.
* <p>
* Equivalent to {@link EbeanServer#filter(Class)}
*/
public Filter<T> filter() {
return db().filter(type);
}
/**
* Creates a query.
* <p>
* Equivalent to {@link EbeanServer#find(Class)}
*/
public Query<T> query() {
return db().find(type);
}
/**
* Creates a query applying the path properties to set the select and fetch clauses.
* <p>
* Equivalent to {@link Query#apply(FetchPath)}
*/
public Query<T> apply(FetchPath fetchPath) {
return db().find(type).apply(fetchPath);
}
/**
* Returns the next identity value.
*
* @see EbeanServer#nextId(Class)
*/
@SuppressWarnings("unchecked")
public I nextId() {
return (I) db().nextId(type);
}
/**
* Executes a query and returns the results as a list of IDs.
* <p>
* Equivalent to {@link Query#findIds()}
*/
public <A> List<A> findIds() {
return query().findIds();
}
/**
* Execute the query consuming each bean one at a time.
* <p>
* This is generally used to process large queries where unlike findList
* you do not want to hold all the results in memory at once but instead
* process them one at a time (requiring far less memory).
* </p>
* Equivalent to {@link Query#findEach(QueryEachConsumer)}
*/
public void findEach(QueryEachConsumer<T> consumer) {
query().findEach(consumer);
}
/**
* Execute the query consuming each bean one at a time.
* <p>
* Equivalent to {@link Query#findEachWhile(QueryEachWhileConsumer)}
* <p>
* This is similar to #findEach except that you return boolean
* true to continue processing beans and return false to stop
* processing early.
* </p>
* <p>
* This is generally used to process large queries where unlike findList
* you do not want to hold all the results in memory at once but instead
* process them one at a time (requiring far less memory).
* </p>
* Equivalent to {@link Query#findEachWhile(QueryEachWhileConsumer)}
*/
public void findEachWhile(QueryEachWhileConsumer<T> consumer) {
query().findEachWhile(consumer);
}
/**
* Retrieves all entities of the given type.
* <p>
* The same as {@link #all()}
* <p>
* Equivalent to {@link Query#findList()}
*/
public List<T> findList() {
return query().findList();
}
/**
* Returns all the entities of the given type as a set.
* <p>
* Equivalent to {@link Query#findSet()}
*/
public Set<T> findSet() {
return query().findSet();
}
/**
* Retrieves all entities of the given type as a map of objects.
* <p>
* Equivalent to {@link Query#findMap()}
*/
public <K> Map<K, T> findMap() {
return query().findMap();
}
/**
* Executes a find row count query in a background thread.
* <p>
* Equivalent to {@link Query#findFutureCount()}
*/
public FutureRowCount<T> findFutureCount() {
return query().findFutureCount();
}
/**
* Deprecated in favor of findFutureCount().
* <p>
* Equivalent to {@link Query#findFutureCount()}
*/
public FutureRowCount<T> findFutureRowCount() {
return query().findFutureCount();
}
/**
* Returns the total number of entities for this type. *
* <p>
* Equivalent to {@link Query#findCount()}
*/
public int findCount() {
return query().findCount();
}
/**
* Deprecated in favor of findCount().
* @deprecated
*/
public int findRowCount() {
return query().findCount();
}
/**
* Returns the <code>ExpressionFactory</code> used by this query.
*/
public ExpressionFactory getExpressionFactory() {
return query().getExpressionFactory();
}
/**
* Explicitly sets a comma delimited list of the properties to fetch on the 'main' entity bean,
* to load a partial object.
* <p>
* Equivalent to {@link Query#select(String)}
*/
public Query<T> select(String fetchProperties) {
return query().select(fetchProperties);
}
/**
* Specifies a path to load including all its properties.
* <p>
* Equivalent to {@link Query#fetch(String)}
*/
public Query<T> fetch(String path) {
return query().fetch(path);
}
/**
* Additionally specifies a <code>FetchConfig</code> to specify a 'query join' and/or define the
* lazy loading query.
* <p>
* Equivalent to {@link Query#fetch(String, FetchConfig)}
*/
public Query<T> fetch(String path, FetchConfig joinConfig) {
return query().fetch(path, joinConfig);
}
/**
* Specifies a path to fetch with a specific list properties to include, to load a partial
* object.
* <p>
* Equivalent to {@link Query#fetch(String, String)}
*/
public Query<T> fetch(String path, String fetchProperties) {
return query().fetch(path, fetchProperties);
}
/**
* Additionally specifies a <code>FetchConfig</code> to use a separate query or lazy loading to
* load this path.
* <p>
* Equivalent to {@link Query#fetch(String, String, FetchConfig)}
*/
public Query<T> fetch(String assocProperty, String fetchProperties, FetchConfig fetchConfig) {
return query().fetch(assocProperty, fetchProperties, fetchConfig);
}
/**
* Adds expressions to the <code>where</code> clause with the ability to chain on the
* <code>ExpressionList</code>.
* <p>
* Equivalent to {@link Query#where()}
*/
public ExpressionList<T> where() {
return query().where();
}
/**
* Returns the <code>order by</code> clause so that you can append an ascending or descending
* property to the <code>order by</code> clause.
* <p>
* This is exactly the same as {@link #orderBy}.
* <p>
* Equivalent to {@link Query#order()}
*/
public OrderBy<T> order() {
return query().order();
}
/**
* Sets the <code>order by</code> clause, replacing the existing <code>order by</code> clause if
* there is one.
* <p>
* This is exactly the same as {@link #orderBy(String)}.
*/
public Query<T> order(String orderByClause) {
return query().order(orderByClause);
}
/**
* Returns the <code>order by</code> clause so that you can append an ascending or descending
* property to the <code>order by</code> clause.
* <p>
* This is exactly the same as {@link #order}.
* <p>
* Equivalent to {@link Query#orderBy()}
*/
public OrderBy<T> orderBy() {
return query().orderBy();
}
/**
* Set the <code>order by</code> clause replacing the existing <code>order by</code> clause if
* there is one.
* <p>
* This is exactly the same as {@link #order(String)}.
*/
public Query<T> orderBy(String orderByClause) {
return query().orderBy(orderByClause);
}
/**
* Sets the first row to return for this query.
* <p>
* Equivalent to {@link Query#setFirstRow(int)}
*/
public Query<T> setFirstRow(int firstRow) {
return query().setFirstRow(firstRow);
}
/**
* Sets the maximum number of rows to return in the query.
* <p>
* Equivalent to {@link Query#setMaxRows(int)}
*/
public Query<T> setMaxRows(int maxRows) {
return query().setMaxRows(maxRows);
}
/**
* Sets the ID value to query.
*
* <p>
* Use this to perform a find byId query but with additional control over the query such as
* using select and fetch to control what parts of the object graph are returned.
* <p>
* Equivalent to {@link Query#setId(Object)}
*/
public Query<T> setId(Object id) {
return query().setId(id);
}
/**
* Create and return a new query based on the <code>RawSql</code>.
* <p>
* Equivalent to {@link Query#setRawSql(RawSql)}
*/
public Query<T> setRawSql(RawSql rawSql) {
return query().setRawSql(rawSql);
}
/**
* Create a query with explicit 'AutoTune' use.
*/
public Query<T> setAutoTune(boolean autoTune) {
return query().setAutoTune(autoTune);
}
/**
* Create a query with the select with "for update" specified.
*
* <p>
* This will typically create row level database locks on the selected rows.
*/
public Query<T> setForUpdate(boolean forUpdate) {
return query().setForUpdate(forUpdate);
}
/**
* Create a query specifying whether the returned beans will be read-only.
*/
public Query<T> setReadOnly(boolean readOnly) {
return query().setReadOnly(readOnly);
}
/**
* Create a query specifying if the beans should be loaded into the L2 cache.
*/
public Query<T> setLoadBeanCache(boolean loadBeanCache) {
return query().setLoadBeanCache(loadBeanCache);
}
/**
* Create a query specifying if the L2 bean cache should be used.
*/
public Query<T> setUseCache(boolean useBeanCache) {
return query().setUseCache(useBeanCache);
}
/**
* Create a query specifying if the L2 query cache should be used.
*/
public Query<T> setUseQueryCache(boolean useQueryCache) {
return query().setUseQueryCache(useQueryCache);
}
}
}
}
+17 -17
View File
@@ -30,7 +30,7 @@ public final class OrderBy<T> implements Serializable {
public OrderBy() {
this.list = new ArrayList<>(3);
}
private OrderBy(List<Property> list) {
this.list = list;
}
@@ -60,8 +60,8 @@ public final class OrderBy<T> implements Serializable {
* Reverse the ascending/descending order on all the properties.
*/
public void reverse() {
for (int i = 0; i < list.size(); i++) {
list.get(i).reverse();
for (Property aList : list) {
aList.reverse();
}
}
@@ -88,8 +88,8 @@ public final class OrderBy<T> implements Serializable {
*/
public boolean containsProperty(String propertyName) {
for (int i = 0; i < list.size(); i++) {
if (propertyName.equals(list.get(i).getProperty())) {
for (Property aList : list) {
if (propertyName.equals(aList.getProperty())) {
return true;
}
}
@@ -101,12 +101,12 @@ public final class OrderBy<T> implements Serializable {
*/
public OrderBy<T> copyWithTrim(String path) {
List<Property> newList = new ArrayList<>(list.size());
for (int i = 0; i < list.size(); i++) {
newList.add(list.get(i).copyWithTrim(path));
for (Property aList : list) {
newList.add(aList.copyWithTrim(path));
}
return new OrderBy<>(newList);
}
/**
* Return the properties for this OrderBy.
*/
@@ -142,8 +142,8 @@ public final class OrderBy<T> implements Serializable {
public OrderBy<T> copy() {
OrderBy<T> copy = new OrderBy<>();
for (int i = 0; i < list.size(); i++) {
copy.add(list.get(i).copy());
for (Property aList : list) {
copy.add(aList.copy());
}
return copy;
}
@@ -192,7 +192,7 @@ public final class OrderBy<T> implements Serializable {
if (!(obj instanceof OrderBy<?>)) {
return false;
}
OrderBy<?> e = (OrderBy<?>) obj;
return e.list.equals(list);
}
@@ -294,7 +294,7 @@ public final class OrderBy<T> implements Serializable {
sb.append(" ").append("desc");
}
sb.append(" ").append(nulls).append(" ").append(highLow);
return sb.toString();
return sb.toString();
}
}
@@ -356,8 +356,8 @@ public final class OrderBy<T> implements Serializable {
}
String[] chunks = orderByClause.split(",");
for (int i = 0; i < chunks.length; i++) {
String[] pairs = chunks[i].split(" ");
for (String chunk : chunks) {
String[] pairs = chunk.split(" ");
Property p = parseProperty(pairs);
if (p != null) {
list.add(p);
@@ -371,9 +371,9 @@ public final class OrderBy<T> implements Serializable {
}
ArrayList<String> wordList = new ArrayList<>(pairs.length);
for (int i = 0; i < pairs.length; i++) {
if (!isEmptyString(pairs[i])) {
wordList.add(pairs[i]);
for (String pair : pairs) {
if (!isEmptyString(pair)) {
wordList.add(pair);
}
}
if (wordList.isEmpty()) {
+5 -13
View File
@@ -16,8 +16,7 @@ import java.util.concurrent.Future;
* the query. This translates into SQL that uses limit offset, rownum or row_number function to
* limit the result set.
* </p>
*
*
* <p>
* <h4>Example: typical use including total row count</h4>
* <pre>{@code
*
@@ -43,8 +42,7 @@ import java.util.concurrent.Future;
* int totalRowCount = pagedList.getTotalRowCount();
*
* }</pre>
*
*
* <p>
* <h4>Example: No total row count required</h4>
* <pre>{@code
*
@@ -57,9 +55,7 @@ import java.util.concurrent.Future;
*
* }</pre>
*
* @param <T>
* the entity bean type
*
* @param <T> the entity bean type
* @see Query#findPagedList()
*/
public interface PagedList<T> {
@@ -79,7 +75,6 @@ public interface PagedList<T> {
* int totalRowCount = pagedList.getTotalRowCount();
*
* }</pre>
*
* <p>
* Also note that using loadRowCount() and getTotalRowCount() rather than getFutureRowCount()
* means that exceptions ExecutionException, InterruptedException, TimeoutException are instead
@@ -192,11 +187,8 @@ public interface PagedList<T> {
* the total row count query if it has not already been invoked.
* </p>
*
* @param to
* String to put between the first and last row
* @param of
* String to put between the last row and the total row count
*
* @param to String to put between the first and last row
* @param of String to put between the last row and the total row count
* @return String of the format XtoYofZ.
*/
String getDisplayXtoYofZ(String to, String of);
@@ -71,6 +71,9 @@ class PrimaryServer {
}
}
}
if (defaultServerName == null) {
defaultServerName = "db";
}
return defaultServerName;
}
+43 -4
View File
@@ -7,6 +7,8 @@ import java.sql.Timestamp;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
* Object relational query for finding a List, Set, Map or single entity bean.
@@ -253,6 +255,43 @@ public interface Query<T> {
*/
Query<T> setPersistenceContextScope(PersistenceContextScope scope);
/**
* Set the index(es) to search for a document store which uses partitions.
* <p>
* For example, when executing a query against ElasticSearch with daily indexes we can
* explicitly specify the indexes to search against.
* </p>
* <pre>{@code
*
* // explicitly specify the indexes to search
* query.setDocIndexName("logstash-2016.11.5,logstash-2016.11.6")
*
* // search today's index
* query.setDocIndexName("$today")
*
* // search the last 3 days
* query.setDocIndexName("$last-3")
*
* }</pre>
* <p>
* If the indexName is specified with ${daily} e.g. "logstash-${daily}" ... then we can use
* $today and $last-x as the search docIndexName like the examples below.
* </p>
* <pre>{@code
*
* // search today's index
* query.setDocIndexName("$today")
*
* // search the last 3 days
* query.setDocIndexName("$last-3")
*
* }</pre>
*
* @param indexName The index or indexes to search against
* @return This query
*/
Query<T> setDocIndexName(String indexName);
/**
* Return the ExpressionFactory used by this query.
*/
@@ -627,7 +666,7 @@ public interface Query<T> {
*
* @param consumer the consumer used to process the queried beans.
*/
void findEach(QueryEachConsumer<T> consumer);
void findEach(Consumer<T> consumer);
/**
* Execute the query using callbacks to a visitor to process the resulting
@@ -662,7 +701,7 @@ public interface Query<T> {
*
* @param consumer the consumer used to process the queried beans.
*/
void findEachWhile(QueryEachWhileConsumer<T> consumer);
void findEachWhile(Predicate<T> consumer);
/**
* Execute the query returning the list of objects.
@@ -724,7 +763,7 @@ public interface Query<T> {
/**
* Execute the query returning a list of values for a single property.
*
* <p>
* <h3>Example 1:</h3>
* <pre>{@code
*
@@ -735,7 +774,7 @@ public interface Query<T> {
* .findSingleAttributeList();
*
* }</pre>
*
* <p>
* <h3>Example 2:</h3>
* <pre>{@code
*
@@ -1,41 +0,0 @@
package com.avaje.ebean;
/**
* Used to process a query result one bean at a time via a callback to this
* visitor.
* <p>
* If you wish to stop further processing return false from the accept method.
* </p>
* <p>
* Unlike findList() and findSet() using a QueryResultVisitor does not require
* all the beans in the query result to be held in memory at once. This makes
* QueryResultVisitor useful for processing large queries.
* </p>
*
* <pre>{@code
*
* Query<Customer> query = server.find(Customer.class)
* .where().eq("status", Status.NEW)
* .order().asc("id");
*
* query.findEach((Customer customer) -> {
*
* // do something with customer
* System.out.println("-- visit " + customer);
* });
*
* }</pre>
*
* @param <T>
* the type of entity bean being queried.
*/
public interface QueryEachConsumer<T> {
/**
* Process the bean.
*
* @param bean
* the entity bean to process
*/
void accept(T bean);
}
@@ -1,45 +0,0 @@
package com.avaje.ebean;
/**
* Used to process a query result one bean at a time via a callback to this
* visitor.
* <p>
* If you wish to stop further processing return false from the accept method.
* </p>
* <p>
* Unlike findList() and findSet() using a QueryResultVisitor does not require
* all the beans in the query result to be held in memory at once. This makes
* QueryResultVisitor useful for processing large queries.
* </p>
* <p/>
* <pre class="code">
*
* Query&lt;Customer&gt; query = server.find(Customer.class)
* .fetch(&quot;contacts&quot;, new FetchConfig().query(2))
* .where().gt(&quot;id&quot;, 0)
* .orderBy(&quot;id&quot;)
* .setMaxRows(2);
*
* query.findEachWhile((Customer customer) -> {
*
* // do something with customer
* System.out.println(&quot;-- visit &quot; + customer);
*
* // return true to continue processing or false to stop
* return (customer.getId() < 40);
* });
* </pre>
*
* @param <T> the type of entity bean being queried.
*/
public interface QueryEachWhileConsumer<T> {
/**
* Process the bean and return true if you want to continue processing more
* beans. Return false if you want to stop processing further.
*
* @param bean the entity bean to process
* @return true to continue processing more beans or false to stop.
*/
boolean accept(T bean);
}
@@ -17,11 +17,12 @@ import java.util.Iterator;
* </p>
* <p>
* Remember that with {@link QueryIterator} you must call {@link QueryIterator#close()}
* when you have finished iterating the results (typically in a finally block).
* when you have finished iterating the results. Use "try with resources" or ensure it
* is closed in a finally block.
* </p>
*
* <h3>Try finally style</h3>
* <pre>{@code
*
*
* Query<Customer> query = server.find(Customer.class)
* .where().gt("id", 0)
* .orderBy("id")
@@ -39,9 +40,21 @@ import java.util.Iterator;
* }
*
* }</pre>
*
* @param <T>
* the type of entity bean in the iteration
* <p>
* <h3>Try with resources style</h3>
* <pre>{@code
*
* // try with resources
* try (QueryIterator<Customer> it = query.findIterate()) {
* while (it.hasNext()) {
* Customer customer = it.next();
* // do something with customer ...
* }
* }
*
* }</pre>
*
* @param <T> the type of entity bean in the iteration
*/
public interface QueryIterator<T> extends Iterator<T>, java.io.Closeable {
+40 -43
View File
@@ -1,10 +1,15 @@
package com.avaje.ebean;
import com.avaje.ebean.util.CamelCaseHelper;
import java.io.Serializable;
import java.sql.ResultSet;
import java.util.*;
import com.avaje.ebean.util.CamelCaseHelper;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Used to build object graphs based on a raw SQL statement (rather than
@@ -51,39 +56,38 @@ import com.avaje.ebean.util.CamelCaseHelper;
* to hold the values for the aggregate functions (sum etc) and a &#064;OneToOne
* to Order.
* </p>
*
* <p>
* <h3>Example OrderAggregate</h3>
*
* <pre>{@code
* ...
* // @Sql indicates to that this bean
* // is based on RawSql rather than a table
*
*
* @Entity
* @Sql
* public class OrderAggregate {
*
*
* @OneToOne
* Order order;
*
*
* Double totalAmount;
*
*
* Double totalItems;
*
*
* // getters and setters
* ...
*
* }</pre>
*
* <p>
* <h3>Example 1:</h3>
*
* <p>
* <pre>{@code
*
* String sql = " select order_id, o.status, c.id, c.name, sum(d.order_qty*d.unit_price) as totalAmount"
* + " from o_order o"
* + " join o_customer c on c.id = o.kcustomer_id "
* + " join o_order_detail d on d.order_id = o.id " + " group by order_id, o.status ";
*
*
* RawSql rawSql = RawSqlBuilder.parse(sql)
* // map the sql result columns to bean properties
* .columnMapping("order_id", "order.id")
@@ -93,35 +97,34 @@ import com.avaje.ebean.util.CamelCaseHelper;
* // we don't need to map this one due to the sql column alias
* // .columnMapping("sum(d.order_qty*d.unit_price)", "totalAmount")
* .create();
*
*
* List<OrderAggregate> list = Ebean.find(OrderAggregate.class)
* .setRawSql(rawSql)
* .where().gt("order.id", 0)
* .having().gt("totalAmount", 20)
* .findList();
*
*
*
* }</pre>
*
* <p>
* <h3>Example 2:</h3>
*
* <p>
* The following example uses a FetchConfig().query() so that after the initial
* RawSql query is executed Ebean executes a secondary query to fetch the
* associated order status, orderDate along with the customer name.
* </p>
*
* <p>
* <pre>{@code
*
* String sql = " select order_id, 'ignoreMe', sum(d.order_qty*d.unit_price) as totalAmount "
* + " from o_order_detail d"
* + " group by order_id ";
*
*
* RawSql rawSql = RawSqlBuilder.parse(sql)
* .columnMapping("order_id", "order.id")
* .columnMappingIgnore("'ignoreMe'")
* .create();
*
*
* List<OrderAggregate> orders = Ebean.find(OrderAggregate.class)
* .setRawSql(rawSql)
* .fetch("order", "status,orderDate", new FetchConfig().query())
@@ -131,13 +134,12 @@ import com.avaje.ebean.util.CamelCaseHelper;
* .order().desc("totalAmount")
* .setMaxRows(10)
* .findList();
*
*
* }</pre>
*
*
* <p>
* <h3>Example 3: tableAliasMapping</h3>
* <p>
* Instead of mapping each column you can map each table alias to a path using tableAliasMapping().
* Instead of mapping each column you can map each table alias to a path using tableAliasMapping().
* </p>
* <pre>{@code
*
@@ -162,19 +164,17 @@ import com.avaje.ebean.util.CamelCaseHelper;
* .findList();
*
* }</pre>
*
*
* <p>
* <p>
* Note that lazy loading also works with object graphs built with RawSql.
* </p>
*
*/
public final class RawSql implements Serializable {
private static final long serialVersionUID = 1L;
private final ResultSet resultSet;
private final Sql sql;
private final ColumnMapping columnMapping;
@@ -192,7 +192,7 @@ public final class RawSql implements Serializable {
this.sql = null;
this.columnMapping = new ColumnMapping(propertyNames);
}
protected RawSql(ResultSet resultSet, Sql sql, ColumnMapping columnMapping) {
this.resultSet = resultSet;
this.sql = sql;
@@ -214,7 +214,7 @@ public final class RawSql implements Serializable {
String unParsedSql = (sql == null) ? "" : sql.unparsedSql;
return new Key(parsed, unParsedSql, columnMapping);
}
/**
* Return the resultSet if this is a ResultSet based RawSql.
*/
@@ -278,7 +278,7 @@ public final class RawSql implements Serializable {
* Construct for parsed SQL.
*/
protected Sql(String unparsedSql, String preFrom, String preWhere, boolean andWhereExpr,
String preHaving, boolean andHavingExpr, String orderByPrefix, String orderBy, boolean distinct) {
String preHaving, boolean andHavingExpr, String orderByPrefix, String orderBy, boolean distinct) {
this.unparsedSql = unparsedSql;
this.parsed = true;
@@ -296,8 +296,7 @@ public final class RawSql implements Serializable {
if (!parsed) {
return "unparsed[" + unparsedSql + "]";
}
return "select[" + preFrom + "] preWhere[" + preWhere + "] preHaving[" + preHaving
+ "] orderBy[" + orderBy + "]";
return "select[" + preFrom + "] preWhere[" + preWhere + "] preHaving[" + preHaving + "] orderBy[" + orderBy + "]";
}
public boolean isDistinct() {
@@ -386,7 +385,7 @@ public final class RawSql implements Serializable {
private final LinkedHashMap<String, Column> dbColumnMap;
private final Map<String, String> propertyMap;
private final Map<String, Column> propertyColumnMap;
private final boolean parsed;
@@ -402,8 +401,7 @@ public final class RawSql implements Serializable {
this.propertyMap = null;
this.propertyColumnMap = null;
this.dbColumnMap = new LinkedHashMap<>();
for (int i = 0; i < columns.size(); i++) {
Column c = columns.get(i);
for (Column c : columns) {
dbColumnMap.put(c.getDbColumnKey(), c);
}
}
@@ -418,7 +416,7 @@ public final class RawSql implements Serializable {
this.propertyColumnMap = null;
this.dbColumnMap = new LinkedHashMap<>();
}
/**
* Construct for ResultSet use.
*/
@@ -476,9 +474,8 @@ public final class RawSql implements Serializable {
/**
* Creates an immutable copy of this ColumnMapping.
*
* @throws IllegalStateException
* when a propertyName has not been defined for a column.
*
* @throws IllegalStateException when a propertyName has not been defined for a column.
*/
protected ColumnMapping createImmutableCopy() {
@@ -567,7 +564,7 @@ public final class RawSql implements Serializable {
*/
public void tableAliasMapping(String tableAlias, String path) {
String startMatch = tableAlias+".";
String startMatch = tableAlias + ".";
for (Map.Entry<String, Column> entry : dbColumnMap.entrySet()) {
if (entry.getKey().startsWith(startMatch)) {
entry.getValue().tableAliasMapping(path);
@@ -720,8 +717,8 @@ public final class RawSql implements Serializable {
Key that = (Key) o;
return parsed == that.parsed
&& columnMapping.equals(that.columnMapping)
&& unParsedSql.equals(that.unParsedSql);
&& columnMapping.equals(that.columnMapping)
&& unParsedSql.equals(that.unParsedSql);
}
@Override
@@ -1,17 +1,17 @@
package com.avaje.ebean;
import java.sql.ResultSet;
import com.avaje.ebean.RawSql.ColumnMapping;
import com.avaje.ebean.RawSql.Sql;
import java.sql.ResultSet;
/**
* Builds RawSql instances from a SQL string and column mappings.
* <p>
* Note that RawSql can also be defined in ebean-orm.xml files and be used as a
* named query.
* </p>
*
*
* @see RawSql
*/
public class RawSqlBuilder {
@@ -22,7 +22,7 @@ public class RawSqlBuilder {
public static final String IGNORE_COLUMN = "$$_IGNORE_COLUMN_$$";
private final ResultSet resultSet;
private final Sql sql;
private final ColumnMapping columnMapping;
@@ -37,7 +37,7 @@ public class RawSqlBuilder {
public static RawSql resultSet(ResultSet resultSet, String... propertyNames) {
return new RawSql(resultSet, propertyNames);
}
/**
* Return an unparsed RawSqlBuilder. Unlike a parsed one this query can not be
* modified - so no additional WHERE or HAVING expressions can be added to
@@ -70,7 +70,7 @@ public class RawSqlBuilder {
ColumnMapping mapping = DRawSqlColumnsParser.parse(select);
return new RawSqlBuilder(sql2, mapping);
}
private RawSqlBuilder(Sql sql, ColumnMapping columnMapping) {
this.sql = sql;
this.columnMapping = columnMapping;
@@ -83,11 +83,9 @@ public class RawSqlBuilder {
* For Unparsed SQL the columnMapping MUST be defined in the same order that
* the columns appear in the SQL statement.
* </p>
*
* @param dbColumn
* the DB column that we are mapping to a bean property
* @param propertyName
* the bean property that we are mapping the DB column to.
*
* @param dbColumn the DB column that we are mapping to a bean property
* @param propertyName the bean property that we are mapping the DB column to.
*/
public RawSqlBuilder columnMapping(String dbColumn, String propertyName) {
columnMapping.columnMapping(dbColumn, propertyName);
@@ -130,6 +128,4 @@ public class RawSqlBuilder {
return sql;
}
}
+10 -10
View File
@@ -2,6 +2,8 @@ package com.avaje.ebean;
import java.io.Serializable;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
* Query object for performing native SQL queries that return SqlRow's.
@@ -18,23 +20,22 @@ import java.util.List;
* The returned SqlRow objects are similar to a LinkedHashMap with some type
* conversion support added.
* </p>
*
* <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
*
*
* 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();
*
* }</pre>
*
*/
public interface SqlQuery extends Serializable {
@@ -49,7 +50,7 @@ public interface SqlQuery extends Serializable {
* This streaming type query is useful for large query execution as only 1 row needs to be held in memory.
* </p>
*/
void findEach(QueryEachConsumer<SqlRow> consumer);
void findEach(Consumer<SqlRow> consumer);
/**
* Execute the SqlQuery iterating a row at a time with the ability to stop consuming part way through.
@@ -60,7 +61,7 @@ public interface SqlQuery extends Serializable {
* This streaming type query is useful for large query execution as only 1 row needs to be held in memory.
* </p>
*/
void findEachWhile(QueryEachWhileConsumer<SqlRow> consumer);
void findEachWhile(Predicate<SqlRow> consumer);
/**
* Execute the query returning a single row or null.
@@ -98,9 +99,8 @@ public interface SqlQuery extends Serializable {
* preparedStatement. If the timeout occurs an exception will be thrown - this
* will be a SQLException wrapped up in a PersistenceException.
* </p>
*
* @param secs
* the query timeout limit in seconds. Zero means there is no limit.
*
* @param secs the query timeout limit in seconds. Zero means there is no limit.
*/
SqlQuery setTimeout(int secs);
+14 -12
View File
@@ -16,19 +16,21 @@ package com.avaje.ebean;
* notify Ebean of external changes and enable Ebean to maintain it's "L2"
* server cache.
* </p>
*
* <pre class="code">
* // example that uses 'named' parameters
* String s = &quot;UPDATE f_topic set post_count = :count where id = :id&quot;
* <p>
* <pre>{@code
*
* // example that uses 'named' parameters
* String s = "UPDATE f_topic set post_count = :count where id = :id";
* SqlUpdate update = Ebean.createSqlUpdate(s);
* update.setParameter(&quot;id&quot;, 1);
* update.setParameter(&quot;count&quot;, 50);
*
* update.setParameter("id", 1);
* update.setParameter("count", 50);
*
* int modifiedCount = Ebean.execute(update);
*
* String msg = &quot;There were &quot; + modifiedCount + &quot; rows updated&quot;
* </pre>
*
*
* String msg = "There were " + modifiedCount + " rows updated";
*
* }</pre>
*
* @see Update
* @see SqlQuery
* @see CallableSql
@@ -47,7 +49,7 @@ public interface SqlUpdate {
* {@link Transaction#setBatchMode(boolean)} and
* {@link Transaction#setBatchSize(int)}.
* </p>
*
*
* @see com.avaje.ebean.Ebean#execute(SqlUpdate)
*/
int execute();
+30 -33
View File
@@ -62,10 +62,10 @@ public interface Transaction extends Closeable {
* </p>
* <h3>Functions/h3>
* <ul>
* <li>Flush the JDBC batch buffer</li>
* <li>Call commit on the underlying JDBC connection</li>
* <li>Trigger any registered TransactionCallbacks</li>
* <li>Perform post-commit processing updating L2 cache, ElasticSearch etc</li>
* <li>Flush the JDBC batch buffer</li>
* <li>Call commit on the underlying JDBC connection</li>
* <li>Trigger any registered TransactionCallbacks</li>
* <li>Perform post-commit processing updating L2 cache, ElasticSearch etc</li>
* </ul>
*/
void commitAndContinue() throws RollbackException;
@@ -78,12 +78,12 @@ public interface Transaction extends Closeable {
* </p>
* <h3>Functions/h3>
* <ul>
* <li>Flush the JDBC batch buffer</li>
* <li>Call commit on the underlying JDBC connection</li>
* <li>Trigger any registered TransactionCallbacks</li>
* <li>Perform post-commit processing updating L2 cache, ElasticSearch etc</li>
* <li>Close any underlying resources, closing the underlying JDBC connection</li>
* <li>Mark the transaction as "Inactive"</li>
* <li>Flush the JDBC batch buffer</li>
* <li>Call commit on the underlying JDBC connection</li>
* <li>Trigger any registered TransactionCallbacks</li>
* <li>Perform post-commit processing updating L2 cache, ElasticSearch etc</li>
* <li>Close any underlying resources, closing the underlying JDBC connection</li>
* <li>Mark the transaction as "Inactive"</li>
* </ul>
*/
void commit() throws RollbackException;
@@ -95,10 +95,10 @@ public interface Transaction extends Closeable {
* </p>
* <h3>Functions/h3>
* <ul>
* <li>Call rollback on the underlying JDBC connection</li>
* <li>Trigger any registered TransactionCallbacks</li>
* <li>Close any underlying resources, closing the underlying JDBC connection</li>
* <li>Mark the transaction as "Inactive"</li>
* <li>Call rollback on the underlying JDBC connection</li>
* <li>Trigger any registered TransactionCallbacks</li>
* <li>Close any underlying resources, closing the underlying JDBC connection</li>
* <li>Mark the transaction as "Inactive"</li>
* </ul>
*/
void rollback() throws PersistenceException;
@@ -136,10 +136,10 @@ public interface Transaction extends Closeable {
/**
* Set the behavior for document store updates on this transaction.
* <p>
* For example, set the mode to DocStoreEvent.IGNORE for this transaction and
* then any changes via this transaction are not sent to the doc store. This
* would be used when doing large bulk inserts into the database and we want
* to control how that is sent to the document store.
* For example, set the mode to DocStoreEvent.IGNORE for this transaction and
* then any changes via this transaction are not sent to the doc store. This
* would be used when doing large bulk inserts into the database and we want
* to control how that is sent to the document store.
* </p>
*/
void setDocStoreMode(DocStoreMode mode);
@@ -147,11 +147,11 @@ public interface Transaction extends Closeable {
/**
* Set the batch size to use for sending messages to the document store.
* <p>
* You might set this if you know the changes in this transaction result in especially large or
* especially small payloads and want to adjust the batch size to match.
* You might set this if you know the changes in this transaction result in especially large or
* especially small payloads and want to adjust the batch size to match.
* </p>
* <p>
* Setting this overrides the default of {@link DocStoreConfig#getBulkBatchSize()}
* Setting this overrides the default of {@link DocStoreConfig#getBulkBatchSize()}
* </p>
*/
void setDocStoreBatchSize(int batchSize);
@@ -197,7 +197,7 @@ public interface Transaction extends Closeable {
* Refer to {@link ServerConfig#setSkipCacheAfterWrite(boolean)} for configuring the default behavior
* for using the L2 bean cache in transactions spanning multiple query/persist requests.
* </p>
*
* <p>
* <pre>{@code
*
* // assume Customer has L2 bean caching enabled ...
@@ -279,23 +279,23 @@ public interface Transaction extends Closeable {
* <p>
* Example: batch processing executing every 3 rows
* </p>
*
* <p>
* <pre>{@code
*
* String data = "This is a simple test of the batch processing"
* + " mode and the transaction execute batch method";
*
*
* String[] da = data.split(" ");
*
*
* String sql = "{call sp_t3(?,?)}";
*
*
* CallableSql cs = new CallableSql(sql);
* cs.registerOut(2, Types.INTEGER);
*
*
* // (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);
@@ -304,16 +304,15 @@ public interface Transaction extends Closeable {
* cs.setParameter(1, da[i]);
* ebeanServer.execute(cs);
* }
*
*
* // NB: commit implicitly flushes
* txn.commit();
*
*
* } finally {
* txn.end();
* }
*
* }</pre>
*
*/
void setBatchMode(boolean useBatch);
@@ -325,7 +324,6 @@ public interface Transaction extends Closeable {
* </p>
*
* @param persistBatchMode the batch mode to use for this transaction
*
* @see com.avaje.ebean.config.ServerConfig#setPersistBatch(com.avaje.ebean.config.PersistBatch)
*/
void setBatch(PersistBatch persistBatchMode);
@@ -347,7 +345,6 @@ public interface Transaction extends Closeable {
* </p>
*
* @param batchOnCascadeMode the batch mode to use per save(), insert(), update() or delete()
*
* @see com.avaje.ebean.config.ServerConfig#setPersistBatchOnCascade(com.avaje.ebean.config.PersistBatch)
*/
void setBatchOnCascade(PersistBatch batchOnCascadeMode);
+12 -10
View File
@@ -12,24 +12,26 @@ package com.avaje.ebean;
* <p>
* See also {@link TxRunnable}.
* </p>
*
* <pre class="code">
* Ebean.execute(new TxCallable&lt;String&gt;() {
* <p>
* <pre>{@code
*
* Ebean.execute(new TxCallable<String>() {
* public String call() {
* User u1 = Ebean.find(User.class, 1);
* User u2 = Ebean.find(User.class, 2);
*
* u1.setName(&quot;u1 mod&quot;);
* u2.setName(&quot;u2 mod&quot;);
*
*
* u1.setName("u1 mod");
* u2.setName("u2 mod");
*
* Ebean.save(u1);
* Ebean.save(u2);
*
*
* return u1.getEmail();
* }
* });
* </pre>
*
*
* }</pre>
*
* @see TxRunnable
*/
public interface TxCallable<T> {
@@ -1,100 +0,0 @@
package com.avaje.ebean;
import java.sql.Connection;
/**
* The Transaction Isolation levels.
* <p>
* These match those of java.sql.Connection with the addition of DEFAULT which
* implies the configured default of the DataSource.
* </p>
* <p>
* This can be used with TxScope to define transactional scopes to execute
* method within.
* </p>
*
* @see TxScope
*/
public enum TxIsolation {
/**
* Read Committed Isolation level. This is typically the default for most
* configurations.
*/
READ_COMMITED(Connection.TRANSACTION_READ_COMMITTED),
/**
* Read uncommitted Isolation level.
*/
READ_UNCOMMITTED(Connection.TRANSACTION_READ_UNCOMMITTED),
/**
* Repeatable Read Isolation level.
*/
REPEATABLE_READ(Connection.TRANSACTION_REPEATABLE_READ),
/**
* Serializable Isolation level.
*/
SERIALIZABLE(Connection.TRANSACTION_SERIALIZABLE),
/**
* No Isolation level.
*/
NONE(Connection.TRANSACTION_NONE),
/**
* The default isolation level. This typically means the default that the
* DataSource is using or configured to use.
*/
DEFAULT(-1);
final int level;
TxIsolation(int level) {
this.level = level;
}
/**
* Return the level as per java.sql.Connection.
* <p>
* Note that -1 denotes the default isolation level.
* </p>
*/
public int getLevel() {
return level;
}
/**
* Return the TxIsolation given the java.sql.Connection isolation level.
* <p>
* Note that -1 denotes the default isolation level.
* </p>
*/
public static TxIsolation fromLevel(int connectionIsolationLevel) {
switch (connectionIsolationLevel) {
case Connection.TRANSACTION_READ_UNCOMMITTED:
return TxIsolation.READ_UNCOMMITTED;
case Connection.TRANSACTION_READ_COMMITTED:
return TxIsolation.READ_COMMITED;
case Connection.TRANSACTION_REPEATABLE_READ:
return TxIsolation.REPEATABLE_READ;
case Connection.TRANSACTION_SERIALIZABLE:
return TxIsolation.SERIALIZABLE;
case Connection.TRANSACTION_NONE:
return TxIsolation.NONE;
case -1:
return TxIsolation.DEFAULT;
default:
throw new RuntimeException("Unknown isolation level " + connectionIsolationLevel);
}
}
}
+11 -10
View File
@@ -8,26 +8,27 @@ package com.avaje.ebean;
* <p>
* See also {@link TxCallable}.
* </p>
*
* <pre class="code">
*
* <p>
* <pre>{@code
*
* // this run method runs in a transaction scope
* // which by default is TxScope.REQUIRED
*
*
* Ebean.execute(new TxRunnable() {
* public void run() {
* User u1 = Ebean.find(User.class, 1);
* User u2 = Ebean.find(User.class, 2);
*
* u1.setName(&quot;u1 mod&quot;);
* u2.setName(&quot;u2 mod&quot;);
*
*
* u1.setName("u1 mod");
* u2.setName("u2 mod");
*
* Ebean.save(u1);
* Ebean.save(u2);
* }
* });
* </pre>
*
*
* }</pre>
*
* @see TxCallable
*/
public interface TxRunnable {
+5 -6
View File
@@ -105,8 +105,7 @@ public final class TxScope {
*/
public String toString() {
return "TxScope[" + type + "] readOnly[" + readOnly + "] isolation[" + isolation
+ "] serverName[" + serverName
+ "] rollbackFor[" + rollbackFor + "] noRollbackFor[" + noRollbackFor + "]";
+ "] serverName[" + serverName + "] rollbackFor[" + rollbackFor + "] noRollbackFor[" + noRollbackFor + "]";
}
/**
@@ -296,8 +295,8 @@ public final class TxScope {
if (rollbackFor == null) {
rollbackFor = new ArrayList<>(rollbackThrowables.length);
}
for (int i = 0; i < rollbackThrowables.length; i++) {
rollbackFor.add((Class<? extends Throwable>) rollbackThrowables[i]);
for (Class<?> rollbackThrowable : rollbackThrowables) {
rollbackFor.add((Class<? extends Throwable>) rollbackThrowable);
}
return this;
}
@@ -330,8 +329,8 @@ public final class TxScope {
if (noRollbackFor == null) {
noRollbackFor = new ArrayList<>(noRollbacks.length);
}
for (int i = 0; i < noRollbacks.length; i++) {
noRollbackFor.add((Class<? extends Throwable>) noRollbacks[i]);
for (Class<?> noRollback : noRollbacks) {
noRollbackFor.add((Class<? extends Throwable>) noRollback);
}
return this;
}
-50
View File
@@ -1,50 +0,0 @@
package com.avaje.ebean;
/**
* Used to define the transactional scope for executing a method. Matches the
* types defined in the EJB TransactionAttributeType.
* <p>
* Used with the Transactional annotation and the {@link TxScope} with
* {@link Ebean#execute(TxScope, TxCallable)} and
* {@link Ebean#execute(TxScope, TxRunnable)}.
* </p>
*
* @see TxScope
*/
public enum TxType {
/**
* Uses an existing transaction and if none exists will starts a new
* Transaction. This is the default.
*/
REQUIRED,
/**
* A transaction MUST already have been started. Throws
* TransactionRequiredException.
*/
MANDATORY,
/**
* Uses the existing transaction if one exists, otherwise the method does not
* run with a transaction. Used this with caution.
*/
SUPPORTS,
/**
* Always start a new transaction. Suspend an existing once if required.
*/
REQUIRES_NEW,
/**
* Suspends an existing transaction if required. Method runs without a
* transaction.
*/
NOT_SUPPORTED,
/**
* If there is an existing transaction throws an Exception. Method runs
* without a transaction.
*/
NEVER
}
+43 -52
View File
@@ -11,43 +11,43 @@ package com.avaje.ebean;
* <p>
* The following is an example of named updates on an entity bean.
* </p>
*
* <pre type="class">
* <pre>{@code
* ...
* &#064;NamedUpdates(value = {
* &#064;NamedUpdate(
* name = &quot;setTitle&quot;,
* notifyCache = false,
* update = &quot;update topic set title = :title, postCount = :count where id = :id&quot;),
* &#064;NamedUpdate(
* name = &quot;setPostCount&quot;,
* notifyCache = false,
* update = &quot;update f_topic set post_count = :postCount where id = :id&quot;),
* &#064;NamedUpdate(
* name = &quot;incrementPostCount&quot;,
* notifyCache = false,
* update = &quot;update Topic set postCount = postCount + 1 where id = :id&quot;)
* //update = &quot;update f_topic set post_count = post_count + 1 where id = :id&quot;)
* @NamedUpdates(value = {
* @NamedUpdate(
* name = "setTitle",
* notifyCache = false,
* update = "update topic set title = :title, postCount = :count where id = :id"),
* @NamedUpdate(
* name = "setPostCount",
* notifyCache = false,
* update = "update f_topic set post_count = :postCount where id = :id"),
* @NamedUpdate(
* name = "incrementPostCount",
* notifyCache = false,
* update = "update Topic set postCount = postCount + 1 where id = :id")
* //update = "update f_topic set post_count = post_count + 1 where id = :id")
* })
* &#064;Entity
* &#064;Table(name = &quot;f_topic&quot;)
* @Entity
* @Table(name = "f_topic")
* public class Topic {
* ...
* </pre>
*
* }</pre>
*
* <p>
* The following show code that would use a named update on the Topic entity
* bean.
* </p>
*
* <pre class="code">
* Update&lt;Topic&gt; update = Ebean.createUpdate(Topic.class, &quot;incrementPostCount&quot;);
* update.setParameter(&quot;id&quot;, 1);
* <p>
* <pre>{@code
*
* Update<Topic> update = Ebean.createUpdate(Topic.class, "incrementPostCount");
* update.setParameter("id", 1);
* int rows = update.execute();
* </pre>
*
* @param <T>
* the type of entity beans inserted updated or deleted
*
* }</pre>
*
* @param <T> the type of entity beans inserted updated or deleted
*/
public interface Update<T> {
@@ -73,9 +73,8 @@ public interface Update<T> {
* preparedStatement. If the timeout occurs an exception will be thrown - this
* will be a SQLException wrapped up in a PersistenceException.
* </p>
*
* @param secs
* the timeout in seconds. Zero implies unlimited.
*
* @param secs the timeout in seconds. Zero implies unlimited.
*/
Update<T> setTimeout(int secs);
@@ -92,21 +91,17 @@ public interface Update<T> {
* <p>
* Set a value for each ? you have in the sql.
* </p>
*
* @param position
* the index position of the parameter starting with 1.
* @param value
* the parameter value to bind.
*
* @param position the index position of the parameter starting with 1.
* @param value the parameter value to bind.
*/
Update<T> set(int position, Object value);
/**
* Set and ordered bind parameter (same as bind).
*
* @param position
* the index position of the parameter starting with 1.
* @param value
* the parameter value to bind.
*
* @param position the index position of the parameter starting with 1.
* @param value the parameter value to bind.
*/
Update<T> setParameter(int position, Object value);
@@ -129,11 +124,9 @@ public interface Update<T> {
* <p>
* A more succinct version of setParameter() to be consistent with Query.
* </p>
*
* @param name
* the parameter name.
* @param value
* the parameter value.
*
* @param name the parameter name.
* @param value the parameter value.
*/
Update<T> set(String name, Object value);
@@ -148,11 +141,9 @@ public interface Update<T> {
* <p>
* A more succinct version of setNullParameter().
* </p>
*
* @param name
* the parameter name.
* @param jdbcType
* the type of the property being bound.
*
* @param name the parameter name.
* @param jdbcType the type of the property being bound.
*/
Update<T> setNull(String name, int jdbcType);
@@ -166,4 +157,4 @@ public interface Update<T> {
*/
String getGeneratedSql();
}
}
+12 -16
View File
@@ -7,9 +7,9 @@ package com.avaje.ebean;
* This UpdateQuery is more for the cases where we want to build the where expression of the update using the
* {@link ExpressionList} "Criteria API" that is used with a normal ORM query.
* </p>
*
* <p>
* <h4>Example: Simple update</h4>
*
* <p>
* <pre>{@code
*
* int rows = ebeanServer
@@ -26,18 +26,17 @@ package com.avaje.ebean;
* update o_customer set status=?, updtime=? where id > ?
*
* }</pre>
*
* <p>
* Note that if the where() clause contains a join then the SQL update changes to use a
* <code> WHERE ID IN () </code> form.
* </p>
*
* <p>
* <h4>Example: Update with a JOIN</h4>
* <p>
* In this example the expression <code>.eq("billingAddress.country", nz)</code> requires a join
* to the address table.
* In this example the expression <code>.eq("billingAddress.country", nz)</code> requires a join
* to the address table.
* </p>
*
* <p>
* <pre>{@code
*
* int rows = ebeanServer
@@ -50,7 +49,7 @@ package com.avaje.ebean;
* .gt("id", 1000)
* .update();
* }</pre>
*
* <p>
* <pre>{@code sql
*
* update o_customer set status=?, updtime=?
@@ -65,15 +64,13 @@ package com.avaje.ebean;
* }</pre>
*
* @param <T> The type of entity bean being updated
*
* @see SqlUpdate
*/
public interface UpdateQuery<T> {
/**
* Set the value of a property.
*
*
* <p>
* <pre>{@code
*
* int rows = ebeanServer
@@ -87,13 +84,13 @@ public interface UpdateQuery<T> {
* }</pre>
*
* @param property The bean property to be set
* @param value The value to set the property to
* @param value The value to set the property to
*/
UpdateQuery<T> set(String property, Object value);
/**
* Set the property to be null.
*
* <p>
* <pre>{@code
*
* int rows = ebeanServer
@@ -110,12 +107,11 @@ public interface UpdateQuery<T> {
UpdateQuery<T> setNull(String property);
/**
*
* Set using a property expression that does not need any bind values.
* <p>
* The property expression typically contains database functions.
* </p>
*
* <p>
* <pre>{@code
*
* int rows = ebeanServer
@@ -148,7 +144,7 @@ public interface UpdateQuery<T> {
* }</pre>
*
* @param propertyExpression A raw property expression
* @param values The values to bind with the property expression
* @param values The values to bind with the property expression
*/
UpdateQuery<T> setRaw(String propertyExpression, Object... values);
+1 -1
View File
@@ -29,7 +29,7 @@ public class ValuePair {
public Object getNewValue() {
return newValue;
}
/**
* Return the old value.
*/
@@ -1,50 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Specify a property to be an aggregation formula.
* <p>
* The aggregation formula should be a sum, count, avg, min or max.
* By default aggregation properties are treated as transient and not
* included in a query. To populate the aggregation property it must be
* explicitly included in the select().
* </p>
*
* <h3>Example:</h3>
* <pre>{@code
*
* @Aggregation("count(details)")
* Long totalCount;
*
* @Aggregation("sum(details.quantity*details.unitPrice)")
* Long totalAmount;
*
* }</pre>
*
* <h3>Example query</h3>
* <pre>{@code
*
* List<TEventOne> list = Ebean.find(TEventOne.class)
* .select("name, totalCount, totalUnits, totalAmount")
* .where()
* .startsWith("logs.description", "a")
* .having()
* .ge("count", 1)
* .orderBy().asc("name")
* .findList();
*
* }</pre>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Aggregation {
/**
* Aggregation formula using sum, count, avg, min, max.
*/
String value();
}
@@ -1,61 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Specify the default cache use specific entity type.
*/
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface Cache {
/**
* Set this to true to enable the use of query cache.
* <p>
* By default query caching is disabled as the query cache invalidates
* frequently and so it is typically used for specific bean types and cases.
* </p>
*/
boolean enableQueryCache() default false;
/**
* Set this to false to disable the use of bean cache.
* <p>
* By default bean caching is expected so this defaults to true. We might
* set this to false on a bean type that we want to use query caching but no
* bean caching (and this is expected to be a rare case).
* </p>
* <p>
* When bean caching is enabled by default "find by id" and "find by unique natural key"
* queries will try to use the bean cache. We use {@link com.avaje.ebean.Query#setUseCache(boolean)}
* with <code>false</code> for the case when we do NOT want to use the bean cache.
* </p>
*/
boolean enableBeanCache() default true;
/**
* Specify the property that is a natural unique identifier for the bean.
* <p>
* When a findUnique() query is used with this property as the sole expression
* then there will be a lookup into the L2 natural key cache.
* </p>
*/
String naturalKey() default "";
/**
* When set to true the beans returned from a query will default to be
* readOnly.
* <p>
* If the bean is readOnly and has no relationships then it may be sharable.
* </p>
* <p>
* If you try to modify a readOnly bean it will throw an
* IllegalStateException.
* </p>
*/
boolean readOnly() default false;
}
@@ -1,56 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Cache tuning hints for the L2 bean cache of a specific entity type.
* <p>
* Note that this is not useful when distributed L2 bean caches are used like
* ElasticSearch, Hazelcast, Ignite etc.
* </p>
*/
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface CacheBeanTuning {
/**
* The maximum size for the cache.
* <p>
* This defaults to 0 which means unlimited.
* </p>
*/
int maxSize() default 0;
/**
* The maximum time (in seconds) that a cache entry is allowed to stay in the
* cache when it has not been accessed.
* <p>
* This defaults to 0 which means unlimited.
* </p>
*/
int maxIdleSecs() default 0;
/**
* The maximum time (in seconds) a cache entry is allowed to stay in the
* cache.
* <p>
* This is not generally required as the cache entries are automatically
* evicted when related data changes are committed.
* </p>
* <p>
* This defaults to 0 which means unlimited.
* </p>
*/
int maxSecsToLive() default 0;
/**
* The frequency (in seconds) that cache trimming should occur.
* <p>
* This is a hint for cache implementations that use background cache trimming.
* </p>
*/
int trimFrequency() default 0;
}
@@ -1,55 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Specify cache tuning for query caching on a specific entity type.
* <p>
* If this is not specified then the system default settings are used.
* </p>
*/
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface CacheQueryTuning {
/**
* The maximum size for the cache.
* <p>
* This defaults to 0 which means unlimited.
* </p>
*/
int maxSize() default 0;
/**
* The maximum time (in seconds) that a cache entry is allowed to stay in the
* cache when it has not been accessed.
* <p>
* This defaults to 0 which means unlimited.
* </p>
*/
int maxIdleSecs() default 0;
/**
* The maximum time (in seconds) a cache entry is allowed to stay in the
* cache.
* <p>
* This is not generally required as the cache entries are automatically
* evicted when related data changes are committed.
* </p>
* <p>
* This defaults to 0 which means unlimited.
* </p>
*/
int maxSecsToLive() default 0;
/**
* The frequency (in seconds) that cache trimming should occur.
* <p>
* This is a hint for cache implementations that use background cache trimming.
* </p>
*/
int trimFrequency() default 0;
}
@@ -1,34 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Marks an entity bean as being included in the change logging.
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ChangeLog {
/**
* Specify if inserts should be explicitly Included or Excluded.
* <p>
* If not defined explicitly then the server default behaviour defined
* on ServerConfig is used.
* </p>
*/
ChangeLogInsertMode inserts() default ChangeLogInsertMode.DEFAULT;
/**
* When specified only include update requests that have at least one
* of the given properties as a dirty property.
* <p>
* This provides a way to filter requests to include in the change log such that
* only updates that include at least one of the given properties is included
* in the change log.
* </p>
*/
String[] updatesThatInclude() default {};
}
@@ -1,22 +0,0 @@
package com.avaje.ebean.annotation;
/**
* The mode used to determine if inserts should be included or not for a given bean type.
*/
public enum ChangeLogInsertMode {
/**
* Use the default behaviour as defined on ServerConfig.
*/
DEFAULT,
/**
* Include inserts in the change log.
*/
INCLUDE,
/**
* Exclude inserts in the change log.
*/
EXCLUDE
}
@@ -1,38 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* For a timestamp property that is set to the datetime when the entity is
* created/inserted.
* <p>
* This is effectively an alias for @WhenCreated which was added as it hints
* towards a better naming convention (WhenCreated, WhenModified).
* </p>
* <p>
* An alternative to using this annotation would be to use insertable=false,
* updateable=false with @Column and have the DB insert the current time
* (default value on the DB column is SYSTIME etc).
* </p>
* <p>
* The downside to this approach is that the inserted entity does not have the
* timestamp value after the insert has occurred. You need to fetch the entity
* back to get the inserted timestamp if you want to used it.
* </p>
*
* <h3>Example:</h3>
* <pre>{@code
*
* @CreatedTimestamp
* Timestamp whenCreated;
*
* }</pre>
*/
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface CreatedTimestamp {
}
@@ -1,40 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Specify a collection property that will be stored into a DB ARRAY type.
* <p>
* If the target database does not support ARRAY type (so not Postgres)
* then the collection will be stored in JSON format into a VARCHAR column.
* </p>
*
* <h3>Example:</h3>
* <pre>{@code
*
* // Store as ARRAY of UUID on Postgres
* @DbArray
* List<UUID> uids = new ArrayList<>();
*
* // Store as ARRAY on Postgres
* @DbArray
* List<String> phoneNumbers = new ArrayList<>();
*
* // Store as ARRAY of INTEGER on Postgres
* @DbArray
* List<Long> someLongs = new ArrayList<>();
*
* }</pre>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DbArray {
/**
* For VARCHAR storage specify the column length (defaults to 1000).
*/
int length() default 0;
}
@@ -1,19 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* A database table or column comment.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
public @interface DbComment {
/**
* The database table or column comment.
*/
String value();
}
@@ -1,17 +0,0 @@
package com.avaje.ebean.annotation;
/**
* Specify the DB storage type used to with <code>@DbEnumValue</code>.
*/
public enum DbEnumType {
/**
* Store values as database INTEGER.
*/
INTEGER,
/**
* Store values as database VARCHAR.
*/
VARCHAR
}
@@ -1,44 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Specify a method on an Enum that returns the value that should be stored in the DB.
* <p>
* This is the preferred option for mapping Enum's to DB values (preferred over the JPA
* standard @Enumerated and Ebean's @EnumValue annotations).
* </p>
* <h3>Example:</h3>
* <pre>{@code
*
* public enum Status {
* NEW("N"),
* ACTIVE("A"),
* INACTIVE("I");
*
* String dbValue;
* Status(String dbValue) {
* this.dbValue = dbValue;
* }
*
* @DbEnumValue
* public String getValue() {
* return dbValue;
* }
* }
*
* }</pre>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DbEnumValue {
/**
* Specify the database type used to store the values (VARCHAR or INTEGER).
*/
DbEnumType storage() default DbEnumType.VARCHAR;
}
@@ -1,30 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Used for mapping a Map<String,String> type property to Postgres HSTORE data type.
* <p>
* The Map property should have keys and values of type String.
* </p>
*
* <h3>Example:</h3>
* <pre>{@code
*
* @DbHstore
* Map<String, String> tags;
*
* }</pre>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DbHstore {
/**
* For VARCHAR storage specify the column length (defaults to 1000).
*/
int length() default 0;
}
@@ -1,44 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Specify a property holding JSON content.
* <p>
* By default the content will be stored in a DB Clob except on Postgres where DB JSON type is used.
* </p>
* <h3>Example:</h3>
* <pre>{@code
*
* // Store as JSON on Postgres or Clob on other databases
* @DbJson
* Map<String,Object> content;
*
* }</pre>
*
* <h3>Example with JSONB storage</h3>
* <pre>{@code
*
* // Store as JSONB on Postgres or Clob on other databases
* @DbJson(storage = DbJsonType.JSONB)
* Map<String,Object> content;
*
* }</pre>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DbJson {
/**
* Specify the database type used to store the JSON content.
*/
DbJsonType storage() default DbJsonType.JSON;
/**
* For VARCHAR storage specify the column length (defaults to 3000).
*/
int length() default 0;
}
@@ -1,43 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Specify a property holding JSON content.
* <p>
* The content will be stored on Postgres using it's JSONB type and as Clob for other databases.
* </p>
* <p>
* This is equivalent to using <code>@DbJson(storage = DbJsonType.JSONB)</code>
* </p>
*
* <h3>Example:</h3>
* <pre>{@code
*
* // Store as JSONB on Postgres or Clob on other databases
* @DbJsonB
* Map<String,Object> content;
*
* }</pre>
*
* <h3>Equivalent to:</h3>
* <pre>{@code
*
* // Store as JSONB on Postgres or Clob on other databases
* @DbJson(storage = DbJsonType.JSONB)
* Map<String,Object> content;
*
* }</pre>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DbJsonB {
/**
* For VARCHAR storage specify the column length.
*/
int length() default 0;
}
@@ -1,32 +0,0 @@
package com.avaje.ebean.annotation;
/**
* Specify the DB storage type used to store JSON content.
*/
public enum DbJsonType {
/**
* Store as JSON on Postgres and for other databases store as CLOB.
*/
JSON,
/**
* Store as JSONB on Postgres and for other databases store as CLOB.
*/
JSONB,
/**
* Store as database VARCHAR.
*/
VARCHAR,
/**
* Store as database CLOB.
*/
CLOB,
/**
* Store as database BLOB.
*/
BLOB
}
@@ -1,32 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Used to indicate that a particular string property should be treated as a 'code' and not analysed for text searching.
* <p>
* By default all Id properties and all Enum properties are treated as 'code' and not analysed.
* </p>
*/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DocCode {
/**
* Set to true to have the property additionally stored separately from _source.
*/
boolean store() default false;
/**
* Set a boost value specific to this property.
*/
float boost() default 1;
/**
* Set a value to use instead of null.
*/
String nullValue() default "";
}
@@ -1,37 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Specify the property is included in the parent document store index.
*
* <pre>{@code
*
*
* @DocStore
* @Entity @Table(name = "o_order")
* public class Order {
*
* ...
* // include some customer details including
* // nested billingAddress
* @DocEmbedded(doc = "id,status,name,billingAddress(*,country(*)")
* @ManyToOne
* Customer customer;
*
*
* }</pre>
*/
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface DocEmbedded {
/**
* The properties on the embedded bean to include in the index.
*/
String doc() default "";
}
@@ -1,24 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Specify the entity type maps to a document store (like ElasticSearch).
*/
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface DocMapping {
/**
* The property name the mapping applies to.
*/
String name();
/**
* Mapping options.
*/
DocProperty options();
}
@@ -1,110 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Specify the entity type maps to a document store (like ElasticSearch).
*/
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface DocProperty {
/**
* Set this to true to indicate that this property should be un-analysed.
*/
boolean code() default false;
/**
* Set this to true to get an additional un-analysed 'raw' field to use for sorting etc.
*/
boolean sortable() default false;
/**
* Set to true to have the property additionally stored separately from _source.
*/
boolean store() default false;
/**
* Set a boost value specific to this property.
*/
float boost() default 1;
/**
* Set a value to use instead of null.
*/
String nullValue() default "";
/**
* Set this to false to exclude this from the _all property.
*/
boolean includeInAll() default true;
/**
* The analyzer to use.
*/
String analyzer() default "";
/**
* The analyzer to use for searches.
*/
String searchAnalyzer() default "";
/**
* The index options for this property.
*/
Option options() default Option.DEFAULT;
/**
* Set this to false such that doc values are not stored separately for this property.
*/
boolean docValues() default true;
/**
* Set a copyTo field.
*/
String copyTo() default "";
/**
* Set to false to disable the field from indexing, it will only be get/set in _source.
*/
boolean enabled() default true;
/**
* Set to false such that norms are not stored.
*/
boolean norms() default true;
/**
* Index options for a property.
*/
enum Option {
/**
* Only index the doc number.
*/
DOCS,
/**
* Doc number and term frequencies are indexed.
*/
FREQS,
/**
* Doc number, term frequencies and term positions are indexed.
*/
POSITIONS,
/**
* Doc number, term frequencies, term positions and start/end offsets are indexed.
*/
OFFSETS,
/**
* Use the default which means analysed string properties use POSITIONS as the default and all other types use DOCS.
*/
DEFAULT
}
}
@@ -1,34 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Used to indicate that a particular string property should support sorting. What this typically means is that
* for ElasticSearch an additional 'raw' field is added that stores the un-analysed value. This un-analysed value
* can be used for sorting etc and the original field used for text searching.
* <p>
* For example, customer name and product name are good candidates for marking with @DocSortable.
* </p>
*/
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface DocSortable {
/**
* Set to true to have the property additionally stored separately from _source.
*/
boolean store() default false;
/**
* Set a boost value specific to this property.
*/
float boost() default 1;
/**
* Set a value to use instead of null.
*/
String nullValue() default "";
}
@@ -1,88 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Specify the entity type maps to a document store (like ElasticSearch).
*/
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface DocStore {
/**
* A unique Id used when queuing reindex events.
*/
String queueId() default "";
/**
* The ElasticSearch index name. If left unspecified the short name of the bean type is used.
*/
String indexName() default "";
/**
* The ElasticSearch index type. If left unspecified the short name of the bean type is used.
*/
String indexType() default "";
/**
* The number of shards this index should use.
*/
int shards() default 0;
/**
* The number of replicas this index should use.
*/
int replicas() default 0;
/**
* Additional mapping that can be defined on the properties.
*/
DocMapping[] mapping() default {};
/**
* Specify the behavior when bean Insert, Update, Delete events occur.
*/
DocStoreMode persist() default DocStoreMode.DEFAULT;
/**
* Specify the behavior when bean Insert occurs.
*/
DocStoreMode insert() default DocStoreMode.DEFAULT;
/**
* Specify the behavior when bean Update occurs.
*/
DocStoreMode update() default DocStoreMode.DEFAULT;
/**
* Specify the behavior when bean Delete occurs.
*/
DocStoreMode delete() default DocStoreMode.DEFAULT;
/**
* Specify to include only some properties in the doc store document.
* <p>
* If this is left as default then all scalar properties are included,
* all @ManyToOne properties are included with just the nested id property
* and no @OneToMany properties are included.
* </p>
* <p>
* Note that typically DocStoreEmbedded is used on @ManyToOne and @OneToMany
* properties to indicate what part of the nested document should be included.
* </p>
*
* <h3>Example:</h3>
* <pre>{@code
*
* // only include the customer id and name
* @DocStore(doc = "id,name")
* @Entity @Table(name = "o_order")
* public class Customer {
*
* }</pre>
*/
String doc() default "";
}
@@ -1,38 +0,0 @@
package com.avaje.ebean.annotation;
/**
* Defines the behavior options when a Insert, Update or Delete event occurs
* on a bean with an associated ElasticSearch index.
* <p>
* For some indexes or some transactions it can be beneficial to queue the event
* for later processing rather than look to update ElasticSearch at that time.
* </p>
*/
public enum DocStoreMode {
/**
* Add the event to the queue for processing later (delaying the update to the document store).
*/
QUEUE,
/**
* Update the document store when transaction succeeds.
*/
UPDATE,
/**
* Ignore the event and not update the document store.
* <p>
* This can be used on a index or for a transaction where you want to have more
* manual programmatic control over the updating of the document store. Say you want to
* IGNORE on a particular transaction and instead manually queue a bulk update.
* </p>
*/
IGNORE,
/**
* The actual mode of QUEUE, UPDATE or IGNORE is set from the default configuration.
*/
DEFAULT
}
@@ -1,19 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Marks a boolean property on a @Draftable bean that indicates if the bean instance is a 'draft' or 'live' bean.
* The property is transient and has no underlying DB column.
* <p>
* For beans returned from an <code>asDraft()</code> query this property will be set to true.
* </p>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Draft {
}
@@ -1,20 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Marks a boolean property on a @Draftable bean that only exists on the 'draft' table
* and is used to detect when a draft has unpublished changes.
* <p>
* This property will automatically have it's value set to true when a draft is saved and
* automatically have it's value set to false when the bean is published.
* </p>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DraftDirty {
}
@@ -1,19 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Marks a property on a @Draftable bean that only exists on the 'draft' and not the 'live' table.
* <p>
* Typically this would be used on a property that is used as part of application 'workflow' such as
* a publish workflow status or when publish timestamp.
* </p>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DraftOnly {
}
@@ -1,19 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Marks a property on a @Draftable bean that is set to null on the 'draft bean' on publish.
* <p>
* This is expected to be put on properties that get 'reset' or 'cleared' after a publish.
* These properties might represent a publish comment or publish timestamp.
* </p>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DraftReset {
}
@@ -1,29 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Used to indicate an entity bean that has 'draftable' support.
* <p>
* This means that a second set of tables is created to hold draft versions of
* the rows and that these can then be published which effectively copies/transfers
* the values from the 'draft' table to the 'live' table.
* </p>
* <p>
* Ebean Query supports 'find as draft' which builds the resulting object graph using
* the draft tables. This object graph is typically edited, approved in some application
* specific manor and then published.
* </p>
* <p>
* EbeanServer has a publish method which transfers/copies the draft object graph to
* the 'live' tables.
* </p>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Draftable {
}
@@ -1,20 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Used to indicate an entity bean that has 'draftable' support but it not a 'top level'
* (or root level) bean but instead child related to another @Draftable entity bean.
* <p>
* Relationships to @DraftableElements (@OneToMany, @ManyToMany etc) are automatically
* deemed to have Cascade.ALL for save and delete (as well as orphan removal mode).
* </p>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface DraftableElement {
}
@@ -1,31 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Specify property name to db column mapping for Embedded beans.
* <p>
* This is designed to be easier to use than the AttributeOverride annotation in
* standard JPA.
* </p>
*/
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface EmbeddedColumns {
/**
* A list of property names mapped to DB columns.
* <p>
* For example <code>currency=IN_CURR, amount=IN_AMOUNT</code>
* </p>
* <p>
* Where currency and amount are properties and IN_CURR and IN_AMOUNT are the
* respective DB columns these properties will be mapped to.
* </p>
*/
String columns() default "";
}
@@ -1,24 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Specify that the property is stored in encrypted form.
*/
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Encrypted {
/**
* When true try to use DB encryption rather than local java encryption.
*/
boolean dbEncryption() default true;
/**
* Used to specify the DB column length.
*/
int dbLength() default 0;
}
@@ -1,48 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Enables you to specify a value to use to persist for an enum value.
*
* <pre>{@code
*
* public enum Status {
*
* @EnumValue("N")
* NEW,
*
* @EnumValue("A")
* ACTIVE,
*
* @EnumValue("I")
* INACTIVE,
* }
*
* }</pre>
* <p>
* This is an alternative to using the JPA standard approach or Ebean's
* {@link DbEnumValue} annotation.
* </p>
* <p>
* Note that if all the EnumValue values are parsable as Integers then Ebean
* will persist and fetch them as integers - otherwise they will be persisted
* and fetched as strings.
* </p>
*/
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface EnumValue {
/**
* Specify the value to persist for a specific enum value.
* <p>
* If all the values are parsable as Integers then Ebean will persist and
* fetch them as integers rather than strings.
* </p>
*/
String value();
}
@@ -1,28 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/*
Copied from gson!!!
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Expose {
/**
* If {@code true}, the field marked with this annotation is written out in the JSON while
* serializing. If {@code false}, the field marked with this annotation is skipped from the
* serialized output. Defaults to {@code true}.
*/
boolean serialize() default true;
/**
* If {@code true}, the field marked with this annotation is deserialized from the JSON.
* If {@code false}, the field marked with this annotation is skipped during deserialization.
* Defaults to {@code true}.
*/
boolean deserialize() default true;
}
@@ -1,12 +1,14 @@
package com.avaje.ebean.annotation;
import com.avaje.ebean.Query;
import com.avaje.ebean.config.Platform;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.avaje.ebean.Query;
/**
* Assign to a property to be based on a SQL formula.
* <p>
@@ -24,28 +26,27 @@ import com.avaje.ebean.Query;
* You may want to do this if the Formula is relatively expensive and only want
* it included in the query when you explicitly state it.
* </p>
*
* <pre class="code">
* // On the Order &quot;master&quot; bean
* <p>
* <pre>{@code
* // On the Order "master" bean
* // ... a formula using the Order details
* // ... sum(order_qty*unit_price)
* &#064;Transient
* &#064;Formula(select = &quot;_b${ta}.total_amount&quot;, join = &quot;join (select order_id, sum(order_qty*unit_price) as total_amount from o_order_detail group by order_id) as _b${ta} on _b${ta}.order_id = ${ta}.id&quot;)
* @Transient
* @Formula(select = "_b${ta}.total_amount", join = "join (select order_id, sum(order_qty*unit_price) as total_amount from o_order_detail group by order_id) as _b${ta} on _b${ta}.order_id = ${ta}.id")
* Double totalAmount;
*
* </pre>
*
* }</pre>
* <p>
* As the totalAmount formula is also Transient it is not included by default in
* queries - it needs to be explicitly included.
* </p>
*
* <pre>{@code
*
* // find by Id
* Order o1 = Ebean.find(Order.class)
* .select("id, totalAmount")
* .setId(1).findUnique();
*
*
* // find list ... using totalAmount in the where clause
* List<Order> list = Ebean.find(Order.class)
* .select("id, totalAmount")
@@ -53,7 +54,7 @@ import com.avaje.ebean.Query;
* .eq("status", Order.Status.NEW)
* .gt("totalAmount", 10)
* .findList();
*
*
* // as a join from customer
* List<Customer> l0 = Ebean.find(Customer.class)
* .select("id, name")
@@ -62,11 +63,12 @@ import com.avaje.ebean.Query;
* .gt("id", 0)
* .gt("orders.totalAmount", 10)
* .findList();
*
*
* }</pre>
*/
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.TYPE })
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Formula.List.class)
public @interface Formula {
/**
@@ -84,7 +86,6 @@ public @interface Formula {
* <p>
* The join string should start with either "left join" or "join".
* </p>
*
* <p>
* You will almost certainly use the "${ta}" as a place holder for the table
* alias of the table you are joining back to (the "base table" of the entity
@@ -94,7 +95,7 @@ public @interface Formula {
* The example below is used to support a total count of topics created by a
* user.
* </p>
*
* <p>
* <pre>{@code
*
* join (select user_id, count(*) as topic_count from f_topic group by user_id) as _tc on _tc.user_id = ${ta}.id
@@ -103,4 +104,16 @@ public @interface Formula {
*/
String join() default "";
Platform[] platforms() default {};
/**
* Repeatable support for {@link Formula}.
*/
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@interface List {
Formula[] value() default {};
}
}
@@ -1,19 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Marks an entity bean as having history support.
* <p>
* In Postgres for example this means there is an associated history table which is
* typically automatically populated via database triggers.
* </p>
*/
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface History {
}
@@ -1,25 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Marks a property as being excluded from history.
* <p>
* This means the property values are not maintained in the history table. Typically this
* would be placed on relatively large properties (Clobs, Blobs, large varchar columns etc)
* that are considered not interesting enough to maintain history on excluding them reduces
* underlying database costs.
* </p>
* <p>
* When placed on a ManyToMany this means that the intersection table does not have history
* support.
* </p>
*/
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface HistoryExclude {
}
@@ -1,38 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* An annotation for declaring an index.
*
* @author rvbiljouw
*/
@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Indices.class)
public @interface Index {
/**
* Name of the index. If left blank a name is derived using the built in naming convention.
*/
String name() default "";
/**
* If set true indicates this is a unique index.
*/
boolean unique() default false;
/**
* When placed on the class (rather than field) you can specify the columns
* to include in the index in order.
*
* Wnen placed on a field, and columnNames are specified, the field-column has to be included.
* You can use "${fa}" for alias
*/
String[] columnNames() default {};
}
@@ -1,20 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* An annotation for declaring multiple indices at class or field level.
*
* @author Roland Praml, FOCONIS AG
*/
@Target({ElementType.TYPE, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Indices {
/**
* Array with {@link Index} definitions.
*/
Index[] value() default {};
}
@@ -1,32 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Similar to Jackson JsonIgnore but provides the option to just ignore serialize or deserialize.
* <p>
* This provides the same features as Expose but from the opposite perspective which is probably
* more common and more familiar to Jackson users.
* </p>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface JsonIgnore {
/**
* If {@code true}, the field marked with this annotation is written out in the JSON while
* serializing. If {@code false}, the field marked with this annotation is skipped from the
* serialized output. Defaults to {@code false}.
*/
boolean serialize() default false;
/**
* If {@code true}, the field marked with this annotation is deserialized from the JSON.
* If {@code false}, the field marked with this annotation is skipped during deserialization.
* Defaults to {@code false}.
*/
boolean deserialize() default false;
}
@@ -1,34 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Specify that the elements of a OneToMany are private owned.
* <p>
* This means that if they are removed from the List/Set/Map they will be
* deleted when their parent object is saved.
* </p>
* <p>
* This could also be described as deleting orphans - in that beans removed from
* the List/Set/Map will be deleted automatically when the parent bean is saved.
* They are considered 'orphans' when they have been removed from the collection
* in that they are no longer associated/linked to their parent bean.
* </p>
*/
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface PrivateOwned {
/**
* Set this to false if you don't want cascade REMOVE on this relationship.
* <p>
* That is, by default PrivateOwned implicitly adds a cascade REMOVE to the
* relationship and if you don't want that you need to set this to false.
* </p>
*/
boolean cascadeRemove() default true;
}
@@ -1,15 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Marks an entity bean as being included in read auditing.
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ReadAudit {
}
@@ -1,25 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Used to indicate a property on an entity bean used to control 'soft delete'
* (also known as 'logical delete').
* <p>
* The property should be of type boolean.
* </p>
* <pre>{@code
*
* @SoftDelete
* boolean deleted;
*
* }</pre>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface SoftDelete {
}
@@ -1,18 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Mark and entity bean that is used solely via RawSql.
* <p>
* This means the entity bean has no base table specified (via @Table).
* </p>
*/
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface Sql {
}
@@ -1,14 +1,14 @@
package com.avaje.ebean.annotation;
import com.avaje.ebean.TxIsolation;
import com.avaje.ebean.TxType;
import com.avaje.ebean.config.PersistBatch;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.avaje.ebean.TxIsolation;
import com.avaje.ebean.TxType;
import com.avaje.ebean.config.PersistBatch;
/**
* Specify transaction scoping for a method.
* <p>
@@ -33,22 +33,22 @@ import com.avaje.ebean.config.PersistBatch;
* to set the default behaviour to rollback on any exception and optionally
* change the setting to be consistent with EJB/Spring if people wish to do so.
* </p>
*
* <p>
* <pre>{@code
*
* // a normal class
* public class MySimpleUserService {
*
*
* // this method is transactional automatically handling
* // transaction begin, commit and rollback etc
* @Transactional
* public void runInTrans() throws IOException {
*
*
* // tasks performed within the transaction
* ...
* // find some objects
* Customer cust = ebeanServer.find(Customer.class, 42);
*
*
* Order order = ...;
* ...
* // save some objects
@@ -58,7 +58,7 @@ import com.avaje.ebean.config.PersistBatch;
*
* }</pre>
*/
@Target({ ElementType.METHOD, ElementType.TYPE })
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Transactional {
@@ -1,34 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Specify the update mode for the specific entity type.
* <p>
* Control whether all 'loaded' properties are included in an Update or whether
* just properties that have changed will be included in the update.
* </p>
* <p>
* Note that the default can be set via ebean.properties.
* </p>
*
* <pre>
* ## Set to update all loaded properties
* ebean.updateChangesOnly=false
* </pre>
*/
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface UpdateMode {
/**
* Set to false if you want to include all the 'loaded' properties in the
* update. Otherwise, just the properties that have changed will be included
* in the update.
*/
boolean updateChangesOnly() default true;
}
@@ -1,20 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* For a timestamp property that is set to the datetime when the entity was last
* updated.
* <p>
* This is effectively an alias for @WhenModified which was added as it hints
* towards a better naming convention (WhenCreated, WhenModified).
* </p>
*/
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface UpdatedTimestamp {
}
@@ -1,38 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotate an entity bean with @View to indicates the bean is based on a view.
* <p>
* As such typically the view is defined in <code>extra-ddl.xml</code> using
* <code>create or replace view ...</code>.
* </p>
* <p>
* When using extra-ddl.xml Ebean will run the resulting DDL script after the
* <code>create-all</code> DDL (which is typically used during development) and for
* DB Migration will copy the scripts as <code>repeatable migration scripts</code> that
* will be run by FlywayDb (or Ebean's own migration runner) when their MD5 hash changes.
* </p>
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface View {
/**
* The name of the view this entity bean is based on.
*/
String name();
/**
* Tables this view is dependent on.
* <p>
* This is used with l2 caching to invalidate the query cache. Changes to these
* tables invalidate the query cache for the entity based on this view.
* </p>
*/
String[] dependentTables() default {};
}
@@ -1,38 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* For a timestamp property that is set to the datetime when the entity is
* created/inserted.
* <p>
* This is effectively an alias for @CreatedTimestamp and added to hint
* towards a better naming convention (WhenCreated, WhenModified).
* </p>
* <p>
* An alternative to using this annotation would be to use insertable=false,
* updateable=false with @Column and have the DB insert the current time
* (default value on the DB column is SYSTIME etc).
* </p>
* <p>
* The downside to this approach is that the inserted entity does not have the
* timestamp value after the insert has occurred. You need to fetch the entity
* back to get the inserted timestamp if you want to used it.
* </p>
*
* <h3>Example:</h3>
* <pre>{@code
*
* @WhenCreated
* Timestamp whenCreated;
*
* }</pre>
*/
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface WhenCreated {
}
@@ -1,19 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* For a timestamp property that is set to the datetime when the entity was last modified.
* <p>
* This is effectively an alias for @UpdatedTimestamp and added to hint
* towards a better naming convention (WhenCreated, WhenModified).
* </p>
*/
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface WhenModified {
}
@@ -1,6 +1,9 @@
package com.avaje.ebean.annotation;
import com.avaje.ebean.config.Platform;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@@ -8,38 +11,35 @@ import java.lang.annotation.Target;
/**
* Add an Literal to add to the where clause when a many property (List, Set or
* Map) is loaded or refreshed.
*
* <pre>{@code
*
* // on a OneToMany property...
*
*
* @OneToMany
* @Where(clause = "deleted='y'")
* List<Topic> topics;
*
* }</pre>
*
* <p>
* Note that you can include "${ta}" as a place holder for the table alias if
* you need to include the table alias in the clause.
* </p>
*
* <pre>{@code
* // ... including the ${ta} table alias placeholder...
*
*
* @OneToMany
* @Where(clause = "${ta}.deleted='y'")
* List<Topic> topics;
*
* }</pre>
*
* <p>
* This will be added to the where clause when lazy loading the OneToMany
* property or when there is a join to that OneToMany property.
* </p>
*/
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.TYPE })
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Where.List.class)
public @interface Where {
/**
@@ -51,4 +51,18 @@ public @interface Where {
*/
String clause();
/**
* The platform where this annotation is active. Default: any platform
*/
Platform[] platforms() default {};
/**
* Repeatable support for {@link Where}.
*/
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@interface List {
Where[] value() default {};
}
}
@@ -1,29 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Mapped onto a entity bean property that represents the user id of
* who created the entity>
* <p>
* To use this annotation you need to implement CurrentUserProvider.
* The type of the bean property should match the type returned by
* CurrentUserProvider.
*</p>
* <h3>Example:</h3>
* <pre>{@code
*
* @WhoCreated
* String whoCreated;
*
* }</pre>
*/
@Target({ ElementType.FIELD, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
public @interface WhoCreated {
}
@@ -1,29 +0,0 @@
package com.avaje.ebean.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Mapped onto a entity bean property that represents the user id of
* who last modified the entity>
* <p>
* To use this annotation you need to implement CurrentUserProvider.
* The type of the bean property should match the type returned by
* CurrentUserProvider.
* </p>
*
* <h3>Example:</h3>
* <pre>{@code
*
* @WhoModified
* String whoModified;
*
* }</pre>
*/
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface WhoModified {
}
@@ -1,14 +0,0 @@
<HTML>
<HEAD>
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
<TITLE>Extra deployment annotations</TITLE>
</HEAD>
<Body BGCOLOR="#ffffff">
Extra deployment annotations
<p>
Extra deployment annotations for entity beans.
</p>
</Body>
</HTML>
@@ -1,11 +1,11 @@
package com.avaje.ebean.bean;
import com.avaje.ebean.ExpressionList;
import java.io.Serializable;
import java.util.Collection;
import java.util.Set;
import com.avaje.ebean.ExpressionList;
/**
* Lazy loading capable Maps, Lists and Sets.
* <p>
@@ -23,11 +23,17 @@ import com.avaje.ebean.ExpressionList;
public interface BeanCollection<E> extends Serializable {
enum ModifyListenMode {
/** The common mode */
/**
* The common mode
*/
NONE,
/** Mode used for PrivateOwned */
/**
* Mode used for PrivateOwned
*/
REMOVALS,
/** Mode used for ManyToMany relationships */
/**
* Mode used for ManyToMany relationships
*/
ALL
}
@@ -34,12 +34,12 @@ public final class CallStack implements Serializable {
public int hashCode() {
int hc = 0;
for (int i = 0; i < callStack.length; i++) {
hc = 31 * hc + callStack[i].hashCode();
for (StackTraceElement aCallStack : callStack) {
hc = 31 * hc + aCallStack.hashCode();
}
return hc;
}
public boolean equals(Object obj) {
if (obj == this) {
return true;
@@ -88,14 +88,14 @@ public final class CallStack implements Serializable {
*/
public String description(String newLine) {
StringBuilder sb = new StringBuilder(400);
for (int i = 0; i < callStack.length; i++) {
sb.append(callStack[i].toString()).append(newLine);
for (StackTraceElement aCallStack : callStack) {
sb.append(aCallStack.toString()).append(newLine);
}
return sb.toString();
}
public String getOriginKey(int queryHash) {
return enc(queryHash)+ "." + zeroHash + "." + pathHash;
return enc(queryHash) + "." + zeroHash + "." + pathHash;
}
private static final int radix = 1 << 6;
@@ -116,10 +116,10 @@ public final class CallStack implements Serializable {
}
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', '-', '_'
'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', '-', '_'
};
}
@@ -15,9 +15,9 @@ import java.io.Serializable;
public interface EntityBean extends Serializable {
String[] _ebean_getPropertyNames();
String _ebean_getPropertyName(int pos);
/**
* Return the enhancement marker value.
* <p>
@@ -30,7 +30,7 @@ public final class EntityBeanIntercept implements Serializable {
private static final int STATE_NEW = 0;
private static final int STATE_REFERENCE = 1;
private static final int STATE_LOADED = 2;
private transient NodeUsageCollector nodeUsageCollector;
private transient PropertyChangeSupport pcs;
@@ -55,11 +55,11 @@ public final class EntityBeanIntercept implements Serializable {
* One of NEW, REF, UPD.
*/
private int state;
private boolean readOnly;
private boolean dirty;
/**
* Flag set to disable lazy loading - typically for SQL "report" type entity beans.
*/
@@ -74,14 +74,14 @@ public final class EntityBeanIntercept implements Serializable {
* Used when a bean is partially filled.
*/
private final boolean[] loadedProps;
private boolean fullyLoadedBean;
/**
* Set of changed properties.
*/
private boolean[] changedProps;
/**
* Flags indicating if a property is a dirty embedded bean. Used to distingush
* between an embedded bean being completely overwritten and one of its
@@ -180,7 +180,7 @@ public final class EntityBeanIntercept implements Serializable {
public Object getEmbeddedOwner() {
return embeddedOwner;
}
/**
* Return the property index (for the parent) of this embedded bean.
*/
@@ -240,8 +240,8 @@ public final class EntityBeanIntercept implements Serializable {
* Check each property to see if the bean is partially loaded.
*/
public boolean isPartial() {
for (int i = 0; i < loadedProps.length; i++) {
if (!loadedProps[i]) {
for (boolean loadedProp : loadedProps) {
if (!loadedProp) {
return true;
}
}
@@ -263,7 +263,7 @@ public final class EntityBeanIntercept implements Serializable {
this.dirty = true;
setEmbeddedPropertyDirty(embeddedProperty);
}
public void setDirty(boolean dirty) {
this.dirty = dirty;
}
@@ -290,12 +290,12 @@ public final class EntityBeanIntercept implements Serializable {
if (i == idIndex) {
if (!loadedProps[i]) return false;
} else if (loadedProps[i]) {
return false;
return false;
}
}
return true;
}
/**
* Return true if the entity is a reference.
*/
@@ -311,8 +311,8 @@ public final class EntityBeanIntercept implements Serializable {
if (idPos > -1) {
// For cases where properties are set on constructor
// set every non Id property to unloaded (for lazy loading)
for (int i=0; i< loadedProps.length; i++) {
if (i != idPos) {
for (int i = 0; i < loadedProps.length; i++) {
if (i != idPos) {
loadedProps[i] = false;
}
}
@@ -448,7 +448,7 @@ public final class EntityBeanIntercept implements Serializable {
}
return origValues[propertyIndex];
}
/**
* Finds the index position of a given property. Returns -1 if the property
* can not be found.
@@ -462,7 +462,7 @@ public final class EntityBeanIntercept implements Serializable {
}
return -1;
}
/**
* Return the property name for the given property.
*/
@@ -472,7 +472,7 @@ public final class EntityBeanIntercept implements Serializable {
}
return owner._ebean_getPropertyName(propertyIndex);
}
/**
* Return the number of properties.s
*/
@@ -486,7 +486,7 @@ public final class EntityBeanIntercept implements Serializable {
public void setPropertyLoaded(String propertyName, boolean loaded) {
int position = findProperty(propertyName);
if (position == -1) {
throw new IllegalArgumentException("Property "+propertyName+" not found");
throw new IllegalArgumentException("Property " + propertyName + " not found");
}
loadedProps[position] = loaded;
}
@@ -498,7 +498,7 @@ public final class EntityBeanIntercept implements Serializable {
public void setPropertyUnloaded(int propertyIndex) {
loadedProps[propertyIndex] = false;
}
/**
* Set the property to be loaded.
*/
@@ -525,8 +525,8 @@ public final class EntityBeanIntercept implements Serializable {
* embedded properties is dirty.
*/
public boolean isDirtyProperty(int propertyIndex) {
return (changedProps != null && changedProps[propertyIndex]
|| embeddedDirty != null && embeddedDirty[propertyIndex]);
return (changedProps != null && changedProps[propertyIndex]
|| embeddedDirty != null && embeddedDirty[propertyIndex]);
}
/**
@@ -536,7 +536,7 @@ public final class EntityBeanIntercept implements Serializable {
setChangedProperty(propertyIndex);
setDirty(true);
}
public void setChangedProperty(int propertyIndex) {
if (changedProps == null) {
changedProps = new boolean[owner._ebean_getPropertyNames().length];
@@ -553,7 +553,7 @@ public final class EntityBeanIntercept implements Serializable {
}
embeddedDirty[propertyIndex] = true;
}
private void setOriginalValue(int propertyIndex, Object value) {
if (origValues == null) {
origValues = new Object[owner._ebean_getPropertyNames().length];
@@ -567,19 +567,19 @@ public final class EntityBeanIntercept implements Serializable {
* For forced update on a 'New' bean set all the loaded properties to changed.
*/
public void setNewBeanForUpdate() {
if (changedProps == null) {
changedProps = new boolean[owner._ebean_getPropertyNames().length];
}
for (int i=0; i< loadedProps.length; i++) {
for (int i = 0; i < loadedProps.length; i++) {
if (loadedProps[i]) {
changedProps[i] = true;
changedProps[i] = true;
}
}
setDirty(true);
}
/**
* Return the set of property names for a partially loaded bean.
*/
@@ -588,7 +588,7 @@ public final class EntityBeanIntercept implements Serializable {
return null;
}
Set<String> props = new LinkedHashSet<>();
for (int i=0; i<loadedProps.length; i++) {
for (int i = 0; i < loadedProps.length; i++) {
if (loadedProps[i]) {
props.add(getProperty(i));
}
@@ -621,7 +621,7 @@ public final class EntityBeanIntercept implements Serializable {
addDirtyPropertyNames(props, null);
return props;
}
/**
* Recursively add dirty properties.
*/
@@ -634,8 +634,8 @@ public final class EntityBeanIntercept implements Serializable {
props.add(propName);
} else if (embeddedDirty != null && embeddedDirty[i]) {
// an embedded property has been changed - recurse
EntityBean embeddedBean = (EntityBean)owner._ebean_getField(i);
embeddedBean._ebean_getIntercept().addDirtyPropertyNames(props, getProperty(i)+".");
EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
embeddedBean._ebean_getIntercept().addDirtyPropertyNames(props, getProperty(i) + ".");
}
}
}
@@ -665,16 +665,16 @@ public final class EntityBeanIntercept implements Serializable {
/**
* Return a map of dirty properties with their new and old values.
*/
public Map<String,ValuePair> getDirtyValues() {
Map<String,ValuePair> dirtyValues = new LinkedHashMap<>();
public Map<String, ValuePair> getDirtyValues() {
Map<String, ValuePair> dirtyValues = new LinkedHashMap<>();
addDirtyPropertyValues(dirtyValues, null);
return dirtyValues;
}
/**
* Recursively add dirty properties.
*/
public void addDirtyPropertyValues(Map<String,ValuePair> dirtyValues, String prefix) {
public void addDirtyPropertyValues(Map<String, ValuePair> dirtyValues, String prefix) {
int len = getPropertyLength();
for (int i = 0; i < len; i++) {
if (changedProps != null && changedProps[i]) {
@@ -684,22 +684,22 @@ public final class EntityBeanIntercept implements Serializable {
Object oldVal = getOrigValue(i);
dirtyValues.put(propName, new ValuePair(newVal, oldVal));
} else if (embeddedDirty != null && embeddedDirty[i]) {
// an embedded property has been changed - recurse
EntityBean embeddedBean = (EntityBean)owner._ebean_getField(i);
EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
embeddedBean._ebean_getIntercept().addDirtyPropertyValues(dirtyValues, getProperty(i) + ".");
}
}
}
/**
* Return a dirty property hash taking into account embedded beans.
*/
public int getDirtyPropertyHash() {
return addDirtyPropertyHash(37);
}
/**
* Add and return a dirty property hash recursing into embedded beans.
*/
@@ -708,10 +708,10 @@ public final class EntityBeanIntercept implements Serializable {
for (int i = 0; i < len; i++) {
if (changedProps != null && changedProps[i]) {
// the property has been changed on this bean
hash = hash * 31 + (i+1);
hash = hash * 31 + (i + 1);
} else if (embeddedDirty != null && embeddedDirty[i]) {
// an embedded property has been changed - recurse
EntityBean embeddedBean = (EntityBean)owner._ebean_getField(i);
EntityBean embeddedBean = (EntityBean) owner._ebean_getField(i);
hash = hash * 31 + embeddedBean._ebean_getIntercept().addDirtyPropertyHash(hash);
}
}
@@ -726,7 +726,7 @@ public final class EntityBeanIntercept implements Serializable {
int len = getPropertyLength();
for (int i = 0; i < len; i++) {
if (isLoadedProperty(i)) {
hash = hash * 31 + (i+1);
hash = hash * 31 + (i + 1);
}
}
return hash;
@@ -749,7 +749,7 @@ public final class EntityBeanIntercept implements Serializable {
public int getLazyLoadPropertyIndex() {
return lazyLoadProperty;
}
/**
* Return the property that triggered the lazy load.
*/
@@ -821,7 +821,7 @@ public final class EntityBeanIntercept implements Serializable {
/**
* Helper method to check if two objects are equal.
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@SuppressWarnings({"unchecked", "rawtypes"})
protected boolean areEqual(Object obj1, Object obj2) {
if (obj1 == null) {
return (obj2 == null);
@@ -849,7 +849,7 @@ public final class EntityBeanIntercept implements Serializable {
}
return obj1.equals(obj2);
}
/**
* Called when a BeanCollection is initialised automatically.
*/
@@ -920,7 +920,7 @@ public final class EntityBeanIntercept implements Serializable {
if (readOnly) {
throw new IllegalStateException("This bean is readOnly");
}
setLoadedProperty(propertyIndex);
// Bean itself not considered dirty when many changed
@@ -930,7 +930,7 @@ public final class EntityBeanIntercept implements Serializable {
return null;
}
}
private void setChangedPropertyValue(int propertyIndex, boolean setDirtyState, Object origValue) {
if (readOnly) {
@@ -941,7 +941,7 @@ public final class EntityBeanIntercept implements Serializable {
if (setDirtyState) {
setOriginalValue(propertyIndex, origValue);
if (!dirty) {
dirty = true;
dirty = true;
if (embeddedOwner != null) {
// Cascade dirty state from Embedded bean to parent bean
embeddedOwner._ebean_getIntercept().setEmbeddedDirty(embeddedOwnerIndex);
@@ -952,7 +952,7 @@ public final class EntityBeanIntercept implements Serializable {
}
}
}
/**
* Check to see if the values are not equal. If they are not equal then create
* the old values for use with ConcurrencyMode.ALL.
@@ -962,15 +962,15 @@ public final class EntityBeanIntercept implements Serializable {
if (state == STATE_NEW) {
setLoadedProperty(propertyIndex);
} else if (!areEqual(oldValue, newValue)) {
setChangedPropertyValue(propertyIndex, intercept, oldValue);
setChangedPropertyValue(propertyIndex, intercept, oldValue);
} else {
return null;
}
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
}
/**
* Check for primitive boolean.
*/
@@ -1007,13 +1007,13 @@ public final class EntityBeanIntercept implements Serializable {
public PropertyChangeEvent preSetter(boolean intercept, int propertyIndex, long oldValue, long newValue) {
if (state == STATE_NEW) {
setLoadedProperty(propertyIndex);
setLoadedProperty(propertyIndex);
} else if (oldValue != newValue) {
setChangedPropertyValue(propertyIndex, intercept, oldValue);
} else {
return null;
}
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
}
@@ -1025,7 +1025,7 @@ public final class EntityBeanIntercept implements Serializable {
if (state == STATE_NEW) {
setLoadedProperty(propertyIndex);
} else if (oldValue != newValue) {
setChangedPropertyValue(propertyIndex, intercept, oldValue);
setChangedPropertyValue(propertyIndex, intercept, oldValue);
} else {
return null;
}
@@ -1044,7 +1044,7 @@ public final class EntityBeanIntercept implements Serializable {
} else {
return null;
}
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
}
/**
@@ -1104,7 +1104,7 @@ public final class EntityBeanIntercept implements Serializable {
} else {
return null;
}
return (pcs == null) ? null: new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
return (pcs == null) ? null : new PropertyChangeEvent(owner, getProperty(propertyIndex), oldValue, newValue);
}
/**
@@ -64,15 +64,15 @@ public final class ObjectGraphNode implements Serializable {
}
public String toString() {
return "origin:" + originQueryPoint + " path[" + path+"]";
return "origin:" + originQueryPoint + " path[" + path + "]";
}
public int hashCode() {
int hc = 31 * originQueryPoint.hashCode();
hc = 31 * hc + (path == null ? 0 : path.hashCode());
return hc;
}
public boolean equals(Object obj) {
if (obj == this) {
return true;
@@ -80,10 +80,10 @@ public final class ObjectGraphNode implements Serializable {
if (!(obj instanceof ObjectGraphNode)) {
return false;
}
ObjectGraphNode e = (ObjectGraphNode) obj;
//noinspection StringEquality
return ((e.path == path) || (e.path != null && e.path.equals(path)))
&& e.originQueryPoint.equals(originQueryPoint);
return ((e.path == path) || (e.path != null && e.path.equals(path)))
&& e.originQueryPoint.equals(originQueryPoint);
}
}

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