mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
292
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54711a96d3 | ||
|
|
6ca5ec986c | ||
|
|
40029edca8 | ||
|
|
4159af9002 | ||
|
|
b0dae02c42 | ||
|
|
0322b37ae7 | ||
|
|
58760fe001 | ||
|
|
99f3bc8c54 | ||
|
|
d3bf219129 | ||
|
|
57813179b2 | ||
|
|
c410700433 | ||
|
|
697e4dd0da | ||
|
|
60dfe6308e | ||
|
|
002d7d9f27 | ||
|
|
2dceccfa78 | ||
|
|
5cf9d14237 | ||
|
|
bdd4370fe3 | ||
|
|
63b08af3d2 | ||
|
|
983306ed86 | ||
|
|
15973c8992 | ||
|
|
b49a52057a | ||
|
|
82151872fd | ||
|
|
709d4151f2 | ||
|
|
d8e3f127c0 | ||
|
|
f4e422a239 | ||
|
|
442f24124c | ||
|
|
259814f4d9 | ||
|
|
41a860ebb9 | ||
|
|
2584fe9b7b | ||
|
|
f815415eb0 | ||
|
|
cf81d1699b | ||
|
|
0f3f79ab2c | ||
|
|
de9576835c | ||
|
|
7e7951df09 | ||
|
|
632cf10096 | ||
|
|
d2b6d06da5 | ||
|
|
b41f3e9d1f | ||
|
|
8357d9c7e7 | ||
|
|
97f1834c4d | ||
|
|
01f551a951 | ||
|
|
482d454fc3 | ||
|
|
7341f742de | ||
|
|
ffb2d6a10c | ||
|
|
56c96923c4 | ||
|
|
e4e850717d | ||
|
|
2953418683 | ||
|
|
5c142a61f6 | ||
|
|
74626184b2 | ||
|
|
019fdd3a12 | ||
|
|
119edbdb9d | ||
|
|
e8237cc04f | ||
|
|
95ee163d8b | ||
|
|
9a22f9735a | ||
|
|
29dbd5ac5d | ||
|
|
8661e1fd3f | ||
|
|
9569b1b0d5 | ||
|
|
3eb9bc1d16 | ||
|
|
ec6a8f5ea2 | ||
|
|
d6ba567763 | ||
|
|
6826fe1015 | ||
|
|
e67860cbe3 | ||
|
|
b41238ddbb | ||
|
|
c0b1c3d3ee | ||
|
|
ae69fcb80a | ||
|
|
6c4c33f1f3 | ||
|
|
2986290947 | ||
|
|
376cb9ebcb | ||
|
|
5cf5629232 | ||
|
|
98aa5e9da9 | ||
|
|
ed1df5bcbb | ||
|
|
6704ccc6a7 | ||
|
|
5f35e3c944 | ||
|
|
0893972115 | ||
|
|
7a8d1b85a9 | ||
|
|
686593e9e8 | ||
|
|
d05b593432 | ||
|
|
b581c893ec | ||
|
|
63f852475d | ||
|
|
51364763fb | ||
|
|
ea408fd4c7 | ||
|
|
8dc521ca8b | ||
|
|
6680e2ea75 | ||
|
|
da30df3b2b | ||
|
|
d12ea89388 | ||
|
|
e0931e41e5 | ||
|
|
c98d258127 | ||
|
|
a4922a5b1d | ||
|
|
edb2a69f6e | ||
|
|
b94f852b67 | ||
|
|
a8778ef14c | ||
|
|
cbfce0d14d | ||
|
|
abb25d397a | ||
|
|
969a3c8b8d | ||
|
|
2a6d38eef2 | ||
|
|
d84080fb76 | ||
|
|
54d7a6fb42 | ||
|
|
e5356e7118 | ||
|
|
e83556cada | ||
|
|
201a2826ab | ||
|
|
670bac52f8 | ||
|
|
77e3346d9e | ||
|
|
4663162f95 | ||
|
|
83a3ef43bd | ||
|
|
3701b314a0 | ||
|
|
fad8358a9d | ||
|
|
78c4dbb44d | ||
|
|
9c74520a4b | ||
|
|
c911c710d5 | ||
|
|
f08dd01035 | ||
|
|
a1b4af2716 | ||
|
|
8c500c5836 | ||
|
|
c1d6cc7b75 | ||
|
|
d6fe16ffda | ||
|
|
d0230491e5 | ||
|
|
3526f71f0a | ||
|
|
18f943ab2b | ||
|
|
03ff53c7af | ||
|
|
c20d111ea2 | ||
|
|
920fa73d11 | ||
|
|
cd62686337 | ||
|
|
e9ad459fa5 | ||
|
|
ea5e9fa75a | ||
|
|
d44460e180 | ||
|
|
0e5ebf3fea | ||
|
|
42d35f8ec6 | ||
|
|
7f52e466e0 | ||
|
|
861a8a4ee5 | ||
|
|
abe2f76d5c | ||
|
|
d0f75a940c | ||
|
|
44ad78b5e0 | ||
|
|
967b4de784 | ||
|
|
ea45201905 | ||
|
|
938f4ec9c2 | ||
|
|
99bd2972d0 | ||
|
|
deac291951 | ||
|
|
3161e24677 | ||
|
|
37804bd083 | ||
|
|
0a2a987695 | ||
|
|
4a085cb819 | ||
|
|
67469ef4d3 | ||
|
|
c3f43d503f | ||
|
|
9158f46bb3 | ||
|
|
b3bfa88eb5 | ||
|
|
185dec9c02 | ||
|
|
20634233ca | ||
|
|
7c9dda586e | ||
|
|
3ca0f7b776 | ||
|
|
85caca48de | ||
|
|
ff85a51994 | ||
|
|
6dc3038d0d | ||
|
|
c0fcb77f3d | ||
|
|
da5d5296b6 | ||
|
|
f04ab28c3f | ||
|
|
d6cd41f8d2 | ||
|
|
504a209a78 | ||
|
|
9f98b5333d | ||
|
|
2a600adbcf | ||
|
|
9ce6007330 | ||
|
|
7780dd6272 | ||
|
|
b01ddea781 | ||
|
|
b848587cd3 | ||
|
|
fe7e929a99 | ||
|
|
3ee0b0224e | ||
|
|
169eba4296 | ||
|
|
91d3279061 | ||
|
|
b4b7c631da | ||
|
|
4f98ca5d91 | ||
|
|
014a9aef6f | ||
|
|
f21c33df7b | ||
|
|
f1eb494e0d | ||
|
|
d26203db1f | ||
|
|
abfe58fb06 | ||
|
|
d0ad5f6c48 | ||
|
|
bc4a246f33 | ||
|
|
61f590944b | ||
|
|
223e53416d | ||
|
|
a3143b1cf6 | ||
|
|
bd3e7c8035 | ||
|
|
b753ce3a73 | ||
|
|
a0f2ebe448 | ||
|
|
7e7810602e | ||
|
|
d218fff374 | ||
|
|
a0e927d353 | ||
|
|
51a58d4993 | ||
|
|
b9f0ee7ac0 | ||
|
|
4f3b461f8e | ||
|
|
adfe5f0305 | ||
|
|
1796c8b9bc | ||
|
|
4bad4358f0 | ||
|
|
92665ebc3b | ||
|
|
59670d0303 | ||
|
|
244275fd72 | ||
|
|
d1e2176a5a | ||
|
|
43968e70b8 | ||
|
|
0aa3bd3c97 | ||
|
|
2d85a9a20c | ||
|
|
157dfcfeb6 | ||
|
|
2b7c204072 | ||
|
|
be731feb6b | ||
|
|
da15d0b2c6 | ||
|
|
9c5fd496c1 | ||
|
|
5075ea32b4 | ||
|
|
f5c8d8896f | ||
|
|
32fdff9f11 | ||
|
|
87f6964995 | ||
|
|
b45226dd41 | ||
|
|
992c40d362 | ||
|
|
9144d60948 | ||
|
|
6396143d49 | ||
|
|
ce045ca0fe | ||
|
|
d722d34072 | ||
|
|
2cc4c2c265 | ||
|
|
0a830841c4 | ||
|
|
c427009b93 | ||
|
|
7f42d045ac | ||
|
|
43afaf1344 | ||
|
|
6c182ecaa5 | ||
|
|
fdb839f90e | ||
|
|
16be213faf | ||
|
|
3344f0ddb0 | ||
|
|
479ac38537 | ||
|
|
e30ad80f5f | ||
|
|
08e46d6bf3 | ||
|
|
876476fdc1 | ||
|
|
81de83a6e7 | ||
|
|
b5b221ffb1 | ||
|
|
3c6eab6c85 | ||
|
|
1be30f1671 | ||
|
|
9a5cb242ce | ||
|
|
ea69cae4a3 | ||
|
|
629fb7a433 | ||
|
|
4ff10da739 | ||
|
|
9472592a50 | ||
|
|
f42682ca90 | ||
|
|
5dc296e644 | ||
|
|
380660913f | ||
|
|
d08ac6973e | ||
|
|
9d23c1d56e | ||
|
|
b5d6c5f70b | ||
|
|
3657d05774 | ||
|
|
2de8ae777d | ||
|
|
16950a5641 | ||
|
|
ad992d07ce | ||
|
|
cbcec8f5ea | ||
|
|
6e2148d20b | ||
|
|
ca1c0a08f3 | ||
|
|
baa6fc355e | ||
|
|
dacdc26902 | ||
|
|
48edf64013 | ||
|
|
e2ee6e8e98 | ||
|
|
e6e6a28245 | ||
|
|
82a695a98a | ||
|
|
cdad31bd8a | ||
|
|
4d16cf9caa | ||
|
|
84a86cad0e | ||
|
|
dfdf87fa2d | ||
|
|
ee0615caec | ||
|
|
79b8395f8f | ||
|
|
87c479cd95 | ||
|
|
abbdda810a | ||
|
|
e621900de9 | ||
|
|
76b33511e1 | ||
|
|
77deab5cf0 | ||
|
|
4a9f8cef0e | ||
|
|
4d1340c16c | ||
|
|
74c6c71301 | ||
|
|
0f0028eb1f | ||
|
|
b4a1d52067 | ||
|
|
d82148248c | ||
|
|
dc7c854432 | ||
|
|
7c83010df1 | ||
|
|
ed41e58073 | ||
|
|
5bab9eb648 | ||
|
|
5ce8eb6046 | ||
|
|
56fee2ea9b | ||
|
|
84f32c2ace | ||
|
|
85288a0652 | ||
|
|
3183287833 | ||
|
|
780ee7c7c0 | ||
|
|
2bac7bf84d | ||
|
|
499862438d | ||
|
|
4ad0b7cf66 | ||
|
|
6108ef484b | ||
|
|
b763f4c875 | ||
|
|
ca7285b2ad | ||
|
|
75b639bc15 | ||
|
|
1a7c4dac3f | ||
|
|
6828fa1786 | ||
|
|
ba7e729ae1 | ||
|
|
c3fba72a24 | ||
|
|
ff401cfc72 | ||
|
|
cf9eb4ed97 |
@@ -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
|
||||
@@ -6,12 +6,12 @@ Goto [https://ebean-orm.github.io/](http://ebean-orm.github.io/ "Ebean ORM's Web
|
||||
|
||||
|
||||
## Maven cental links:
|
||||
[Maven central - avaje-ebeanorm](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.avaje.ebeanorm%22%20AND%20a%3A%22avaje-ebeanorm%22 "maven central ebeanorm")
|
||||
[Maven central - ebean](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.avaje.ebean%22%20AND%20a%3A%22ebean%22 "maven central ebean")
|
||||
|
||||
[Maven central - all related projects](http://search.maven.org/#search%7Cga%7C1%7Cavaje-ebeanorm "maven central ebeanorm")
|
||||
[Maven central - all related projects](http://search.maven.org/#search%7Cga%7C1%7Cebean "maven central all related projects")
|
||||
|
||||
## Current versions
|
||||
* [](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebeanorm/avaje-ebeanorm) - avaje-ebeanorm
|
||||
* [](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebeanorm/avaje-ebeanorm-agent) - avaje-ebeanorm-agent
|
||||
* [](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebeanorm/avaje-ebeanorm-mavenenhancer) - avaje-ebeanorm-mavenenhancer
|
||||
* [](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebean/ebean) - ebean
|
||||
* [](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebean/ebean-agent) - ebean-agent
|
||||
* [](https://maven-badges.herokuapp.com/maven-central/org.avaje.ebean/ebean-maven-plugin) - ebean-maven-plugin
|
||||
|
||||
|
||||
@@ -3,41 +3,25 @@
|
||||
|
||||
<parent>
|
||||
<groupId>org.avaje</groupId>
|
||||
<artifactId>oss-parent</artifactId>
|
||||
<artifactId>java8-parent</artifactId>
|
||||
<version>1.1</version>
|
||||
</parent>
|
||||
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm</artifactId>
|
||||
<version>7.19.1</version>
|
||||
<groupId>org.avaje.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>9.2.1</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>avaje-ebeanorm</name>
|
||||
<name>ebean</name>
|
||||
<url>http://ebean-orm.github.io/</url>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<licenses>
|
||||
<license>
|
||||
<name>The Apache Software License, Version 2.0</name>
|
||||
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||
<distribution>repo</distribution>
|
||||
</license>
|
||||
</licenses>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<id>rbygrave</id>
|
||||
<name>Rob Bygrave</name>
|
||||
<email>robin.bygrave@gmail.com</email>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:https://github.com/ebean-orm/avaje-ebeanorm.git</developerConnection>
|
||||
<tag>avaje-ebeanorm-7.19.1</tag>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-9.2.1</tag>
|
||||
</scm>
|
||||
|
||||
<dependencies>
|
||||
@@ -69,19 +53,19 @@
|
||||
<dependency>
|
||||
<groupId>org.avaje</groupId>
|
||||
<artifactId>avaje-classpath-scanner-api</artifactId>
|
||||
<version>2.1</version>
|
||||
<version>2.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.avaje</groupId>
|
||||
<artifactId>avaje-classpath-scanner</artifactId>
|
||||
<version>2.1.1</version>
|
||||
<version>2.2.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.avaje</groupId>
|
||||
<artifactId>avaje-dbmigration</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<version>1.2.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -172,9 +156,9 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm-agent</artifactId>
|
||||
<version>4.11.1</version>
|
||||
<groupId>org.avaje.ebean</groupId>
|
||||
<artifactId>ebean-agent</artifactId>
|
||||
<version>8.1.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -237,26 +221,15 @@
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.2</version>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm-mavenenhancer</artifactId>
|
||||
<version>4.11.1</version>
|
||||
<groupId>org.avaje.ebean</groupId>
|
||||
<artifactId>ebean-maven-plugin</artifactId>
|
||||
<version>8.1.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>test</id>
|
||||
<phase>process-test-classes</phase>
|
||||
<configuration>
|
||||
<classSource>target/test-classes</classSource>
|
||||
<!--<packages>com.avaje.tests.**</packages>-->
|
||||
<transformArgs>debug=1</transformArgs>
|
||||
</configuration>
|
||||
<goals>
|
||||
@@ -304,7 +277,7 @@
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<version>2.9.1</version>
|
||||
<configuration>
|
||||
<doctitle>Ebean 7</doctitle>
|
||||
<doctitle>Ebean 9</doctitle>
|
||||
<overview>src/main/java/com/avaje/ebean/overview.html</overview>
|
||||
<source>1.8</source>
|
||||
<doclet>org.avaje.doclet.PygmentsDoclet</doclet>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>
|
||||
@@ -120,4 +117,9 @@ public interface BeanState {
|
||||
* for a fully loaded entity bean.
|
||||
*/
|
||||
void setLoaded();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the bean putting it into NEW state such that a save() results in an insert.
|
||||
*/
|
||||
void resetForInsert();
|
||||
}
|
||||
|
||||
@@ -13,65 +13,66 @@ import java.sql.SQLException;
|
||||
* <p>
|
||||
* Example 1:
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* String sql = "{call sp_order_mod(?,?)}";
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* String sql = "{call sp_order_mod(?,?)}";
|
||||
*
|
||||
* CallableSql cs = Ebean.createCallableSql(sql);
|
||||
* cs.setParameter(1, "turbo");
|
||||
* 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 = "{call sp_insert_order(?,?)}";
|
||||
*
|
||||
*
|
||||
* <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("oe_order", true, false, false);
|
||||
* cs.addModification("oe_order_detail", 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, "Was");
|
||||
* cs.setParameter(2, "Banana");
|
||||
* cs.setParameter(1, "Was");
|
||||
* cs.setParameter(2, "Banana");
|
||||
* Ebean.execute(cs);
|
||||
*
|
||||
* cs.setParameter(1, "Here");
|
||||
* cs.setParameter(2, "Kumera");
|
||||
*
|
||||
* cs.setParameter(1, "Here");
|
||||
* cs.setParameter(2, "Kumera");
|
||||
* Ebean.execute(cs);
|
||||
*
|
||||
* cs.setParameter(1, "More");
|
||||
* cs.setParameter(2, "Apple");
|
||||
*
|
||||
* cs.setParameter(1, "More");
|
||||
* cs.setParameter(2, "Apple");
|
||||
* Ebean.execute(cs);
|
||||
*
|
||||
* // Ebean.externalModification("oe_order",true,false,false);
|
||||
* // Ebean.externalModification("oe_order_detail",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.
|
||||
@@ -30,7 +29,7 @@ final class DRawSqlColumnsParser {
|
||||
|
||||
private ColumnMapping parse() {
|
||||
|
||||
ArrayList<ColumnMapping.Column> columns = new ArrayList<ColumnMapping.Column>();
|
||||
ArrayList<ColumnMapping.Column> columns = new ArrayList<>();
|
||||
while (pos <= end) {
|
||||
ColumnMapping.Column c = nextColumnInfo();
|
||||
columns.add(c);
|
||||
@@ -47,10 +46,10 @@ final class DRawSqlColumnsParser {
|
||||
|
||||
String[] split = colInfo.split("\\s(?=[^\\)]*(?:\\(|$))");
|
||||
if (split.length > 1) {
|
||||
ArrayList<String> tmp = new ArrayList<String>(split.length);
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
if (!split[i].trim().isEmpty()) {
|
||||
tmp.add(split[i].trim());
|
||||
ArrayList<String> tmp = new ArrayList<>(split.length);
|
||||
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]);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import com.avaje.ebean.RawSql.Sql;
|
||||
import com.avaje.ebeaninternal.server.querydefn.SimpleTextParser;
|
||||
|
||||
/**
|
||||
* Parses sql-select queries to try and determine the location where WHERE and
|
||||
@@ -8,13 +9,13 @@ import com.avaje.ebean.RawSql.Sql;
|
||||
*/
|
||||
class DRawSqlParser {
|
||||
|
||||
public static final String $_AND_HAVING = "${andHaving}";
|
||||
private static final String $_AND_HAVING = "${andHaving}";
|
||||
|
||||
public static final String $_HAVING = "${having}";
|
||||
private static final String $_HAVING = "${having}";
|
||||
|
||||
public static final String $_AND_WHERE = "${andWhere}";
|
||||
private static final String $_AND_WHERE = "${andWhere}";
|
||||
|
||||
public static final String $_WHERE = "${where}";
|
||||
private static final String $_WHERE = "${where}";
|
||||
|
||||
private final SimpleTextParser textParser;
|
||||
|
||||
@@ -46,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);
|
||||
|
||||
@@ -93,7 +93,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 +103,6 @@ public interface DocumentStore {
|
||||
* .findPagedList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
*/
|
||||
<T> PagedList<T> findPagedList(DocQueryRequest<T> request);
|
||||
|
||||
@@ -117,7 +115,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)
|
||||
@@ -146,8 +143,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)
|
||||
@@ -175,7 +170,6 @@ public interface DocumentStore {
|
||||
|
||||
/**
|
||||
* Drop the index from the document store (similar to DDL drop table).
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* DocumentStore documentStore = server.docStore();
|
||||
@@ -183,13 +177,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 +193,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 +214,6 @@ public interface DocumentStore {
|
||||
* documentStore.indexSettings("product", settings);
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // refresh_interval 1s ... restore after bulk loading
|
||||
@@ -244,7 +235,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 +253,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 +268,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
|
||||
|
||||
@@ -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);
|
||||
*
|
||||
@@ -132,13 +126,13 @@ public final class Ebean {
|
||||
/**
|
||||
* Cache for fast concurrent read access.
|
||||
*/
|
||||
private final ConcurrentHashMap<String, EbeanServer> concMap = new ConcurrentHashMap<String, EbeanServer>();
|
||||
private final ConcurrentHashMap<String, EbeanServer> concMap = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Cache for synchronized read, creation and put. Protected by the monitor
|
||||
* object.
|
||||
*/
|
||||
private final HashMap<String, EbeanServer> syncMap = new HashMap<String, EbeanServer>();
|
||||
private final HashMap<String, EbeanServer> syncMap = new HashMap<>();
|
||||
|
||||
private final Object monitor = new Object();
|
||||
|
||||
@@ -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();
|
||||
@@ -499,6 +482,13 @@ public final class Ebean {
|
||||
serverMgr.getDefaultServer().endTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the current transaction as rollback only.
|
||||
*/
|
||||
public static void setRollbackOnly() {
|
||||
serverMgr.getDefaultServer().currentTransaction().setRollbackOnly();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a map of the differences between two objects of the same type.
|
||||
* <p>
|
||||
@@ -525,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
|
||||
@@ -569,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 {
|
||||
@@ -607,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)
|
||||
*/
|
||||
@@ -724,7 +710,6 @@ public final class Ebean {
|
||||
|
||||
/**
|
||||
* Refresh a 'many' property of a bean.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* Order order = ...;
|
||||
@@ -733,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);
|
||||
@@ -748,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);
|
||||
@@ -789,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);
|
||||
@@ -819,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();
|
||||
@@ -857,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) {
|
||||
@@ -896,7 +871,7 @@ public final class Ebean {
|
||||
|
||||
/**
|
||||
* Create a CallableSql to execute a given stored procedure.
|
||||
*
|
||||
*
|
||||
* @see CallableSql
|
||||
*/
|
||||
public static CallableSql createCallableSql(String sql) {
|
||||
@@ -914,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);
|
||||
*
|
||||
@@ -976,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) {
|
||||
@@ -989,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 ";
|
||||
@@ -1016,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) {
|
||||
@@ -1033,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) {
|
||||
@@ -1096,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)
|
||||
@@ -1131,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)
|
||||
*/
|
||||
@@ -1161,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
|
||||
@@ -1186,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);
|
||||
* }
|
||||
@@ -1214,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
|
||||
@@ -1229,7 +1190,6 @@ public final class Ebean {
|
||||
* });
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
*/
|
||||
public static <T> T execute(TxScope scope, TxCallable<T> c) {
|
||||
return serverMgr.getDefaultServer().execute(scope, c);
|
||||
@@ -1245,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();
|
||||
* }
|
||||
* });
|
||||
@@ -1293,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) {
|
||||
|
||||
@@ -1320,7 +1275,6 @@ public final class Ebean {
|
||||
|
||||
/**
|
||||
* Return the manager of the server cache ("L2" cache).
|
||||
*
|
||||
*/
|
||||
public static ServerCacheManager getServerCacheManager() {
|
||||
return serverMgr.getDefaultServer().getServerCacheManager();
|
||||
|
||||
@@ -167,8 +167,9 @@ public interface EbeanServer {
|
||||
/**
|
||||
* Create a new instance of T that is an EntityBean.
|
||||
* <p>
|
||||
* Generally not expected to be useful (now dynamic subclassing support was removed in
|
||||
* favour of always using enhancement).
|
||||
* Useful if you use BeanPostConstructListeners or @PostConstruct Annotations.
|
||||
* In this case you should not use "new Bean...()". Making all bean construtors protected
|
||||
* could be a good idea here.
|
||||
* </p>
|
||||
*/
|
||||
<T> T createEntityBean(Class<T> type);
|
||||
@@ -223,9 +224,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.
|
||||
@@ -249,9 +249,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);
|
||||
@@ -739,20 +738,38 @@ public interface EbeanServer {
|
||||
<T> T getReference(Class<T> beanType, Object id);
|
||||
|
||||
/**
|
||||
* Return the number of 'top level' or 'root' entities this query should
|
||||
* return.
|
||||
* Return the number of 'top level' or 'root' entities this query should return.
|
||||
*
|
||||
* @see Query#findRowCount()
|
||||
* @see com.avaje.ebean.Query#findFutureRowCount()
|
||||
* @see Query#findCount()
|
||||
* @see Query#findFutureCount()
|
||||
*/
|
||||
<T> int findRowCount(Query<T> query, Transaction transaction);
|
||||
<T> int findCount(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Return the Id values of the query as a List.
|
||||
*
|
||||
* @see com.avaje.ebean.Query#findIds()
|
||||
* @see Query#findIds()
|
||||
*/
|
||||
<T> List<Object> findIds(Query<T> query, Transaction transaction);
|
||||
<A, T> List<A> findIds(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Return a QueryIterator for the query.
|
||||
* <p>
|
||||
* Generally using {@link #findEach(Query, QueryEachConsumer, Transaction)} or
|
||||
* {@link #findEachWhile(Query, QueryEachWhileConsumer, Transaction)} is preferred
|
||||
* to findIterate(). The reason is that those methods automatically take care of
|
||||
* closing the queryIterator (and the underlying jdbc statement and resultSet).
|
||||
* </p>
|
||||
* <p>
|
||||
* This is similar to findEach in that not all the result beans need to be held
|
||||
* in memory at the same time and as such is good for processing large queries.
|
||||
* </p>
|
||||
*
|
||||
* @see Query#findIterate()
|
||||
* @see Query#findEach(QueryEachConsumer)
|
||||
* @see Query#findEachWhile(QueryEachWhileConsumer)
|
||||
*/
|
||||
<T> QueryIterator<T> findIterate(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the query visiting the each bean one at a time.
|
||||
@@ -866,9 +883,9 @@ public interface EbeanServer {
|
||||
* @param query the query to execute the row count on
|
||||
* @param transaction the transaction (can be null).
|
||||
* @return a Future object for the row count query
|
||||
* @see com.avaje.ebean.Query#findFutureRowCount()
|
||||
* @see com.avaje.ebean.Query#findFutureCount()
|
||||
*/
|
||||
<T> FutureRowCount<T> findFutureRowCount(Query<T> query, Transaction transaction);
|
||||
<T> FutureRowCount<T> findFutureCount(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute find Id's query in a background thread.
|
||||
@@ -971,7 +988,39 @@ public interface EbeanServer {
|
||||
* @return the map of fetched beans.
|
||||
* @see Query#findMap()
|
||||
*/
|
||||
<T> Map<?, T> findMap(Query<T> query, Transaction transaction);
|
||||
<K, T> Map<K, T> findMap(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the query returning a list of values for a single property.
|
||||
* <p>
|
||||
* <h3>Example 1:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<String> names =
|
||||
* Ebean.find(Customer.class)
|
||||
* .select("name")
|
||||
* .orderBy().asc("name")
|
||||
* .findSingleAttributeList();
|
||||
*
|
||||
* }</pre>
|
||||
* <h3>Example 2:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<String> names =
|
||||
* Ebean.find(Customer.class)
|
||||
* .setDistinct(true)
|
||||
* .select("name")
|
||||
* .where().eq("status", Customer.Status.NEW)
|
||||
* .orderBy().asc("name")
|
||||
* .setMaxRows(100)
|
||||
* .findSingleAttributeList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @return the list of values for the selected property
|
||||
* @see Query#findSingleAttributeList()
|
||||
*/
|
||||
<A, T> List<A> findSingleAttributeList(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute the query returning at most one entity bean or null (if no matching
|
||||
|
||||
@@ -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("Rob%");
|
||||
* example.setNotes("%something%");
|
||||
*
|
||||
* example.setName("Rob%");
|
||||
* example.setNotes("%something%");
|
||||
*
|
||||
* List<Customer> list =
|
||||
* Ebean.find(Customer.class)
|
||||
* .where()
|
||||
* // pass the bean into the where() clause
|
||||
* .exampleLike(example)
|
||||
* // you can add other expressions to the same query
|
||||
* .gt("id", 2)
|
||||
* .gt("id", 2)
|
||||
* .findList();
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* Similarly you can create an ExampleExpression
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* Customer example = new Customer();
|
||||
* example.setName("Rob%");
|
||||
* example.setNotes("%something%");
|
||||
*
|
||||
* example.setName("Rob%");
|
||||
* example.setNotes("%something%");
|
||||
*
|
||||
* // create a ExampleExpression with more control
|
||||
* ExampleExpression qbe = new ExampleExpression(example, true, LikeType.EQUAL_TO)
|
||||
* .includeZeros();
|
||||
*
|
||||
* List<Customer> 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();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<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>{@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("status", Order.Status.NEW),
|
||||
* Expr.gt("orderDate", lastWeek));
|
||||
*
|
||||
* Query<Order> 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<Order> 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);
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ import java.util.Set;
|
||||
* more methods than you would initially expect (the ones duplicated from
|
||||
* Query).
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @see Query#where()
|
||||
*/
|
||||
public interface ExpressionList<T> {
|
||||
@@ -83,14 +83,14 @@ public interface ExpressionList<T> {
|
||||
|
||||
/**
|
||||
* Add an orderBy clause to the query.
|
||||
*
|
||||
*
|
||||
* @see Query#orderBy(String)
|
||||
*/
|
||||
Query<T> orderBy(String orderBy);
|
||||
|
||||
/**
|
||||
* Add an orderBy clause to the query.
|
||||
*
|
||||
*
|
||||
* @see Query#orderBy(String)
|
||||
*/
|
||||
Query<T> setOrderBy(String orderBy);
|
||||
@@ -104,7 +104,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
|
||||
@@ -116,12 +116,6 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
Query<T> asDraft();
|
||||
|
||||
/**
|
||||
* Deprecated in favour of setIncludeSoftDeletes().
|
||||
*/
|
||||
@Deprecated
|
||||
Query<T> includeSoftDeletes();
|
||||
|
||||
/**
|
||||
* Execute the query including soft deleted rows.
|
||||
*/
|
||||
@@ -147,6 +141,13 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
int update();
|
||||
|
||||
/**
|
||||
* Execute the query iterating over the results.
|
||||
*
|
||||
* @see Query#findIterate()
|
||||
*/
|
||||
QueryIterator<T> findIterate();
|
||||
|
||||
/**
|
||||
* Execute the query process the beans one at a time.
|
||||
*
|
||||
@@ -164,17 +165,17 @@ public interface ExpressionList<T> {
|
||||
|
||||
/**
|
||||
* Execute the query returning a list.
|
||||
*
|
||||
*
|
||||
* @see Query#findList()
|
||||
*/
|
||||
List<T> findList();
|
||||
|
||||
/**
|
||||
* Execute the query returning the list of Id's.
|
||||
*
|
||||
*
|
||||
* @see Query#findIds()
|
||||
*/
|
||||
List<Object> findIds();
|
||||
<A> List<A> findIds();
|
||||
|
||||
/**
|
||||
* Return the count of entities this query should return.
|
||||
@@ -182,26 +183,53 @@ public interface ExpressionList<T> {
|
||||
* This is the number of 'top level' or 'root level' entities.
|
||||
* </p>
|
||||
*/
|
||||
int findRowCount();
|
||||
int findCount();
|
||||
|
||||
/**
|
||||
* Execute the query returning a set.
|
||||
*
|
||||
*
|
||||
* @see Query#findSet()
|
||||
*/
|
||||
Set<T> findSet();
|
||||
|
||||
/**
|
||||
* Execute the query returning a map.
|
||||
*
|
||||
*
|
||||
* @see Query#findMap()
|
||||
*/
|
||||
Map<?, T> findMap();
|
||||
<K> Map<K, T> findMap();
|
||||
|
||||
/**
|
||||
* Return a typed map specifying the key property and type.
|
||||
* Execute the query returning a list of values for a single property.
|
||||
* <p>
|
||||
* <h3>Example 1:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<String> names =
|
||||
* Ebean.find(Customer.class)
|
||||
* .select("name")
|
||||
* .orderBy().asc("name")
|
||||
* .findSingleAttributeList();
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* <h3>Example 2:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<String> names =
|
||||
* Ebean.find(Customer.class)
|
||||
* .setDistinct(true)
|
||||
* .select("name")
|
||||
* .where().eq("status", Customer.Status.NEW)
|
||||
* .orderBy().asc("name")
|
||||
* .setMaxRows(100)
|
||||
* .findSingleAttributeList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @return the list of values for the selected property
|
||||
*/
|
||||
<K> Map<K, T> findMap(String keyProperty, Class<K> keyType);
|
||||
<A> List<A> findSingleAttributeList();
|
||||
|
||||
/**
|
||||
* Execute the query returning a single bean or null (if no matching
|
||||
@@ -212,7 +240,6 @@ public interface ExpressionList<T> {
|
||||
* </p>
|
||||
*
|
||||
* @throws NonUniqueResultException if more than one result was found
|
||||
*
|
||||
* @see Query#findUnique()
|
||||
*/
|
||||
@Nullable
|
||||
@@ -225,10 +252,10 @@ public interface ExpressionList<T> {
|
||||
* execution status (isDone etc) and get the value (with or without a
|
||||
* timeout).
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @return a Future object for the row count query
|
||||
*/
|
||||
FutureRowCount<T> findFutureRowCount();
|
||||
FutureRowCount<T> findFutureCount();
|
||||
|
||||
/**
|
||||
* Execute find Id's query in a background thread.
|
||||
@@ -237,7 +264,7 @@ public interface ExpressionList<T> {
|
||||
* execution status (isDone etc) and get the value (with or without a
|
||||
* timeout).
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @return a Future object for the list of Id's
|
||||
*/
|
||||
FutureIds<T> findFutureIds();
|
||||
@@ -249,7 +276,7 @@ public interface ExpressionList<T> {
|
||||
* execution status (isDone etc) and get the value (with or without a
|
||||
* timeout).
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @return a Future object for the list result of the query
|
||||
*/
|
||||
FutureList<T> findFutureList();
|
||||
@@ -264,7 +291,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)
|
||||
@@ -281,7 +308,6 @@ public interface ExpressionList<T> {
|
||||
* }</pre>
|
||||
*
|
||||
* @return The PagedList
|
||||
*
|
||||
* @see Query#findPagedList()
|
||||
*/
|
||||
PagedList<T> findPagedList();
|
||||
@@ -289,8 +315,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();
|
||||
@@ -298,8 +324,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);
|
||||
@@ -312,7 +338,7 @@ public interface ExpressionList<T> {
|
||||
/**
|
||||
* Specify specific properties to fetch on the main/root bean (aka partial
|
||||
* object).
|
||||
*
|
||||
*
|
||||
* @see Query#select(String)
|
||||
*/
|
||||
Query<T> select(String properties);
|
||||
@@ -337,28 +363,28 @@ public interface ExpressionList<T> {
|
||||
|
||||
/**
|
||||
* Set the first row to fetch.
|
||||
*
|
||||
*
|
||||
* @see Query#setFirstRow(int)
|
||||
*/
|
||||
Query<T> setFirstRow(int firstRow);
|
||||
|
||||
/**
|
||||
* Set the maximum number of rows to fetch.
|
||||
*
|
||||
*
|
||||
* @see Query#setMaxRows(int)
|
||||
*/
|
||||
Query<T> setMaxRows(int maxRows);
|
||||
|
||||
/**
|
||||
* Set the name of the property which values become the key of a map.
|
||||
*
|
||||
*
|
||||
* @see Query#setMapKey(String)
|
||||
*/
|
||||
Query<T> setMapKey(String mapKey);
|
||||
|
||||
/**
|
||||
* Set to true to use the query for executing this query.
|
||||
*
|
||||
*
|
||||
* @see Query#setUseCache(boolean)
|
||||
*/
|
||||
Query<T> setUseCache(boolean useCache);
|
||||
@@ -412,7 +438,6 @@ public interface ExpressionList<T> {
|
||||
|
||||
/**
|
||||
* Path exists - for the given path in a JSON document.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* where().jsonExists("content", "path.other")
|
||||
@@ -420,13 +445,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")
|
||||
@@ -434,13 +458,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)
|
||||
@@ -448,14 +472,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)
|
||||
@@ -463,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> 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)
|
||||
@@ -481,7 +505,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)
|
||||
@@ -492,7 +516,7 @@ public interface ExpressionList<T> {
|
||||
|
||||
/**
|
||||
* Less than - for the given path in a JSON document.
|
||||
*
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* where().jsonLessThan("content", "path.other", 34)
|
||||
@@ -503,7 +527,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)
|
||||
@@ -514,7 +538,7 @@ public interface ExpressionList<T> {
|
||||
|
||||
/**
|
||||
* Between - for the given path in a JSON document.
|
||||
*
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* where().jsonBetween("content", "orderDate", lowerDateTime, upperDateTime)
|
||||
@@ -528,7 +552,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);
|
||||
@@ -619,7 +643,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
|
||||
@@ -627,26 +651,26 @@ public interface ExpressionList<T> {
|
||||
* Customer example = new Customer();
|
||||
* example.setName("Rob%");
|
||||
* example.setNotes("%something%");
|
||||
*
|
||||
*
|
||||
* List<Customer> list = Ebean.find(Customer.class).where()
|
||||
* // pass the bean into the where() clause
|
||||
* .exampleLike(example)
|
||||
* // you can add other expressions to the same query
|
||||
* .gt("id", 2).findList();
|
||||
*
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* Similarly you can create an ExampleExpression
|
||||
*
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* Customer example = new Customer();
|
||||
* example.setName("Rob%");
|
||||
* example.setNotes("%something%");
|
||||
*
|
||||
*
|
||||
* // create a ExampleExpression with more control
|
||||
* ExampleExpression qbe = new ExampleExpression(example, true, LikeType.EQUAL_TO).includeZeros();
|
||||
*
|
||||
*
|
||||
* List<Customer> list = Ebean.find(Customer.class).where().add(qbe).findList();
|
||||
*
|
||||
* }</pre>
|
||||
@@ -748,7 +772,7 @@ public interface ExpressionList<T> {
|
||||
* Exists expression
|
||||
*/
|
||||
ExpressionList<T> exists(Query<?> subQuery);
|
||||
|
||||
|
||||
/**
|
||||
* Not exists expression
|
||||
*/
|
||||
@@ -775,9 +799,8 @@ public interface ExpressionList<T> {
|
||||
* 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.
|
||||
*/
|
||||
ExpressionList<T> allEq(Map<String, Object> propertyMap);
|
||||
|
||||
@@ -821,7 +844,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
|
||||
*
|
||||
@@ -853,7 +876,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")
|
||||
@@ -866,7 +889,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);
|
||||
|
||||
@@ -874,14 +897,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.
|
||||
@@ -932,7 +955,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()
|
||||
@@ -957,11 +980,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
|
||||
@@ -988,10 +1011,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()
|
||||
@@ -1001,7 +1024,7 @@ public interface ExpressionList<T> {
|
||||
* .endNot()
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* <pre>@{code
|
||||
*
|
||||
* // Example: nested not()
|
||||
|
||||
@@ -21,48 +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
|
||||
* 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 =
|
||||
@@ -74,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"
|
||||
* //
|
||||
@@ -92,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>
|
||||
@@ -113,27 +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.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
|
||||
* // .. use a batch size of 5 to load the customers
|
||||
*
|
||||
* find customer (name)
|
||||
* fetch customer.contacts (contactName, phone, email)
|
||||
* fetch customer.shippingAddress (*)
|
||||
* where id in (?,?,?,?,?)
|
||||
*
|
||||
* //
|
||||
* // .. if lazy loading of customers is invoked
|
||||
* // .. use a batch size of 5 to load the customers
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
*
|
||||
* @author mario
|
||||
* @author rbygrave
|
||||
*/
|
||||
@@ -165,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;
|
||||
@@ -199,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;
|
||||
@@ -217,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;
|
||||
@@ -233,7 +231,7 @@ public class FetchConfig implements Serializable {
|
||||
public int getLazyBatchSize() {
|
||||
return lazyBatchSize;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the batch size for separate query load.
|
||||
*/
|
||||
|
||||
@@ -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<MetaQueryStatistic> 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<MetaQueryStatistic> filteredList =
|
||||
*
|
||||
* List<MetaQueryStatistic> filteredList =
|
||||
* Ebean.filter(MetaQueryStatistic.class)
|
||||
* .sort("avgTimeMicros desc")
|
||||
* .gt("executionCount", 0)
|
||||
* .gt("lastQueryTime", nowMinus24Hrs)
|
||||
* .eq("autoTuned", 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<Order> orders =
|
||||
*
|
||||
* List<Order> orders =
|
||||
* Ebean.find(Order.class).findList();
|
||||
*
|
||||
*
|
||||
* // Apply a filter...
|
||||
*
|
||||
* List<Order> filteredOrders =
|
||||
*
|
||||
* List<Order> filteredOrders =
|
||||
* Ebean.filter(Order.class)
|
||||
* .startsWith("customer.name", "Rob")
|
||||
* .eq("customer.shippingAddress.city", "Auckland")
|
||||
* .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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)}
|
||||
*/
|
||||
|
||||
@@ -9,8 +9,6 @@ import java.util.concurrent.Future;
|
||||
* It extends the java.util.concurrent.Future with the ability to get the Id's
|
||||
* while the query is still executing in the background.
|
||||
* </p>
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public interface FutureIds<T> extends Future<List<Object>> {
|
||||
|
||||
@@ -19,16 +17,4 @@ public interface FutureIds<T> extends Future<List<Object>> {
|
||||
*/
|
||||
Query<T> getQuery();
|
||||
|
||||
/**
|
||||
* Return the list of Id's which could be partially populated.
|
||||
* <p>
|
||||
* That is the query getting the id's could still be running and adding id's
|
||||
* to this list.
|
||||
* </p>
|
||||
* <p>
|
||||
* To get the list of Id's ensuring the query has finished use the
|
||||
* {@link Future#get()} method instead of this one.
|
||||
* </p>
|
||||
*/
|
||||
List<Object> getPartialIds();
|
||||
}
|
||||
|
||||
@@ -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,7 +8,8 @@ import java.util.concurrent.Future;
|
||||
* <p>
|
||||
* It extends the java.util.concurrent.Future.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @param <T> the BeanType
|
||||
* @author rbygrave
|
||||
*/
|
||||
public interface FutureRowCount<T> extends Future<Integer> {
|
||||
|
||||
@@ -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 > 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.
|
||||
*/
|
||||
|
||||
@@ -13,31 +13,26 @@ 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
|
||||
* tools to still mock out the underlying 'default EbeanServer' for testing purposes.
|
||||
*
|
||||
* <p>
|
||||
* You may choose not use this Model mapped superclass if you don't like the 'Active Record' style
|
||||
* or if you believe it 'pollutes' your entity beans.
|
||||
*
|
||||
* <p>
|
||||
* You can use Dependency Injection like Guice or Spring to construct and wire a EbeanServer instance
|
||||
* and have that same instance used with this Model and Finder. The way that works is that when the
|
||||
* DI container creates the EbeanServer instance it can be registered with the Ebean singleton. In this
|
||||
* way the EbeanServer instance can be injected as per normal Guice / Spring dependency injection and
|
||||
* that same instance also used to support the Model and Finder active record style.
|
||||
*
|
||||
* <p>
|
||||
* If you choose to use the Model mapped superclass you will probably also chose to additionally add
|
||||
* a {@link Find} as a public static field to complete the active record pattern and provide a
|
||||
* relatively nice clean way to write queries.
|
||||
*
|
||||
* <p>
|
||||
* <h3>Typical common @MappedSuperclass</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -58,7 +53,7 @@ import java.util.UUID;
|
||||
* ...
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* <h3>Extend the Model</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -78,7 +73,7 @@ import java.util.UUID;
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* <h3>Modal: save()</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -90,7 +85,7 @@ import java.util.UUID;
|
||||
* customer.save();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* <h3>Find byId</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -98,7 +93,7 @@ import java.util.UUID;
|
||||
* Customer customer = Customer.find.byId(42);
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* <h3>Find where</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -115,39 +110,37 @@ 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("Roberto");
|
||||
* customer.save();
|
||||
*
|
||||
*
|
||||
* Customer otherCustomer = new Customer();
|
||||
* otherCustomer.setName("Franko");
|
||||
* otherCustomer.save();
|
||||
*
|
||||
*
|
||||
* transaction.commit();
|
||||
*
|
||||
*
|
||||
* } finally {
|
||||
* transaction.end();
|
||||
* }
|
||||
*
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
public static EbeanServer db() {
|
||||
@@ -156,13 +149,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 +167,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 +188,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 +206,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.
|
||||
@@ -319,6 +309,7 @@ public abstract class Model {
|
||||
* 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
|
||||
*/
|
||||
@@ -326,7 +317,7 @@ public abstract class Model {
|
||||
|
||||
/**
|
||||
* Create with the type of the entity bean.
|
||||
*
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* @Entity
|
||||
@@ -336,11 +327,11 @@ public abstract class Model {
|
||||
* ...
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* <p/>
|
||||
* The preferred approach is to instead use <code>Find</code> as below. This approach is more DRY in that it does
|
||||
* not require the class literal Customer.class to be passed into the constructor.
|
||||
*
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* @Entity
|
||||
@@ -366,13 +357,13 @@ public abstract class Model {
|
||||
|
||||
/**
|
||||
* Helper object for performing queries.
|
||||
*
|
||||
* <p>
|
||||
* <p>
|
||||
* Typically a Find instance is defined as a public static field on an entity bean class to provide a
|
||||
* nice way to write queries.
|
||||
*
|
||||
* <p>
|
||||
* <h3>Example use:</h3>
|
||||
*
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* @Entity
|
||||
@@ -395,7 +386,7 @@ public abstract class Model {
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* <h3>Kotlin</h3>
|
||||
* In Kotlin you would typically create Find as a companion object.
|
||||
* <pre>{@code
|
||||
@@ -404,12 +395,10 @@ public abstract class Model {
|
||||
* 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
|
||||
* @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> {
|
||||
|
||||
@@ -427,11 +416,11 @@ public abstract class Model {
|
||||
* Creates a finder for entity of type <code>T</code> with ID of type <code>I</code>.
|
||||
* <p/>
|
||||
* Typically you create Find as a public static field on each entity bean as the example below.
|
||||
*
|
||||
* <p>
|
||||
* <p/>
|
||||
* Note that Find is an abstract class and hence <code>{}</code> is required. This is done so
|
||||
* that the type (class literal) of the entity bean can be derived from the generics parameter.
|
||||
*
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* @Entity
|
||||
@@ -456,10 +445,10 @@ public abstract class Model {
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* <h3>Kotlin</h3>
|
||||
* In Kotlin you would typically create it as a companion object.
|
||||
*
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // kotlin
|
||||
@@ -470,7 +459,7 @@ public abstract class Model {
|
||||
@SuppressWarnings("unchecked")
|
||||
public Find() {
|
||||
this.serverName = null;
|
||||
this.type = (Class<T>)ClassUtil.getSecondArgumentType(getClass());
|
||||
this.type = (Class<T>) ClassUtil.getSecondArgumentType(getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -483,10 +472,9 @@ public abstract class Model {
|
||||
|
||||
/**
|
||||
* Return the underlying 'default' EbeanServer.
|
||||
*
|
||||
* <p>
|
||||
* <p>
|
||||
* This provides full access to the API such as explicit transaction demarcation etc.
|
||||
*
|
||||
*/
|
||||
public EbeanServer db() {
|
||||
return Ebean.getServer(serverName);
|
||||
@@ -495,11 +483,10 @@ public abstract class Model {
|
||||
/**
|
||||
* Return typically a different EbeanServer to the default.
|
||||
* <p>
|
||||
* This is equivilent to {@link Ebean#getServer(String)}
|
||||
*
|
||||
* @param server
|
||||
* The name of the EbeanServer. If this is null then the default EbeanServer is
|
||||
* returned.
|
||||
* 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);
|
||||
@@ -507,12 +494,12 @@ public abstract class Model {
|
||||
|
||||
/**
|
||||
* Creates a Finder for the named EbeanServer.
|
||||
*
|
||||
* <p>
|
||||
* <p>
|
||||
* Create and return a new Finder for a different server.
|
||||
*/
|
||||
public Finder<I, T> on(String server) {
|
||||
return new Finder<I, T>(server, type);
|
||||
return new Finder<>(server, type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -526,7 +513,7 @@ public abstract class Model {
|
||||
|
||||
/**
|
||||
* Retrieves all entities of the given type.
|
||||
*
|
||||
* <p>
|
||||
* <p>
|
||||
* This is the same as (synonym for) {@link #findList()}
|
||||
*/
|
||||
@@ -536,7 +523,7 @@ public abstract class Model {
|
||||
|
||||
/**
|
||||
* Retrieves an entity by ID.
|
||||
*
|
||||
* <p>
|
||||
* <p>
|
||||
* Equivalent to {@link EbeanServer#find(Class, Object)}
|
||||
*/
|
||||
@@ -547,7 +534,7 @@ public abstract class Model {
|
||||
|
||||
/**
|
||||
* Creates an entity reference for this ID.
|
||||
*
|
||||
* <p>
|
||||
* <p>
|
||||
* Equivalent to {@link EbeanServer#getReference(Class, Object)}
|
||||
*/
|
||||
@@ -585,7 +572,7 @@ public abstract class Model {
|
||||
|
||||
/**
|
||||
* Returns the next identity value.
|
||||
*
|
||||
*
|
||||
* @see EbeanServer#nextId(Class)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -598,7 +585,7 @@ public abstract class Model {
|
||||
* <p>
|
||||
* Equivalent to {@link Query#findIds()}
|
||||
*/
|
||||
public List<Object> findIds() {
|
||||
public <A> List<A> findIds() {
|
||||
return query().findIds();
|
||||
}
|
||||
|
||||
@@ -660,36 +647,44 @@ public abstract class Model {
|
||||
* <p>
|
||||
* Equivalent to {@link Query#findMap()}
|
||||
*/
|
||||
public Map<?, T> findMap() {
|
||||
public <K> Map<K, T> findMap() {
|
||||
return query().findMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the query and returns the results as a map of the objects specifying the map key
|
||||
* property.
|
||||
* <p>
|
||||
* Equivalent to {@link Query#findMap(String, Class)}
|
||||
*/
|
||||
public <K> Map<K, T> findMap(String keyProperty, Class<K> keyType) {
|
||||
return query().findMap(keyProperty, keyType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a find row count query in a background thread.
|
||||
* <p>
|
||||
* Equivalent to {@link Query#findFutureRowCount()}
|
||||
* 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().findFutureRowCount();
|
||||
return query().findFutureCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total number of entities for this type. *
|
||||
* <p>
|
||||
* Equivalent to {@link Query#findRowCount()}
|
||||
* Equivalent to {@link Query#findCount()}
|
||||
*/
|
||||
public int findCount() {
|
||||
return query().findCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated in favor of findCount().
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
public int findRowCount() {
|
||||
return query().findRowCount();
|
||||
return query().findCount();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -822,7 +817,7 @@ public abstract class Model {
|
||||
|
||||
/**
|
||||
* Sets the ID value to query.
|
||||
*
|
||||
* <p>
|
||||
* <p>
|
||||
* Use this to perform a find byId query but with additional control over the query such as
|
||||
* using select and fetch to control what parts of the object graph are returned.
|
||||
@@ -851,7 +846,7 @@ public abstract class Model {
|
||||
|
||||
/**
|
||||
* Create a query with the select with "for update" specified.
|
||||
*
|
||||
* <p>
|
||||
* <p>
|
||||
* This will typically create row level database locks on the selected rows.
|
||||
*/
|
||||
@@ -888,4 +883,4 @@ public abstract class Model {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,9 +28,9 @@ public final class OrderBy<T> implements Serializable {
|
||||
* Create an empty OrderBy with no associated query.
|
||||
*/
|
||||
public OrderBy() {
|
||||
this.list = new ArrayList<Property>(3);
|
||||
this.list = new ArrayList<>(3);
|
||||
}
|
||||
|
||||
|
||||
private OrderBy(List<Property> list) {
|
||||
this.list = list;
|
||||
}
|
||||
@@ -52,7 +52,7 @@ public final class OrderBy<T> implements Serializable {
|
||||
*/
|
||||
public OrderBy(Query<T> query, String orderByClause) {
|
||||
this.query = query;
|
||||
this.list = new ArrayList<Property>(3);
|
||||
this.list = new ArrayList<>(3);
|
||||
parse(orderByClause);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -100,13 +100,13 @@ public final class OrderBy<T> implements Serializable {
|
||||
* Return a copy of this OrderBy with the path trimmed.
|
||||
*/
|
||||
public OrderBy<T> copyWithTrim(String path) {
|
||||
List<Property> newList = new ArrayList<Property>(list.size());
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
newList.add(list.get(i).copyWithTrim(path));
|
||||
List<Property> newList = new ArrayList<>(list.size());
|
||||
for (Property aList : list) {
|
||||
newList.add(aList.copyWithTrim(path));
|
||||
}
|
||||
return new OrderBy<T>(newList);
|
||||
return new OrderBy<>(newList);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the properties for this OrderBy.
|
||||
*/
|
||||
@@ -141,9 +141,9 @@ public final class OrderBy<T> implements Serializable {
|
||||
*/
|
||||
public OrderBy<T> copy() {
|
||||
|
||||
OrderBy<T> copy = new OrderBy<T>();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
copy.add(list.get(i).copy());
|
||||
OrderBy<T> copy = new OrderBy<>();
|
||||
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);
|
||||
@@ -370,10 +370,10 @@ public final class OrderBy<T> implements Serializable {
|
||||
return null;
|
||||
}
|
||||
|
||||
ArrayList<String> wordList = new ArrayList<String>(pairs.length);
|
||||
for (int i = 0; i < pairs.length; i++) {
|
||||
if (!isEmptyString(pairs[i])) {
|
||||
wordList.add(pairs[i]);
|
||||
ArrayList<String> wordList = new ArrayList<>(pairs.length);
|
||||
for (String pair : pairs) {
|
||||
if (!isEmptyString(pair)) {
|
||||
wordList.add(pair);
|
||||
}
|
||||
}
|
||||
if (wordList.isEmpty()) {
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.util.concurrent.Future;
|
||||
* <p>
|
||||
* The benefit of using PagedList over just using the normal Query with
|
||||
* {@link Query#setFirstRow(int)} and {@link Query#setMaxRows(int)} is that it additionally wraps
|
||||
* functionality that can call {@link Query#findFutureRowCount()} to determine total row count,
|
||||
* functionality that can call {@link Query#findFutureCount()} to determine total row count,
|
||||
* total page count etc.
|
||||
* </p>
|
||||
* <p>
|
||||
@@ -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,32 +42,7 @@ import java.util.concurrent.Future;
|
||||
* int totalRowCount = pagedList.getTotalRowCount();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h4>Example: typical use including total row count</h4>
|
||||
* <pre>{@code
|
||||
*
|
||||
* // We want to find the first 100 new orders
|
||||
* // ... 0 means first page
|
||||
* // ... page size is 100
|
||||
*
|
||||
* PagedList<Order> pagedList
|
||||
* = ebeanServer.find(Order.class)
|
||||
* .where().eq("status", Order.Status.NEW)
|
||||
* .order().asc("id")
|
||||
* .findPagedList(0, 100);
|
||||
*
|
||||
* // Optional: initiate the loading of the total
|
||||
* // row count in a background thread
|
||||
* pagedList.loadRowCount();
|
||||
*
|
||||
* // fetch and return the list in the foreground thread
|
||||
* List<Order> orders = pagedList.getList();
|
||||
*
|
||||
* // get the total row count (from the future)
|
||||
* int totalRowCount = pagedList.getTotalRowCount();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* <h4>Example: No total row count required</h4>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -81,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> {
|
||||
@@ -103,14 +75,13 @@ 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
|
||||
* wrapped in the unchecked PersistenceException (which might be preferrable).
|
||||
* </p>
|
||||
*/
|
||||
void loadRowCount();
|
||||
void loadCount();
|
||||
|
||||
/**
|
||||
* Return the Future row count. You might get this if you wish to cancel the total row count query
|
||||
@@ -138,7 +109,7 @@ public interface PagedList<T> {
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
Future<Integer> getFutureRowCount();
|
||||
Future<Integer> getFutureCount();
|
||||
|
||||
/**
|
||||
* Return the list of entities for this page.
|
||||
@@ -170,7 +141,7 @@ public interface PagedList<T> {
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
int getTotalRowCount();
|
||||
int getTotalCount();
|
||||
|
||||
/**
|
||||
* Return the total number of pages based on the page size and total row count.
|
||||
@@ -186,6 +157,14 @@ public interface PagedList<T> {
|
||||
*/
|
||||
int getPageSize();
|
||||
|
||||
/**
|
||||
* Return the index position of this page (Zero based).
|
||||
* <p>
|
||||
* This is a calculated value based on firstRow/maxRows.
|
||||
* </p>
|
||||
*/
|
||||
int getPageIndex();
|
||||
|
||||
/**
|
||||
* Return true if there is a next page.
|
||||
* <p>
|
||||
@@ -208,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);
|
||||
|
||||
@@ -7,6 +7,8 @@ import javax.persistence.PersistenceException;
|
||||
*/
|
||||
public class PersistenceIOException extends PersistenceException {
|
||||
|
||||
private static final long serialVersionUID = -7630050437148176148L;
|
||||
|
||||
public PersistenceIOException(String msg, Exception cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
@@ -13,10 +13,10 @@ import java.util.Set;
|
||||
* <p>
|
||||
* Example: Create the query using the API.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<Order> orderList =
|
||||
* List<Order> orderList =
|
||||
* ebeanServer.find(Order.class)
|
||||
* .fetch("customer")
|
||||
* .fetch("details")
|
||||
@@ -26,46 +26,40 @@ import java.util.Set;
|
||||
* .orderBy("customer.id, id desc")
|
||||
* .setMaxRows(50)
|
||||
* .findList();
|
||||
*
|
||||
*
|
||||
* ...
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* Example: The same query using the query language
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* String oql =
|
||||
* " find order "
|
||||
* String oql =
|
||||
* +" fetch customer "
|
||||
* +" fetch details "
|
||||
* +" where customer.name like :custName and orderDate > :minOrderDate "
|
||||
* +" order by customer.id, id desc "
|
||||
* +" limit 50 ";
|
||||
*
|
||||
*
|
||||
* Query<Order> query = ebeanServer.createQuery(Order.class, oql);
|
||||
* query.setParameter("custName", "Rob%");
|
||||
* query.setParameter("minOrderDate", lastWeek);
|
||||
*
|
||||
*
|
||||
* List<Order> orderList = query.findList();
|
||||
* ...
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* Example: Using a named query called "with.cust.and.details"
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* Query<Order> query = ebeanServer.createNamedQuery(Order.class,"with.cust.and.details");
|
||||
* query.setParameter("custName", "Rob%");
|
||||
* query.setParameter("minOrderDate", lastWeek);
|
||||
*
|
||||
*
|
||||
* List<Order> orderList = query.findList();
|
||||
* ...
|
||||
* }</pre>
|
||||
*
|
||||
* <h3>AutoTune</h3>
|
||||
* <p>
|
||||
* Ebean has built in support for "AutoTune". This is a mechanism where a query
|
||||
@@ -82,7 +76,6 @@ import java.util.Set;
|
||||
* to a remote client or where there is some requirement for "Read Consistency"
|
||||
* guarantees.
|
||||
* </p>
|
||||
*
|
||||
* <h3>Query Language</h3>
|
||||
* <p>
|
||||
* <b>Partial Objects</b>
|
||||
@@ -101,36 +94,25 @@ import java.util.Set;
|
||||
* concurrency checking will occur but only include the fetched properties.
|
||||
* Refer to "ALL Properties/Columns" mode of Optimistic Concurrency checking.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
* [ find {bean type} [ ( * | {fetch properties} ) ] ]
|
||||
* [ fetch {associated bean} [ ( * | {fetch properties} ) ] ]
|
||||
* [ select [ ( * | {fetch properties} ) ] ]
|
||||
* [ fetch {path} [ ( * | {fetch properties} ) ] ]
|
||||
* [ where {predicates} ]
|
||||
* [ order by {order by properties} ]
|
||||
* [ limit {max rows} [ offset {first row} ] ]
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* <b>FIND</b> <b>{bean type}</b> [ ( <i>*</i> | <i>{fetch properties}</i> ) ]
|
||||
* <b>SELECT</b> [ ( <i>*</i> | <i>{fetch properties}</i> ) ]
|
||||
* </p>
|
||||
* <p>
|
||||
* With the find you specify the type of beans to fetch. You can optionally
|
||||
* specify a list of properties to fetch. If you do not specify a list of
|
||||
* properties ALL the properties for those beans are fetched.
|
||||
* With the select you can specify a list of properties to fetch.
|
||||
* </p>
|
||||
* <p>
|
||||
* In object graph terms the <em>find</em> clause specifies the type of bean at
|
||||
* the root level and the <em>fetch</em> clauses specify the paths of the object
|
||||
* graph to populate.
|
||||
* </p>
|
||||
* <p>
|
||||
* <b>FETCH</b> <b>{associated property}</b> [ ( <i>*</i> | <i>{fetch
|
||||
* properties}</i> ) ]
|
||||
* <b>FETCH</b> <b>{path}</b> [ ( <i>*</i> | <i>{fetch properties}</i> ) ]
|
||||
* </p>
|
||||
* <p>
|
||||
* With the fetch you specify the associated property to fetch and populate. The
|
||||
* associated property is a OneToOnem, ManyToOne, OneToMany or ManyToMany
|
||||
* property. When the query is executed Ebean will fetch the associated data.
|
||||
* path is a OneToOne, ManyToOne, OneToMany or ManyToMany property.
|
||||
* </p>
|
||||
* <p>
|
||||
* For fetch of a path we can optionally specify a list of properties to fetch.
|
||||
@@ -161,52 +143,34 @@ import java.util.Set;
|
||||
* </p>
|
||||
* <h4>Examples of Ebean's Query Language</h4>
|
||||
* <p>
|
||||
* Find orders fetching all its properties
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
* find order
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* Find orders fetching all its properties
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
* find order (*)
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* Find orders fetching its id, shipDate and status properties. Note that the id
|
||||
* property is always fetched even if it is not included in the list of fetch
|
||||
* properties.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
* find order (shipDate, status)
|
||||
*
|
||||
* select (shipDate, status)
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* Find orders with a named bind variable (that will need to be bound via
|
||||
* {@link Query#setParameter(String, Object)}).
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
* find order
|
||||
*
|
||||
* where customer.name like :custLike
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* Find orders and also fetch the customer with a named bind parameter. This
|
||||
* will fetch and populate both the order and customer objects.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
* find order
|
||||
*
|
||||
* fetch customer
|
||||
* where customer.id = :custId
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* Find orders and also fetch the customer, customer shippingAddress, order
|
||||
* details and related product. Note that customer and product objects will be
|
||||
@@ -215,63 +179,16 @@ import java.util.Set;
|
||||
* objects (associated with each order detail) will have their id, sku and name
|
||||
* populated.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
* find order
|
||||
*
|
||||
* fetch customer (name)
|
||||
* fetch customer.shippingAddress
|
||||
* fetch details
|
||||
* fetch details.product (sku, name)
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <h3>Early parsing of the Query</h3>
|
||||
* <p>
|
||||
* When you get a Query object from a named query, the query statement has
|
||||
* already been parsed. You can then add to that query (add fetch paths, add to
|
||||
* the where clause) or override some of its settings (override the order by
|
||||
* clause, first rows, max rows).
|
||||
* </p>
|
||||
* <p>
|
||||
* The thought is that you can use named queries as a 'starting point' and then
|
||||
* modify the query to suit specific needs.
|
||||
* </p>
|
||||
* <h3>Building the Where clause</h3>
|
||||
* <p>
|
||||
* You can add to the where clause using Expression objects or a simple String.
|
||||
* Note that the ExpressionList has methods to add most of the common
|
||||
* expressions that you will need.
|
||||
* <ul>
|
||||
* <li>where(String addToWhereClause)</li>
|
||||
* <li>where().add(Expression expression)</li>
|
||||
* <li>where().eq(propertyName, value).like(propertyName , value)...</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
* <p>
|
||||
* The full WHERE clause is constructed by appending together
|
||||
* <li>original query where clause (Named query or query.setQuery(String oql))</li>
|
||||
* <li>clauses added via query.where(String addToWhereClause)</li>
|
||||
* <li>clauses added by Expression objects</li>
|
||||
* </p>
|
||||
* <p>
|
||||
* The above is the order that these are clauses are appended to give the full
|
||||
* WHERE clause.
|
||||
* </p>
|
||||
* <h3>Design Goal</h3>
|
||||
* <p>
|
||||
* This query language is NOT designed to be a replacement for SQL. It is
|
||||
* designed to be a simple way to describe the "Object Graph" you want Ebean to
|
||||
* build for you. Each find/fetch represents a node in that "Object Graph" which
|
||||
* makes it easy to define for each node which properties you want to fetch.
|
||||
* </p>
|
||||
* <p>
|
||||
* Once you hit the limits of this language such as wanting aggregate functions
|
||||
* (sum, average, min etc) or recursive queries etc you use SQL. Ebean's goal is
|
||||
* to make it as easy as possible to use your own SQL to populate entity beans.
|
||||
* Refer to {@link RawSql} .
|
||||
* </p>
|
||||
*
|
||||
* @param <T>
|
||||
* the type of Entity bean this query will fetch.
|
||||
*
|
||||
* @param <T> the type of Entity bean this query will fetch.
|
||||
*/
|
||||
public interface Query<T> {
|
||||
|
||||
@@ -289,7 +206,7 @@ public interface Query<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
|
||||
@@ -325,7 +242,7 @@ public interface Query<T> {
|
||||
* Specify the PersistenceContextScope to use for this query.
|
||||
* <p/>
|
||||
* When this is not set the 'default' configured on {@link com.avaje.ebean.config.ServerConfig#setPersistenceContextScope(PersistenceContextScope)}
|
||||
* is used - this value defaults to {@link com.avaje.ebean.PersistenceContextScope#TRANSACTION}.
|
||||
* is used - this value defaults to {@link PersistenceContextScope#TRANSACTION}.
|
||||
* <p/>
|
||||
* Note that the same persistence Context is used for subsequent lazy loading and query join queries.
|
||||
* <p/>
|
||||
@@ -392,14 +309,15 @@ public interface Query<T> {
|
||||
Query<T> setDisableReadAuditing();
|
||||
|
||||
/**
|
||||
* Explicitly set a comma delimited list of the properties to fetch on the
|
||||
* 'main' root level entity bean (aka partial object). Note that '*' means all
|
||||
* properties.
|
||||
* Specify the properties to fetch on the root level entity bean in comma delimited format.
|
||||
* <p>
|
||||
* You use {@link #fetch(String, String)} to specify specific properties to fetch
|
||||
* The Id property is automatically included in the properties to fetch unless setDistinct(true)
|
||||
* is set on the query.
|
||||
* </p>
|
||||
* <p>
|
||||
* Use {@link #fetch(String, String)} to specify specific properties to fetch
|
||||
* on other non-root level paths of the object graph.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<Customer> customers =
|
||||
@@ -412,42 +330,33 @@ public interface Query<T> {
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param fetchProperties
|
||||
* the properties to fetch for this bean (* = all properties).
|
||||
* @param fetchProperties the properties to fetch for this bean (* = all properties).
|
||||
*/
|
||||
Query<T> select(String fetchProperties);
|
||||
|
||||
/**
|
||||
* Specify a path to <em>fetch</em> with its specific properties to include
|
||||
* (aka partial object).
|
||||
* Specify a path to fetch eagerly including specific properties.
|
||||
* <p>
|
||||
* When you specify a join this means that property (associated bean(s)) will
|
||||
* be fetched and populated. If you specify "*" then all the properties of the
|
||||
* associated bean will be fetched and populated. You can specify a comma
|
||||
* delimited list of the properties of that associated bean which means that
|
||||
* only those properties are fetched and populated resulting in a
|
||||
* "Partial Object" - a bean that only has some of its properties populated.
|
||||
* Ebean will endeavour to fetch this path using a SQL join. If Ebean determines that it can
|
||||
* not use a SQL join (due to maxRows or because it would result in a cartesian product) Ebean
|
||||
* will automatically convert this fetch query into a "query join" - i.e. use fetchQuery().
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // query orders...
|
||||
* List<Order> orders =
|
||||
* ebeanserver.find(Order.class)
|
||||
* ebeanServer.find(Order.class)
|
||||
* // fetch the customer...
|
||||
* // ... getting the customers name and phone number
|
||||
* .fetch("customer", "name, phoneNumber")
|
||||
*
|
||||
*
|
||||
* // ... also fetch the customers billing address (* = all properties)
|
||||
* .fetch("customer.billingAddress", "*")
|
||||
* .findList();
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* If columns is null or "*" then all columns/properties for that path are
|
||||
* fetched.
|
||||
* If columns is null or "*" then all columns/properties for that path are fetched.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // fetch customers (their id, name and status)
|
||||
@@ -458,19 +367,66 @@ public interface Query<T> {
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param path
|
||||
* the path of an associated (1-1,1-M,M-1,M-M) bean.
|
||||
* @param fetchProperties
|
||||
* properties of the associated bean that you want to include in the
|
||||
* fetch (* means all properties, null also means all properties).
|
||||
*
|
||||
* @param path the property path we wish to fetch eagerly.
|
||||
* @param fetchProperties properties of the associated bean that you want to include in the
|
||||
* fetch (* means all properties, null also means all properties).
|
||||
*/
|
||||
Query<T> fetch(String path, String fetchProperties);
|
||||
|
||||
/**
|
||||
* Fetch the path and properties using a "query join" (separate SQL query).
|
||||
* <p>
|
||||
* This is the same as:
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* fetch(path, fetchProperties, new FetchConfig().query())
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* This would be used instead of a fetch() when we use a separate SQL query to fetch this
|
||||
* part of the object graph rather than a SQL join.
|
||||
* </p>
|
||||
* <p>
|
||||
* We might typically get a performance benefit when the path to fetch is a OneToMany
|
||||
* or ManyToMany, the 'width' of the 'root bean' is wide and the cardinality of the many
|
||||
* is high.
|
||||
* </p>
|
||||
*
|
||||
* @param path the property path we wish to fetch eagerly.
|
||||
* @param fetchProperties properties of the associated bean that you want to include in the
|
||||
* fetch (* means all properties, null also means all properties).
|
||||
*/
|
||||
Query<T> fetchQuery(String path, String fetchProperties);
|
||||
|
||||
/**
|
||||
* Fetch the path and properties lazily (via batch lazy loading).
|
||||
* <p>
|
||||
* This is the same as:
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* fetch(path, fetchProperties, new FetchConfig().lazy())
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* The reason for using fetchLazy() is to either:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>Control/tune what is fetched as part of lazy loading</li>
|
||||
* <li>Make use of the L2 cache, build this part of the graph from L2 cache</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param path the property path we wish to fetch lazily.
|
||||
* @param fetchProperties properties of the associated bean that you want to include in the
|
||||
* fetch (* means all properties, null also means all properties).
|
||||
*/
|
||||
Query<T> fetchLazy(String path, String fetchProperties);
|
||||
|
||||
/**
|
||||
* Additionally specify a FetchConfig to use a separate query or lazy loading
|
||||
* to load this path.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // fetch customers (their id, name and status)
|
||||
@@ -481,13 +437,17 @@ public interface Query<T> {
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param path the property path we wish to fetch eagerly.
|
||||
*/
|
||||
Query<T> fetch(String assocProperty, String fetchProperties, FetchConfig fetchConfig);
|
||||
Query<T> fetch(String path, String fetchProperties, FetchConfig fetchConfig);
|
||||
|
||||
/**
|
||||
* Specify a path to load including all its properties.
|
||||
* Specify a path to fetch eagerly including all its properties.
|
||||
* <p>
|
||||
* The same as {@link #fetch(String, String)} with the fetchProperties as "*".
|
||||
* Ebean will endeavour to fetch this path using a SQL join. If Ebean determines that it can
|
||||
* not use a SQL join (due to maxRows or because it would result in a cartesian product) Ebean
|
||||
* will automatically convert this fetch query into a "query join" - i.e. use fetchQuery().
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -500,16 +460,59 @@ public interface Query<T> {
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param path
|
||||
* the property of an associated (1-1,1-M,M-1,M-M) bean.
|
||||
* @param path the property path we wish to fetch eagerly.
|
||||
*/
|
||||
Query<T> fetch(String path);
|
||||
|
||||
/**
|
||||
* Fetch the path eagerly using a "query join" (separate SQL query).
|
||||
* <p>
|
||||
* This is the same as:
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* fetch(path, new FetchConfig().query())
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* This would be used instead of a fetch() when we use a separate SQL query to fetch this
|
||||
* part of the object graph rather than a SQL join.
|
||||
* </p>
|
||||
* <p>
|
||||
* We might typically get a performance benefit when the path to fetch is a OneToMany
|
||||
* or ManyToMany, the 'width' of the 'root bean' is wide and the cardinality of the many
|
||||
* is high.
|
||||
* </p>
|
||||
*
|
||||
* @param path the property path we wish to fetch eagerly
|
||||
*/
|
||||
Query<T> fetchQuery(String path);
|
||||
|
||||
/**
|
||||
* Fetch the path lazily (via batch lazy loading).
|
||||
* <p>
|
||||
* This is the same as:
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* fetch(path, new FetchConfig().lazy())
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* The reason for using fetchLazy() is to either:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>Control/tune what is fetched as part of lazy loading</li>
|
||||
* <li>Make use of the L2 cache, build this part of the graph from L2 cache</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param path the property path we wish to fetch lazily.
|
||||
*/
|
||||
Query<T> fetchLazy(String path);
|
||||
|
||||
/**
|
||||
* Additionally specify a JoinConfig to specify a "query join" and or define
|
||||
* the lazy loading query.
|
||||
*
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // fetch customers (their id, name and status)
|
||||
@@ -536,10 +539,50 @@ public interface Query<T> {
|
||||
* <p>
|
||||
* This query will execute against the EbeanServer that was used to create it.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @see EbeanServer#findIds(Query, Transaction)
|
||||
*/
|
||||
List<Object> findIds();
|
||||
<A> List<A> findIds();
|
||||
|
||||
/**
|
||||
* Execute the query iterating over the results.
|
||||
* <p>
|
||||
* Note that findIterate (and findEach and findEachWhile) uses a "per graph"
|
||||
* persistence context scope and adjusts jdbc fetch buffer size for large
|
||||
* queries. As such it is better to use findList for small queries.
|
||||
* </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).
|
||||
* </p>
|
||||
* <p>
|
||||
* findEach() and findEachWhile() are preferred to findIterate() as they ensure
|
||||
* the jdbc statement and resultSet are closed at the end of the iteration.
|
||||
* </p>
|
||||
* <p>
|
||||
* This query will execute against the EbeanServer that was used to create it.
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* Query<Customer> query =
|
||||
* ebeanServer.find(Customer.class)
|
||||
* .where().eq("status", Status.NEW)
|
||||
* .order().asc("id");
|
||||
*
|
||||
* QueryIterator<Customer> it = query.findIterate();
|
||||
* try {
|
||||
* while (it.hasNext()) {
|
||||
* Customer customer = it.next();
|
||||
* // do something with customer ...
|
||||
* }
|
||||
* } finally {
|
||||
* // close the underlying resources
|
||||
* it.close();
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
QueryIterator<T> findIterate();
|
||||
|
||||
/**
|
||||
* Execute the query processing the beans one at a time.
|
||||
@@ -549,6 +592,11 @@ public interface Query<T> {
|
||||
* (unlike #findList #findSet etc)
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that findEach (and findEachWhile and findIterate) uses a "per graph"
|
||||
* persistence context scope and adjusts jdbc fetch buffer size for large
|
||||
* queries. As such it is better to use findList for small queries.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that internally Ebean can inform the JDBC driver that it is expecting larger
|
||||
* resultSet and specifically for MySQL this hint is required to stop it's JDBC driver
|
||||
* from buffering the entire resultSet. As such, for smaller resultSets findList() is
|
||||
@@ -564,7 +612,6 @@ public interface Query<T> {
|
||||
* iterator uses the QueryEachConsumer (SAM) interface which is better suited to use
|
||||
* with Java8 closures.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* ebeanServer.find(Customer.class)
|
||||
@@ -578,8 +625,7 @@ public interface Query<T> {
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param consumer
|
||||
* the consumer used to process the queried beans.
|
||||
* @param consumer the consumer used to process the queried beans.
|
||||
*/
|
||||
void findEach(QueryEachConsumer<T> consumer);
|
||||
|
||||
@@ -587,12 +633,15 @@ public interface Query<T> {
|
||||
* Execute the query using callbacks to a visitor to process the resulting
|
||||
* beans one at a time.
|
||||
* <p>
|
||||
* Note that findEachWhile (and findEach and findIterate) uses a "per graph"
|
||||
* persistence context scope and adjusts jdbc fetch buffer size for large
|
||||
* queries. As such it is better to use findList for small queries.
|
||||
* </p>
|
||||
* <p>
|
||||
* This method is functionally equivalent to findIterate() but instead of using an
|
||||
* iterator uses the QueryEachWhileConsumer (SAM) interface which is better suited to use
|
||||
* with Java8 closures.
|
||||
* </p>
|
||||
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* ebeanServer.find(Customer.class)
|
||||
@@ -611,8 +660,7 @@ public interface Query<T> {
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param consumer
|
||||
* the consumer used to process the queried beans.
|
||||
* @param consumer the consumer used to process the queried beans.
|
||||
*/
|
||||
void findEachWhile(QueryEachWhileConsumer<T> consumer);
|
||||
|
||||
@@ -621,7 +669,6 @@ public interface Query<T> {
|
||||
* <p>
|
||||
* This query will execute against the EbeanServer that was used to create it.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<Customer> customers =
|
||||
@@ -640,7 +687,6 @@ public interface Query<T> {
|
||||
* <p>
|
||||
* This query will execute against the EbeanServer that was used to create it.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* Set<Customer> customers =
|
||||
@@ -663,24 +709,50 @@ public interface Query<T> {
|
||||
* You can use setMapKey() so specify the property values to be used as keys
|
||||
* on the map. If one is not specified then the id property is used.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* Map<?, Product> map =
|
||||
* Map<String, Product> map =
|
||||
* ebeanServer.find(Product.class)
|
||||
* .setMapKey("sku")
|
||||
* .findMap();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
*
|
||||
* @see EbeanServer#findMap(Query, Transaction)
|
||||
*/
|
||||
Map<?, T> findMap();
|
||||
<K> Map<K, T> findMap();
|
||||
|
||||
/**
|
||||
* Return a typed map specifying the key property and type.
|
||||
* Execute the query returning a list of values for a single property.
|
||||
* <p>
|
||||
* <h3>Example 1:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<String> names =
|
||||
* Ebean.find(Customer.class)
|
||||
* .select("name")
|
||||
* .orderBy().asc("name")
|
||||
* .findSingleAttributeList();
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* <h3>Example 2:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<String> names =
|
||||
* Ebean.find(Customer.class)
|
||||
* .setDistinct(true)
|
||||
* .select("name")
|
||||
* .where().eq("status", Customer.Status.NEW)
|
||||
* .orderBy().asc("name")
|
||||
* .setMaxRows(100)
|
||||
* .findSingleAttributeList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @return the list of values for the selected property
|
||||
*/
|
||||
<K> Map<K, T> findMap(String keyProperty, Class<K> keyType);
|
||||
<A> List<A> findSingleAttributeList();
|
||||
|
||||
/**
|
||||
* Execute the query returning either a single bean or null (if no matching
|
||||
@@ -693,7 +765,6 @@ public interface Query<T> {
|
||||
* This is useful when your predicates dictate that your query should only
|
||||
* return 0 or 1 results.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // assuming the sku of products is unique...
|
||||
@@ -703,16 +774,14 @@ public interface Query<T> {
|
||||
* .findUnique();
|
||||
* ...
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* It is also useful with finding objects by their id when you want to specify
|
||||
* further join information.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // Fetch order 1 and additionally fetch join its order details...
|
||||
* Order order =
|
||||
* Order order =
|
||||
* ebeanServer.find(Order.class)
|
||||
* .setId(1)
|
||||
* .fetch("details")
|
||||
@@ -731,13 +800,13 @@ public interface Query<T> {
|
||||
/**
|
||||
* Return versions of a @History entity bean.
|
||||
* <p>
|
||||
* Note that this query will work against view based history implementations
|
||||
* but not sql2011 standards based implementations that require a start and
|
||||
* end timestamp to be specified.
|
||||
* Note that this query will work against view based history implementations
|
||||
* but not sql2011 standards based implementations that require a start and
|
||||
* end timestamp to be specified.
|
||||
* </p>
|
||||
* <p>
|
||||
* Generally this query is expected to be a find by id or unique predicates query.
|
||||
* It will execute the query against the history returning the versions of the bean.
|
||||
* 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();
|
||||
@@ -745,8 +814,8 @@ public interface Query<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);
|
||||
@@ -774,7 +843,7 @@ public interface Query<T> {
|
||||
* This is the number of 'top level' or 'root level' entities.
|
||||
* </p>
|
||||
*/
|
||||
int findRowCount();
|
||||
int findCount();
|
||||
|
||||
/**
|
||||
* Execute find row count query in a background thread.
|
||||
@@ -783,10 +852,10 @@ public interface Query<T> {
|
||||
* execution status (isDone etc) and get the value (with or without a
|
||||
* timeout).
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @return a Future object for the row count query
|
||||
*/
|
||||
FutureRowCount<T> findFutureRowCount();
|
||||
FutureRowCount<T> findFutureCount();
|
||||
|
||||
/**
|
||||
* Execute find Id's query in a background thread.
|
||||
@@ -795,7 +864,7 @@ public interface Query<T> {
|
||||
* execution status (isDone etc) and get the value (with or without a
|
||||
* timeout).
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @return a Future object for the list of Id's
|
||||
*/
|
||||
FutureIds<T> findFutureIds();
|
||||
@@ -821,7 +890,6 @@ public interface Query<T> {
|
||||
* If maxRows is not set on the query prior to calling findPagedList() then a
|
||||
* PersistenceException is thrown.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* PagedList<Order> pagedList = Ebean.find(Order.class)
|
||||
@@ -843,24 +911,21 @@ public interface Query<T> {
|
||||
|
||||
/**
|
||||
* Set a named bind parameter. Named parameters have a colon to prefix the name.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // a query with a named parameter
|
||||
* String oql = "find order where status = :orderStatus";
|
||||
*
|
||||
*
|
||||
* Query<Order> query = ebeanServer.find(Order.class, oql);
|
||||
*
|
||||
*
|
||||
* // bind the named parameter
|
||||
* query.bind("orderStatus", OrderStatus.NEW);
|
||||
* List<Order> list = query.findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param name
|
||||
* the parameter name
|
||||
* @param value
|
||||
* the parameter value
|
||||
*
|
||||
* @param name the parameter name
|
||||
* @param value the parameter value
|
||||
*/
|
||||
Query<T> setParameter(String name, Object value);
|
||||
|
||||
@@ -868,25 +933,22 @@ public interface Query<T> {
|
||||
* Set an ordered bind parameter according to its position. Note that the
|
||||
* position starts at 1 to be consistent with JDBC PreparedStatement. You need
|
||||
* to set a parameter value for each ? you have in the query.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // a query with a positioned parameter
|
||||
* String oql = "where status = ? order by id desc";
|
||||
*
|
||||
*
|
||||
* Query<Order> query = ebeanServer.createQuery(Order.class, oql);
|
||||
*
|
||||
*
|
||||
* // bind the parameter
|
||||
* query.setParameter(1, OrderStatus.NEW);
|
||||
*
|
||||
*
|
||||
* List<Order> list = query.findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param position
|
||||
* the parameter bind position starting from 1 (not 0)
|
||||
* @param value
|
||||
* the parameter bind value.
|
||||
*
|
||||
* @param position the parameter bind position starting from 1 (not 0)
|
||||
* @param value the parameter bind value.
|
||||
*/
|
||||
Query<T> setParameter(int position, Object value);
|
||||
|
||||
@@ -896,7 +958,6 @@ public interface Query<T> {
|
||||
* You can use this to have further control over the query. For example adding
|
||||
* fetch joins.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* Order order =
|
||||
@@ -919,10 +980,9 @@ public interface Query<T> {
|
||||
|
||||
/**
|
||||
* Add a single Expression to the where clause returning the query.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<Order> newOrders =
|
||||
* List<Order> newOrders =
|
||||
* ebeanServer.find(Order.class)
|
||||
* .where().eq("status", Order.NEW)
|
||||
* .findList();
|
||||
@@ -936,7 +996,6 @@ public interface Query<T> {
|
||||
* Add Expressions to the where clause with the ability to chain on the
|
||||
* ExpressionList. You can use this for adding multiple expressions to the
|
||||
* where clause.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* List<Order> orders =
|
||||
@@ -947,9 +1006,9 @@ public interface Query<T> {
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @see Expr
|
||||
*
|
||||
* @return The ExpressionList for adding expressions to.
|
||||
* @see Expr
|
||||
*/
|
||||
ExpressionList<T> where();
|
||||
|
||||
@@ -984,9 +1043,8 @@ public interface Query<T> {
|
||||
* each customer you only want to get the new orders they placed since last
|
||||
* week. In this case you can use filterMany() to filter the orders.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
*
|
||||
* List<Customer> list =
|
||||
* ebeanServer.find(Customer.class)
|
||||
* // .fetch("orders", new FetchConfig().lazy())
|
||||
@@ -995,20 +1053,17 @@ public interface Query<T> {
|
||||
* .where().ilike("name", "rob%")
|
||||
* .filterMany("orders").eq("status", Order.Status.NEW).gt("orderDate", lastWeek)
|
||||
* .findList();
|
||||
*
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* Please note you have to be careful that you add expressions to the correct
|
||||
* expression list - as there is one for the 'root level' and one for each
|
||||
* filterMany that you have.
|
||||
* </p>
|
||||
*
|
||||
* @param propertyName
|
||||
* the name of the many property that you want to have a filter on.
|
||||
*
|
||||
*
|
||||
* @param propertyName the name of the many property that you want to have a filter on.
|
||||
* @return the expression list that you add filter expressions for the many
|
||||
* to.
|
||||
* to.
|
||||
*/
|
||||
ExpressionList<T> filterMany(String propertyName);
|
||||
|
||||
@@ -1021,9 +1076,9 @@ public interface Query<T> {
|
||||
* Note that this returns the ExpressionList (so you can add multiple
|
||||
* expressions to the query in a fluent API way).
|
||||
* </p>
|
||||
*
|
||||
* @see Expr
|
||||
*
|
||||
* @return The ExpressionList for adding more expressions to.
|
||||
* @see Expr
|
||||
*/
|
||||
ExpressionList<T> having();
|
||||
|
||||
@@ -1037,9 +1092,8 @@ public interface Query<T> {
|
||||
* than the ExpressionList. This is useful when you want to further specify
|
||||
* something on the query.
|
||||
* </p>
|
||||
*
|
||||
* @param addExpressionToHaving
|
||||
* the expression to add to the having clause.
|
||||
*
|
||||
* @param addExpressionToHaving the expression to add to the having clause.
|
||||
* @return the Query object
|
||||
*/
|
||||
Query<T> having(Expression addExpressionToHaving);
|
||||
@@ -1151,9 +1205,8 @@ public interface Query<T> {
|
||||
|
||||
/**
|
||||
* Set the maximum number of rows to return in the query.
|
||||
*
|
||||
* @param maxRows
|
||||
* the maximum number of rows to return in the query.
|
||||
*
|
||||
* @param maxRows the maximum number of rows to return in the query.
|
||||
*/
|
||||
Query<T> setMaxRows(int maxRows);
|
||||
|
||||
@@ -1162,11 +1215,10 @@ public interface Query<T> {
|
||||
* <p>
|
||||
* If no property is set then the id property is used.
|
||||
* </p>
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
* // Assuming sku is unique for products...
|
||||
*
|
||||
*
|
||||
* Map<?,Product> productMap =
|
||||
* ebeanServer.find(Product.class)
|
||||
* // use sku for keys...
|
||||
@@ -1174,9 +1226,8 @@ public interface Query<T> {
|
||||
* .findMap();
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param mapKey
|
||||
* the property to use as keys for a map.
|
||||
*
|
||||
* @param mapKey the property to use as keys for a map.
|
||||
*/
|
||||
Query<T> setMapKey(String mapKey);
|
||||
|
||||
@@ -1203,7 +1254,7 @@ public interface Query<T> {
|
||||
/**
|
||||
* Set to true if this query should execute against the doc store.
|
||||
* <p>
|
||||
* When setting this you may also consider disabling lazy loading.
|
||||
* When setting this you may also consider disabling lazy loading.
|
||||
* </p>
|
||||
*/
|
||||
Query<T> setUseDocStore(boolean useDocStore);
|
||||
@@ -1226,9 +1277,8 @@ public interface Query<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 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.
|
||||
*/
|
||||
Query<T> setTimeout(int secs);
|
||||
|
||||
@@ -1238,6 +1288,16 @@ public interface Query<T> {
|
||||
* Gives the JDBC driver a hint as to the number of rows that should be
|
||||
* fetched from the database when more rows are needed for ResultSet.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that internally findEach and findEachWhile will set the fetch size
|
||||
* if it has not already as these queries expect to process a lot of rows.
|
||||
* If we didn't then Postgres and MySql for example would eagerly pull back
|
||||
* all the row data and potentially consume a lot of memory in the process.
|
||||
* </p>
|
||||
* <p>
|
||||
* As findEach and findEachWhile automatically set the fetch size we don't have
|
||||
* to do so generally but we might still wish to for tuning a specific use case.
|
||||
* </p>
|
||||
*/
|
||||
Query<T> setBufferFetchSizeHint(int fetchSize);
|
||||
|
||||
@@ -1260,7 +1320,7 @@ public interface Query<T> {
|
||||
* Return true if this query has forUpdate set.
|
||||
*/
|
||||
boolean isForUpdate();
|
||||
|
||||
|
||||
/**
|
||||
* Set root table alias.
|
||||
*/
|
||||
@@ -1274,7 +1334,7 @@ public interface Query<T> {
|
||||
/**
|
||||
* Set true if you want to disable lazy loading.
|
||||
* <p>
|
||||
* That is, once the object graph is returned further lazy loading is disabled.
|
||||
* That is, once the object graph is returned further lazy loading is disabled.
|
||||
* </p>
|
||||
*/
|
||||
Query<T> setDisableLazyLoading(boolean disableLazyLoading);
|
||||
|
||||
@@ -11,7 +11,7 @@ package com.avaje.ebean;
|
||||
* 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>{@code
|
||||
*
|
||||
* Query<Customer> query = server.find(Customer.class)
|
||||
@@ -25,17 +25,15 @@ package com.avaje.ebean;
|
||||
* });
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param <T>
|
||||
* the type of entity bean being queried.
|
||||
*
|
||||
* @param <T> the type of entity bean being queried.
|
||||
*/
|
||||
public interface QueryEachConsumer<T> {
|
||||
|
||||
/**
|
||||
* Process the bean.
|
||||
*
|
||||
* @param bean
|
||||
* the entity bean to process
|
||||
*
|
||||
* @param bean the entity bean to process
|
||||
*/
|
||||
void accept(T bean);
|
||||
}
|
||||
|
||||
@@ -12,23 +12,24 @@ package com.avaje.ebean;
|
||||
* QueryResultVisitor useful for processing large queries.
|
||||
* </p>
|
||||
* <p/>
|
||||
* <pre class="code">
|
||||
* <pre>{@code
|
||||
*
|
||||
* Query<Customer> query = server.find(Customer.class)
|
||||
* .fetch("contacts", new FetchConfig().query(2))
|
||||
* .where().gt("id", 0)
|
||||
* .orderBy("id")
|
||||
* Query<Customer> query = server.find(Customer.class)
|
||||
* .fetchQuery("contacts")
|
||||
* .where().gt("id", 0)
|
||||
* .orderBy("id")
|
||||
* .setMaxRows(2);
|
||||
*
|
||||
* query.findEachWhile((Customer customer) -> {
|
||||
*
|
||||
* // do something with customer
|
||||
* System.out.println("-- visit " + customer);
|
||||
* System.out.println("-- visit " + customer);
|
||||
*
|
||||
* // return true to continue processing or false to stop
|
||||
* return (customer.getId() < 40);
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param <T> the type of entity bean being queried.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Used to provide iteration over query results.
|
||||
* <p>
|
||||
* This can be used when you want to process a very large number of results and
|
||||
* means that you don't have to hold all the results in memory at once (unlike
|
||||
* findList(), findSet() etc where all the beans are held in the List or Set
|
||||
* etc).
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that findIterate (and findEach and findEachWhile) uses a "per graph"
|
||||
* persistence context scope and adjusts jdbc fetch buffer size for large
|
||||
* queries. As such it is better to use findList for small queries.
|
||||
* </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).
|
||||
* </p>
|
||||
* <pre>{@code
|
||||
*
|
||||
* Query<Customer> query = server.find(Customer.class)
|
||||
* .where().gt("id", 0)
|
||||
* .orderBy("id")
|
||||
* .setMaxRows(2);
|
||||
*
|
||||
* QueryIterator<Customer> it = query.findIterate();
|
||||
* try {
|
||||
* while (it.hasNext()) {
|
||||
* Customer customer = it.next();
|
||||
* // do something with customer ...
|
||||
* }
|
||||
* } finally {
|
||||
* // close the underlying resources
|
||||
* it.close();
|
||||
* }
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @param <T> the type of entity bean in the iteration
|
||||
*/
|
||||
public interface QueryIterator<T> extends Iterator<T>, java.io.Closeable {
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if the iteration has more elements.
|
||||
*/
|
||||
boolean hasNext();
|
||||
|
||||
/**
|
||||
* Returns the next element in the iteration.
|
||||
*/
|
||||
T next();
|
||||
|
||||
/**
|
||||
* Remove is not allowed.
|
||||
*/
|
||||
void remove();
|
||||
|
||||
/**
|
||||
* Close the underlying resources held by this iterator.
|
||||
*/
|
||||
void close();
|
||||
}
|
||||
@@ -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 @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;
|
||||
@@ -401,9 +400,8 @@ public final class RawSql implements Serializable {
|
||||
this.parsed = true;
|
||||
this.propertyMap = null;
|
||||
this.propertyColumnMap = null;
|
||||
this.dbColumnMap = new LinkedHashMap<String, Column>();
|
||||
for (int i = 0; i < columns.size(); i++) {
|
||||
Column c = columns.get(i);
|
||||
this.dbColumnMap = new LinkedHashMap<>();
|
||||
for (Column c : columns) {
|
||||
dbColumnMap.put(c.getDbColumnKey(), c);
|
||||
}
|
||||
}
|
||||
@@ -416,9 +414,9 @@ public final class RawSql implements Serializable {
|
||||
this.parsed = false;
|
||||
this.propertyMap = null;
|
||||
this.propertyColumnMap = null;
|
||||
this.dbColumnMap = new LinkedHashMap<String, Column>();
|
||||
this.dbColumnMap = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct for ResultSet use.
|
||||
*/
|
||||
@@ -426,7 +424,7 @@ public final class RawSql implements Serializable {
|
||||
this.immutable = false;
|
||||
this.parsed = false;
|
||||
this.propertyMap = null;
|
||||
this.dbColumnMap = new LinkedHashMap<String, Column>();
|
||||
this.dbColumnMap = new LinkedHashMap<>();
|
||||
|
||||
int pos = 0;
|
||||
for (String prop : propertyNames) {
|
||||
@@ -443,8 +441,8 @@ public final class RawSql implements Serializable {
|
||||
this.parsed = parsed;
|
||||
this.dbColumnMap = dbColumnMap;
|
||||
|
||||
HashMap<String, Column> pcMap = new HashMap<String, Column>();
|
||||
HashMap<String, String> pMap = new HashMap<String, String>();
|
||||
HashMap<String, Column> pcMap = new HashMap<>();
|
||||
HashMap<String, String> pMap = new HashMap<>();
|
||||
|
||||
for (Column c : dbColumnMap.values()) {
|
||||
pMap.put(c.getPropertyName(), c.getDbColumn());
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,167 +0,0 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
class SimpleTextParser {
|
||||
|
||||
private final String oql;
|
||||
private final char[] chars;
|
||||
private final int eof;
|
||||
|
||||
private int pos;
|
||||
private String word;
|
||||
private String lowerWord;
|
||||
|
||||
SimpleTextParser(String oql) {
|
||||
this.oql = oql;
|
||||
this.chars = oql.toCharArray();
|
||||
this.eof = oql.length();
|
||||
}
|
||||
|
||||
public int getPos() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
public String getWord() {
|
||||
return word;
|
||||
}
|
||||
|
||||
public String peekNextWord() {
|
||||
int origPos = pos;
|
||||
String nw = nextWordInternal();
|
||||
pos = origPos;
|
||||
return nw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the current and the next word.
|
||||
*/
|
||||
public boolean isMatch(String lowerMatch, String nextWordMatch) {
|
||||
|
||||
if (isMatch(lowerMatch)) {
|
||||
String nw = peekNextWord();
|
||||
if (nw != null) {
|
||||
nw = nw.toLowerCase();
|
||||
return nw.equals(nextWordMatch);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return word == null;
|
||||
}
|
||||
|
||||
public int findWordLower(String lowerMatch, int afterPos) {
|
||||
this.pos = afterPos;
|
||||
return findWordLower(lowerMatch);
|
||||
}
|
||||
|
||||
public int findWordLower(String lowerMatch) {
|
||||
do {
|
||||
if (nextWord() == null) {
|
||||
return -1;
|
||||
}
|
||||
if (lowerMatch.equals(lowerWord)) {
|
||||
return pos - lowerWord.length();
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Match the current word.
|
||||
*/
|
||||
public boolean isMatch(String lowerMatch) {
|
||||
return lowerMatch.equals(lowerWord);
|
||||
}
|
||||
|
||||
public String nextWord() {
|
||||
word = nextWordInternal();
|
||||
if (word != null) {
|
||||
lowerWord = word.toLowerCase();
|
||||
}
|
||||
return word;
|
||||
}
|
||||
|
||||
private String nextWordInternal() {
|
||||
trimLeadingWhitespace();
|
||||
if (pos >= eof) {
|
||||
return null;
|
||||
}
|
||||
int start = pos;
|
||||
if (chars[pos] == '(') {
|
||||
moveToClose();
|
||||
} else {
|
||||
moveToEndOfWord();
|
||||
}
|
||||
return oql.substring(start, pos);
|
||||
}
|
||||
|
||||
private void moveToClose() {
|
||||
|
||||
pos++;
|
||||
int openParenthesisCount = 0;
|
||||
|
||||
for (; pos < eof; pos++) {
|
||||
char c = chars[pos];
|
||||
if (c == '(') {
|
||||
// count nested parenthesis
|
||||
openParenthesisCount++;
|
||||
|
||||
} else if (c == ')') {
|
||||
if (openParenthesisCount > 0) {
|
||||
// still in nested parenthesis
|
||||
--openParenthesisCount;
|
||||
} else {
|
||||
// we have found the end
|
||||
pos++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void moveToEndOfWord() {
|
||||
char c = chars[pos];
|
||||
boolean isOperator = isOperator(c);
|
||||
for (; pos < eof; pos++) {
|
||||
c = chars[pos];
|
||||
if (isWordTerminator(c, isOperator)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isWordTerminator(char c, boolean isOperator) {
|
||||
if (Character.isWhitespace(c)) {
|
||||
return true;
|
||||
}
|
||||
if (isOperator(c)) {
|
||||
return !isOperator;
|
||||
}
|
||||
return c == '(' || isOperator;
|
||||
}
|
||||
|
||||
private boolean isOperator(char c) {
|
||||
switch (c) {
|
||||
case '<':
|
||||
return true;
|
||||
case '>':
|
||||
return true;
|
||||
case '=':
|
||||
return true;
|
||||
case '!':
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void trimLeadingWhitespace() {
|
||||
for (; pos < eof; pos++) {
|
||||
char c = chars[pos];
|
||||
if (!Character.isWhitespace(c)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,6 @@ package com.avaje.ebean;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Query object for performing native SQL queries that return SqlRow's.
|
||||
@@ -20,23 +18,22 @@ import java.util.Set;
|
||||
* 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 {
|
||||
|
||||
@@ -100,9 +97,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);
|
||||
|
||||
|
||||
@@ -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 = "UPDATE f_topic set post_count = :count where id = :id"
|
||||
* <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);
|
||||
*
|
||||
* update.setParameter("id", 1);
|
||||
* update.setParameter("count", 50);
|
||||
*
|
||||
* int modifiedCount = Ebean.execute(update);
|
||||
*
|
||||
* String msg = "There were " + modifiedCount + " rows updated"
|
||||
* </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();
|
||||
@@ -117,8 +119,7 @@ public interface SqlUpdate {
|
||||
SqlUpdate setParameter(int position, Object value);
|
||||
|
||||
/**
|
||||
* Set a null parameter via its index position. Exactly the same as
|
||||
* {@link #setNull(int, int)}.
|
||||
* Set a null parameter via its index position.
|
||||
*/
|
||||
SqlUpdate setNull(int position, int jdbcType);
|
||||
|
||||
|
||||
@@ -54,13 +54,52 @@ public interface Transaction extends Closeable {
|
||||
*/
|
||||
void setReadOnly(boolean readOnly);
|
||||
|
||||
/**
|
||||
* Commits the transaction at this point with the expectation that another
|
||||
* commit (or rollback or end) will occur later to complete the transaction.
|
||||
* <p>
|
||||
* This is similar to commit() but leaves the transaction "Active".
|
||||
* </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>
|
||||
* </ul>
|
||||
*/
|
||||
void commitAndContinue() throws RollbackException;
|
||||
|
||||
/**
|
||||
* Commit the transaction.
|
||||
* <p>
|
||||
* This performs commit and completes the transaction closing underlying resources and
|
||||
* marking the transaction as "In active".
|
||||
* </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>
|
||||
* </ul>
|
||||
*/
|
||||
void commit() throws RollbackException;
|
||||
|
||||
/**
|
||||
* Rollback the transaction.
|
||||
* <p>
|
||||
* This performs rollback, closes underlying resources and marks the transaction as "In active".
|
||||
* </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>
|
||||
* </ul>
|
||||
*/
|
||||
void rollback() throws PersistenceException;
|
||||
|
||||
@@ -74,6 +113,16 @@ public interface Transaction extends Closeable {
|
||||
*/
|
||||
void rollback(Throwable e) throws PersistenceException;
|
||||
|
||||
/**
|
||||
* Mark the transaction for rollback only.
|
||||
*/
|
||||
void setRollbackOnly();
|
||||
|
||||
/**
|
||||
* Return true if the transaction is marked as rollback only.
|
||||
*/
|
||||
boolean isRollbackOnly();
|
||||
|
||||
/**
|
||||
* If the transaction is active then perform rollback. Otherwise do nothing.
|
||||
*/
|
||||
@@ -87,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);
|
||||
@@ -98,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);
|
||||
@@ -148,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 ...
|
||||
@@ -230,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);
|
||||
@@ -255,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);
|
||||
|
||||
@@ -276,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);
|
||||
@@ -298,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);
|
||||
@@ -417,9 +463,8 @@ public interface Transaction extends Closeable {
|
||||
|
||||
/**
|
||||
* Add an arbitrary user object to the transaction. The objects added have no
|
||||
* impact on any internals of ebena and are solely meant as a convenient
|
||||
* method push user information to e.g. the
|
||||
* {@link com.avaje.ebean.event.TransactionEventListener}.
|
||||
* impact on any internals of ebean and are solely meant as a convenient
|
||||
* method push user information (although somewhat replaced by TransactionCallback).
|
||||
*/
|
||||
void putUserObject(String name, Object value);
|
||||
|
||||
|
||||
@@ -12,24 +12,26 @@ package com.avaje.ebean;
|
||||
* <p>
|
||||
* See also {@link TxRunnable}.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* Ebean.execute(new TxCallable<String>() {
|
||||
* <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");
|
||||
*
|
||||
*
|
||||
* 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> {
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.sql.Connection;
|
||||
* This can be used with TxScope to define transactional scopes to execute
|
||||
* method within.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @see TxScope
|
||||
*/
|
||||
public enum TxIsolation {
|
||||
@@ -74,26 +74,26 @@ public enum TxIsolation {
|
||||
public static TxIsolation fromLevel(int connectionIsolationLevel) {
|
||||
|
||||
switch (connectionIsolationLevel) {
|
||||
case Connection.TRANSACTION_READ_UNCOMMITTED:
|
||||
return TxIsolation.READ_UNCOMMITTED;
|
||||
case Connection.TRANSACTION_READ_UNCOMMITTED:
|
||||
return TxIsolation.READ_UNCOMMITTED;
|
||||
|
||||
case Connection.TRANSACTION_READ_COMMITTED:
|
||||
return TxIsolation.READ_COMMITED;
|
||||
case Connection.TRANSACTION_READ_COMMITTED:
|
||||
return TxIsolation.READ_COMMITED;
|
||||
|
||||
case Connection.TRANSACTION_REPEATABLE_READ:
|
||||
return TxIsolation.REPEATABLE_READ;
|
||||
case Connection.TRANSACTION_REPEATABLE_READ:
|
||||
return TxIsolation.REPEATABLE_READ;
|
||||
|
||||
case Connection.TRANSACTION_SERIALIZABLE:
|
||||
return TxIsolation.SERIALIZABLE;
|
||||
case Connection.TRANSACTION_SERIALIZABLE:
|
||||
return TxIsolation.SERIALIZABLE;
|
||||
|
||||
case Connection.TRANSACTION_NONE:
|
||||
return TxIsolation.NONE;
|
||||
case Connection.TRANSACTION_NONE:
|
||||
return TxIsolation.NONE;
|
||||
|
||||
case -1:
|
||||
return TxIsolation.DEFAULT;
|
||||
case -1:
|
||||
return TxIsolation.DEFAULT;
|
||||
|
||||
default:
|
||||
throw new RuntimeException("Unknown isolation level " + connectionIsolationLevel);
|
||||
default:
|
||||
throw new RuntimeException("Unknown isolation level " + connectionIsolationLevel);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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("u1 mod");
|
||||
* u2.setName("u2 mod");
|
||||
*
|
||||
*
|
||||
* u1.setName("u1 mod");
|
||||
* u2.setName("u2 mod");
|
||||
*
|
||||
* Ebean.save(u1);
|
||||
* Ebean.save(u2);
|
||||
* }
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* @see TxCallable
|
||||
*/
|
||||
public interface TxRunnable {
|
||||
|
||||
@@ -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 + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -282,7 +281,7 @@ public final class TxScope {
|
||||
*/
|
||||
public TxScope setRollbackFor(Class<? extends Throwable> rollbackThrowable) {
|
||||
if (rollbackFor == null) {
|
||||
rollbackFor = new ArrayList<Class<? extends Throwable>>(2);
|
||||
rollbackFor = new ArrayList<>(2);
|
||||
}
|
||||
rollbackFor.add(rollbackThrowable);
|
||||
return this;
|
||||
@@ -294,10 +293,10 @@ public final class TxScope {
|
||||
@SuppressWarnings("unchecked")
|
||||
public TxScope setRollbackFor(Class<?>[] rollbackThrowables) {
|
||||
if (rollbackFor == null) {
|
||||
rollbackFor = new ArrayList<Class<? extends Throwable>>(rollbackThrowables.length);
|
||||
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;
|
||||
}
|
||||
@@ -316,7 +315,7 @@ public final class TxScope {
|
||||
*/
|
||||
public TxScope setNoRollbackFor(Class<? extends Throwable> noRollback) {
|
||||
if (noRollbackFor == null) {
|
||||
noRollbackFor = new ArrayList<Class<? extends Throwable>>(2);
|
||||
noRollbackFor = new ArrayList<>(2);
|
||||
}
|
||||
this.noRollbackFor.add(noRollback);
|
||||
return this;
|
||||
@@ -328,10 +327,10 @@ public final class TxScope {
|
||||
@SuppressWarnings("unchecked")
|
||||
public TxScope setNoRollbackFor(Class<?>[] noRollbacks) {
|
||||
if (noRollbackFor == null) {
|
||||
noRollbackFor = new ArrayList<Class<? extends Throwable>>(noRollbacks.length);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ package com.avaje.ebean;
|
||||
* {@link Ebean#execute(TxScope, TxCallable)} and
|
||||
* {@link Ebean#execute(TxScope, TxRunnable)}.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @see TxScope
|
||||
*/
|
||||
public enum TxType {
|
||||
|
||||
@@ -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
|
||||
* ...
|
||||
* @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")
|
||||
* @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")
|
||||
* })
|
||||
* @Entity
|
||||
* @Table(name = "f_topic")
|
||||
* @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<Topic> update = Ebean.createUpdate(Topic.class, "incrementPostCount");
|
||||
* update.setParameter("id", 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();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,14 +49,14 @@ package com.avaje.ebean;
|
||||
* .gt("id", 1000)
|
||||
* .update();
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* <pre>{@code sql
|
||||
*
|
||||
* update o_customer set status=?, updtime=?
|
||||
* where id in (
|
||||
* select t0.id c0
|
||||
* from o_customer t0
|
||||
* left outer join o_address t1 on t1.id = t0.billing_address_id
|
||||
* left join o_address t1 on t1.id = t0.billing_address_id
|
||||
* where t0.status = ?
|
||||
* and t1.country_code = ?
|
||||
* and t0.id > ? )
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ public class ValuePair {
|
||||
public Object getNewValue() {
|
||||
return newValue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the old value.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
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>
|
||||
* <p>
|
||||
* <h3>Example:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* @Aggregation("count(details)")
|
||||
* Long totalCount;
|
||||
*
|
||||
* @Aggregation("sum(details.quantity*details.unitPrice)")
|
||||
* Long totalAmount;
|
||||
*
|
||||
* }</pre>
|
||||
* <p>
|
||||
* <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();
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import java.lang.annotation.Target;
|
||||
/**
|
||||
* Specify the default cache use specific entity type.
|
||||
*/
|
||||
@Target({ ElementType.TYPE })
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Cache {
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.lang.annotation.Target;
|
||||
* ElasticSearch, Hazelcast, Ignite etc.
|
||||
* </p>
|
||||
*/
|
||||
@Target({ ElementType.TYPE })
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface CacheBeanTuning {
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.lang.annotation.Target;
|
||||
* If this is not specified then the system default settings are used.
|
||||
* </p>
|
||||
*/
|
||||
@Target({ ElementType.TYPE })
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface CacheQueryTuning {
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.lang.annotation.Target;
|
||||
* 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>
|
||||
*
|
||||
* <p>
|
||||
* <h3>Example:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -31,7 +31,7 @@ import java.lang.annotation.Target;
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD })
|
||||
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface CreatedTimestamp {
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.lang.annotation.Target;
|
||||
* 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>
|
||||
*
|
||||
* <p>
|
||||
* <h3>Example:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
|
||||
@@ -10,7 +10,7 @@ import java.lang.annotation.Target;
|
||||
* <p>
|
||||
* The Map property should have keys and values of type String.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* <h3>Example:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -27,4 +27,4 @@ public @interface DbHstore {
|
||||
* For VARCHAR storage specify the column length (defaults to 1000).
|
||||
*/
|
||||
int length() default 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import java.lang.annotation.Target;
|
||||
* Map<String,Object> content;
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* <h3>Example with JSONB storage</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -41,4 +41,4 @@ public @interface DbJson {
|
||||
* For VARCHAR storage specify the column length (defaults to 3000).
|
||||
*/
|
||||
int length() default 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,9 +11,9 @@ import java.lang.annotation.Target;
|
||||
* 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>
|
||||
* This is equivalent to using <code>@DbJson(storage = DbJsonType.JSONB)</code>
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* <h3>Example:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -22,7 +22,7 @@ import java.lang.annotation.Target;
|
||||
* Map<String,Object> content;
|
||||
*
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* <h3>Equivalent to:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -40,4 +40,4 @@ public @interface DbJsonB {
|
||||
* For VARCHAR storage specify the column length.
|
||||
*/
|
||||
int length() default 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Specify the property is included in the parent document store index.
|
||||
*
|
||||
* <pre>{@code
|
||||
*
|
||||
*
|
||||
@@ -25,7 +24,7 @@ import java.lang.annotation.Target;
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@Target({ ElementType.FIELD })
|
||||
@Target({ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DocEmbedded {
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.lang.annotation.Target;
|
||||
/**
|
||||
* Specify the entity type maps to a document store (like ElasticSearch).
|
||||
*/
|
||||
@Target({ ElementType.TYPE })
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DocMapping {
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.lang.annotation.Target;
|
||||
/**
|
||||
* Specify the entity type maps to a document store (like ElasticSearch).
|
||||
*/
|
||||
@Target({ ElementType.FIELD })
|
||||
@Target({ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DocProperty {
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import java.lang.annotation.Target;
|
||||
* For example, customer name and product name are good candidates for marking with @DocSortable.
|
||||
* </p>
|
||||
*/
|
||||
@Target({ ElementType.FIELD })
|
||||
@Target({ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DocSortable {
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.lang.annotation.Target;
|
||||
/**
|
||||
* Specify the entity type maps to a document store (like ElasticSearch).
|
||||
*/
|
||||
@Target({ ElementType.TYPE })
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DocStore {
|
||||
|
||||
@@ -73,7 +73,6 @@ public @interface DocStore {
|
||||
* 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
|
||||
*
|
||||
|
||||
@@ -23,9 +23,9 @@ public enum DocStoreMode {
|
||||
/**
|
||||
* 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.
|
||||
* 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,
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.lang.annotation.Target;
|
||||
* standard JPA.
|
||||
* </p>
|
||||
*/
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD })
|
||||
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface EmbeddedColumns {
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.lang.annotation.Target;
|
||||
/**
|
||||
* Specify that the property is stored in encrypted form.
|
||||
*/
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD })
|
||||
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Encrypted {
|
||||
|
||||
|
||||
@@ -7,21 +7,20 @@ 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
|
||||
@@ -33,7 +32,7 @@ import java.lang.annotation.Target;
|
||||
* and fetched as strings.
|
||||
* </p>
|
||||
*/
|
||||
@Target({ ElementType.FIELD })
|
||||
@Target({ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface EnumValue {
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import com.avaje.ebean.Query;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
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 +24,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 "master" bean
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
* // On the Order "master" bean
|
||||
* // ... a formula using the Order details
|
||||
* // ... sum(order_qty*unit_price)
|
||||
* @Transient
|
||||
* @Formula(select = "_b${ta}.total_amount", join = "join (select order_id, sum(order_qty*unit_price) as total_amount from o_order_detail group by order_id) as _b${ta} on _b${ta}.order_id = ${ta}.id")
|
||||
* @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 +52,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,10 +61,10 @@ 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)
|
||||
public @interface Formula {
|
||||
|
||||
@@ -82,9 +81,8 @@ public @interface Formula {
|
||||
* as count, sum etc.
|
||||
* </p>
|
||||
* <p>
|
||||
* The join string should start with either "left outer join" or "join".
|
||||
* 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 +92,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
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.lang.annotation.Target;
|
||||
* typically automatically populated via database triggers.
|
||||
* </p>
|
||||
*/
|
||||
@Target({ ElementType.TYPE })
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface History {
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import java.lang.annotation.Target;
|
||||
* support.
|
||||
* </p>
|
||||
*/
|
||||
@Target({ ElementType.FIELD })
|
||||
@Target({ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface HistoryExclude {
|
||||
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
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 on a single column.
|
||||
* An annotation for declaring an index.
|
||||
*
|
||||
* @author rvbiljouw
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Repeatable(Indices.class)
|
||||
public @interface Index {
|
||||
|
||||
/**
|
||||
@@ -27,6 +29,9 @@ public @interface Index {
|
||||
/**
|
||||
* When placed on the class (rather than field) you can specify the columns
|
||||
* to include in the index in order.
|
||||
* <p>
|
||||
* 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 {};
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
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 {};
|
||||
}
|
||||
@@ -8,8 +8,8 @@ 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.
|
||||
* 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)
|
||||
@@ -29,4 +29,4 @@ public @interface JsonIgnore {
|
||||
* Defaults to {@code false}.
|
||||
*/
|
||||
boolean deserialize() default false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import java.lang.annotation.Target;
|
||||
* in that they are no longer associated/linked to their parent bean.
|
||||
* </p>
|
||||
*/
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD })
|
||||
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface PrivateOwned {
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.lang.annotation.Target;
|
||||
* This means the entity bean has no base table specified (via @Table).
|
||||
* </p>
|
||||
*/
|
||||
@Target({ ElementType.TYPE })
|
||||
@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 {
|
||||
|
||||
|
||||
@@ -14,13 +14,13 @@ import java.lang.annotation.Target;
|
||||
* <p>
|
||||
* Note that the default can be set via ebean.properties.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* <pre>
|
||||
* ## Set to update all loaded properties
|
||||
* ebean.updateChangesOnly=false
|
||||
* </pre>
|
||||
*/
|
||||
@Target({ ElementType.TYPE })
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface UpdateMode {
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import java.lang.annotation.Target;
|
||||
* towards a better naming convention (WhenCreated, WhenModified).
|
||||
* </p>
|
||||
*/
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD })
|
||||
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface UpdatedTimestamp {
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.lang.annotation.Target;
|
||||
* 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>
|
||||
*
|
||||
* <p>
|
||||
* <h3>Example:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -31,7 +31,7 @@ import java.lang.annotation.Target;
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD })
|
||||
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface WhenCreated {
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.lang.annotation.Target;
|
||||
* towards a better naming convention (WhenCreated, WhenModified).
|
||||
* </p>
|
||||
*/
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD })
|
||||
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface WhenModified {
|
||||
|
||||
|
||||
@@ -8,37 +8,33 @@ 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)
|
||||
public @interface Where {
|
||||
|
||||
|
||||
@@ -12,8 +12,7 @@ import java.lang.annotation.Target;
|
||||
* To use this annotation you need to implement CurrentUserProvider.
|
||||
* The type of the bean property should match the type returned by
|
||||
* CurrentUserProvider.
|
||||
*</p>
|
||||
|
||||
* </p>
|
||||
* <h3>Example:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
@@ -22,7 +21,7 @@ import java.lang.annotation.Target;
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD })
|
||||
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface WhoCreated {
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ import java.lang.annotation.Target;
|
||||
* The type of the bean property should match the type returned by
|
||||
* CurrentUserProvider.
|
||||
* </p>
|
||||
*
|
||||
* <h3>Example:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
|
||||
<TITLE>Extra deployment annotations</TITLE>
|
||||
<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.
|
||||
Extra deployment annotations for entity beans.
|
||||
</p>
|
||||
|
||||
</Body>
|
||||
</HTML>
|
||||
</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;
|
||||
@@ -39,6 +39,8 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
|
||||
private transient BeanLoader beanLoader;
|
||||
|
||||
private transient PreGetterCallback preGetterCallback;
|
||||
|
||||
private String ebeanServerName;
|
||||
|
||||
/**
|
||||
@@ -53,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.
|
||||
*/
|
||||
@@ -72,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
|
||||
@@ -178,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.
|
||||
*/
|
||||
@@ -186,6 +188,21 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
return embeddedOwnerIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the getter callback.
|
||||
*/
|
||||
public void clearGetterCallback() {
|
||||
this.preGetterCallback = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the callback to be triggered when getter is called.
|
||||
* This is used primarily to automatically flush the JDBC batch.
|
||||
*/
|
||||
public void registerGetterCallback(PreGetterCallback getterCallback) {
|
||||
this.preGetterCallback = getterCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the embedded beans owning bean.
|
||||
*/
|
||||
@@ -223,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;
|
||||
}
|
||||
}
|
||||
@@ -246,7 +263,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
this.dirty = true;
|
||||
setEmbeddedPropertyDirty(embeddedProperty);
|
||||
}
|
||||
|
||||
|
||||
public void setDirty(boolean dirty) {
|
||||
this.dirty = dirty;
|
||||
}
|
||||
@@ -273,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.
|
||||
*/
|
||||
@@ -294,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;
|
||||
}
|
||||
}
|
||||
@@ -325,6 +342,13 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
return state == STATE_LOADED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bean into NEW state.
|
||||
*/
|
||||
public void setNew() {
|
||||
this.state = STATE_NEW;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the loaded state to true.
|
||||
* <p>
|
||||
@@ -424,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.
|
||||
@@ -438,7 +462,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the property name for the given property.
|
||||
*/
|
||||
@@ -448,7 +472,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
}
|
||||
return owner._ebean_getPropertyName(propertyIndex);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the number of properties.s
|
||||
*/
|
||||
@@ -462,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;
|
||||
}
|
||||
@@ -474,7 +498,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
public void setPropertyUnloaded(int propertyIndex) {
|
||||
loadedProps[propertyIndex] = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the property to be loaded.
|
||||
*/
|
||||
@@ -501,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]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -512,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];
|
||||
@@ -529,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];
|
||||
@@ -543,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.
|
||||
*/
|
||||
@@ -563,8 +587,8 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
if (fullyLoadedBean) {
|
||||
return null;
|
||||
}
|
||||
Set<String> props = new LinkedHashSet<String>();
|
||||
for (int i=0; i<loadedProps.length; i++) {
|
||||
Set<String> props = new LinkedHashSet<>();
|
||||
for (int i = 0; i < loadedProps.length; i++) {
|
||||
if (loadedProps[i]) {
|
||||
props.add(getProperty(i));
|
||||
}
|
||||
@@ -593,11 +617,11 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
* Return the set of dirty properties.
|
||||
*/
|
||||
public Set<String> getDirtyPropertyNames() {
|
||||
Set<String> props = new LinkedHashSet<String>();
|
||||
Set<String> props = new LinkedHashSet<>();
|
||||
addDirtyPropertyNames(props, null);
|
||||
return props;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Recursively add dirty properties.
|
||||
*/
|
||||
@@ -610,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) + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -641,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<String, ValuePair>();
|
||||
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]) {
|
||||
@@ -660,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.
|
||||
*/
|
||||
@@ -684,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);
|
||||
}
|
||||
}
|
||||
@@ -702,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;
|
||||
@@ -725,7 +749,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
public int getLazyLoadPropertyIndex() {
|
||||
return lazyLoadProperty;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the property that triggered the lazy load.
|
||||
*/
|
||||
@@ -797,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);
|
||||
@@ -825,26 +849,38 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
}
|
||||
return obj1.equals(obj2);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called when a BeanCollection is initialised automatically.
|
||||
*/
|
||||
public void initialisedMany(int propertyIndex) {
|
||||
loadedProps[propertyIndex] = true;
|
||||
}
|
||||
|
||||
|
||||
private final void preGetterCallback() {
|
||||
if (preGetterCallback != null) {
|
||||
preGetterCallback.preGetterTrigger();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called prior to Id property getter.
|
||||
*/
|
||||
public void preGetId() {
|
||||
preGetterCallback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that is called prior to a getter method on the actual entity.
|
||||
*/
|
||||
public void preGetter(int propertyIndex) {
|
||||
preGetterCallback();
|
||||
if (state == STATE_NEW || disableLazyLoad) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isLoadedProperty(propertyIndex)) {
|
||||
loadBean(propertyIndex);
|
||||
}
|
||||
|
||||
if (nodeUsageCollector != null) {
|
||||
nodeUsageCollector.addUsed(getProperty(propertyIndex));
|
||||
}
|
||||
@@ -884,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
|
||||
@@ -894,7 +930,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void setChangedPropertyValue(int propertyIndex, boolean setDirtyState, Object origValue) {
|
||||
|
||||
if (readOnly) {
|
||||
@@ -905,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);
|
||||
@@ -916,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.
|
||||
@@ -926,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.
|
||||
*/
|
||||
@@ -971,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);
|
||||
}
|
||||
|
||||
@@ -989,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;
|
||||
}
|
||||
@@ -1008,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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1068,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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,7 +29,7 @@ public final class NodeUsageCollector {
|
||||
/**
|
||||
* The properties used at this profile point.
|
||||
*/
|
||||
private final Set<String> used = new LinkedHashSet<String>();
|
||||
private final Set<String> used = new LinkedHashSet<>();
|
||||
|
||||
/**
|
||||
* set to true if the bean is modified (setter called)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public final class ObjectGraphOrigin implements Serializable {
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "key["+ key + "] type[" + beanType + "] " + callStack.getFirstStackTraceElement()+" ";
|
||||
return "key[" + key + "] type[" + beanType + "] " + callStack.getFirstStackTraceElement() + " ";
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
@@ -67,7 +67,7 @@ public final class ObjectGraphOrigin implements Serializable {
|
||||
hc = 31 * hc + queryHash;
|
||||
return hc;
|
||||
}
|
||||
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
@@ -75,10 +75,10 @@ public final class ObjectGraphOrigin implements Serializable {
|
||||
if (!(obj instanceof ObjectGraphOrigin)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
ObjectGraphOrigin e = (ObjectGraphOrigin) obj;
|
||||
return e.queryHash == queryHash
|
||||
&& e.beanType.equals(beanType)
|
||||
&& e.callStack.equals(callStack);
|
||||
return e.queryHash == queryHash
|
||||
&& e.beanType.equals(beanType)
|
||||
&& e.callStack.equals(callStack);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.avaje.ebean.bean;
|
||||
|
||||
/**
|
||||
* A callback that can be registered to fire on getter method calls.
|
||||
* It's primary purpose is to automatically flush JDBC batch buffer.
|
||||
*/
|
||||
public interface PreGetterCallback {
|
||||
|
||||
/**
|
||||
* Trigger the callback.
|
||||
*/
|
||||
void preGetterTrigger();
|
||||
}
|
||||
@@ -1,12 +1,11 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
|
||||
<TITLE>Enhanced beans API and Support objects</TITLE>
|
||||
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
|
||||
<TITLE>Enhanced beans API and Support objects</TITLE>
|
||||
</HEAD>
|
||||
<Body BGCOLOR="#ffffff">
|
||||
Enhanced beans API and Support objects
|
||||
|
||||
|
||||
|
||||
</Body>
|
||||
</HTML>
|
||||
</HTML>
|
||||
|
||||
+3
-4
@@ -10,7 +10,7 @@ package com.avaje.ebean.cache;
|
||||
* which holds beans of a given type. The other is the 'query cache' holding
|
||||
* query results for a given type.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public interface ServerCache {
|
||||
@@ -52,9 +52,8 @@ public interface ServerCache {
|
||||
|
||||
/**
|
||||
* Return statistics for the cache.
|
||||
*
|
||||
* @param reset
|
||||
* if true the statistics are reset.
|
||||
*
|
||||
* @param reset if true the statistics are reset.
|
||||
*/
|
||||
ServerCacheStatistics getStatistics(boolean reset);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.avaje.ebean.cache;
|
||||
|
||||
import com.avaje.ebean.annotation.CacheQueryTuning;
|
||||
import com.avaje.ebean.annotation.CacheBeanTuning;
|
||||
import com.avaje.ebean.annotation.CacheQueryTuning;
|
||||
|
||||
/**
|
||||
* Options for controlling a cache.
|
||||
|
||||
@@ -71,7 +71,7 @@ public class ServerCacheStatistics {
|
||||
if (totalCount == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return (int)(hitCount * 100 / totalCount);
|
||||
return (int) (hitCount * 100 / totalCount);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
|
||||
<TITLE>Server Cache Service</TITLE>
|
||||
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
|
||||
<TITLE>Server Cache Service</TITLE>
|
||||
</HEAD>
|
||||
<Body BGCOLOR="#ffffff">
|
||||
Server Cache Service
|
||||
|
||||
</Body>
|
||||
</HTML>
|
||||
</HTML>
|
||||
|
||||
@@ -11,10 +11,8 @@ import java.util.Set;
|
||||
|
||||
/**
|
||||
* Base class for List Set and Map implementations of BeanCollection.
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
|
||||
private static final long serialVersionUID = 3365725236140187588L;
|
||||
|
||||
@@ -56,13 +54,13 @@ public abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
/**
|
||||
* Constructor not non-lazy loading collection.
|
||||
*/
|
||||
public AbstractBeanCollection() {
|
||||
AbstractBeanCollection() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to create deferred fetch proxy.
|
||||
*/
|
||||
public AbstractBeanCollection(BeanCollectionLoader loader, EntityBean ownerBean, String propertyName) {
|
||||
AbstractBeanCollection(BeanCollectionLoader loader, EntityBean ownerBean, String propertyName) {
|
||||
this.loader = loader;
|
||||
this.ebeanServerName = loader.getName();
|
||||
this.ownerBean = ownerBean;
|
||||
@@ -91,14 +89,14 @@ public abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
this.disableLazyLoad = disableLazyLoad;
|
||||
}
|
||||
|
||||
protected void lazyLoadCollection(boolean onlyIds) {
|
||||
void lazyLoadCollection(boolean onlyIds) {
|
||||
if (loader == null) {
|
||||
loader = (BeanCollectionLoader) Ebean.getServer(ebeanServerName);
|
||||
}
|
||||
if (loader == null) {
|
||||
String msg = "Lazy loading but LazyLoadEbeanServer is null?"
|
||||
+ " The LazyLoadEbeanServer needs to be set after deserialization"
|
||||
+ " to support lazy loading.";
|
||||
+ " The LazyLoadEbeanServer needs to be set after deserialization"
|
||||
+ " to support lazy loading.";
|
||||
throw new PersistenceException(msg);
|
||||
}
|
||||
|
||||
@@ -124,7 +122,7 @@ public abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
this.readOnly = readOnly;
|
||||
}
|
||||
|
||||
protected void checkReadOnly() {
|
||||
void checkReadOnly() {
|
||||
if (readOnly) {
|
||||
String msg = "This collection is in ReadOnly mode";
|
||||
throw new IllegalStateException(msg);
|
||||
@@ -157,9 +155,9 @@ public abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
return modifyListenMode;
|
||||
}
|
||||
|
||||
protected ModifyHolder<E> getModifyHolder() {
|
||||
ModifyHolder<E> getModifyHolder() {
|
||||
if (modifyHolder == null) {
|
||||
modifyHolder = new ModifyHolder<E>();
|
||||
modifyHolder = new ModifyHolder<>();
|
||||
}
|
||||
return modifyHolder;
|
||||
}
|
||||
@@ -201,7 +199,7 @@ public abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
/**
|
||||
* Return true if there are underlying additions or removals.
|
||||
*/
|
||||
public boolean holdsModifications() {
|
||||
boolean holdsModifications() {
|
||||
return modifyHolder != null && modifyHolder.hasModifications();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
* Uses an ArrayList as the underlying List implementation.
|
||||
*/
|
||||
public BeanList() {
|
||||
this(new ArrayList<E>());
|
||||
this(new ArrayList<>());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,7 +68,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
@SuppressWarnings("unchecked")
|
||||
public void loadFrom(BeanCollection<?> other) {
|
||||
if (list == null) {
|
||||
list = new ArrayList<E>();
|
||||
list = new ArrayList<>();
|
||||
}
|
||||
list.addAll((Collection<? extends E>) other.getActualDetails());
|
||||
}
|
||||
@@ -76,7 +76,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
@SuppressWarnings("unchecked")
|
||||
public void internalAdd(Object bean) {
|
||||
if (list == null) {
|
||||
list = new ArrayList<E>();
|
||||
list = new ArrayList<>();
|
||||
}
|
||||
if (bean != null) {
|
||||
list.add((E) bean);
|
||||
@@ -85,14 +85,26 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
|
||||
@Override
|
||||
public void internalAddWithCheck(Object bean) {
|
||||
if (list == null || !list.contains(bean)) {
|
||||
if (list == null || !containsInstance(bean)) {
|
||||
internalAdd(bean);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains using instance equality for List (specifically not .equals() based).
|
||||
*/
|
||||
private boolean containsInstance(Object bean) {
|
||||
for (Object element : list) {
|
||||
if (element == bean) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean checkEmptyLazyLoad() {
|
||||
if (list == null) {
|
||||
list = new ArrayList<E>();
|
||||
list = new ArrayList<>();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -105,7 +117,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
if (!disableLazyLoad && modifyListening) {
|
||||
lazyLoadCollection(true);
|
||||
} else {
|
||||
list = new ArrayList<E>();
|
||||
list = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -115,7 +127,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
synchronized (this) {
|
||||
if (list == null) {
|
||||
if (disableLazyLoad) {
|
||||
list = new ArrayList<E>();
|
||||
list = new ArrayList<>();
|
||||
} else {
|
||||
lazyLoadCollection(false);
|
||||
}
|
||||
@@ -261,8 +273,8 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
// and fetch just the Id's
|
||||
initClear();
|
||||
if (modifyRemoveListening) {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
getModifyHolder().modifyRemoval(list.get(i));
|
||||
for (E aList : list) {
|
||||
getModifyHolder().modifyRemoval(aList);
|
||||
}
|
||||
}
|
||||
list.clear();
|
||||
@@ -296,11 +308,11 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
public Iterator<E> iterator() {
|
||||
init();
|
||||
if (isReadOnly()) {
|
||||
return new ReadOnlyListIterator<E>(list.listIterator());
|
||||
return new ReadOnlyListIterator<>(list.listIterator());
|
||||
}
|
||||
if (modifyListening) {
|
||||
Iterator<E> it = list.iterator();
|
||||
return new ModifyIterator<E>(this, it);
|
||||
return new ModifyIterator<>(this, it);
|
||||
}
|
||||
return list.iterator();
|
||||
}
|
||||
@@ -313,11 +325,11 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
public ListIterator<E> listIterator() {
|
||||
init();
|
||||
if (isReadOnly()) {
|
||||
return new ReadOnlyListIterator<E>(list.listIterator());
|
||||
return new ReadOnlyListIterator<>(list.listIterator());
|
||||
}
|
||||
if (modifyListening) {
|
||||
ListIterator<E> it = list.listIterator();
|
||||
return new ModifyListIterator<E>(this, it);
|
||||
return new ModifyListIterator<>(this, it);
|
||||
}
|
||||
return list.listIterator();
|
||||
}
|
||||
@@ -325,11 +337,11 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
public ListIterator<E> listIterator(int index) {
|
||||
init();
|
||||
if (isReadOnly()) {
|
||||
return new ReadOnlyListIterator<E>(list.listIterator(index));
|
||||
return new ReadOnlyListIterator<>(list.listIterator(index));
|
||||
}
|
||||
if (modifyListening) {
|
||||
ListIterator<E> it = list.listIterator(index);
|
||||
return new ModifyListIterator<E>(this, it);
|
||||
return new ModifyListIterator<>(this, it);
|
||||
}
|
||||
return list.listIterator(index);
|
||||
}
|
||||
@@ -425,7 +437,7 @@ public final class BeanList<E> extends AbstractBeanCollection<E> implements List
|
||||
return Collections.unmodifiableList(list.subList(fromIndex, toIndex));
|
||||
}
|
||||
if (modifyListening) {
|
||||
return new ModifyList<E>(this, list.subList(fromIndex, toIndex));
|
||||
return new ModifyList<>(this, list.subList(fromIndex, toIndex));
|
||||
}
|
||||
return list.subList(fromIndex, toIndex);
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
* Create using a underlying LinkedHashMap.
|
||||
*/
|
||||
public BeanMap() {
|
||||
this(new LinkedHashMap<K, E>());
|
||||
this(new LinkedHashMap<>());
|
||||
}
|
||||
|
||||
public BeanMap(BeanCollectionLoader ebeanServer, EntityBean ownerBean, String propertyName) {
|
||||
@@ -54,21 +54,21 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void loadFrom(BeanCollection<?> other) {
|
||||
BeanMap<K,E> otherMap = (BeanMap<K,E>)other;
|
||||
BeanMap<K, E> otherMap = (BeanMap<K, E>) other;
|
||||
internalPutNull();
|
||||
map.putAll(otherMap.getActualMap());
|
||||
}
|
||||
|
||||
public void internalPutNull() {
|
||||
if (map == null) {
|
||||
map = new LinkedHashMap<K, E>();
|
||||
map = new LinkedHashMap<>();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings("unchecked")
|
||||
public void internalPut(Object key, Object bean) {
|
||||
if (map == null) {
|
||||
map = new LinkedHashMap<K, E>();
|
||||
map = new LinkedHashMap<>();
|
||||
}
|
||||
if (key != null) {
|
||||
map.put((K) key, (E) bean);
|
||||
@@ -108,7 +108,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
|
||||
public boolean checkEmptyLazyLoad() {
|
||||
if (map == null) {
|
||||
map = new LinkedHashMap<K, E>();
|
||||
map = new LinkedHashMap<>();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -121,7 +121,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
if (modifyListening) {
|
||||
lazyLoadCollection(true);
|
||||
} else {
|
||||
map = new LinkedHashMap<K, E>();
|
||||
map = new LinkedHashMap<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -219,7 +219,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
return map.containsValue(value);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public Set<Entry<K, E>> entrySet() {
|
||||
init();
|
||||
if (isReadOnly()) {
|
||||
@@ -265,7 +265,6 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
return map.put(key, value);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public void putAll(Map<? extends K, ? extends E> puts) {
|
||||
checkReadOnly();
|
||||
init();
|
||||
@@ -314,7 +313,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
}
|
||||
if (modifyListening) {
|
||||
Collection<E> c = map.values();
|
||||
return new ModifyCollection<E>(this, c);
|
||||
return new ModifyCollection<>(this, c);
|
||||
}
|
||||
return map.values();
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
* Create using an underlying LinkedHashSet.
|
||||
*/
|
||||
public BeanSet() {
|
||||
this(new LinkedHashSet<E>());
|
||||
this(new LinkedHashSet<>());
|
||||
}
|
||||
|
||||
public BeanSet(BeanCollectionLoader loader, EntityBean ownerBean, String propertyName) {
|
||||
@@ -61,7 +61,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
@SuppressWarnings("unchecked")
|
||||
public void loadFrom(BeanCollection<?> other) {
|
||||
if (set == null) {
|
||||
set = new LinkedHashSet<E>();
|
||||
set = new LinkedHashSet<>();
|
||||
}
|
||||
set.addAll((Collection<? extends E>) other.getActualDetails());
|
||||
}
|
||||
@@ -76,7 +76,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
@SuppressWarnings("unchecked")
|
||||
public void internalAdd(Object bean) {
|
||||
if (set == null) {
|
||||
set = new LinkedHashSet<E>();
|
||||
set = new LinkedHashSet<>();
|
||||
}
|
||||
if (bean != null) {
|
||||
set.add((E) bean);
|
||||
@@ -100,7 +100,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
|
||||
public boolean checkEmptyLazyLoad() {
|
||||
if (set == null) {
|
||||
set = new LinkedHashSet<E>();
|
||||
set = new LinkedHashSet<>();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -113,7 +113,7 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
if (modifyListening) {
|
||||
lazyLoadCollection(true);
|
||||
} else {
|
||||
set = new LinkedHashSet<E>();
|
||||
set = new LinkedHashSet<>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -256,10 +256,10 @@ public final class BeanSet<E> extends AbstractBeanCollection<E> implements Set<E
|
||||
public Iterator<E> iterator() {
|
||||
init();
|
||||
if (isReadOnly()) {
|
||||
return new ReadOnlyIterator<E>(set.iterator());
|
||||
return new ReadOnlyIterator<>(set.iterator());
|
||||
}
|
||||
if (modifyListening) {
|
||||
return new ModifyIterator<E>(this, set.iterator());
|
||||
return new ModifyIterator<>(this, set.iterator());
|
||||
}
|
||||
return set.iterator();
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package com.avaje.ebean.common;
|
||||
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
|
||||
/**
|
||||
* Wraps a collection for the purposes of notifying removals and additions to
|
||||
* the BeanCollection owner.
|
||||
@@ -72,7 +72,7 @@ class ModifyCollection<E> implements Collection<E> {
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
Iterator<E> it = c.iterator();
|
||||
return new ModifyIterator<E>(owner, it);
|
||||
return new ModifyIterator<>(owner, it);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,16 +21,16 @@ class ModifyHolder<E> implements Serializable {
|
||||
/**
|
||||
* Deletions list for manyToMany persistence.
|
||||
*/
|
||||
private Set<E> modifyDeletions = new LinkedHashSet<E>();
|
||||
private Set<E> modifyDeletions = new LinkedHashSet<>();
|
||||
|
||||
/**
|
||||
* Additions list for manyToMany persistence.
|
||||
*/
|
||||
private Set<E> modifyAdditions = new LinkedHashSet<E>();
|
||||
private Set<E> modifyAdditions = new LinkedHashSet<>();
|
||||
|
||||
void reset() {
|
||||
modifyDeletions = new LinkedHashSet<E>();
|
||||
modifyAdditions = new LinkedHashSet<E>();
|
||||
modifyDeletions = new LinkedHashSet<>();
|
||||
modifyAdditions = new LinkedHashSet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.avaje.ebean.common;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Wraps an iterator for the purposes of notifying removals and additions to the
|
||||
* BeanCollection owner.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user