mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
108
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a49b99156b | ||
|
|
54f3dbf35a | ||
|
|
27847424b3 | ||
|
|
a5e94f6ae2 | ||
|
|
9f8b3799eb | ||
|
|
7734919010 | ||
|
|
19f40cb2e5 | ||
|
|
3d4bd15dac | ||
|
|
a3c81c3a31 | ||
|
|
3549f88232 | ||
|
|
59d009bc94 | ||
|
|
a6edafbf2d | ||
|
|
5fab66204c | ||
|
|
2fa7c57357 | ||
|
|
890e924eb0 | ||
|
|
1c6592a6ec | ||
|
|
554c5a7bfc | ||
|
|
7a32c50894 | ||
|
|
3fa8f04a4c | ||
|
|
962d7f601d | ||
|
|
f2aa2b5b8b | ||
|
|
87b485cfa4 | ||
|
|
5a55b5235d | ||
|
|
97adb76eac | ||
|
|
d0d5ab474d | ||
|
|
d396f09b3a | ||
|
|
3baa5bca46 | ||
|
|
c00484026c | ||
|
|
71798afadd | ||
|
|
1ec2f74df9 | ||
|
|
61a0651439 | ||
|
|
eae06059c9 | ||
|
|
a1ff9034b6 | ||
|
|
1085a8d608 | ||
|
|
3a547bf487 | ||
|
|
82489636d5 | ||
|
|
3cafb37a73 | ||
|
|
b4c7cf529d | ||
|
|
ba5c67f936 | ||
|
|
2bd7995ca1 | ||
|
|
cc8c860709 | ||
|
|
7d25e31289 | ||
|
|
936e56835c | ||
|
|
0d848e9311 | ||
|
|
b794b6c77e | ||
|
|
f45d240682 | ||
|
|
1a6f68edd3 | ||
|
|
81683c5d2a | ||
|
|
2b535d59b8 | ||
|
|
ae0bbaaaf8 | ||
|
|
aaca20f9c3 | ||
|
|
245cbb0ea1 | ||
|
|
dbe984c668 | ||
|
|
89088f9480 | ||
|
|
80253c4e07 | ||
|
|
f96ce11c73 | ||
|
|
b8f8cb5ae7 | ||
|
|
b8a2aac95a | ||
|
|
7b090a6346 | ||
|
|
b10c68489f | ||
|
|
2dbb2d9911 | ||
|
|
b3b4c72a77 | ||
|
|
1c040e4583 | ||
|
|
9677e585b6 | ||
|
|
c53806224f | ||
|
|
6fd5927c64 | ||
|
|
920635c6df | ||
|
|
fb1c29b57c | ||
|
|
89bed8be67 | ||
|
|
776e48a501 | ||
|
|
0666a72df7 | ||
|
|
55000a3515 | ||
|
|
8307e259ba | ||
|
|
95b7574d04 | ||
|
|
f6466d3211 | ||
|
|
160e4d7dd1 | ||
|
|
a00980c61f | ||
|
|
72d2fcb59e | ||
|
|
0f503b2a2f | ||
|
|
a79e2e786a | ||
|
|
c9ffa2673f | ||
|
|
0e0fa37f0d | ||
|
|
f7bbd5b3bb | ||
|
|
ba614cd287 | ||
|
|
7d028f3318 | ||
|
|
21b04c244b | ||
|
|
957c2def43 | ||
|
|
35f9cd3821 | ||
|
|
e95d3304bf | ||
|
|
0f7c9da5d2 | ||
|
|
b4008da70c | ||
|
|
34a0f16c74 | ||
|
|
a880109201 | ||
|
|
0607151ac8 | ||
|
|
5c4ad4c01c | ||
|
|
3564504e00 | ||
|
|
49babef495 | ||
|
|
9e3362d004 | ||
|
|
3f0dcdb6d1 | ||
|
|
481116251d | ||
|
|
d490966025 | ||
|
|
5bc0b01a6c | ||
|
|
2bd14db8f7 | ||
|
|
17a0933860 | ||
|
|
5bb8384567 | ||
|
|
29a6bbb6e6 | ||
|
|
46a1324f58 | ||
|
|
d2c3142de4 |
@@ -1,5 +1,6 @@
|
||||
*.autofetch
|
||||
*.sql
|
||||
*.orig
|
||||
.classpath
|
||||
.project
|
||||
.settings/
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
[](https://waffle.io/ebean-orm/avaje-ebeanorm)
|
||||
* [](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
|
||||
|
||||
|
||||
Ebean ORM
|
||||
==============
|
||||
|
||||
Project Website
|
||||
----------------
|
||||
[http://ebean-orm.github.io/](http://ebean-orm.github.io/ "Ebean ORM's Website")
|
||||
|
||||
|
||||
@@ -12,7 +13,7 @@ Maven Dependency
|
||||
<dependency>
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm</artifactId>
|
||||
<version>4.7.1</version>
|
||||
<version>4.7.3</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm</artifactId>
|
||||
<version>4.7.2</version>
|
||||
<version>6.2.2</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>avaje-ebeanorm</name>
|
||||
@@ -43,6 +43,12 @@
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jetbrains</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>13.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.persistence</groupId>
|
||||
<artifactId>persistence-api</artifactId>
|
||||
@@ -152,36 +158,16 @@
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>5.1.27</version>
|
||||
<version>5.1.36</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.11</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-integration</artifactId>
|
||||
<version>1.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>1.9.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.0.9</version>
|
||||
<groupId>org.avaje.composite</groupId>
|
||||
<artifactId>avaje-composite-testing</artifactId>
|
||||
<version>1.1</version>
|
||||
<scope>test</scope>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -33,6 +33,11 @@ public interface BeanState {
|
||||
*/
|
||||
boolean isDirty();
|
||||
|
||||
/**
|
||||
* This can be called with true to disable lazy loading on the bean.
|
||||
*/
|
||||
void setDisableLazyLoad(boolean disableLazyLoading);
|
||||
|
||||
/**
|
||||
* For partially populated beans returns the properties that are loaded on the
|
||||
* bean.
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.avaje.ebean;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -10,6 +9,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import javax.persistence.OptimisticLockException;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -101,7 +101,7 @@ import com.avaje.ebean.text.json.JsonContext;
|
||||
* specific database.
|
||||
* </p>
|
||||
*
|
||||
* <pre> {@code
|
||||
* <pre>{@code
|
||||
*
|
||||
* // Get access to the Human Resources EbeanServer/Database
|
||||
* EbeanServer hrDb = Ebean.getServer("hr");
|
||||
@@ -146,9 +146,9 @@ public final class Ebean {
|
||||
private final Object monitor = new Object();
|
||||
|
||||
/**
|
||||
* The 'default/primary' EbeanServer.
|
||||
* The 'default' EbeanServer.
|
||||
*/
|
||||
private EbeanServer primaryServer;
|
||||
private EbeanServer defaultServer;
|
||||
|
||||
private ServerManager() {
|
||||
|
||||
@@ -162,10 +162,10 @@ public final class Ebean {
|
||||
|
||||
} else {
|
||||
// look to see if there is a default server defined
|
||||
String primaryName = PrimaryServer.getPrimaryServerName();
|
||||
logger.debug("primaryName:" + primaryName);
|
||||
if (primaryName != null && primaryName.trim().length() > 0) {
|
||||
primaryServer = getWithCreate(primaryName.trim());
|
||||
String defaultName = PrimaryServer.getDefaultServerName();
|
||||
logger.debug("defaultName:" + defaultName);
|
||||
if (defaultName != null && defaultName.trim().length() > 0) {
|
||||
defaultServer = getWithCreate(defaultName.trim());
|
||||
}
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
@@ -174,19 +174,19 @@ public final class Ebean {
|
||||
}
|
||||
}
|
||||
|
||||
private EbeanServer getPrimaryServer() {
|
||||
if (primaryServer == null) {
|
||||
private EbeanServer getDefaultServer() {
|
||||
if (defaultServer == null) {
|
||||
String msg = "The default EbeanServer has not been defined?";
|
||||
msg += " This is normally set via the ebean.datasource.default property.";
|
||||
msg += " Otherwise it should be registered programatically via registerServer()";
|
||||
throw new PersistenceException(msg);
|
||||
}
|
||||
return primaryServer;
|
||||
return defaultServer;
|
||||
}
|
||||
|
||||
private EbeanServer get(String name) {
|
||||
if (name == null || name.length() == 0) {
|
||||
return primaryServer;
|
||||
return defaultServer;
|
||||
}
|
||||
// non-synchronized read
|
||||
EbeanServer server = concMap.get(name);
|
||||
@@ -221,12 +221,12 @@ public final class Ebean {
|
||||
registerWithName(server.getName(), server, isPrimaryServer);
|
||||
}
|
||||
|
||||
private void registerWithName(String name, EbeanServer server, boolean isPrimaryServer) {
|
||||
private void registerWithName(String name, EbeanServer server, boolean isDefaultServer) {
|
||||
synchronized (monitor) {
|
||||
concMap.put(name, server);
|
||||
syncMap.put(name, server);
|
||||
if (isPrimaryServer) {
|
||||
primaryServer = server;
|
||||
if (isDefaultServer) {
|
||||
defaultServer = server;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -254,12 +254,22 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*
|
||||
* @param name
|
||||
* the name of the server, use null for the 'default server'
|
||||
* the name of the server, can use null for the 'default server'
|
||||
*/
|
||||
public static EbeanServer getServer(String name) {
|
||||
return serverMgr.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default EbeanServer.
|
||||
* <p>
|
||||
* This is equivalent to <code>Ebean.getServer(null);</code>
|
||||
* </p>
|
||||
*/
|
||||
public static EbeanServer getDefaultServer() {
|
||||
return serverMgr.getDefaultServer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ExpressionFactory from the default server.
|
||||
* <p>
|
||||
@@ -278,23 +288,23 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static ExpressionFactory getExpressionFactory() {
|
||||
return serverMgr.getPrimaryServer().getExpressionFactory();
|
||||
return serverMgr.getDefaultServer().getExpressionFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the server with this Ebean singleton. Specify if the registered
|
||||
* server is the primary/default server.
|
||||
*/
|
||||
public static void register(EbeanServer server, boolean isPrimaryServer) {
|
||||
serverMgr.register(server, isPrimaryServer);
|
||||
public static void register(EbeanServer server, boolean defaultServer) {
|
||||
serverMgr.register(server, defaultServer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Backdoor for registering a mock implementation of EbeanServer as the default server.
|
||||
*/
|
||||
protected static EbeanServer mock(String name, EbeanServer server, boolean isPrimaryServer) {
|
||||
EbeanServer originalPrimaryServer = serverMgr.primaryServer;
|
||||
serverMgr.registerWithName(name, server, isPrimaryServer);
|
||||
protected static EbeanServer mock(String name, EbeanServer server, boolean defaultServer) {
|
||||
EbeanServer originalPrimaryServer = serverMgr.defaultServer;
|
||||
serverMgr.registerWithName(name, server, defaultServer);
|
||||
return originalPrimaryServer;
|
||||
}
|
||||
|
||||
@@ -311,7 +321,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static Object nextId(Class<?> beanType) {
|
||||
return serverMgr.getPrimaryServer().nextId(beanType);
|
||||
return serverMgr.getDefaultServer().nextId(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -359,7 +369,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static Transaction beginTransaction() {
|
||||
return serverMgr.getPrimaryServer().beginTransaction();
|
||||
return serverMgr.getDefaultServer().beginTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -370,7 +380,7 @@ public final class Ebean {
|
||||
*
|
||||
*/
|
||||
public static Transaction beginTransaction(TxIsolation isolation) {
|
||||
return serverMgr.getPrimaryServer().beginTransaction(isolation);
|
||||
return serverMgr.getDefaultServer().beginTransaction(isolation);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -425,7 +435,7 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static Transaction beginTransaction(TxScope scope){
|
||||
return serverMgr.getPrimaryServer().beginTransaction(scope);
|
||||
return serverMgr.getDefaultServer().beginTransaction(scope);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -433,7 +443,7 @@ public final class Ebean {
|
||||
* in scope.
|
||||
*/
|
||||
public static Transaction currentTransaction() {
|
||||
return serverMgr.getPrimaryServer().currentTransaction();
|
||||
return serverMgr.getDefaultServer().currentTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -446,21 +456,21 @@ public final class Ebean {
|
||||
* @throws PersistenceException if there is no currently active transaction
|
||||
*/
|
||||
public static void register(TransactionCallback transactionCallback) throws PersistenceException {
|
||||
serverMgr.getPrimaryServer().register(transactionCallback);
|
||||
serverMgr.getDefaultServer().register(transactionCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit the current transaction.
|
||||
*/
|
||||
public static void commitTransaction() {
|
||||
serverMgr.getPrimaryServer().commitTransaction();
|
||||
serverMgr.getDefaultServer().commitTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rollback the current transaction.
|
||||
*/
|
||||
public static void rollbackTransaction() {
|
||||
serverMgr.getPrimaryServer().rollbackTransaction();
|
||||
serverMgr.getDefaultServer().rollbackTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -489,7 +499,7 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static void endTransaction() {
|
||||
serverMgr.getPrimaryServer().endTransaction();
|
||||
serverMgr.getDefaultServer().endTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -500,7 +510,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static Map<String, ValuePair> diff(Object a, Object b) {
|
||||
return serverMgr.getPrimaryServer().diff(a, b);
|
||||
return serverMgr.getDefaultServer().diff(a, b);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -523,7 +533,6 @@ public final class Ebean {
|
||||
* public class Order { ...
|
||||
*
|
||||
* @OneToMany(cascade=CascadeType.ALL, mappedBy="order")
|
||||
* @JoinColumn(name="order_id")
|
||||
* List<OrderDetail> details;
|
||||
* ...
|
||||
* }
|
||||
@@ -537,7 +546,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static void save(Object bean) throws OptimisticLockException {
|
||||
serverMgr.getPrimaryServer().save(bean);
|
||||
serverMgr.getDefaultServer().save(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -545,14 +554,14 @@ public final class Ebean {
|
||||
* want to explicitly insert it.
|
||||
*/
|
||||
public static void insert(Object bean) {
|
||||
serverMgr.getPrimaryServer().insert(bean);
|
||||
serverMgr.getDefaultServer().insert(bean);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Insert a collection of beans.
|
||||
*/
|
||||
public static void insert(Collection<?> beans) {
|
||||
serverMgr.getPrimaryServer().insert(beans);
|
||||
public static void insertAll(Collection<?> beans) {
|
||||
serverMgr.getDefaultServer().insertAll(beans);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -576,7 +585,7 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static void markAsDirty(Object bean) throws OptimisticLockException {
|
||||
serverMgr.getPrimaryServer().markAsDirty(bean);
|
||||
serverMgr.getDefaultServer().markAsDirty(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -616,28 +625,21 @@ public final class Ebean {
|
||||
* @see ServerConfig#setUpdateChangesOnly(boolean)
|
||||
*/
|
||||
public static void update(Object bean) throws OptimisticLockException {
|
||||
serverMgr.getPrimaryServer().update(bean);
|
||||
serverMgr.getDefaultServer().update(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the beans in the collection.
|
||||
*/
|
||||
public static void update(Collection<?> beans) throws OptimisticLockException {
|
||||
serverMgr.getPrimaryServer().update(beans);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save all the beans from an Iterator.
|
||||
*/
|
||||
public static int save(Iterator<?> iterator) throws OptimisticLockException {
|
||||
return serverMgr.getPrimaryServer().save(iterator);
|
||||
public static void updateAll(Collection<?> beans) throws OptimisticLockException {
|
||||
serverMgr.getDefaultServer().updateAll(beans);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save all the beans from a Collection.
|
||||
*/
|
||||
public static int save(Collection<?> beans) throws OptimisticLockException {
|
||||
return serverMgr.getPrimaryServer().save(beans);
|
||||
public static int saveAll(Collection<?> beans) throws OptimisticLockException {
|
||||
return serverMgr.getDefaultServer().saveAll(beans);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -651,7 +653,7 @@ public final class Ebean {
|
||||
* @return the number of associations deleted (from the intersection table).
|
||||
*/
|
||||
public static int deleteManyToManyAssociations(Object ownerBean, String propertyName) {
|
||||
return serverMgr.getPrimaryServer().deleteManyToManyAssociations(ownerBean, propertyName);
|
||||
return serverMgr.getDefaultServer().deleteManyToManyAssociations(ownerBean, propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -669,7 +671,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static void saveManyToManyAssociations(Object ownerBean, String propertyName) {
|
||||
serverMgr.getPrimaryServer().saveManyToManyAssociations(ownerBean, propertyName);
|
||||
serverMgr.getDefaultServer().saveManyToManyAssociations(ownerBean, propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -689,7 +691,7 @@ public final class Ebean {
|
||||
* the property we want to save
|
||||
*/
|
||||
public static void saveAssociation(Object ownerBean, String propertyName) {
|
||||
serverMgr.getPrimaryServer().saveAssociation(ownerBean, propertyName);
|
||||
serverMgr.getDefaultServer().saveAssociation(ownerBean, propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -700,35 +702,28 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static void delete(Object bean) throws OptimisticLockException {
|
||||
serverMgr.getPrimaryServer().delete(bean);
|
||||
serverMgr.getDefaultServer().delete(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the bean given its type and id.
|
||||
*/
|
||||
public static int delete(Class<?> beanType, Object id) {
|
||||
return serverMgr.getPrimaryServer().delete(beanType, id);
|
||||
return serverMgr.getDefaultServer().delete(beanType, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete several beans given their type and id values.
|
||||
*/
|
||||
public static void delete(Class<?> beanType, Collection<?> ids) {
|
||||
serverMgr.getPrimaryServer().delete(beanType, ids);
|
||||
public static void deleteAll(Class<?> beanType, Collection<?> ids) {
|
||||
serverMgr.getDefaultServer().deleteAll(beanType, ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all the beans from an Iterator.
|
||||
* Delete all the beans in the Collection.
|
||||
*/
|
||||
public static int delete(Iterator<?> it) throws OptimisticLockException {
|
||||
return serverMgr.getPrimaryServer().delete(it);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all the beans from a Collection.
|
||||
*/
|
||||
public static int delete(Collection<?> c) throws OptimisticLockException {
|
||||
return delete(c.iterator());
|
||||
public static int deleteAll(Collection<?> beans) throws OptimisticLockException {
|
||||
return serverMgr.getDefaultServer().deleteAll(beans);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -739,7 +734,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static void refresh(Object bean) {
|
||||
serverMgr.getPrimaryServer().refresh(bean);
|
||||
serverMgr.getDefaultServer().refresh(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -760,7 +755,7 @@ public final class Ebean {
|
||||
* the property name of the List Set or Map to refresh.
|
||||
*/
|
||||
public static void refreshMany(Object bean, String manyPropertyName) {
|
||||
serverMgr.getPrimaryServer().refreshMany(bean, manyPropertyName);
|
||||
serverMgr.getDefaultServer().refreshMany(bean, manyPropertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -788,7 +783,7 @@ public final class Ebean {
|
||||
* the id value
|
||||
*/
|
||||
public static <T> T getReference(Class<T> beanType, Object id) {
|
||||
return serverMgr.getPrimaryServer().getReference(beanType, id);
|
||||
return serverMgr.getDefaultServer().getReference(beanType, id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -834,7 +829,7 @@ public final class Ebean {
|
||||
* the properties to sort the list by
|
||||
*/
|
||||
public static <T> void sort(List<T> list, String sortByClause) {
|
||||
serverMgr.getPrimaryServer().sort(list, sortByClause);
|
||||
serverMgr.getDefaultServer().sort(list, sortByClause);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -883,8 +878,9 @@ public final class Ebean {
|
||||
* @param id
|
||||
* the id value
|
||||
*/
|
||||
@Nullable
|
||||
public static <T> T find(Class<T> beanType, Object id) {
|
||||
return serverMgr.getPrimaryServer().find(beanType, id);
|
||||
return serverMgr.getDefaultServer().find(beanType, id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -896,7 +892,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static SqlQuery createSqlQuery(String sql) {
|
||||
return serverMgr.getPrimaryServer().createSqlQuery(sql);
|
||||
return serverMgr.getDefaultServer().createSqlQuery(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -909,7 +905,7 @@ public final class Ebean {
|
||||
* the name of the query
|
||||
*/
|
||||
public static SqlQuery createNamedSqlQuery(String namedQuery) {
|
||||
return serverMgr.getPrimaryServer().createNamedSqlQuery(namedQuery);
|
||||
return serverMgr.getDefaultServer().createNamedSqlQuery(namedQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -927,7 +923,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static SqlUpdate createSqlUpdate(String sql) {
|
||||
return serverMgr.getPrimaryServer().createSqlUpdate(sql);
|
||||
return serverMgr.getDefaultServer().createSqlUpdate(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -936,7 +932,7 @@ public final class Ebean {
|
||||
* @see CallableSql
|
||||
*/
|
||||
public static CallableSql createCallableSql(String sql) {
|
||||
return serverMgr.getPrimaryServer().createCallableSql(sql);
|
||||
return serverMgr.getDefaultServer().createCallableSql(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -959,7 +955,7 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static SqlUpdate createNamedSqlUpdate(String namedQuery) {
|
||||
return serverMgr.getPrimaryServer().createNamedSqlUpdate(namedQuery);
|
||||
return serverMgr.getDefaultServer().createNamedSqlUpdate(namedQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -987,7 +983,7 @@ public final class Ebean {
|
||||
*/
|
||||
public static <T> Query<T> createNamedQuery(Class<T> beanType, String namedQuery) {
|
||||
|
||||
return serverMgr.getPrimaryServer().createNamedQuery(beanType, namedQuery);
|
||||
return serverMgr.getDefaultServer().createNamedQuery(beanType, namedQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1015,7 +1011,7 @@ public final class Ebean {
|
||||
* the object query
|
||||
*/
|
||||
public static <T> Query<T> createQuery(Class<T> beanType, String query) {
|
||||
return serverMgr.getPrimaryServer().createQuery(beanType, query);
|
||||
return serverMgr.getDefaultServer().createQuery(beanType, query);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1074,7 +1070,7 @@ public final class Ebean {
|
||||
*/
|
||||
public static <T> Update<T> createNamedUpdate(Class<T> beanType, String namedUpdate) {
|
||||
|
||||
return serverMgr.getPrimaryServer().createNamedUpdate(beanType, namedUpdate);
|
||||
return serverMgr.getDefaultServer().createNamedUpdate(beanType, namedUpdate);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1108,7 +1104,7 @@ public final class Ebean {
|
||||
*/
|
||||
public static <T> Update<T> createUpdate(Class<T> beanType, String ormUpdate) {
|
||||
|
||||
return serverMgr.getPrimaryServer().createUpdate(beanType, ormUpdate);
|
||||
return serverMgr.getDefaultServer().createUpdate(beanType, ormUpdate);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1116,7 +1112,7 @@ public final class Ebean {
|
||||
*/
|
||||
public static <T> CsvReader<T> createCsvReader(Class<T> beanType) {
|
||||
|
||||
return serverMgr.getPrimaryServer().createCsvReader(beanType);
|
||||
return serverMgr.getDefaultServer().createCsvReader(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1173,7 +1169,7 @@ public final class Ebean {
|
||||
*/
|
||||
public static <T> Query<T> createQuery(Class<T> beanType) {
|
||||
|
||||
return serverMgr.getPrimaryServer().createQuery(beanType);
|
||||
return serverMgr.getDefaultServer().createQuery(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1190,7 +1186,7 @@ public final class Ebean {
|
||||
*/
|
||||
public static <T> Query<T> find(Class<T> beanType) {
|
||||
|
||||
return serverMgr.getPrimaryServer().find(beanType);
|
||||
return serverMgr.getDefaultServer().find(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1204,7 +1200,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static <T> Filter<T> filter(Class<T> beanType) {
|
||||
return serverMgr.getPrimaryServer().filter(beanType);
|
||||
return serverMgr.getDefaultServer().filter(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1251,7 +1247,7 @@ public final class Ebean {
|
||||
* @see Ebean#execute(CallableSql)
|
||||
*/
|
||||
public static int execute(SqlUpdate sqlUpdate) {
|
||||
return serverMgr.getPrimaryServer().execute(sqlUpdate);
|
||||
return serverMgr.getDefaultServer().execute(sqlUpdate);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1280,7 +1276,7 @@ public final class Ebean {
|
||||
* @see Ebean#execute(SqlUpdate)
|
||||
*/
|
||||
public static int execute(CallableSql callableSql) {
|
||||
return serverMgr.getPrimaryServer().execute(callableSql);
|
||||
return serverMgr.getDefaultServer().execute(callableSql);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1305,7 +1301,7 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static void execute(TxScope scope, TxRunnable r) {
|
||||
serverMgr.getPrimaryServer().execute(scope, r);
|
||||
serverMgr.getDefaultServer().execute(scope, r);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1333,7 +1329,7 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static void execute(TxRunnable r) {
|
||||
serverMgr.getPrimaryServer().execute(r);
|
||||
serverMgr.getDefaultServer().execute(r);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1360,7 +1356,7 @@ public final class Ebean {
|
||||
*
|
||||
*/
|
||||
public static <T> T execute(TxScope scope, TxCallable<T> c) {
|
||||
return serverMgr.getPrimaryServer().execute(scope, c);
|
||||
return serverMgr.getDefaultServer().execute(scope, c);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1394,7 +1390,7 @@ public final class Ebean {
|
||||
* }</pre>
|
||||
*/
|
||||
public static <T> T execute(TxCallable<T> c) {
|
||||
return serverMgr.getPrimaryServer().execute(c);
|
||||
return serverMgr.getDefaultServer().execute(c);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1431,10 +1427,9 @@ public final class Ebean {
|
||||
* @param deletes
|
||||
* true if rows on the table where deleted
|
||||
*/
|
||||
public static void externalModification(String tableName, boolean inserts, boolean updates,
|
||||
boolean deletes) {
|
||||
public static void externalModification(String tableName, boolean inserts, boolean updates, boolean deletes) {
|
||||
|
||||
serverMgr.getPrimaryServer().externalModification(tableName, inserts, updates, deletes);
|
||||
serverMgr.getDefaultServer().externalModification(tableName, inserts, updates, deletes);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1444,7 +1439,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static BeanState getBeanState(Object bean) {
|
||||
return serverMgr.getPrimaryServer().getBeanState(bean);
|
||||
return serverMgr.getDefaultServer().getBeanState(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1452,7 +1447,7 @@ public final class Ebean {
|
||||
*
|
||||
*/
|
||||
public static ServerCacheManager getServerCacheManager() {
|
||||
return serverMgr.getPrimaryServer().getServerCacheManager();
|
||||
return serverMgr.getDefaultServer().getServerCacheManager();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1460,7 +1455,7 @@ public final class Ebean {
|
||||
* queries.
|
||||
*/
|
||||
public static BackgroundExecutor getBackgroundExecutor() {
|
||||
return serverMgr.getPrimaryServer().getBackgroundExecutor();
|
||||
return serverMgr.getDefaultServer().getBackgroundExecutor();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1471,7 +1466,7 @@ public final class Ebean {
|
||||
* </p>
|
||||
*/
|
||||
public static void runCacheWarming() {
|
||||
serverMgr.getPrimaryServer().runCacheWarming();
|
||||
serverMgr.getDefaultServer().runCacheWarming();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1483,22 +1478,14 @@ public final class Ebean {
|
||||
*/
|
||||
public static void runCacheWarming(Class<?> beanType) {
|
||||
|
||||
serverMgr.getPrimaryServer().runCacheWarming(beanType);
|
||||
serverMgr.getDefaultServer().runCacheWarming(beanType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JsonContext for reading/writing JSON.
|
||||
*/
|
||||
public static JsonContext json() {
|
||||
return serverMgr.getPrimaryServer().json();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JsonContext for reading/writing JSON.
|
||||
* @deprecated Please use #json instead.
|
||||
*/
|
||||
public static JsonContext createJsonContext() {
|
||||
return json();
|
||||
return serverMgr.getDefaultServer().json();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -15,6 +14,7 @@ import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.meta.MetaInfoManager;
|
||||
import com.avaje.ebean.text.csv.CsvReader;
|
||||
import com.avaje.ebean.text.json.JsonContext;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Provides the API for fetching and saving beans to a particular DataSource.
|
||||
@@ -148,7 +148,7 @@ public interface EbeanServer {
|
||||
* difference comparison.
|
||||
* </p>
|
||||
*/
|
||||
Map<String, ValuePair> diff(Object a, Object b);
|
||||
Map<String, ValuePair> diff(Object newBean, Object oldBean);
|
||||
|
||||
/**
|
||||
* Create a new instance of T that is an EntityBean.
|
||||
@@ -905,17 +905,13 @@ public interface EbeanServer {
|
||||
<T> void findEachWhile(Query<T> query, QueryEachWhileConsumer<T> consumer, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Deprecated in favor of #findEachWhile which is functionally exactly the same
|
||||
* but has a much better name.
|
||||
* Return versions of a @History entity bean.
|
||||
* <p>
|
||||
* Execute the query visiting the results. This is similar to findIterate in
|
||||
* that not all the result beans need to be held in memory at the same time
|
||||
* and as such is go for processing large queries.
|
||||
* Generally this query is expected to be a find by id or unique predicates query.
|
||||
* It will execute the query against the history returning the versions of the bean.
|
||||
* </p>
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
<T> void findVisit(Query<T> query, QueryResultVisitor<T> visitor, Transaction transaction);
|
||||
<T> List<Version<T>> findVersions(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute a query returning a list of beans.
|
||||
@@ -1109,6 +1105,7 @@ public interface EbeanServer {
|
||||
*
|
||||
* @see Query#findUnique()
|
||||
*/
|
||||
@Nullable
|
||||
<T> T findUnique(Query<T> query, Transaction transaction);
|
||||
|
||||
/**
|
||||
@@ -1185,6 +1182,7 @@ public interface EbeanServer {
|
||||
*
|
||||
* @see SqlQuery#findUnique()
|
||||
*/
|
||||
@Nullable
|
||||
SqlRow findUnique(SqlQuery query, Transaction transaction);
|
||||
|
||||
/**
|
||||
@@ -1222,15 +1220,10 @@ public interface EbeanServer {
|
||||
*/
|
||||
void save(Object bean) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Save all the beans in the iterator.
|
||||
*/
|
||||
int save(Iterator<?> it) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Save all the beans in the collection.
|
||||
*/
|
||||
int save(Collection<?> beans) throws OptimisticLockException;
|
||||
int saveAll(Collection<?> beans) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Delete the bean.
|
||||
@@ -1241,15 +1234,10 @@ public interface EbeanServer {
|
||||
*/
|
||||
void delete(Object bean) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Delete all the beans from an Iterator.
|
||||
*/
|
||||
int delete(Iterator<?> it) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Delete all the beans in the collection.
|
||||
*/
|
||||
int delete(Collection<?> c) throws OptimisticLockException;
|
||||
int deleteAll(Collection<?> beans) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Delete the bean given its type and id.
|
||||
@@ -1264,13 +1252,18 @@ public interface EbeanServer {
|
||||
/**
|
||||
* Delete several beans given their type and id values.
|
||||
*/
|
||||
void delete(Class<?> beanType, Collection<?> ids);
|
||||
void deleteAll(Class<?> beanType, Collection<?> ids);
|
||||
|
||||
/**
|
||||
* Delete several beans given their type and id values with an explicit
|
||||
* transaction.
|
||||
*/
|
||||
void delete(Class<?> beanType, Collection<?> ids, Transaction transaction);
|
||||
void deleteAll(Class<?> beanType, Collection<?> ids, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Delete the bean with an explicit transaction.
|
||||
*/
|
||||
void delete(Object bean, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Execute a Sql Update Delete or Insert statement. This returns the number of
|
||||
@@ -1328,7 +1321,7 @@ public interface EbeanServer {
|
||||
* Execute a ORM insert update or delete statement with an explicit
|
||||
* transaction.
|
||||
*/
|
||||
int execute(Update<?> update, Transaction t);
|
||||
int execute(Update<?> update, Transaction transaction);
|
||||
|
||||
/**
|
||||
* For making calls to stored procedures.
|
||||
@@ -1400,27 +1393,22 @@ public interface EbeanServer {
|
||||
* the type of entity bean to find
|
||||
* @param beanType
|
||||
* the type of entity bean to find
|
||||
* @param uid
|
||||
* @param id
|
||||
* the bean id value
|
||||
* @param transaction
|
||||
* the transaction to use (can be null)
|
||||
*/
|
||||
<T> T find(Class<T> beanType, Object uid, Transaction transaction);
|
||||
<T> T find(Class<T> beanType, Object id, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Insert or update a bean with an explicit transaction.
|
||||
*/
|
||||
void save(Object bean, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Save all the beans in the iterator with an explicit transaction.
|
||||
*/
|
||||
int save(Iterator<?> it, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Save all the beans in the collection with an explicit transaction.
|
||||
*/
|
||||
int save(Collection<?> beans, Transaction transaction) throws OptimisticLockException;
|
||||
int saveAll(Collection<?> beans, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Marks the entity bean as dirty.
|
||||
@@ -1485,7 +1473,7 @@ public interface EbeanServer {
|
||||
/**
|
||||
* Update a bean additionally specifying a transaction.
|
||||
*/
|
||||
void update(Object bean, Transaction t) throws OptimisticLockException;
|
||||
void update(Object bean, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Update a bean additionally specifying a transaction and the deleteMissingChildren setting.
|
||||
@@ -1505,13 +1493,13 @@ public interface EbeanServer {
|
||||
* Update a collection of beans. If there is no current transaction one is created and used to
|
||||
* update all the beans in the collection.
|
||||
*/
|
||||
void update(Collection<?> beans) throws OptimisticLockException;
|
||||
void updateAll(Collection<?> beans) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Update a collection of beans with an explicit transaction.
|
||||
*/
|
||||
void update(Collection<?> beans, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
void updateAll(Collection<?> beans, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Insert the bean.
|
||||
* <p>
|
||||
@@ -1525,18 +1513,18 @@ public interface EbeanServer {
|
||||
/**
|
||||
* Insert the bean with a transaction.
|
||||
*/
|
||||
void insert(Object bean, Transaction t);
|
||||
void insert(Object bean, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Insert a collection of beans. If there is no current transaction one is created and used to
|
||||
* insert all the beans in the collection.
|
||||
*/
|
||||
void insert(Collection<?> beans);
|
||||
void insertAll(Collection<?> beans);
|
||||
|
||||
/**
|
||||
* Insert a collection of beans with an explicit transaction.
|
||||
*/
|
||||
void insert(Collection<?> beans, Transaction t);
|
||||
void insertAll(Collection<?> beans, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Delete the associations (from the intersection table) of a ManyToMany given
|
||||
@@ -1545,7 +1533,7 @@ public interface EbeanServer {
|
||||
* Typically these deletions occur automatically when persisting a ManyToMany
|
||||
* collection and this provides a way to invoke those deletions directly.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @return the number of associations deleted (from the intersection table).
|
||||
*/
|
||||
int deleteManyToManyAssociations(Object ownerBean, String propertyName);
|
||||
@@ -1560,10 +1548,10 @@ public interface EbeanServer {
|
||||
* Typically these deletions occur automatically when persisting a ManyToMany
|
||||
* collection and this provides a way to invoke those deletions directly.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @return the number of associations deleted (from the intersection table).
|
||||
*/
|
||||
int deleteManyToManyAssociations(Object ownerBean, String propertyName, Transaction t);
|
||||
int deleteManyToManyAssociations(Object ownerBean, String propertyName, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Save the associations of a ManyToMany given the owner bean and the
|
||||
@@ -1585,7 +1573,7 @@ public interface EbeanServer {
|
||||
* way to invoke those insertions directly.
|
||||
* </p>
|
||||
*/
|
||||
void saveManyToManyAssociations(Object ownerBean, String propertyName, Transaction t);
|
||||
void saveManyToManyAssociations(Object ownerBean, String propertyName, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Save the associated collection or bean given the property name.
|
||||
@@ -1622,27 +1610,18 @@ public interface EbeanServer {
|
||||
* @param propertyName
|
||||
* the property we want to save
|
||||
*/
|
||||
void saveAssociation(Object ownerBean, String propertyName, Transaction t);
|
||||
void saveAssociation(Object ownerBean, String propertyName, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Delete the bean with an explicit transaction.
|
||||
*/
|
||||
void delete(Object bean, Transaction t) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Delete all the beans from an iterator.
|
||||
*/
|
||||
int delete(Iterator<?> it, Transaction t) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Execute explicitly passing a transaction.
|
||||
*/
|
||||
int execute(SqlUpdate updSql, Transaction t);
|
||||
int execute(SqlUpdate updSql, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute explicitly passing a transaction.
|
||||
*/
|
||||
int execute(CallableSql callableSql, Transaction t);
|
||||
int execute(CallableSql callableSql, Transaction transaction);
|
||||
|
||||
/**
|
||||
* Execute a TxRunnable in a Transaction with an explicit scope.
|
||||
@@ -1665,7 +1644,7 @@ public interface EbeanServer {
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
void execute(TxScope scope, TxRunnable r);
|
||||
void execute(TxScope scope, TxRunnable runnable);
|
||||
|
||||
/**
|
||||
* Execute a TxRunnable in a Transaction with the default scope.
|
||||
@@ -1691,7 +1670,7 @@ public interface EbeanServer {
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
void execute(TxRunnable r);
|
||||
void execute(TxRunnable runnable);
|
||||
|
||||
/**
|
||||
* Execute a TxCallable in a Transaction with an explicit scope.
|
||||
@@ -1715,7 +1694,7 @@ public interface EbeanServer {
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
<T> T execute(TxScope scope, TxCallable<T> c);
|
||||
<T> T execute(TxScope scope, TxCallable<T> callable);
|
||||
|
||||
/**
|
||||
* Execute a TxCallable in a Transaction with the default scope.
|
||||
@@ -1747,7 +1726,7 @@ public interface EbeanServer {
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
<T> T execute(TxCallable<T> c);
|
||||
<T> T execute(TxCallable<T> callable);
|
||||
|
||||
/**
|
||||
* Return the manager of the server cache ("L2" cache).
|
||||
@@ -1777,12 +1756,6 @@ public interface EbeanServer {
|
||||
*/
|
||||
void runCacheWarming(Class<?> beanType);
|
||||
|
||||
/**
|
||||
* Return the JsonContext for reading/writing JSON.
|
||||
* @deprecated Please use #json instead.
|
||||
*/
|
||||
JsonContext createJsonContext();
|
||||
|
||||
/**
|
||||
* Return the JsonContext for reading/writing JSON.
|
||||
* <p>
|
||||
|
||||
@@ -169,7 +169,22 @@ public interface ExpressionFactory {
|
||||
* In - property has a value in the collection of values.
|
||||
*/
|
||||
Expression in(String propertyName, Collection<?> values);
|
||||
|
||||
|
||||
/**
|
||||
* Not In - property has a value in the array of values.
|
||||
*/
|
||||
Expression notIn(String propertyName, Object[] values);
|
||||
|
||||
/**
|
||||
* Not In - property has a value in the collection of values.
|
||||
*/
|
||||
Expression notIn(String propertyName, Collection<?> values);
|
||||
|
||||
/**
|
||||
* Not In - using a subQuery.
|
||||
*/
|
||||
Expression notIn(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Exists expression
|
||||
*/
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import com.avaje.ebean.text.PathProperties;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -94,6 +96,17 @@ public interface ExpressionList<T> extends Serializable {
|
||||
*/
|
||||
Query<T> apply(PathProperties pathProperties);
|
||||
|
||||
/**
|
||||
* Perform an 'As of' query using history tables to return the object graph
|
||||
* as of a time in the past.
|
||||
* <p>
|
||||
* To perform this query the DB must have underlying history tables.
|
||||
* </p>
|
||||
*
|
||||
* @param asOf the date time in the past at which you want to view the data
|
||||
*/
|
||||
Query<T> asOf(Timestamp asOf);
|
||||
|
||||
/**
|
||||
* Execute the query iterating over the results.
|
||||
*
|
||||
@@ -116,14 +129,6 @@ public interface ExpressionList<T> extends Serializable {
|
||||
*/
|
||||
void findEachWhile(QueryEachWhileConsumer<T> consumer);
|
||||
|
||||
/**
|
||||
* Deprecated in favor of #findEachWhile which is functionally exactly the same
|
||||
* but has a much better name.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
void findVisit(QueryResultVisitor<T> visitor);
|
||||
|
||||
/**
|
||||
* Execute the query returning a list.
|
||||
*
|
||||
@@ -170,6 +175,7 @@ public interface ExpressionList<T> extends Serializable {
|
||||
*
|
||||
* @see Query#findUnique()
|
||||
*/
|
||||
@Nullable
|
||||
T findUnique();
|
||||
|
||||
/**
|
||||
@@ -229,6 +235,15 @@ public interface ExpressionList<T> extends Serializable {
|
||||
*/
|
||||
PagedList<T> findPagedList(int pageIndex, int pageSize);
|
||||
|
||||
/**
|
||||
* Return versions of a @History entity bean.
|
||||
* <p>
|
||||
* Generally this query is expected to be a find by id or unique predicates query.
|
||||
* It will execute the query against the history returning the versions of the bean.
|
||||
* </p>
|
||||
*/
|
||||
List<Version<T>> findVersions();
|
||||
|
||||
/**
|
||||
* Add some filter predicate expressions to the many property.
|
||||
*/
|
||||
@@ -473,7 +488,22 @@ public interface ExpressionList<T> extends Serializable {
|
||||
* In - property has a value in the collection of values.
|
||||
*/
|
||||
ExpressionList<T> in(String propertyName, Collection<?> values);
|
||||
|
||||
|
||||
/**
|
||||
* Not In - property has a value in the array of values.
|
||||
*/
|
||||
ExpressionList<T> notIn(String propertyName, Object... values);
|
||||
|
||||
/**
|
||||
* Not In - property has a value in the collection of values.
|
||||
*/
|
||||
ExpressionList<T> notIn(String propertyName, Collection<?> values);
|
||||
|
||||
/**
|
||||
* Not In - using a subQuery.
|
||||
*/
|
||||
ExpressionList<T> notIn(String propertyName, Query<?> subQuery);
|
||||
|
||||
/**
|
||||
* Exists expression
|
||||
*/
|
||||
|
||||
@@ -22,57 +22,57 @@ import java.io.Serializable;
|
||||
* efficient loaded as 2 SQL queries.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* <pre>{@code
|
||||
* // Normal fetch join results in a single SQL query
|
||||
* List<Order> list = Ebean.find(Order.class).fetch("details").findList();
|
||||
* List<Order> list = Ebean.find(Order.class).fetch("details").findList();
|
||||
*
|
||||
* // Find Orders join details using a single SQL query
|
||||
* </pre>
|
||||
* }</pre>
|
||||
* <p>
|
||||
* Example: Using a "query join" instead of a "fetch join" we instead use 2 SQL
|
||||
* queries
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* <pre>{@code
|
||||
* // This will use 2 SQL queries to build this object graph
|
||||
* List<Order> list =
|
||||
* List<Order> list =
|
||||
* Ebean.find(Order.class)
|
||||
* .fetch("details", new FetchConfig().query())
|
||||
* .fetch("details", new FetchConfig().query())
|
||||
* .findList();
|
||||
*
|
||||
* // query 1) find order
|
||||
* // query 2) find orderDetails where order.id in (?,?...) // first 100 order id's
|
||||
* </pre>
|
||||
* }</pre>
|
||||
* <p>
|
||||
* Example: Using 2 "query joins"
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* <pre>{@code
|
||||
* // This will use 3 SQL queries to build this object graph
|
||||
* List<Order> list =
|
||||
* List<Order> list =
|
||||
* Ebean.find(Order.class)
|
||||
* .fetch("details", new FetchConfig().query())
|
||||
* .fetch("customer", new FetchConfig().queryFirst(5))
|
||||
* .fetch("details", new FetchConfig().query())
|
||||
* .fetch("customer", new FetchConfig().queryFirst(5))
|
||||
* .findList();
|
||||
*
|
||||
* // query 1) find order
|
||||
* // query 2) find orderDetails where order.id in (?,?...) // first 100 order id's
|
||||
* // query 3) find customer where id in (?,?,?,?,?) // first 5 customers
|
||||
* </pre>
|
||||
* }</pre>
|
||||
* <p>
|
||||
* Example: Using "query joins" and partial objects
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* <pre>{@code
|
||||
* // This will use 3 SQL queries to build this object graph
|
||||
* List<Order> list =
|
||||
* List<Order> list =
|
||||
* Ebean.find(Order.class)
|
||||
* .select("status, shipDate")
|
||||
* .fetch("details", "quantity, price", new FetchConfig().query())
|
||||
* .fetch("details.product", "sku, name")
|
||||
* .fetch("customer", "name", new FetchConfig().queryFirst(5))
|
||||
* .fetch("customer.contacts")
|
||||
* .fetch("customer.shippingAddress")
|
||||
* .select("status, shipDate")
|
||||
* .fetch("details", "quantity, price", new FetchConfig().query())
|
||||
* .fetch("details.product", "sku, name")
|
||||
* .fetch("customer", "name", new FetchConfig().queryFirst(5))
|
||||
* .fetch("customer.contacts")
|
||||
* .fetch("customer.shippingAddress")
|
||||
* .findList();
|
||||
*
|
||||
* // query 1) find order (status, shipDate)
|
||||
@@ -81,22 +81,22 @@ import java.io.Serializable;
|
||||
* // query 3) find customer (name) fetch contacts (*) fetch shippingAddress (*)
|
||||
* // where id in (?,?,?,?,?)
|
||||
*
|
||||
* // Note: the fetch of "details.product" is automatically included into the
|
||||
* // fetch of "details"
|
||||
* // Note: the fetch of "details.product" is automatically included into the
|
||||
* // fetch of "details"
|
||||
* //
|
||||
* // Note: the fetch of "customer.contacts" and "customer.shippingAddress"
|
||||
* // are automatically included in the fetch of "customer"
|
||||
* </pre>
|
||||
* // Note: the fetch of "customer.contacts" and "customer.shippingAddress"
|
||||
* // are automatically included in the fetch of "customer"
|
||||
* }</pre>
|
||||
* <p>
|
||||
* You can use query() and lazy together on a single join. The query is executed
|
||||
* immediately and the lazy defines the batch size to use for further lazy
|
||||
* loading (if lazy loading is invoked).
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* List<Order> list =
|
||||
* <pre>{@code
|
||||
* List<Order> list =
|
||||
* Ebean.find(Order.class)
|
||||
* .fetch("customer", new FetchConfig().query(10).lazy(5))
|
||||
* .fetch("customer", new FetchConfig().query(10).lazy(5))
|
||||
* .findList();
|
||||
*
|
||||
* // query 1) find order
|
||||
@@ -104,7 +104,7 @@ import java.io.Serializable;
|
||||
* // .. then if lazy loading of customers is invoked
|
||||
* // .. use a batch size of 5 to load the customers
|
||||
*
|
||||
* </pre>
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* Example of controlling the lazy loading query:
|
||||
@@ -114,12 +114,12 @@ import java.io.Serializable;
|
||||
* case.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* List<Order> list = Ebean.find(Order.class)
|
||||
* .fetch("customer","name", new FetchConfig().lazy(5))
|
||||
* .fetch("customer.contacts","contactName, phone, email")
|
||||
* .fetch("customer.shippingAddress")
|
||||
* .where().eq("status",Order.Status.NEW)
|
||||
* <pre>{@code
|
||||
* List<Order> list = Ebean.find(Order.class)
|
||||
* .fetch("customer","name", new FetchConfig().lazy(5))
|
||||
* .fetch("customer.contacts","contactName, phone, email")
|
||||
* .fetch("customer.shippingAddress")
|
||||
* .where().eq("status",Order.Status.NEW)
|
||||
* .findList();
|
||||
*
|
||||
* // query 1) find order where status = Order.Status.NEW
|
||||
@@ -132,7 +132,7 @@ import java.io.Serializable;
|
||||
* fetch customer.shippingAddress (*)
|
||||
* where id in (?,?,?,?,?)
|
||||
*
|
||||
* </pre>
|
||||
* }</pre>
|
||||
*
|
||||
* @author mario
|
||||
* @author rbygrave
|
||||
|
||||
@@ -2,14 +2,13 @@ package com.avaje.ebean;
|
||||
|
||||
import com.avaje.ebean.text.PathProperties;
|
||||
import com.avaje.ebean.util.ClassUtil;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* A MappedSuperclass base class that provides convenience methods for inserting, updating and
|
||||
@@ -152,7 +151,7 @@ public abstract class Model {
|
||||
* }</pre>
|
||||
*/
|
||||
public static EbeanServer db() {
|
||||
return Ebean.getServer(null);
|
||||
return Ebean.getDefaultServer();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -451,8 +450,8 @@ public abstract class Model {
|
||||
* Construct passing the class literal type of the entity type.
|
||||
*/
|
||||
protected Find(String serverName, Class<T> type) {
|
||||
this.type = type;
|
||||
this.serverName = serverName;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -514,6 +513,7 @@ public abstract class Model {
|
||||
* <p>
|
||||
* Equivalent to {@link EbeanServer#find(Class, Object)}
|
||||
*/
|
||||
@Nullable
|
||||
public T byId(I id) {
|
||||
return db().find(type, id);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ class PrimaryServer {
|
||||
/**
|
||||
* Return the default server name.
|
||||
*/
|
||||
static synchronized String getPrimaryServerName() {
|
||||
static synchronized String getDefaultServerName() {
|
||||
getProperties();
|
||||
return defaultServerName;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import com.avaje.ebean.text.PathProperties;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -284,6 +286,17 @@ public interface Query<T> extends Serializable {
|
||||
*/
|
||||
Query<T> setRawSql(RawSql rawSql);
|
||||
|
||||
/**
|
||||
* Perform an 'As of' query using history tables to return the object graph
|
||||
* as of a time in the past.
|
||||
* <p>
|
||||
* To perform this query the DB must have underlying history tables.
|
||||
* </p>
|
||||
*
|
||||
* @param asOf the date time in the past at which you want to view the data
|
||||
*/
|
||||
Query<T> asOf(Timestamp asOf);
|
||||
|
||||
/**
|
||||
* Cancel the query execution if supported by the underlying database and
|
||||
* driver.
|
||||
@@ -483,7 +496,7 @@ public interface Query<T> extends Serializable {
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
Query<T> fetch(String path, FetchConfig joinConfig);
|
||||
Query<T> fetch(String path, FetchConfig fetchConfig);
|
||||
|
||||
/**
|
||||
* Apply the path properties replacing the select and fetch clauses.
|
||||
@@ -520,19 +533,7 @@ public interface Query<T> extends Serializable {
|
||||
*/
|
||||
QueryIterator<T> findIterate();
|
||||
|
||||
/**
|
||||
* This is deprecated in favor of #findEachWhile.
|
||||
* <p>
|
||||
* This is functionally exactly the same as #findEachWhile. It is
|
||||
* replaced by findEachWhile because the method name is much better.
|
||||
* </p>
|
||||
*
|
||||
* @param visitor
|
||||
* the visitor used to process the queried beans.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
void findVisit(QueryResultVisitor<T> visitor);
|
||||
|
||||
|
||||
/**
|
||||
* Execute the query processing the beans one at a time.
|
||||
@@ -716,8 +717,18 @@ public interface Query<T> extends Serializable {
|
||||
* ...
|
||||
* }</pre>
|
||||
*/
|
||||
@Nullable
|
||||
T findUnique();
|
||||
|
||||
/**
|
||||
* Return versions of a @History entity bean.
|
||||
* <p>
|
||||
* Generally this query is expected to be a find by id or unique predicates query.
|
||||
* It will execute the query against the history returning the versions of the bean.
|
||||
* </p>
|
||||
*/
|
||||
List<Version<T>> findVersions();
|
||||
|
||||
/**
|
||||
* Return the count of entities this query should return.
|
||||
* <p>
|
||||
@@ -878,6 +889,11 @@ public interface Query<T> extends Serializable {
|
||||
*/
|
||||
Query<T> setId(Object id);
|
||||
|
||||
/**
|
||||
* Return the Id value.
|
||||
*/
|
||||
Object getId();
|
||||
|
||||
/**
|
||||
* Add additional clause(s) to the where clause.
|
||||
* <p>
|
||||
@@ -1123,8 +1139,8 @@ public interface Query<T> extends Serializable {
|
||||
|
||||
/**
|
||||
* Set the first row to return for this query.
|
||||
*
|
||||
* @param firstRow
|
||||
*
|
||||
* @param firstRow the first row to include in the query result.
|
||||
*/
|
||||
Query<T> setFirstRow(int firstRow);
|
||||
|
||||
@@ -1235,4 +1251,17 @@ public interface Query<T> extends Serializable {
|
||||
* Set root table alias.
|
||||
*/
|
||||
Query<T> alias(String alias);
|
||||
|
||||
/**
|
||||
* Return the type of beans being queried.
|
||||
*/
|
||||
Class<T> getBeanType();
|
||||
|
||||
/**
|
||||
* Set true if you want to disable lazy loading.
|
||||
* <p>
|
||||
* That is, once the object graph is returned further lazy loading is disabled.
|
||||
* </p>
|
||||
*/
|
||||
Query<T> setDisableLazyLoading(boolean disableLazyLoading);
|
||||
}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
/**
|
||||
* Used to process a query result one bean at a time via a callback to this
|
||||
* visitor.
|
||||
* <p>
|
||||
* If you wish to stop further processing return false from the accept method.
|
||||
* </p>
|
||||
* <p>
|
||||
* Unlike findList() and findSet() using a QueryResultVisitor does not require
|
||||
* all the beans in the query result to be held in memory at once. This makes
|
||||
* QueryResultVisitor useful for processing large queries.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
*
|
||||
* Query<Customer> query = server.find(Customer.class)
|
||||
* .fetch("contacts", new FetchConfig().query(2))
|
||||
* .where().gt("id", 0)
|
||||
* .orderBy("id")
|
||||
* .setMaxRows(2);
|
||||
*
|
||||
* query.findVisit(new QueryResultVisitor<Customer>() {
|
||||
*
|
||||
* public boolean accept(Customer customer) {
|
||||
* // do something with customer
|
||||
* System.out.println("-- visit " + customer);
|
||||
* return true;
|
||||
* }
|
||||
* });
|
||||
* </pre>
|
||||
*
|
||||
* @author rbygrave
|
||||
*
|
||||
* @param <T>
|
||||
* the type of entity bean being queried.
|
||||
*/
|
||||
public interface QueryResultVisitor<T> {
|
||||
|
||||
/**
|
||||
* Process the bean and return true if you want to continue processing more
|
||||
* beans. Return false if you want to stop processing further.
|
||||
*
|
||||
* @param bean
|
||||
* the entity bean to process
|
||||
* @return true to continue processing or false to stop.
|
||||
*/
|
||||
boolean accept(T bean);
|
||||
}
|
||||
@@ -480,6 +480,13 @@ public final class RawSql implements Serializable {
|
||||
this.queryHashCode = hc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the property is mapped.
|
||||
*/
|
||||
public boolean contains(String property) {
|
||||
return this.propertyColumnMap.containsKey(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an immutable copy of this ColumnMapping.
|
||||
*
|
||||
|
||||
@@ -97,6 +97,17 @@ public interface Transaction extends Closeable {
|
||||
*/
|
||||
void setPersistCascade(boolean persistCascade);
|
||||
|
||||
/**
|
||||
* Set to true when you want all loaded properties to be included in the update
|
||||
* (rather than just the changed properties).
|
||||
* <p>
|
||||
* You might set this when using JDBC batch in order to get multiple updates
|
||||
* with slightly different sets of changed properties into the same statement
|
||||
* and hence better JDBC batch performance.
|
||||
* </p>
|
||||
*/
|
||||
void setUpdateAllLoadedProperties(boolean updateAllLoadedProperties);
|
||||
|
||||
/**
|
||||
* Turn on or off statement batching. Statement batching can be transparent
|
||||
* for drivers and databases that support getGeneratedKeys. Otherwise you may
|
||||
|
||||
@@ -5,10 +5,19 @@ package com.avaje.ebean;
|
||||
*/
|
||||
public class ValuePair {
|
||||
|
||||
private final Object newValue;
|
||||
protected Object newValue;
|
||||
|
||||
private final Object oldValue;
|
||||
protected Object oldValue;
|
||||
|
||||
/**
|
||||
* Default constructor for JSON tools.
|
||||
*/
|
||||
public ValuePair() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct with the pair of new and old values.
|
||||
*/
|
||||
public ValuePair(Object newValue, Object oldValue) {
|
||||
this.newValue = newValue;
|
||||
this.oldValue = oldValue;
|
||||
@@ -27,21 +36,19 @@ public class ValuePair {
|
||||
public Object getOldValue() {
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the new value.
|
||||
* Set the new value.
|
||||
*/
|
||||
@Deprecated
|
||||
public Object getValue1() {
|
||||
return newValue;
|
||||
public void setNewValue(Object newValue) {
|
||||
this.newValue = newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the old value.
|
||||
* Set the old value.
|
||||
*/
|
||||
@Deprecated
|
||||
public Object getValue2() {
|
||||
return oldValue;
|
||||
public void setOldValue(Object oldValue) {
|
||||
this.oldValue = oldValue;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Wraps a version of a @History bean.
|
||||
*/
|
||||
public class Version<T> {
|
||||
|
||||
/**
|
||||
* The version of the bean.
|
||||
*/
|
||||
protected T bean;
|
||||
|
||||
/**
|
||||
* The effective start date time of this version.
|
||||
*/
|
||||
protected Timestamp start;
|
||||
|
||||
/**
|
||||
* The effective end date time of this version.
|
||||
*/
|
||||
protected Timestamp end;
|
||||
|
||||
/**
|
||||
* The map of changed properties.
|
||||
*/
|
||||
protected Map<String, ValuePair> diff;
|
||||
|
||||
/**
|
||||
* Construct with bean and an effective date time range.
|
||||
*/
|
||||
public Version(T bean, Timestamp start, Timestamp end) {
|
||||
this.bean = bean;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor - useful for JSON tools such as Jackson.
|
||||
*/
|
||||
public Version() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bean instance for this version.
|
||||
*/
|
||||
public T getBean() {
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bean instance for this version.
|
||||
*/
|
||||
public void setBean(T bean) {
|
||||
this.bean = bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the effective start date time of this version.
|
||||
*/
|
||||
public Timestamp getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the effective start date time of this version.
|
||||
*/
|
||||
public void setStart(Timestamp start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the effective end date time of this version.
|
||||
*/
|
||||
public Timestamp getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the effective end date time of this version.
|
||||
*/
|
||||
public void setEnd(Timestamp end) {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the map of differences from this bean to the prior version.
|
||||
*/
|
||||
public void setDiff(Map<String, ValuePair> diff) {
|
||||
this.diff = diff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the map of differences from this bean to the prior version.
|
||||
*/
|
||||
public Map<String, ValuePair> getDiff() {
|
||||
return diff;
|
||||
}
|
||||
}
|
||||
@@ -44,4 +44,12 @@ public @interface CacheTuning {
|
||||
* </p>
|
||||
*/
|
||||
int maxSecsToLive() default 0;
|
||||
|
||||
/**
|
||||
* The frequency (in seconds) that cache trimming should occur.
|
||||
* <p>
|
||||
* This is a hint for cache implementations that use background cache trimming.
|
||||
* </p>
|
||||
*/
|
||||
int trimFrequency() default 0;
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Deprecated - please use @DbHstore instead.
|
||||
* @see DbHstore
|
||||
*/
|
||||
@Deprecated
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface ColumnHstore {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Marks an entity bean as having history support.
|
||||
* <p>
|
||||
* In Postgres for example this means there is an associated history table which is
|
||||
* typically automatically populated via database triggers.
|
||||
* </p>
|
||||
*/
|
||||
@Target({ ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface History {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Marks a property as being excluded from history.
|
||||
* <p>
|
||||
* This means the property values are not maintained in the history table. Typically this
|
||||
* would be placed on relatively large properties (Clobs, Blobs, large varchar columns etc)
|
||||
* that are considered not interesting enough to maintain history on excluding them reduces
|
||||
* underlying database costs.
|
||||
* </p>
|
||||
* <p>
|
||||
* When placed on a ManyToMany this means that the intersection table does not have history
|
||||
* support.
|
||||
* </p>
|
||||
*/
|
||||
@Target({ ElementType.FIELD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface HistoryExclude {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Similar to Jackson JsonIgnore but provides the option to just ignore serialize or deserialize.
|
||||
* <p>
|
||||
* This provides the same features as Expose but from the opposite perspective which is probably
|
||||
* more common and more familiar to Jackson users.
|
||||
* </p>
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface JsonIgnore {
|
||||
|
||||
/**
|
||||
* If {@code true}, the field marked with this annotation is written out in the JSON while
|
||||
* serializing. If {@code false}, the field marked with this annotation is skipped from the
|
||||
* serialized output. Defaults to {@code false}.
|
||||
*/
|
||||
boolean serialize() default false;
|
||||
|
||||
/**
|
||||
* If {@code true}, the field marked with this annotation is deserialized from the JSON.
|
||||
* If {@code false}, the field marked with this annotation is skipped during deserialization.
|
||||
* Defaults to {@code false}.
|
||||
*/
|
||||
boolean deserialize() default false;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* For a timestamp property that is set to the datetime when the entity is
|
||||
* created/inserted.
|
||||
* <p>
|
||||
* This is effectively an alias for @CreatedTimestamp and added to hint
|
||||
* towards a better naming convention (WhenCreated, WhenModified).
|
||||
* </p>
|
||||
* <p>
|
||||
* An alternative to using this annotation would be to use insertable=false,
|
||||
* updateable=false with @Column and have the DB insert the current time
|
||||
* (default value on the DB column is SYSTIME etc).
|
||||
* </p>
|
||||
* <p>
|
||||
* The downside to this approach is that the inserted entity does not have the
|
||||
* timestamp value after the insert has occurred. You need to fetch the entity
|
||||
* back to get the inserted timestamp if you want to used it.
|
||||
* </p>
|
||||
*
|
||||
* <h3>Example:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* @WhenCreated
|
||||
* Timestamp whenCreated;
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface WhenCreated {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* For a timestamp property that is set to the datetime when the entity was last modified.
|
||||
* <p>
|
||||
* This is effectively an alias for @UpdatedTimestamp and added to hint
|
||||
* towards a better naming convention (WhenCreated, WhenModified).
|
||||
* </p>
|
||||
* </p>
|
||||
*/
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface WhenModified {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Mapped onto a entity bean property that represents the user id of
|
||||
* who created the entity>
|
||||
* <p>
|
||||
* To use this annotation you need to implement CurrentUserProvider.
|
||||
* The type of the bean property should match the type returned by
|
||||
* CurrentUserProvider.
|
||||
*</p>
|
||||
|
||||
* <h3>Example:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* @WhoCreated
|
||||
* String whoCreated;
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@Target({ ElementType.FIELD, ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface WhoCreated {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.avaje.ebean.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Mapped onto a entity bean property that represents the user id of
|
||||
* who last modified the entity>
|
||||
* <p>
|
||||
* To use this annotation you need to implement CurrentUserProvider.
|
||||
* The type of the bean property should match the type returned by
|
||||
* CurrentUserProvider.
|
||||
* </p>
|
||||
*
|
||||
* <h3>Example:</h3>
|
||||
* <pre>{@code
|
||||
*
|
||||
* @WhoModified
|
||||
* String whoModified;
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface WhoModified {
|
||||
|
||||
}
|
||||
@@ -608,7 +608,7 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
} else if (embeddedDirty != null && embeddedDirty[i]) {
|
||||
// an embedded property has been changed - recurse
|
||||
EntityBean embeddedBean = (EntityBean)owner._ebean_getField(i);
|
||||
embeddedBean._ebean_getIntercept().addDirtyPropertyValues(dirtyValues, getProperty(i)+".");
|
||||
embeddedBean._ebean_getIntercept().addDirtyPropertyValues(dirtyValues, getProperty(i) + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -638,6 +638,20 @@ public final class EntityBeanIntercept implements Serializable {
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a loaded property hash.
|
||||
*/
|
||||
public int getLoadedPropertyHash() {
|
||||
int hash = 37;
|
||||
int len = getPropertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (isLoadedProperty(i)) {
|
||||
hash = hash * 31 + (i+1);
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the set of property names for changed properties.
|
||||
*/
|
||||
|
||||
@@ -48,12 +48,6 @@ public interface ServerCache {
|
||||
*/
|
||||
Object put(Object id, Object value);
|
||||
|
||||
/**
|
||||
* Put the value in the cache but only if a matching value is not already in
|
||||
* the cache.
|
||||
*/
|
||||
Object putIfAbsent(Object id, Object value);
|
||||
|
||||
/**
|
||||
* Remove a entry from the cache given its id.
|
||||
*/
|
||||
|
||||
+24
-5
@@ -10,6 +10,7 @@ public class ServerCacheOptions {
|
||||
private int maxSize;
|
||||
private int maxIdleSecs;
|
||||
private int maxSecsToLive;
|
||||
private int trimFrequency;
|
||||
|
||||
/**
|
||||
* Construct with no set options.
|
||||
@@ -25,15 +26,17 @@ public class ServerCacheOptions {
|
||||
this.maxSize = cacheTuning.maxSize();
|
||||
this.maxIdleSecs = cacheTuning.maxIdleSecs();
|
||||
this.maxSecsToLive = cacheTuning.maxSecsToLive();
|
||||
this.trimFrequency = cacheTuning.trimFrequency();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create merging default options with the deployment specified ones.
|
||||
*/
|
||||
public ServerCacheOptions(ServerCacheOptions d) {
|
||||
this.maxSize = d.getMaxSize();
|
||||
this.maxIdleSecs = d.getMaxIdleSecs();
|
||||
this.maxSecsToLive = d.getMaxIdleSecs();
|
||||
public ServerCacheOptions(ServerCacheOptions defaults) {
|
||||
this.maxSize = defaults.getMaxSize();
|
||||
this.maxIdleSecs = defaults.getMaxIdleSecs();
|
||||
this.maxSecsToLive = defaults.getMaxIdleSecs();
|
||||
this.trimFrequency = defaults.getTrimFrequency();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,6 +53,9 @@ public class ServerCacheOptions {
|
||||
if (maxSecsToLive == 0) {
|
||||
maxSecsToLive = defaults.getMaxSecsToLive();
|
||||
}
|
||||
if (trimFrequency == 0) {
|
||||
trimFrequency = defaults.getTrimFrequency();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,7 +67,7 @@ public class ServerCacheOptions {
|
||||
copy.maxSize = maxSize;
|
||||
copy.maxIdleSecs = maxIdleSecs;
|
||||
copy.maxSecsToLive = maxSecsToLive;
|
||||
|
||||
copy.trimFrequency = trimFrequency;
|
||||
return copy;
|
||||
}
|
||||
|
||||
@@ -107,4 +113,17 @@ public class ServerCacheOptions {
|
||||
this.maxSecsToLive = maxSecsToLive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the trim frequency in seconds.
|
||||
*/
|
||||
public int getTrimFrequency() {
|
||||
return trimFrequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the trim frequency in seconds.
|
||||
*/
|
||||
public void setTrimFrequency(int trimFrequency) {
|
||||
this.trimFrequency = trimFrequency;
|
||||
}
|
||||
}
|
||||
|
||||
+175
-23
@@ -5,9 +5,9 @@ package com.avaje.ebean.cache;
|
||||
* <p>
|
||||
* These can be monitored to review the effectiveness of a particular cache.
|
||||
* </p>
|
||||
*
|
||||
* @author rbygrave
|
||||
*
|
||||
* <p>
|
||||
* Depending on the cache implementation not all the statistics may be collected.
|
||||
* </p>
|
||||
*/
|
||||
public class ServerCacheStatistics {
|
||||
|
||||
@@ -17,21 +17,63 @@ public class ServerCacheStatistics {
|
||||
|
||||
protected int size;
|
||||
|
||||
protected int hitCount;
|
||||
protected long hitCount;
|
||||
|
||||
protected int missCount;
|
||||
protected long missCount;
|
||||
|
||||
protected long insertCount;
|
||||
|
||||
protected long updateCount;
|
||||
|
||||
protected long removeCount;
|
||||
|
||||
protected long clearCount;
|
||||
|
||||
protected long evictionRunCount;
|
||||
|
||||
protected long evictionRunMicros;
|
||||
|
||||
protected long evictByIdle;
|
||||
|
||||
protected long evictByTTL;
|
||||
|
||||
protected long evictByLRU;
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(cacheName);
|
||||
sb.append(" maxSize:").append(maxSize);
|
||||
sb.append(" size:").append(size);
|
||||
sb.append(" hitRatio:").append(getHitRatio());
|
||||
sb.append(" hitCount:").append(hitCount);
|
||||
sb.append(" missCount:").append(missCount);
|
||||
sb.append(" maxSize:").append(maxSize);
|
||||
sb.append(" hit:").append(hitCount);
|
||||
sb.append(" miss:").append(missCount);
|
||||
sb.append(" insert:").append(insertCount);
|
||||
sb.append(" update:").append(updateCount);
|
||||
sb.append(" remove:").append(removeCount);
|
||||
sb.append(" clear:").append(clearCount);
|
||||
sb.append(" evictByIdle:").append(evictByIdle);
|
||||
sb.append(" evictByTTL:").append(evictByTTL);
|
||||
sb.append(" evictByLRU:").append(evictByLRU);
|
||||
sb.append(" evictionRunCount:").append(evictionRunCount);
|
||||
sb.append(" evictionRunMicros:").append(evictionRunMicros);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an int from 0 to 100 (percentage) for the hit ratio.
|
||||
* <p>
|
||||
* A hit ratio of 100 means every get request against the cache hits an entry.
|
||||
* </p>
|
||||
*/
|
||||
public int getHitRatio() {
|
||||
long totalCount = hitCount + missCount;
|
||||
if (totalCount == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return (int)(hitCount * 100 / totalCount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the cache.
|
||||
*/
|
||||
@@ -49,28 +91,28 @@ public class ServerCacheStatistics {
|
||||
/**
|
||||
* Return the hit count. The number of successful gets.
|
||||
*/
|
||||
public int getHitCount() {
|
||||
public long getHitCount() {
|
||||
return hitCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the hit count.
|
||||
*/
|
||||
public void setHitCount(int hitCount) {
|
||||
public void setHitCount(long hitCount) {
|
||||
this.hitCount = hitCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the miss count. The number of gets that returned null.
|
||||
*/
|
||||
public int getMissCount() {
|
||||
public long getMissCount() {
|
||||
return missCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the miss count.
|
||||
*/
|
||||
public void setMissCount(int missCount) {
|
||||
public void setMissCount(long missCount) {
|
||||
this.missCount = missCount;
|
||||
}
|
||||
|
||||
@@ -107,18 +149,128 @@ public class ServerCacheStatistics {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an int from 0 to 100 (percentage) for the hit ratio.
|
||||
* <p>
|
||||
* A hit ratio of 100 means every get request against the cache hits an entry.
|
||||
* </p>
|
||||
* Set the put insert count.
|
||||
*/
|
||||
public int getHitRatio() {
|
||||
int totalCount = hitCount + missCount;
|
||||
if (totalCount == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return hitCount * 100 / totalCount;
|
||||
}
|
||||
public void setInsertCount(long insertCount) {
|
||||
this.insertCount = insertCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the put insert count.
|
||||
*/
|
||||
public long getInsertCount() {
|
||||
return insertCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the put update count.
|
||||
*/
|
||||
public void setUpdateCount(long updateCount) {
|
||||
this.updateCount = updateCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the put update count.
|
||||
*/
|
||||
public long getUpdateCount() {
|
||||
return updateCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the remove count.
|
||||
*/
|
||||
public void setRemoveCount(long removeCount) {
|
||||
this.removeCount = removeCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the remove count.
|
||||
*/
|
||||
public long getRemoveCount() {
|
||||
return removeCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the clear count.
|
||||
*/
|
||||
public void setClearCount(long clearCount) {
|
||||
this.clearCount = clearCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the clear count.
|
||||
*/
|
||||
public long getClearCount() {
|
||||
return clearCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the eviction run count.
|
||||
*/
|
||||
public void setEvictionRunCount(long evictCount) {
|
||||
this.evictionRunCount = evictCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the eviction run count.
|
||||
*/
|
||||
public long getEvictionRunCount() {
|
||||
return evictionRunCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the eviction run time in micros.
|
||||
*/
|
||||
public void setEvictionRunMicros(long evictionRunMicros) {
|
||||
this.evictionRunMicros = evictionRunMicros;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the eviction run time in micros.
|
||||
*/
|
||||
public long getEvictionRunMicros() {
|
||||
return evictionRunMicros;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the count of entries evicted due to idle time.
|
||||
*/
|
||||
public void setEvictByIdle(long evictByIdle) {
|
||||
this.evictByIdle = evictByIdle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of entries evicted due to idle time.
|
||||
*/
|
||||
public long getEvictByIdle() {
|
||||
return evictByIdle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the count of entries evicted due to time to live.
|
||||
*/
|
||||
public void setEvictByTTL(long evictByTTL) {
|
||||
this.evictByTTL = evictByTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of entries evicted due to time to live.
|
||||
*/
|
||||
public long getEvictByTTL() {
|
||||
return evictByTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the count of entries evicted due to time least recently used.
|
||||
*/
|
||||
public void setEvictByLRU(long evictByLRU) {
|
||||
this.evictByLRU = evictByLRU;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of entries evicted due to time least recently used.
|
||||
*/
|
||||
public long getEvictByLRU() {
|
||||
return evictByLRU;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.avaje.ebean.config;
|
||||
|
||||
/**
|
||||
* Provides the current user in order to support 'Who created', 'Who modified' and other audit features.
|
||||
*/
|
||||
public interface CurrentUserProvider {
|
||||
|
||||
/**
|
||||
* Return the current user id.
|
||||
* <p>
|
||||
* The type returned should match the type of the properties annotated
|
||||
* with @WhoCreated and @WhoModified. These are typically String, Long or UUID.
|
||||
* </p>
|
||||
*/
|
||||
Object currentUser();
|
||||
}
|
||||
@@ -26,4 +26,22 @@ public abstract class JsonConfig {
|
||||
ISO8601
|
||||
}
|
||||
|
||||
|
||||
public enum Include {
|
||||
|
||||
/**
|
||||
* Include all values including null and empty collections.
|
||||
*/
|
||||
ALL,
|
||||
|
||||
/**
|
||||
* Exclude null values (include empty collections).
|
||||
*/
|
||||
NON_NULL,
|
||||
|
||||
/**
|
||||
* Exclude null values and empty collections.
|
||||
*/
|
||||
NON_EMPTY
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,6 +113,12 @@ public class ServerConfig {
|
||||
*/
|
||||
private String classPathReaderClassName;
|
||||
|
||||
/**
|
||||
* This is used to populate @WhoCreated, @WhoModified and
|
||||
* support other audit features (who executed a query etc).
|
||||
*/
|
||||
private CurrentUserProvider currentUserProvider;
|
||||
|
||||
/**
|
||||
* Config controlling the autofetch behaviour.
|
||||
*/
|
||||
@@ -123,6 +129,12 @@ public class ServerConfig {
|
||||
*/
|
||||
private JsonConfig.DateTime jsonDateTime = JsonConfig.DateTime.MILLIS;
|
||||
|
||||
/**
|
||||
* For writing JSON specify if null values or empty collections should be exluded.
|
||||
* By default all values are included.
|
||||
*/
|
||||
private JsonConfig.Include jsonInclude = JsonConfig.Include.ALL;
|
||||
|
||||
/**
|
||||
* The database platform name. Used to imply a DatabasePlatform to use.
|
||||
*/
|
||||
@@ -138,6 +150,18 @@ public class ServerConfig {
|
||||
*/
|
||||
private int databaseSequenceBatchSize = 20;
|
||||
|
||||
/**
|
||||
* Suffix appended to the base table to derive the view that contains the union
|
||||
* of the base table and the history table in order to support asOf queries.
|
||||
*/
|
||||
private String asOfViewSuffix = "_with_history";
|
||||
|
||||
/**
|
||||
* Column used to support history and 'As of' queries. This column is a timestamp range
|
||||
* or equivalent.
|
||||
*/
|
||||
private String asOfSysPeriod = "sys_period";
|
||||
|
||||
/**
|
||||
* Use for transaction scoped batch mode.
|
||||
*/
|
||||
@@ -219,7 +243,12 @@ public class ServerConfig {
|
||||
* Behaviour of update to include on the change properties.
|
||||
*/
|
||||
private boolean updateChangesOnly = true;
|
||||
|
||||
|
||||
/**
|
||||
* Behaviour of updates in JDBC batch to by default include all properties.
|
||||
*/
|
||||
private boolean updateAllPropertiesInBatch = true;
|
||||
|
||||
/**
|
||||
* Default behaviour for updates when cascade save on a O2M or M2M to delete any missing children.
|
||||
*/
|
||||
@@ -231,6 +260,7 @@ public class ServerConfig {
|
||||
private boolean uuidStoreAsBinary;
|
||||
|
||||
|
||||
private List<BeanFindController> findControllers = new ArrayList<BeanFindController>();
|
||||
private List<BeanPersistController> persistControllers = new ArrayList<BeanPersistController>();
|
||||
private List<BeanPersistListener> persistListeners = new ArrayList<BeanPersistListener>();
|
||||
private List<BeanQueryAdapter> queryAdapters = new ArrayList<BeanQueryAdapter>();
|
||||
@@ -292,6 +322,12 @@ public class ServerConfig {
|
||||
private int queryCacheMaxIdleTime = 600;
|
||||
private int queryCacheMaxTimeToLive = 60*60*6;
|
||||
private Object objectMapper;
|
||||
private boolean diffFlatMode;
|
||||
|
||||
/**
|
||||
* Set to true if you want eq("someProperty", null) to generate 1=1 rather than "is null" sql expression.
|
||||
*/
|
||||
private boolean expressionEqualsWithNullAsNoop;
|
||||
|
||||
/**
|
||||
* Construct a Server Configuration for programmatically creating an EbeanServer.
|
||||
@@ -303,7 +339,7 @@ public class ServerConfig {
|
||||
/**
|
||||
* Return the Jackson JsonFactory to use.
|
||||
* <p>
|
||||
* If not set a default implmentation will be used.
|
||||
* If not set a default implementation will be used.
|
||||
*/
|
||||
public JsonFactory getJsonFactory() {
|
||||
return jsonFactory;
|
||||
@@ -312,7 +348,7 @@ public class ServerConfig {
|
||||
/**
|
||||
* Set the Jackson JsonFactory to use.
|
||||
* <p>
|
||||
* If not set a default implmentation will be used.
|
||||
* If not set a default implementation will be used.
|
||||
*/
|
||||
public void setJsonFactory(JsonFactory jsonFactory) {
|
||||
this.jsonFactory = jsonFactory;
|
||||
@@ -332,6 +368,23 @@ public class ServerConfig {
|
||||
this.jsonDateTime = jsonDateTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the JSON include mode used when writing JSON.
|
||||
*/
|
||||
public JsonConfig.Include getJsonInclude() {
|
||||
return jsonInclude;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JSON include mode used when writing JSON.
|
||||
* <p>
|
||||
* Set to NON_NULL or NON_EMPTY to suppress nulls or null & empty collections respectively.
|
||||
* </p>
|
||||
*/
|
||||
public void setJsonInclude(JsonConfig.Include jsonInclude) {
|
||||
this.jsonInclude = jsonInclude;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the EbeanServer.
|
||||
*/
|
||||
@@ -410,6 +463,22 @@ public class ServerConfig {
|
||||
this.defaultServer = defaultServer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the CurrentUserProvider. This is used to populate @WhoCreated, @WhoModified and
|
||||
* support other audit features (who executed a query etc).
|
||||
*/
|
||||
public CurrentUserProvider getCurrentUserProvider() {
|
||||
return currentUserProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the CurrentUserProvider. This is used to populate @WhoCreated, @WhoModified and
|
||||
* support other audit features (who executed a query etc).
|
||||
*/
|
||||
public void setCurrentUserProvider(CurrentUserProvider currentUserProvider) {
|
||||
this.currentUserProvider = currentUserProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the PersistBatch mode to use by default at the transaction level.
|
||||
* <p>
|
||||
@@ -555,6 +624,38 @@ public class ServerConfig {
|
||||
this.databaseSequenceBatchSize = databaseSequenceBatchSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the suffix appended to the base table to derive the view that contains the union
|
||||
* of the base table and the history table in order to support asOf queries.
|
||||
*/
|
||||
public String getAsOfViewSuffix() {
|
||||
return asOfViewSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the suffix appended to the base table to derive the view that contains the union
|
||||
* of the base table and the history table in order to support asOf queries.
|
||||
*/
|
||||
public void setAsOfViewSuffix(String asOfViewSuffix) {
|
||||
this.asOfViewSuffix = asOfViewSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the database column used to support history and 'As of' queries. This column is a timestamp range
|
||||
* or equivalent.
|
||||
*/
|
||||
public String getAsOfSysPeriod() {
|
||||
return asOfSysPeriod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the database column used to support history and 'As of' queries. This column is a timestamp range
|
||||
* or equivalent.
|
||||
*/
|
||||
public void setAsOfSysPeriod(String asOfSysPeriod) {
|
||||
this.asOfSysPeriod = asOfSysPeriod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if we are running in a JTA Transaction manager.
|
||||
*/
|
||||
@@ -1425,7 +1526,26 @@ public class ServerConfig {
|
||||
public void setUpdateChangesOnly(boolean updateChangesOnly) {
|
||||
this.updateChangesOnly = updateChangesOnly;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if updates in JDBC batch default to include all properties by default.
|
||||
*/
|
||||
public boolean isUpdateAllPropertiesInBatch() {
|
||||
return updateAllPropertiesInBatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to false if by default updates in JDBC batch should not include all properties.
|
||||
* <p>
|
||||
* This mode can be explicitly set per transaction.
|
||||
* </p>
|
||||
*
|
||||
* @see com.avaje.ebean.Transaction#setUpdateAllLoadedProperties(boolean)
|
||||
*/
|
||||
public void setUpdateAllPropertiesInBatch(boolean updateAllPropertiesInBatch) {
|
||||
this.updateAllPropertiesInBatch = updateAllPropertiesInBatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if updates by default delete missing children when cascading save to a OneToMany or
|
||||
* ManyToMany. When not set this defaults to true.
|
||||
@@ -1540,6 +1660,14 @@ public class ServerConfig {
|
||||
persistControllers.add(beanPersistController);
|
||||
}
|
||||
|
||||
public List<BeanFindController> getFindControllers() {
|
||||
return findControllers;
|
||||
}
|
||||
|
||||
public void setFindControllers(List<BeanFindController> findControllers) {
|
||||
this.findControllers = findControllers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BeanPersistController instances.
|
||||
*/
|
||||
@@ -1736,6 +1864,7 @@ public class ServerConfig {
|
||||
autoCommitMode = p.getBoolean("autoCommitMode", autoCommitMode);
|
||||
useJtaTransactionManager = p.getBoolean("useJtaTransactionManager", useJtaTransactionManager);
|
||||
|
||||
currentUserProvider = createInstance(p, CurrentUserProvider.class, "currentUserProvider");
|
||||
disableClasspathSearch = p.getBoolean("disableClasspathSearch", disableClasspathSearch);
|
||||
databasePlatform = createInstance(p, DatabasePlatform.class, "databasePlatform");
|
||||
encryptKeyManager = createInstance(p, EncryptKeyManager.class, "encryptKeyManager");
|
||||
@@ -1760,6 +1889,7 @@ public class ServerConfig {
|
||||
collectQueryStatsByNode = p.getBoolean("collectQueryStatsByNode", collectQueryStatsByNode);
|
||||
collectQueryOrigins = p.getBoolean("collectQueryOrigins", collectQueryOrigins);
|
||||
|
||||
updateAllPropertiesInBatch = p.getBoolean("updateAllPropertiesInBatch", updateAllPropertiesInBatch);
|
||||
updateChangesOnly = p.getBoolean("updateChangesOnly", updateChangesOnly);
|
||||
|
||||
boolean defaultDeleteMissingChildren = p.getBoolean("defaultDeleteMissingChildren", updatesDeleteMissingChildren);
|
||||
@@ -1775,8 +1905,12 @@ public class ServerConfig {
|
||||
int batchSize = p.getInt("batch.size", persistBatchSize);
|
||||
persistBatchSize = p.getInt("persistBatchSize", batchSize);
|
||||
|
||||
persistenceContextScope = PersistenceContextScope.valueOf(p.get("persistenceContextScope","TRANSACTION"));
|
||||
persistenceContextScope = PersistenceContextScope.valueOf(p.get("persistenceContextScope", "TRANSACTION"));
|
||||
|
||||
expressionEqualsWithNullAsNoop = p.getBoolean("expressionEqualsWithNullAsNoop", expressionEqualsWithNullAsNoop);
|
||||
diffFlatMode = p.getBoolean("diffFlatMode", diffFlatMode);
|
||||
asOfViewSuffix = p.get("asOfViewSuffix", asOfViewSuffix);
|
||||
asOfSysPeriod = p.get("asOfSysPeriod", asOfSysPeriod);
|
||||
dataSourceJndiName = p.get("dataSourceJndiName", dataSourceJndiName);
|
||||
databaseSequenceBatchSize = p.getInt("databaseSequenceBatchSize", databaseSequenceBatchSize);
|
||||
databaseBooleanTrue = p.get("databaseBooleanTrue", databaseBooleanTrue);
|
||||
@@ -1788,6 +1922,7 @@ public class ServerConfig {
|
||||
lazyLoadBatchSize = p.getInt("lazyLoadBatchSize", lazyLoadBatchSize);
|
||||
queryBatchSize = p.getInt("queryBatchSize", queryBatchSize);
|
||||
|
||||
jsonInclude = p.getEnum(JsonConfig.Include.class, "jsonInclude", jsonInclude);
|
||||
String jsonDateTimeFormat = p.get("jsonDateTime", null);
|
||||
if (jsonDateTimeFormat != null) {
|
||||
jsonDateTime = JsonConfig.DateTime.valueOf(jsonDateTimeFormat);
|
||||
@@ -1819,8 +1954,7 @@ public class ServerConfig {
|
||||
|
||||
String classNames = properties.get("classes", null);
|
||||
if (classNames == null) {
|
||||
|
||||
return null;
|
||||
return classes;
|
||||
}
|
||||
|
||||
List<Class<?>> classes = new ArrayList<Class<?>>();
|
||||
@@ -1866,11 +2000,58 @@ public class ServerConfig {
|
||||
return databasePlatform.isDisallowBatchOnCascade() ? PersistBatch.NONE : persistBatchOnCascade;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Jackson ObjectMapper.
|
||||
* <p>
|
||||
* Note that this is not strongly typed as Jackson ObjectMapper is an optional dependency.
|
||||
* </p>
|
||||
*/
|
||||
public Object getObjectMapper() {
|
||||
return objectMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Jackson ObjectMapper.
|
||||
* <p>
|
||||
* Note that this is not strongly typed as Jackson ObjectMapper is an optional dependency.
|
||||
* </p>
|
||||
*/
|
||||
public void setObjectMapper(Object objectMapper) {
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if diff should return flat properties with dot notation rather than
|
||||
* embedded beans or reference beans (when the associated bean id is different).
|
||||
*/
|
||||
public boolean isDiffFlatMode() {
|
||||
return diffFlatMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if diff should return flat properties with dot notation rather than
|
||||
* embedded beans or reference beans (when the associated bean id is different).
|
||||
*/
|
||||
public void setDiffFlatMode(boolean diffFlatMode) {
|
||||
this.diffFlatMode = diffFlatMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if eq("someProperty", null) should to generate "1=1" rather than "is null" sql expression.
|
||||
*/
|
||||
public boolean isExpressionEqualsWithNullAsNoop() {
|
||||
return expressionEqualsWithNullAsNoop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if you want eq("someProperty", null) to generate "1=1" rather than "is null" sql expression.
|
||||
* <p>
|
||||
* Setting this to true has the effect that eq(propertyName, value), ieq(propertyName, value) and
|
||||
* ne(propertyName, value) have no effect when the value is null. The expression factory adds a NoopExpression
|
||||
* which will add "1=1" into the SQL rather than "is null".
|
||||
* </p>
|
||||
*/
|
||||
public void setExpressionEqualsWithNullAsNoop(boolean expressionEqualsWithNullAsNoop) {
|
||||
this.expressionEqualsWithNullAsNoop = expressionEqualsWithNullAsNoop;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,11 @@ public class DatabasePlatform {
|
||||
*/
|
||||
protected DbIdentity dbIdentity = new DbIdentity();
|
||||
|
||||
/**
|
||||
* The history support for this database platform.
|
||||
*/
|
||||
protected DbHistorySupport historySupport;
|
||||
|
||||
/**
|
||||
* The JDBC type to map booleans to (by default).
|
||||
*/
|
||||
@@ -215,6 +220,20 @@ public class DatabasePlatform {
|
||||
this.dbEncrypt = dbEncrypt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the history support for this database platform.
|
||||
*/
|
||||
public DbHistorySupport getHistorySupport() {
|
||||
return historySupport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the history support for this database platform.
|
||||
*/
|
||||
public void setHistorySupport(DbHistorySupport historySupport) {
|
||||
this.historySupport = historySupport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mapping of JDBC to DB types.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.avaje.ebean.config.dbplatform;
|
||||
|
||||
/**
|
||||
* History support for the database platform.
|
||||
*/
|
||||
public interface DbHistorySupport {
|
||||
|
||||
/**
|
||||
* Return the 'as of' predicate added for the given table alias.
|
||||
*
|
||||
* @param tableAlias The table alias this predicate is added for
|
||||
* @param sysPeriod The name of the 'sys_period' column used for effective date time range.
|
||||
* @return The predicate containing a single ? bind parameter which will be bound to the 'as at' timestamp value
|
||||
*/
|
||||
String getAsOfPredicate(String tableAlias, String sysPeriod);
|
||||
|
||||
/**
|
||||
* Return the column for the system period lower bound that will be included in findVersions() queries.
|
||||
*
|
||||
* @param tableAlias the table alias which will typically be 't0'
|
||||
* @param sysPeriod the name of the sys_period column
|
||||
*/
|
||||
String getSysPeriodLower(String tableAlias, String sysPeriod);
|
||||
|
||||
/**
|
||||
* Return the column for the system period upper bound that will be included in findVersions() queries.
|
||||
*
|
||||
* @param tableAlias the table alias which will typically be 't0'
|
||||
* @param sysPeriod the name of the sys_period column
|
||||
*/
|
||||
String getSysPeriodUpper(String tableAlias, String sysPeriod);
|
||||
|
||||
}
|
||||
@@ -21,6 +21,7 @@ public class Postgres8Platform extends DatabasePlatform {
|
||||
this.clobDbType = Types.VARCHAR;
|
||||
|
||||
this.dbEncrypt = new PostgresDbEncrypt();
|
||||
this.historySupport = new PostgresHistorySupport();
|
||||
|
||||
this.dbIdentity.setSupportsGetGeneratedKeys(false);
|
||||
this.dbIdentity.setIdType(IdType.SEQUENCE);
|
||||
@@ -47,15 +48,13 @@ public class Postgres8Platform extends DatabasePlatform {
|
||||
|
||||
dbDdlSyntax.setDropTableCascade("cascade");
|
||||
dbDdlSyntax.setDropIfExists("if exists");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Postgres specific sequence IdGenerator.
|
||||
*/
|
||||
@Override
|
||||
public IdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds,
|
||||
String seqName, int batchSize) {
|
||||
public IdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
|
||||
|
||||
return new PostgresSequenceIdGenerator(be, ds, seqName, batchSize);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.avaje.ebean.config.dbplatform;
|
||||
|
||||
/**
|
||||
* Postgres support for history features.
|
||||
*/
|
||||
public class PostgresHistorySupport implements DbHistorySupport {
|
||||
|
||||
/**
|
||||
* Build and return the 'as of' predicate for a given table alias.
|
||||
* <p>
|
||||
* Each @History entity involved in the query has this predicate added using the related table alias.
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
public String getAsOfPredicate(String asOfTableAlias, String asOfSysPeriod) {
|
||||
|
||||
// for Postgres we are using the 'timestamp with timezone range' data type
|
||||
// as our sys_period column so hence the predicate below
|
||||
StringBuilder sb = new StringBuilder(40);
|
||||
sb.append(asOfTableAlias).append(".").append(asOfSysPeriod).append(" @> ?::timestamptz");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSysPeriodLower(String tableAlias, String sysPeriod) {
|
||||
return "lower("+tableAlias+"."+sysPeriod+")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSysPeriodUpper(String tableAlias, String sysPeriod) {
|
||||
return "upper("+tableAlias+"."+sysPeriod+")";
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ public class PostgresPlatform extends DatabasePlatform {
|
||||
this.clobDbType = Types.VARCHAR;
|
||||
|
||||
this.dbEncrypt = new PostgresDbEncrypt();
|
||||
this.historySupport = new PostgresHistorySupport();
|
||||
|
||||
// Use Identity and getGeneratedKeys
|
||||
this.dbIdentity.setIdType(IdType.IDENTITY);
|
||||
@@ -57,15 +58,14 @@ public class PostgresPlatform extends DatabasePlatform {
|
||||
|
||||
dbDdlSyntax.setDropTableCascade("cascade");
|
||||
dbDdlSyntax.setDropIfExists("if exists");
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a Postgres specific sequence IdGenerator.
|
||||
*/
|
||||
@Override
|
||||
public IdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds,
|
||||
String seqName, int batchSize) {
|
||||
public IdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
|
||||
|
||||
return new PostgresSequenceIdGenerator(be, ds, seqName, batchSize);
|
||||
}
|
||||
|
||||
+23
-3
@@ -15,12 +15,32 @@ import com.avaje.ebean.bean.BeanCollection;
|
||||
* com.avaje.ebean.meta and finders in com.avaje.ebean.server.meta.
|
||||
* </p>
|
||||
*/
|
||||
public interface BeanFinder<T> {
|
||||
public interface BeanFindController {
|
||||
|
||||
/**
|
||||
* Return true if this BeanPersistController should be registered for events
|
||||
* on this entity type.
|
||||
*/
|
||||
boolean isRegisterFor(Class<?> cls);
|
||||
|
||||
/**
|
||||
* Return true if this controller should intercept and process this find request.
|
||||
*
|
||||
* Return false to allow the default behavior to process the request.
|
||||
*/
|
||||
boolean isInterceptFind(BeanQueryRequest<?> request);
|
||||
|
||||
/**
|
||||
* Find a bean using its id or unique predicate.
|
||||
*/
|
||||
T find(BeanQueryRequest<T> request);
|
||||
<T> T find(BeanQueryRequest<T> request);
|
||||
|
||||
/**
|
||||
* Return true if this controller should intercept and process this findMany request.
|
||||
*
|
||||
* Return false to allow the default behavior to process the request.
|
||||
*/
|
||||
boolean isInterceptFindMany(BeanQueryRequest<?> request);
|
||||
|
||||
/**
|
||||
* Return a List, Set or Map for the given find request.
|
||||
@@ -29,6 +49,6 @@ public interface BeanFinder<T> {
|
||||
* get the return type right.
|
||||
* </p>
|
||||
*/
|
||||
BeanCollection<T> findMany(BeanQueryRequest<T> request);
|
||||
<T> BeanCollection<T> findMany(BeanQueryRequest<T> request);
|
||||
|
||||
}
|
||||
@@ -163,8 +163,6 @@ public interface JsonContext {
|
||||
/**
|
||||
* Deprecated in favour of using PathProperties by itself.
|
||||
* Write json to the JsonGenerator using the JsonWriteOptions.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
void toJson(Object value, JsonGenerator generator, JsonWriteOptions options) throws JsonIOException;
|
||||
|
||||
@@ -173,7 +171,6 @@ public interface JsonContext {
|
||||
* With additional options.
|
||||
*
|
||||
* @throws JsonIOException When IOException occurs
|
||||
* @deprecated
|
||||
*/
|
||||
void toJson(Object value, Writer writer, JsonWriteOptions options) throws JsonIOException;
|
||||
|
||||
@@ -182,7 +179,6 @@ public interface JsonContext {
|
||||
* Convert a bean or collection to json string.
|
||||
*
|
||||
* @throws JsonIOException When IOException occurs
|
||||
* @deprecated
|
||||
*/
|
||||
String toJson(Object value, JsonWriteOptions options) throws JsonIOException;
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ public class JsonReadOptions {
|
||||
|
||||
protected Map<String, JsonReadBeanVisitor<?>> visitorMap;
|
||||
|
||||
protected Object objectMapper;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
@@ -44,4 +46,17 @@ public class JsonReadOptions {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Jackson ObjectMapper to use (if not wanted to use the objectMapper set on the ServerConfig).
|
||||
*/
|
||||
public Object getObjectMapper() {
|
||||
return objectMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Jackson ObjectMapper to use (if not wanted to use the objectMapper set on the ServerConfig).
|
||||
*/
|
||||
public void setObjectMapper(Object objectMapper) {
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,23 @@
|
||||
package com.avaje.ebean.text.json;
|
||||
|
||||
import com.avaje.ebean.config.JsonConfig;
|
||||
import com.avaje.ebean.text.PathProperties;
|
||||
|
||||
/**
|
||||
* Deprecated in favour of just using PathProperties.
|
||||
*
|
||||
* Provides options for customising the JSON write process.
|
||||
* <p>
|
||||
* You can explicitly state which properties to include in the JSON output for
|
||||
* the root level and each path.
|
||||
* </p>
|
||||
* @deprecated
|
||||
*/
|
||||
public class JsonWriteOptions {
|
||||
|
||||
protected PathProperties pathProperties;
|
||||
|
||||
protected Object objectMapper;
|
||||
|
||||
protected JsonConfig.Include include;
|
||||
|
||||
/**
|
||||
* Parse and return a PathProperties from nested string format like
|
||||
* (a,b,c(d,e),f(g)) where "c" is a path containing "d" and "e" and "f" is a
|
||||
@@ -51,4 +53,35 @@ public class JsonWriteOptions {
|
||||
return pathProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the include mode for this request.
|
||||
*/
|
||||
public JsonConfig.Include getInclude() {
|
||||
return include;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the include mode for this request.
|
||||
*/
|
||||
public void setInclude(JsonConfig.Include include) {
|
||||
this.include = include;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the jackson object mapper to use.
|
||||
* <p/>
|
||||
* If null the ObjectMapper from serverConfig will be used.
|
||||
*/
|
||||
public Object getObjectMapper() {
|
||||
return objectMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the jackson object mapper to use.
|
||||
* <p/>
|
||||
* If null the ObjectMapper from serverConfig will be used.
|
||||
*/
|
||||
public void setObjectMapper(Object objectMapper) {
|
||||
this.objectMapper = objectMapper;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.avaje.ebeaninternal.api;
|
||||
|
||||
import com.avaje.ebeaninternal.server.util.ClassPathSearchFilter;
|
||||
import com.avaje.ebeaninternal.server.util.ClassPathSearchMatcher;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* This interface allows us to have more than one ClassPathSearch
|
||||
* to scan the resources by a customized way.
|
||||
*
|
||||
* @author Kefeng Deng (deng@51any.com)
|
||||
*/
|
||||
public interface ClassPathSearchService {
|
||||
|
||||
/**
|
||||
* Initialize this ClassPathSearchService with given parameters
|
||||
*
|
||||
* @param classLoader is current classLoader
|
||||
* @param filter is filter
|
||||
* @param matcher
|
||||
* @param classPathReaderClassName
|
||||
*/
|
||||
void init(ClassLoader classLoader, ClassPathSearchFilter filter, ClassPathSearchMatcher matcher, String classPathReaderClassName);
|
||||
|
||||
/**
|
||||
* Searches the class path for all matching classes.
|
||||
*
|
||||
* @return a collection of all matching classes
|
||||
* @throws IOException if a resource is un-reachable
|
||||
*/
|
||||
List<Class<?>> findClasses() throws IOException;
|
||||
|
||||
/**
|
||||
* Return the set of jars that contained classes that matched.
|
||||
*/
|
||||
Set<String> getJarHits();
|
||||
|
||||
/**
|
||||
* Return the set of packages that contained classes that matched.
|
||||
*/
|
||||
Set<String> getPackageHits();
|
||||
|
||||
}
|
||||
@@ -6,88 +6,108 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Helper to find classes taking into account the context class loader.
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public class ClassUtil {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ClassUtil.class);
|
||||
|
||||
private static boolean preferContext = true;
|
||||
private static final Logger logger = LoggerFactory.getLogger(ClassUtil.class);
|
||||
|
||||
/**
|
||||
* Load a class taking into account a context class loader (if present).
|
||||
*/
|
||||
public static Class<?> forName(String name) throws ClassNotFoundException {
|
||||
return forName(name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a class taking into account a context class loader (if present).
|
||||
*/
|
||||
public static Class<?> forName(String name, Class<?> caller) throws ClassNotFoundException {
|
||||
|
||||
if (caller == null){
|
||||
caller = ClassUtil.class;
|
||||
}
|
||||
ClassLoadContext ctx = ClassLoadContext.of(caller, preferContext);
|
||||
|
||||
return ctx.forName(name);
|
||||
}
|
||||
|
||||
private static boolean preferContext = true;
|
||||
|
||||
public static ClassLoader getClassLoader(Class<?> caller, boolean preferContext) {
|
||||
|
||||
if (caller == null){
|
||||
caller = ClassUtil.class;
|
||||
}
|
||||
ClassLoadContext ctx = ClassLoadContext.of(caller, preferContext);
|
||||
ClassLoader classLoader = ctx.getDefault(preferContext);
|
||||
if (ctx.isAmbiguous()){
|
||||
logger.info("Ambigous ClassLoader (Context vs Caller) chosen "+classLoader);
|
||||
}
|
||||
return classLoader;
|
||||
}
|
||||
/**
|
||||
* Load a class taking into account a context class loader (if present).
|
||||
*/
|
||||
public static Class<?> forName(String name) throws ClassNotFoundException {
|
||||
return forName(name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the given class is present.
|
||||
*/
|
||||
public static boolean isPresent(String className) {
|
||||
return isPresent(className, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the given class is present.
|
||||
*/
|
||||
public static boolean isPresent(String className, Class<?> caller) {
|
||||
try {
|
||||
forName(className, caller);
|
||||
return true;
|
||||
} catch (Throwable ex) {
|
||||
// Class or one of its dependencies is not present...
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Load a class taking into account a context class loader (if present).
|
||||
*/
|
||||
public static Class<?> forName(String name, Class<?> caller) throws ClassNotFoundException {
|
||||
|
||||
/**
|
||||
* Return a new instance of the class using the default constructor.
|
||||
*/
|
||||
public static Object newInstance(String className) {
|
||||
return newInstance(className,null);
|
||||
if (caller == null) {
|
||||
caller = ClassUtil.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new instance of the class using the default constructor.
|
||||
*/
|
||||
public static Object newInstance(String className, Class<?> caller) {
|
||||
|
||||
try {
|
||||
Class<?> cls = forName(className, caller);
|
||||
return cls.newInstance();
|
||||
} catch (Exception e){
|
||||
String msg = "Error constructing "+className;
|
||||
throw new IllegalArgumentException(msg, e);
|
||||
}
|
||||
ClassLoadContext ctx = ClassLoadContext.of(caller, preferContext);
|
||||
|
||||
return ctx.forName(name);
|
||||
}
|
||||
|
||||
|
||||
public static ClassLoader getClassLoader(Class<?> caller, boolean preferContext) {
|
||||
|
||||
if (caller == null) {
|
||||
caller = ClassUtil.class;
|
||||
}
|
||||
ClassLoadContext ctx = ClassLoadContext.of(caller, preferContext);
|
||||
ClassLoader classLoader = ctx.getDefault(preferContext);
|
||||
if (ctx.isAmbiguous()) {
|
||||
logger.info("Ambigous ClassLoader (Context vs Caller) chosen " + classLoader);
|
||||
}
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if javax validation annotations like Size and NotNull are present.
|
||||
*/
|
||||
public static boolean isJavaxValidationAnnotationsPresent() {
|
||||
return isPresent("javax.validation.constraints.NotNull", null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if Jackson annotations like JsonIgnore are present.
|
||||
*/
|
||||
public static boolean isJacksonAnnotationsPresent() {
|
||||
return isPresent("com.fasterxml.jackson.annotation.JsonIgnore", null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if Jackson ObjectMapper is present.
|
||||
*/
|
||||
public static boolean isJacksonObjectMapperPresent() {
|
||||
return isPresent("com.fasterxml.jackson.databind.ObjectMapper", null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if the given class is present.
|
||||
*/
|
||||
public static boolean isPresent(String className) {
|
||||
return isPresent(className, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the given class is present.
|
||||
*/
|
||||
public static boolean isPresent(String className, Class<?> caller) {
|
||||
try {
|
||||
forName(className, caller);
|
||||
return true;
|
||||
} catch (Throwable ex) {
|
||||
// Class or one of its dependencies is not present...
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new instance of the class using the default constructor.
|
||||
*/
|
||||
public static Object newInstance(String className) {
|
||||
return newInstance(className, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new instance of the class using the default constructor.
|
||||
*/
|
||||
public static Object newInstance(String className, Class<?> caller) {
|
||||
|
||||
try {
|
||||
Class<?> cls = forName(className, caller);
|
||||
return cls.newInstance();
|
||||
} catch (Exception e) {
|
||||
String msg = "Error constructing " + className;
|
||||
throw new IllegalArgumentException(msg, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,16 +11,16 @@ import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
*/
|
||||
public interface LoadBeanBuffer {
|
||||
|
||||
public int getBatchSize();
|
||||
int getBatchSize();
|
||||
|
||||
public List<EntityBeanIntercept> getBatch();
|
||||
List<EntityBeanIntercept> getBatch();
|
||||
|
||||
public BeanDescriptor<?> getBeanDescriptor();
|
||||
BeanDescriptor<?> getBeanDescriptor();
|
||||
|
||||
public PersistenceContext getPersistenceContext();
|
||||
PersistenceContext getPersistenceContext();
|
||||
|
||||
public String getFullPath();
|
||||
String getFullPath();
|
||||
|
||||
public void configureQuery(SpiQuery<?> query, String lazyLoadProperty);
|
||||
void configureQuery(SpiQuery<?> query, String lazyLoadProperty);
|
||||
|
||||
}
|
||||
@@ -14,13 +14,13 @@ public interface LoadContext {
|
||||
/**
|
||||
* Return the minimum batch size when using QueryIterator with query joins.
|
||||
*/
|
||||
public int getSecondaryQueriesMinBatchSize(OrmQueryRequest<?> parentRequest, int defaultQueryBatch);
|
||||
int getSecondaryQueriesMinBatchSize(OrmQueryRequest<?> parentRequest, int defaultQueryBatch);
|
||||
|
||||
/**
|
||||
* Execute any secondary (+query) queries if there are any defined.
|
||||
* @param parentRequest the originating query request
|
||||
*/
|
||||
public void executeSecondaryQueries(OrmQueryRequest<?> parentRequest);
|
||||
void executeSecondaryQueries(OrmQueryRequest<?> parentRequest);
|
||||
|
||||
/**
|
||||
* Register any secondary queries (+query or +lazy) with their
|
||||
@@ -30,17 +30,17 @@ public interface LoadContext {
|
||||
* defined query for +query and +lazy execution.
|
||||
* </p>
|
||||
*/
|
||||
public void registerSecondaryQueries(SpiQuery<?> query);
|
||||
void registerSecondaryQueries(SpiQuery<?> query);
|
||||
|
||||
/**
|
||||
* Return the node for a given path which is used by autofetch profiling.
|
||||
*/
|
||||
public ObjectGraphNode getObjectGraphNode(String path);
|
||||
ObjectGraphNode getObjectGraphNode(String path);
|
||||
|
||||
/**
|
||||
* Return the persistence context used by this query and future lazy loading.
|
||||
*/
|
||||
public PersistenceContext getPersistenceContext();
|
||||
PersistenceContext getPersistenceContext();
|
||||
|
||||
/**
|
||||
* Set the persistence context used by this query and future lazy loading.
|
||||
@@ -48,16 +48,16 @@ public interface LoadContext {
|
||||
* Used by query iterator when processing large result sets.
|
||||
* </p>
|
||||
*/
|
||||
public void resetPersistenceContext(PersistenceContext persistenceContext);
|
||||
void resetPersistenceContext(PersistenceContext persistenceContext);
|
||||
|
||||
/**
|
||||
* Register a Bean for lazy loading.
|
||||
*/
|
||||
public void register(String path, EntityBeanIntercept ebi);
|
||||
void register(String path, EntityBeanIntercept ebi);
|
||||
|
||||
/**
|
||||
* Register a collection for lazy loading.
|
||||
*/
|
||||
public void register(String path, BeanCollection<?> bc);
|
||||
void register(String path, BeanCollection<?> bc);
|
||||
|
||||
}
|
||||
|
||||
@@ -13,20 +13,20 @@ import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
*/
|
||||
public interface LoadManyBuffer {
|
||||
|
||||
public int getBatchSize();
|
||||
int getBatchSize();
|
||||
|
||||
public List<BeanCollection<?>> getBatch();
|
||||
List<BeanCollection<?>> getBatch();
|
||||
|
||||
public BeanPropertyAssocMany<?> getBeanProperty();
|
||||
BeanPropertyAssocMany<?> getBeanProperty();
|
||||
|
||||
public ObjectGraphNode getObjectGraphNode();
|
||||
ObjectGraphNode getObjectGraphNode();
|
||||
|
||||
public BeanDescriptor<?> getBeanDescriptor();
|
||||
BeanDescriptor<?> getBeanDescriptor();
|
||||
|
||||
public PersistenceContext getPersistenceContext();
|
||||
PersistenceContext getPersistenceContext();
|
||||
|
||||
public String getFullPath();
|
||||
String getFullPath();
|
||||
|
||||
public void configureQuery(SpiQuery<?> query);
|
||||
void configureQuery(SpiQuery<?> query);
|
||||
|
||||
}
|
||||
@@ -14,5 +14,5 @@ public interface LoadSecondaryQuery {
|
||||
/**
|
||||
* Execute the secondary query with a given batch size.
|
||||
*/
|
||||
public void loadSecondaryQuery(OrmQueryRequest<?> parentRequest);
|
||||
void loadSecondaryQuery(OrmQueryRequest<?> parentRequest);
|
||||
}
|
||||
|
||||
@@ -152,6 +152,16 @@ public class ScopedTransaction implements SpiTransaction {
|
||||
transaction.setPersistCascade(persistCascade);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUpdateAllLoadedProperties(boolean updateAllLoaded) {
|
||||
transaction.setUpdateAllLoadedProperties(updateAllLoaded);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean isUpdateAllLoadedProperties() {
|
||||
return transaction.isUpdateAllLoadedProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchMode(boolean useBatch) {
|
||||
transaction.setBatchMode(useBatch);
|
||||
|
||||
@@ -10,5 +10,5 @@ public interface SpiBackgroundExecutor extends BackgroundExecutor {
|
||||
/**
|
||||
* Shutdown any associated thread pools.
|
||||
*/
|
||||
public void shutdown();
|
||||
void shutdown();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import com.avaje.ebean.CallableSql;
|
||||
|
||||
public interface SpiCallableSql extends CallableSql {
|
||||
|
||||
public BindParams getBindParams();
|
||||
BindParams getBindParams();
|
||||
|
||||
public TransactionEventTable getTransactionEventTable();
|
||||
TransactionEventTable getTransactionEventTable();
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.avaje.ebean.config.dbplatform.DatabasePlatform;
|
||||
* author: Richard Vowles - http://gplus.to/RichardVowles
|
||||
*/
|
||||
public interface SpiEbeanPlugin {
|
||||
|
||||
/**
|
||||
* initializes the plugin.
|
||||
*
|
||||
@@ -16,7 +17,10 @@ public interface SpiEbeanPlugin {
|
||||
* @param dbPlatform - the database we are using - this is available from the server, but it is provided for convenience
|
||||
* @param serverConfig - the configured server information. It allows access to pre-collected information (but not the collector PropertySource, yet)
|
||||
*/
|
||||
public void setup(SpiEbeanServer server, DatabasePlatform dbPlatform, ServerConfig serverConfig);
|
||||
void setup(SpiEbeanServer server, DatabasePlatform dbPlatform, ServerConfig serverConfig);
|
||||
|
||||
public void execute(boolean online);
|
||||
/**
|
||||
* Execute the plugin (generate DDL for example).
|
||||
*/
|
||||
void execute(boolean online);
|
||||
}
|
||||
|
||||
@@ -26,22 +26,27 @@ public interface SpiEbeanServer extends EbeanServer, BeanLoader, BeanCollectionL
|
||||
/**
|
||||
* For internal use, shutdown of the server invoked by JVM Shutdown.
|
||||
*/
|
||||
public void shutdownManaged();
|
||||
void shutdownManaged();
|
||||
|
||||
/**
|
||||
* Return true if query origins should be collected.
|
||||
*/
|
||||
public boolean isCollectQueryOrigins();
|
||||
|
||||
boolean isCollectQueryOrigins();
|
||||
|
||||
/**
|
||||
* Return true if updates in JDBC batch should include all columns if unspecified on the transaction.
|
||||
*/
|
||||
boolean isUpdateAllPropertiesInBatch();
|
||||
|
||||
/**
|
||||
* Return the server configuration.
|
||||
*/
|
||||
public ServerConfig getServerConfig();
|
||||
ServerConfig getServerConfig();
|
||||
|
||||
/**
|
||||
* Return the DatabasePlatform for this server.
|
||||
*/
|
||||
public DatabasePlatform getDatabasePlatform();
|
||||
DatabasePlatform getDatabasePlatform();
|
||||
|
||||
/**
|
||||
* Return a JDBC driver specific handler for batching.
|
||||
@@ -49,7 +54,7 @@ public interface SpiEbeanServer extends EbeanServer, BeanLoader, BeanCollectionL
|
||||
* Required for Oracle specific batch handling.
|
||||
* </p>
|
||||
*/
|
||||
public PstmtBatch getPstmtBatch();
|
||||
PstmtBatch getPstmtBatch();
|
||||
|
||||
/**
|
||||
* Create an object to represent the current CallStack.
|
||||
@@ -58,47 +63,47 @@ public interface SpiEbeanServer extends EbeanServer, BeanLoader, BeanCollectionL
|
||||
* graph costing.
|
||||
* </p>
|
||||
*/
|
||||
public CallStack createCallStack();
|
||||
CallStack createCallStack();
|
||||
|
||||
/**
|
||||
* Return the PersistenceContextScope to use defined at query or server level.
|
||||
*/
|
||||
public PersistenceContextScope getPersistenceContextScope(SpiQuery<?> query);
|
||||
PersistenceContextScope getPersistenceContextScope(SpiQuery<?> query);
|
||||
|
||||
/**
|
||||
* Return the DDL generator.
|
||||
*/
|
||||
public DdlGenerator getDdlGenerator();
|
||||
DdlGenerator getDdlGenerator();
|
||||
|
||||
/**
|
||||
* Return the AutoFetchListener.
|
||||
*/
|
||||
public AutoFetchManager getAutoFetchManager();
|
||||
AutoFetchManager getAutoFetchManager();
|
||||
|
||||
/**
|
||||
* Clear the query execution statistics.
|
||||
*/
|
||||
public void clearQueryStatistics();
|
||||
void clearQueryStatistics();
|
||||
|
||||
/**
|
||||
* Return all the descriptors.
|
||||
*/
|
||||
public List<BeanDescriptor<?>> getBeanDescriptors();
|
||||
List<BeanDescriptor<?>> getBeanDescriptors();
|
||||
|
||||
/**
|
||||
* Return the BeanDescriptor for a given type of bean.
|
||||
*/
|
||||
public <T> BeanDescriptor<T> getBeanDescriptor(Class<T> type);
|
||||
<T> BeanDescriptor<T> getBeanDescriptor(Class<T> type);
|
||||
|
||||
/**
|
||||
* Return BeanDescriptor using it's unique id.
|
||||
*/
|
||||
public BeanDescriptor<?> getBeanDescriptorById(String descriptorId);
|
||||
BeanDescriptor<?> getBeanDescriptorById(String descriptorId);
|
||||
|
||||
/**
|
||||
* Return BeanDescriptors mapped to this table.
|
||||
*/
|
||||
public List<BeanDescriptor<?>> getBeanDescriptors(String tableName);
|
||||
List<BeanDescriptor<?>> getBeanDescriptors(String tableName);
|
||||
|
||||
/**
|
||||
* Process committed changes from another framework.
|
||||
@@ -108,7 +113,7 @@ public interface SpiEbeanServer extends EbeanServer, BeanLoader, BeanCollectionL
|
||||
* this to maintain its cache and text indexes appropriately.
|
||||
* </p>
|
||||
*/
|
||||
public void externalModification(TransactionEventTable event);
|
||||
void externalModification(TransactionEventTable event);
|
||||
|
||||
/**
|
||||
* Create a ServerTransaction.
|
||||
@@ -116,44 +121,44 @@ public interface SpiEbeanServer extends EbeanServer, BeanLoader, BeanCollectionL
|
||||
* To specify to use the default transaction isolation use a value of -1.
|
||||
* </p>
|
||||
*/
|
||||
public SpiTransaction createServerTransaction(boolean isExplicit, int isolationLevel);
|
||||
SpiTransaction createServerTransaction(boolean isExplicit, int isolationLevel);
|
||||
|
||||
/**
|
||||
* Return the current transaction or null if there is no current transaction.
|
||||
*/
|
||||
public SpiTransaction getCurrentServerTransaction();
|
||||
SpiTransaction getCurrentServerTransaction();
|
||||
|
||||
/**
|
||||
* Create a ScopeTrans for a method for the given scope definition.
|
||||
*/
|
||||
public ScopeTrans createScopeTrans(TxScope txScope);
|
||||
ScopeTrans createScopeTrans(TxScope txScope);
|
||||
|
||||
/**
|
||||
* Create a ServerTransaction for query purposes.
|
||||
*/
|
||||
public SpiTransaction createQueryTransaction();
|
||||
SpiTransaction createQueryTransaction();
|
||||
|
||||
/**
|
||||
* An event from another server in the cluster used to notify local
|
||||
* BeanListeners of remote inserts updates and deletes.
|
||||
*/
|
||||
public void remoteTransactionEvent(RemoteTransactionEvent event);
|
||||
void remoteTransactionEvent(RemoteTransactionEvent event);
|
||||
|
||||
/**
|
||||
* Create a query request object.
|
||||
*/
|
||||
public <T> SpiOrmQueryRequest<T> createQueryRequest(BeanDescriptor<T> desc, SpiQuery<T> q,
|
||||
<T> SpiOrmQueryRequest<T> createQueryRequest(BeanDescriptor<T> desc, SpiQuery<T> q,
|
||||
Transaction t);
|
||||
|
||||
/**
|
||||
* Compile a query.
|
||||
*/
|
||||
public <T> CQuery<T> compileQuery(Query<T> query, Transaction t);
|
||||
<T> CQuery<T> compileQuery(Query<T> query, Transaction t);
|
||||
|
||||
/**
|
||||
* Return the queryEngine for this server.
|
||||
*/
|
||||
public CQueryEngine getQueryEngine();
|
||||
CQueryEngine getQueryEngine();
|
||||
|
||||
/**
|
||||
* Execute the findId's query but without copying the query.
|
||||
@@ -162,37 +167,37 @@ public interface SpiEbeanServer extends EbeanServer, BeanLoader, BeanCollectionL
|
||||
* the query has finished (if executing in a background thread).
|
||||
* </p>
|
||||
*/
|
||||
public <T> List<Object> findIdsWithCopy(Query<T> query, Transaction t);
|
||||
<T> List<Object> findIdsWithCopy(Query<T> query, Transaction t);
|
||||
|
||||
/**
|
||||
* Execute the findRowCount query but without copying the query.
|
||||
*/
|
||||
public <T> int findRowCountWithCopy(Query<T> query, Transaction t);
|
||||
<T> int findRowCountWithCopy(Query<T> query, Transaction t);
|
||||
|
||||
/**
|
||||
* Load a batch of Associated One Beans.
|
||||
*/
|
||||
public void loadBean(LoadBeanRequest loadRequest);
|
||||
void loadBean(LoadBeanRequest loadRequest);
|
||||
|
||||
/**
|
||||
* Lazy load a batch of Many's.
|
||||
*/
|
||||
public void loadMany(LoadManyRequest loadRequest);
|
||||
void loadMany(LoadManyRequest loadRequest);
|
||||
|
||||
/**
|
||||
* Return the default batch size for lazy loading.
|
||||
*/
|
||||
public int getLazyLoadBatchSize();
|
||||
int getLazyLoadBatchSize();
|
||||
|
||||
/**
|
||||
* Return true if the type is known as an Entity or Xml type or a List Set or
|
||||
* Map of known bean types.
|
||||
*/
|
||||
public boolean isSupportedType(java.lang.reflect.Type genericType);
|
||||
boolean isSupportedType(java.lang.reflect.Type genericType);
|
||||
|
||||
/**
|
||||
* Collect query statistics by ObjectGraphNode. Used for Lazy loading reporting.
|
||||
*/
|
||||
public void collectQueryStats(ObjectGraphNode objectGraphNode, long loadedBeanCount, long timeMicros);
|
||||
void collectQueryStats(ObjectGraphNode objectGraphNode, long loadedBeanCount, long timeMicros);
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ public interface SpiExpression extends Expression {
|
||||
* Predicates on Many properties require an extra independent join clause.
|
||||
* </p>
|
||||
*/
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins whereManyJoins);
|
||||
void containsMany(BeanDescriptor<?> desc, ManyWhereJoins whereManyJoins);
|
||||
|
||||
/**
|
||||
* Calculate a hash value used to identify a query for AutoFetch tuning.
|
||||
@@ -25,7 +25,7 @@ public interface SpiExpression extends Expression {
|
||||
* from an AutoFetch perspective and get different tuning.
|
||||
* </p>
|
||||
*/
|
||||
public void queryAutoFetchHash(HashQueryPlanBuilder builder);
|
||||
void queryAutoFetchHash(HashQueryPlanBuilder builder);
|
||||
|
||||
/**
|
||||
* Calculate a hash value for the expression.
|
||||
@@ -36,12 +36,12 @@ public interface SpiExpression extends Expression {
|
||||
* case the query execution plan can be reused.
|
||||
* </p>
|
||||
*/
|
||||
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder);
|
||||
void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder);
|
||||
|
||||
/**
|
||||
* Return the hash value for the values that will be bound.
|
||||
*/
|
||||
public int queryBindHash();
|
||||
int queryBindHash();
|
||||
|
||||
/**
|
||||
* Add some sql to the query.
|
||||
@@ -56,7 +56,7 @@ public interface SpiExpression extends Expression {
|
||||
* @param request
|
||||
* the associated request.
|
||||
*/
|
||||
public void addSql(SpiExpressionRequest request);
|
||||
void addSql(SpiExpressionRequest request);
|
||||
|
||||
/**
|
||||
* Add the parameter values to be set against query. For each ? place holder
|
||||
@@ -65,5 +65,5 @@ public interface SpiExpression extends Expression {
|
||||
* @param request
|
||||
* the associated request.
|
||||
*/
|
||||
public void addBindValues(SpiExpressionRequest request);
|
||||
void addBindValues(SpiExpressionRequest request);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,6 @@ public interface SpiExpressionFactory extends ExpressionFactory {
|
||||
/**
|
||||
* Create another expression factory with a given sub path.
|
||||
*/
|
||||
public ExpressionFactory createExpressionFactory();
|
||||
ExpressionFactory createExpressionFactory();
|
||||
|
||||
}
|
||||
|
||||
@@ -16,17 +16,17 @@ public interface SpiExpressionList<T> extends ExpressionList<T> {
|
||||
/**
|
||||
* Return the underlying list of expressions.
|
||||
*/
|
||||
public List<SpiExpression> getUnderlyingList();
|
||||
List<SpiExpression> getUnderlyingList();
|
||||
|
||||
/**
|
||||
* Return a copy of the ExpressionList with the path trimmed for filterMany() expressions.
|
||||
*/
|
||||
public SpiExpressionList<?> trimPath(int prefixTrim);
|
||||
SpiExpressionList<?> trimPath(int prefixTrim);
|
||||
|
||||
/**
|
||||
* Restore the ExpressionFactory after deserialisation.
|
||||
*/
|
||||
public void setExpressionFactory(ExpressionFactory expr);
|
||||
void setExpressionFactory(ExpressionFactory expr);
|
||||
|
||||
/**
|
||||
* Process "Many" properties populating ManyWhereJoins.
|
||||
@@ -34,12 +34,12 @@ public interface SpiExpressionList<T> extends ExpressionList<T> {
|
||||
* Predicates on Many properties require an extra independent join clause.
|
||||
* </p>
|
||||
*/
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoins);
|
||||
void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoins);
|
||||
|
||||
/**
|
||||
* Return true if this list is empty.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Concatenate the expression sql into a String.
|
||||
@@ -48,7 +48,7 @@ public interface SpiExpressionList<T> extends ExpressionList<T> {
|
||||
* with bind parameters.
|
||||
* </p>
|
||||
*/
|
||||
public String buildSql(SpiExpressionRequest request);
|
||||
String buildSql(SpiExpressionRequest request);
|
||||
|
||||
/**
|
||||
* Combine the expression bind values into a list.
|
||||
@@ -59,12 +59,12 @@ public interface SpiExpressionList<T> extends ExpressionList<T> {
|
||||
*
|
||||
* @return the list of all the bind values in order.
|
||||
*/
|
||||
public ArrayList<Object> buildBindValues(SpiExpressionRequest request);
|
||||
ArrayList<Object> buildBindValues(SpiExpressionRequest request);
|
||||
|
||||
/**
|
||||
* Calculate a hash based on the expressions but excluding the actual bind
|
||||
* values.
|
||||
*/
|
||||
public void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder);
|
||||
void queryPlanHash(BeanQueryRequest<?> request, HashQueryPlanBuilder builder);
|
||||
|
||||
}
|
||||
|
||||
@@ -13,45 +13,45 @@ public interface SpiExpressionRequest {
|
||||
/**
|
||||
* Parse the logical property name to the deployment name.
|
||||
*/
|
||||
public String parseDeploy(String logicalProp);
|
||||
String parseDeploy(String logicalProp);
|
||||
|
||||
/**
|
||||
* Return the bean descriptor for the root type.
|
||||
*/
|
||||
public BeanDescriptor<?> getBeanDescriptor();
|
||||
BeanDescriptor<?> getBeanDescriptor();
|
||||
|
||||
/**
|
||||
* Return the associated QueryRequest.
|
||||
*/
|
||||
public SpiOrmQueryRequest<?> getQueryRequest();
|
||||
SpiOrmQueryRequest<?> getQueryRequest();
|
||||
|
||||
/**
|
||||
* Append to the expression sql.
|
||||
*/
|
||||
public SpiExpressionRequest append(String sql);
|
||||
SpiExpressionRequest append(String sql);
|
||||
|
||||
/**
|
||||
* Add a bind value to this request.
|
||||
*/
|
||||
public void addBindValue(Object bindValue);
|
||||
void addBindValue(Object bindValue);
|
||||
|
||||
/**
|
||||
* Return the accumulated expression sql for all expressions in this request.
|
||||
*/
|
||||
public String getSql();
|
||||
String getSql();
|
||||
|
||||
/**
|
||||
* Return the ordered list of bind values for all expressions in this request.
|
||||
*/
|
||||
public ArrayList<Object> getBindValues();
|
||||
ArrayList<Object> getBindValues();
|
||||
|
||||
/**
|
||||
* Increments the parameter index and returns that value.
|
||||
*/
|
||||
public int nextParameter();
|
||||
int nextParameter();
|
||||
|
||||
/**
|
||||
* Append a DB Like clause.
|
||||
*/
|
||||
public void appendLike();
|
||||
void appendLike();
|
||||
}
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
package com.avaje.ebeaninternal.api;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebean.ExpressionList;
|
||||
import com.avaje.ebean.OrderBy;
|
||||
import com.avaje.ebean.PersistenceContextScope;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.bean.BeanCollectionTouched;
|
||||
import com.avaje.ebean.bean.CallStack;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebean.bean.ObjectGraphNode;
|
||||
import com.avaje.ebean.bean.PersistenceContext;
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
@@ -22,6 +19,9 @@ import com.avaje.ebeaninternal.server.querydefn.NaturalKeyBindParam;
|
||||
import com.avaje.ebeaninternal.server.querydefn.OrmQueryDetail;
|
||||
import com.avaje.ebeaninternal.server.querydefn.OrmQueryProperties;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Object Relational query - Internal extension to Query object.
|
||||
*/
|
||||
@@ -87,6 +87,30 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
SUBQUERY
|
||||
}
|
||||
|
||||
enum TemporalMode {
|
||||
/**
|
||||
* Query runs against current data (normal).
|
||||
*/
|
||||
CURRENT,
|
||||
|
||||
/**
|
||||
* Query runs potentially returning many versions of the same bean.
|
||||
*/
|
||||
VERSIONS,
|
||||
|
||||
/**
|
||||
* Query runs 'As Of' a given date time.
|
||||
*/
|
||||
AS_OF;
|
||||
|
||||
/**
|
||||
* Return the mode of the query of if null return CURRENT mode.
|
||||
*/
|
||||
public static TemporalMode of(SpiQuery<?> query) {
|
||||
return (query != null) ? query.getTemporalMode() : TemporalMode.CURRENT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the PersistenceContextScope that this query should use.
|
||||
* <p>
|
||||
@@ -116,6 +140,31 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
Mode getMode();
|
||||
|
||||
/**
|
||||
* Return the Temporal mode for the query.
|
||||
*/
|
||||
TemporalMode getTemporalMode();
|
||||
|
||||
/**
|
||||
* Return true if this is a 'As Of' query.
|
||||
*/
|
||||
boolean isAsOfQuery();
|
||||
|
||||
/**
|
||||
* Return the asOf Timestamp which the query should run as.
|
||||
*/
|
||||
Timestamp getAsOf();
|
||||
|
||||
/**
|
||||
* Add a table alias for a @History entity involved in a 'As Of' query.
|
||||
*/
|
||||
void addAsOfTableAlias(String tableAlias);
|
||||
|
||||
/**
|
||||
* Return the list of table alias involved in a 'As Of' query that have @History support.
|
||||
*/
|
||||
List<String> getAsOfTableAlias();
|
||||
|
||||
/**
|
||||
* Return a listener that wants to be notified when the bean collection is
|
||||
* first used.
|
||||
@@ -148,6 +197,11 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
SpiQuery<T> copy();
|
||||
|
||||
/**
|
||||
* Return a copy of the query attaching to a different EbeanServer.
|
||||
*/
|
||||
SpiQuery<T> copy(EbeanServer server);
|
||||
|
||||
/**
|
||||
* Return the type of query (List, Set, Map, Bean, rowCount etc).
|
||||
*/
|
||||
@@ -171,18 +225,13 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
/**
|
||||
* This becomes a lazy loading query for a many relationship.
|
||||
*/
|
||||
void setLazyLoadForParents(List<Object> parentIds, BeanPropertyAssocMany<?> many);
|
||||
void setLazyLoadForParents(BeanPropertyAssocMany<?> many);
|
||||
|
||||
/**
|
||||
* Return the lazy loading 'many' property.
|
||||
*/
|
||||
BeanPropertyAssocMany<?> getLazyLoadForParentsProperty();
|
||||
|
||||
/**
|
||||
* Return the list of parent Id's for lazy loading.
|
||||
*/
|
||||
List<Object> getLazyLoadForParentIds();
|
||||
|
||||
/**
|
||||
* Set the load mode (+lazy or +query) and the load description.
|
||||
*/
|
||||
@@ -203,11 +252,6 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
ManyWhereJoins getManyWhereJoins();
|
||||
|
||||
/**
|
||||
* Convert this natural key query into a find by id query.
|
||||
*/
|
||||
void convertWhereNaturalKeyToId(Object idValue);
|
||||
|
||||
/**
|
||||
* Return a Natural Key bind parameter if supported by this query.
|
||||
*/
|
||||
@@ -341,11 +385,6 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
String getLazyLoadProperty();
|
||||
|
||||
/**
|
||||
* Return the lazy load path.
|
||||
*/
|
||||
String getLazyLoadManyPath();
|
||||
|
||||
/**
|
||||
* Used to hook back a lazy loading query to the original query (query
|
||||
* point).
|
||||
@@ -476,27 +515,11 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
Boolean isReadOnly();
|
||||
|
||||
/**
|
||||
* Adds this bean to the persistence context prior to executing the query.
|
||||
*/
|
||||
void contextAdd(EntityBean bean);
|
||||
|
||||
/**
|
||||
* Return the type of beans queries.
|
||||
*/
|
||||
Class<T> getBeanType();
|
||||
|
||||
/**
|
||||
* Return the query timeout.
|
||||
*/
|
||||
int getTimeout();
|
||||
|
||||
/**
|
||||
* Return the objects that should be added to the persistence context prior
|
||||
* to executing the query.
|
||||
*/
|
||||
ArrayList<EntityBean> getContextAdditions();
|
||||
|
||||
/**
|
||||
* Return the bind parameters.
|
||||
*/
|
||||
@@ -553,9 +576,14 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
int getFirstRow();
|
||||
|
||||
/**
|
||||
* Return true if lazy loading has been disabled on the query.
|
||||
*/
|
||||
boolean isDisableLazyLoading();
|
||||
|
||||
/**
|
||||
* Internally set by Ebean when this query must use the DISTINCT keyword.
|
||||
* <p/>
|
||||
* <p>
|
||||
* This does not exclude/remove the use of the id property.
|
||||
*/
|
||||
Query<T> setSqlDistinct(boolean sqlDistinct);
|
||||
@@ -580,11 +608,6 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
String getRawWhereClause();
|
||||
|
||||
/**
|
||||
* Return the Id value.
|
||||
*/
|
||||
Object getId();
|
||||
|
||||
/**
|
||||
* Set the generated sql for debug purposes.
|
||||
*/
|
||||
|
||||
@@ -10,68 +10,68 @@ import com.avaje.ebean.SqlQueryListener;
|
||||
*/
|
||||
public interface SpiSqlQuery extends SqlQuery {
|
||||
|
||||
/**
|
||||
* Return the named or positioned parameters.
|
||||
*/
|
||||
public BindParams getBindParams();
|
||||
/**
|
||||
* Return the named or positioned parameters.
|
||||
*/
|
||||
BindParams getBindParams();
|
||||
|
||||
/**
|
||||
* return the query.
|
||||
*/
|
||||
public String getQuery();
|
||||
/**
|
||||
* return the query.
|
||||
*/
|
||||
String getQuery();
|
||||
|
||||
/**
|
||||
* Return the queryListener.
|
||||
*/
|
||||
public SqlQueryListener getListener();
|
||||
|
||||
/**
|
||||
* Return the first row to fetch.
|
||||
*/
|
||||
public int getFirstRow();
|
||||
|
||||
/**
|
||||
* Return the maximum number of rows to fetch.
|
||||
*/
|
||||
public int getMaxRows();
|
||||
|
||||
/**
|
||||
* Return the number of rows after which background fetching occurs.
|
||||
*/
|
||||
public int getBackgroundFetchAfter();
|
||||
|
||||
/**
|
||||
* Return the key property for maps.
|
||||
*/
|
||||
public String getMapKey();
|
||||
|
||||
/**
|
||||
* Return the query timeout.
|
||||
*/
|
||||
public int getTimeout();
|
||||
/**
|
||||
* Return the queryListener.
|
||||
*/
|
||||
SqlQueryListener getListener();
|
||||
|
||||
/**
|
||||
* Return the hint for Statement.setFetchSize().
|
||||
*/
|
||||
public int getBufferFetchSizeHint();
|
||||
/**
|
||||
* Return the first row to fetch.
|
||||
*/
|
||||
int getFirstRow();
|
||||
|
||||
/**
|
||||
* Return true if this is a future fetch type query.
|
||||
*/
|
||||
public boolean isFutureFetch();
|
||||
/**
|
||||
* Return the maximum number of rows to fetch.
|
||||
*/
|
||||
int getMaxRows();
|
||||
|
||||
/**
|
||||
* Set to true if this is a future fetch type query.
|
||||
*/
|
||||
public void setFutureFetch(boolean futureFetch);
|
||||
/**
|
||||
* Return the number of rows after which background fetching occurs.
|
||||
*/
|
||||
int getBackgroundFetchAfter();
|
||||
|
||||
/**
|
||||
* Set the PreparedStatement for the purposes of supporting cancel.
|
||||
*/
|
||||
public void setPreparedStatement(PreparedStatement pstmt);
|
||||
|
||||
/**
|
||||
* Return true if the query has been cancelled.
|
||||
*/
|
||||
public boolean isCancelled();
|
||||
/**
|
||||
* Return the key property for maps.
|
||||
*/
|
||||
String getMapKey();
|
||||
|
||||
/**
|
||||
* Return the query timeout.
|
||||
*/
|
||||
int getTimeout();
|
||||
|
||||
/**
|
||||
* Return the hint for Statement.setFetchSize().
|
||||
*/
|
||||
int getBufferFetchSizeHint();
|
||||
|
||||
/**
|
||||
* Return true if this is a future fetch type query.
|
||||
*/
|
||||
boolean isFutureFetch();
|
||||
|
||||
/**
|
||||
* Set to true if this is a future fetch type query.
|
||||
*/
|
||||
void setFutureFetch(boolean futureFetch);
|
||||
|
||||
/**
|
||||
* Set the PreparedStatement for the purposes of supporting cancel.
|
||||
*/
|
||||
void setPreparedStatement(PreparedStatement pstmt);
|
||||
|
||||
/**
|
||||
* Return true if the query has been cancelled.
|
||||
*/
|
||||
boolean isCancelled();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import com.avaje.ebean.SqlUpdate;
|
||||
|
||||
public interface SpiSqlUpdate extends SqlUpdate {
|
||||
|
||||
public BindParams getBindParams();
|
||||
BindParams getBindParams();
|
||||
|
||||
public void setGeneratedSql(String sql);
|
||||
void setGeneratedSql(String sql);
|
||||
}
|
||||
|
||||
@@ -20,45 +20,45 @@ public interface SpiTransaction extends Transaction {
|
||||
/**
|
||||
* End the transaction when had query only use.
|
||||
*/
|
||||
public void endQueryOnly();
|
||||
void endQueryOnly();
|
||||
|
||||
/**
|
||||
* Return the string prefix with the transactin id and label used in logging.
|
||||
*/
|
||||
public String getLogPrefix();
|
||||
String getLogPrefix();
|
||||
|
||||
/**
|
||||
* Return true if generated SQL and Bind values should be logged to the
|
||||
* transaction log.
|
||||
*/
|
||||
public boolean isLogSql();
|
||||
boolean isLogSql();
|
||||
|
||||
/**
|
||||
* Return true if summary level events should be logged to the transaction
|
||||
* log.
|
||||
*/
|
||||
public boolean isLogSummary();
|
||||
boolean isLogSummary();
|
||||
|
||||
/**
|
||||
* Log a message to the SQL logger.
|
||||
*/
|
||||
public void logSql(String msg);
|
||||
void logSql(String msg);
|
||||
|
||||
/**
|
||||
* Log a message to the SUMMARY logger.
|
||||
*/
|
||||
public void logSummary(String msg);
|
||||
void logSummary(String msg);
|
||||
|
||||
/**
|
||||
* Register a "Derived Relationship" (that requires an additional update).
|
||||
*/
|
||||
public void registerDerivedRelationship(DerivedRelationshipData assocBean);
|
||||
void registerDerivedRelationship(DerivedRelationshipData assocBean);
|
||||
|
||||
/**
|
||||
* Return the list of "Derived Relationships" that must be maintained after
|
||||
* insert.
|
||||
*/
|
||||
public List<DerivedRelationshipData> getDerivedRelationship(Object bean);
|
||||
List<DerivedRelationshipData> getDerivedRelationship(Object bean);
|
||||
|
||||
/**
|
||||
* Add a deleting bean to the registered list.
|
||||
@@ -66,22 +66,22 @@ public interface SpiTransaction extends Transaction {
|
||||
* This is to handle bi-directional relationships where both sides Cascade.
|
||||
* </p>
|
||||
*/
|
||||
public void registerDeleteBean(Integer hash);
|
||||
void registerDeleteBean(Integer hash);
|
||||
|
||||
/**
|
||||
* Unregister the hash of the bean.
|
||||
*/
|
||||
public void unregisterDeleteBean(Integer hash);
|
||||
void unregisterDeleteBean(Integer hash);
|
||||
|
||||
/**
|
||||
* Return true if this is a bean that has already been saved/deleted.
|
||||
*/
|
||||
public boolean isRegisteredDeleteBean(Integer hash);
|
||||
boolean isRegisteredDeleteBean(Integer hash);
|
||||
|
||||
/**
|
||||
* Unregister the persisted bean.
|
||||
*/
|
||||
public void unregisterBean(Object bean);
|
||||
void unregisterBean(Object bean);
|
||||
|
||||
/**
|
||||
* Return true if this is a bean that has already been persisted in the
|
||||
@@ -91,13 +91,19 @@ public interface SpiTransaction extends Transaction {
|
||||
* This will register the bean if it is not already.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isRegisteredBean(Object bean);
|
||||
boolean isRegisteredBean(Object bean);
|
||||
|
||||
/**
|
||||
* Returns a String used to identify the transaction. This id is used for
|
||||
* Transaction logging.
|
||||
*/
|
||||
public String getId();
|
||||
String getId();
|
||||
|
||||
/**
|
||||
* Return true if this transaction has updateAllLoadedProperties set.
|
||||
* If null is returned the server default is used (set on ServerConfig).
|
||||
*/
|
||||
Boolean isUpdateAllLoadedProperties();
|
||||
|
||||
/**
|
||||
* Return the batchSize specifically set for this transaction or 0.
|
||||
@@ -105,7 +111,7 @@ public interface SpiTransaction extends Transaction {
|
||||
* Returning 0 implies to use the system wide default batch size.
|
||||
* </p>
|
||||
*/
|
||||
public int getBatchSize();
|
||||
int getBatchSize();
|
||||
|
||||
/**
|
||||
* Modify and return the current 'depth' of the transaction.
|
||||
@@ -119,18 +125,18 @@ public interface SpiTransaction extends Transaction {
|
||||
* executed first during save.
|
||||
* </p>
|
||||
*/
|
||||
public int depth(int diff);
|
||||
int depth(int diff);
|
||||
|
||||
/**
|
||||
* Return the current depth.
|
||||
*/
|
||||
public int depth();
|
||||
int depth();
|
||||
|
||||
/**
|
||||
* Return true if this transaction was created explicitly via
|
||||
* <code>Ebean.beginTransaction()</code>.
|
||||
*/
|
||||
public boolean isExplicit();
|
||||
boolean isExplicit();
|
||||
|
||||
/**
|
||||
* Get the object that holds the event details.
|
||||
@@ -140,29 +146,29 @@ public interface SpiTransaction extends Transaction {
|
||||
* around the cluster (if you have a cluster).
|
||||
* </p>
|
||||
*/
|
||||
public TransactionEvent getEvent();
|
||||
TransactionEvent getEvent();
|
||||
|
||||
/**
|
||||
* Whether persistCascade is on for save and delete.
|
||||
*/
|
||||
public boolean isPersistCascade();
|
||||
boolean isPersistCascade();
|
||||
|
||||
/**
|
||||
* Return true if this request should be batched. Conversely returns false
|
||||
* if this request should be executed immediately.
|
||||
*/
|
||||
public boolean isBatchThisRequest(PersistRequest.Type type);
|
||||
boolean isBatchThisRequest(PersistRequest.Type type);
|
||||
|
||||
/**
|
||||
* Return the queue used to batch up persist requests.
|
||||
*/
|
||||
public BatchControl getBatchControl();
|
||||
BatchControl getBatchControl();
|
||||
|
||||
/**
|
||||
* Set the queue used to batch up persist requests. There should only be one
|
||||
* PersistQueue set per transaction.
|
||||
*/
|
||||
public void setBatchControl(BatchControl control);
|
||||
void setBatchControl(BatchControl control);
|
||||
|
||||
/**
|
||||
* Return the persistence context associated with this transaction.
|
||||
@@ -172,7 +178,7 @@ public interface SpiTransaction extends Transaction {
|
||||
* behaviour.
|
||||
* </p>
|
||||
*/
|
||||
public PersistenceContext getPersistenceContext();
|
||||
PersistenceContext getPersistenceContext();
|
||||
|
||||
/**
|
||||
* Set the persistence context to this transaction.
|
||||
@@ -185,47 +191,46 @@ public interface SpiTransaction extends Transaction {
|
||||
* PersistenceContext with multiple transactions.
|
||||
* </p>
|
||||
*/
|
||||
public void setPersistenceContext(PersistenceContext context);
|
||||
void setPersistenceContext(PersistenceContext context);
|
||||
|
||||
/**
|
||||
* Return the underlying Connection for internal use.
|
||||
* <p>
|
||||
* If the connection is made public from Transaction and the user code calls
|
||||
* If the connection is made from Transaction and the user code calls
|
||||
* that method we can no longer trust the query only status of a
|
||||
* Transaction.
|
||||
* </p>
|
||||
*/
|
||||
public Connection getInternalConnection();
|
||||
Connection getInternalConnection();
|
||||
|
||||
/**
|
||||
* Return true if the manyToMany intersection should be persisted for this particular relationship direction.
|
||||
*/
|
||||
public boolean isSaveAssocManyIntersection(String intersectionTable, String beanName);
|
||||
boolean isSaveAssocManyIntersection(String intersectionTable, String beanName);
|
||||
|
||||
/**
|
||||
* Return true if batch mode got escalated for this request (and associated cascades).
|
||||
*/
|
||||
public boolean checkBatchEscalationOnCascade(PersistRequestBean<?> request);
|
||||
boolean checkBatchEscalationOnCascade(PersistRequestBean<?> request);
|
||||
|
||||
/**
|
||||
* If batch mode was turned on for the request then flush the batch.
|
||||
*/
|
||||
public void flushBatchOnCascade();
|
||||
void flushBatchOnCascade();
|
||||
|
||||
/**
|
||||
* Mark the transaction explicitly as not being query only.
|
||||
*/
|
||||
public void markNotQueryOnly();
|
||||
void markNotQueryOnly();
|
||||
|
||||
/**
|
||||
* Potentially escalate batch mode on saving or deleting a collection.
|
||||
*/
|
||||
public void checkBatchEscalationOnCollection();
|
||||
void checkBatchEscalationOnCollection();
|
||||
|
||||
/**
|
||||
* Flush batch if we escalated batch mode on saving or deleting a collection.
|
||||
*/
|
||||
public void flushBatchOnCollection();
|
||||
|
||||
void flushBatchOnCollection();
|
||||
|
||||
}
|
||||
|
||||
@@ -2,5 +2,5 @@ package com.avaje.ebeaninternal.api;
|
||||
|
||||
public interface SpiTransactionScopeManager {
|
||||
|
||||
public void replace(SpiTransaction t);
|
||||
void replace(SpiTransaction t);
|
||||
}
|
||||
|
||||
@@ -11,66 +11,66 @@ public interface SpiUpdate<T> extends Update<T> {
|
||||
* The type of the update request.
|
||||
*/
|
||||
enum OrmUpdateType {
|
||||
INSERT{
|
||||
INSERT {
|
||||
public String toString() {
|
||||
return "Insert";
|
||||
}
|
||||
},
|
||||
UPDATE{
|
||||
UPDATE {
|
||||
public String toString() {
|
||||
return "Update";
|
||||
}
|
||||
},
|
||||
DELETE{
|
||||
},
|
||||
DELETE {
|
||||
public String toString() {
|
||||
return "Delete";
|
||||
}
|
||||
},
|
||||
UNKNOWN{
|
||||
UNKNOWN {
|
||||
public String toString() {
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the type of bean being updated.
|
||||
*/
|
||||
public Class<?> getBeanType();
|
||||
Class<?> getBeanType();
|
||||
|
||||
/**
|
||||
* Return the type of this - insert, update or delete.
|
||||
*/
|
||||
public OrmUpdateType getOrmUpdateType();
|
||||
OrmUpdateType getOrmUpdateType();
|
||||
|
||||
/**
|
||||
* Return the name of the table being modified.
|
||||
*/
|
||||
public String getBaseTable();
|
||||
String getBaseTable();
|
||||
|
||||
/**
|
||||
* Return the update statement. This could be either sql or an orm update with bean types and property names.
|
||||
*/
|
||||
public String getUpdateStatement();
|
||||
String getUpdateStatement();
|
||||
|
||||
/**
|
||||
* Return the timeout in seconds.
|
||||
*/
|
||||
public int getTimeout();
|
||||
int getTimeout();
|
||||
|
||||
/**
|
||||
* Return true if the cache should be notified to invalidate objects.
|
||||
*/
|
||||
public boolean isNotifyCache();
|
||||
boolean isNotifyCache();
|
||||
|
||||
/**
|
||||
* Return the bind parameters.
|
||||
*/
|
||||
public BindParams getBindParams();
|
||||
BindParams getBindParams();
|
||||
|
||||
/**
|
||||
* Set the generated sql used.
|
||||
*/
|
||||
public void setGeneratedSql(String sql);
|
||||
void setGeneratedSql(String sql);
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@ import com.avaje.ebeaninternal.server.persist.dmlbind.Bindable;
|
||||
* <p>
|
||||
* The plans are cached by the BeanDescriptors.
|
||||
* </>
|
||||
*
|
||||
* @author rbygrave
|
||||
*/
|
||||
public interface SpiUpdatePlan {
|
||||
|
||||
@@ -28,48 +26,42 @@ public interface SpiUpdatePlan {
|
||||
* deployment.
|
||||
* </p>
|
||||
*/
|
||||
public boolean isEmptySetClause();
|
||||
boolean isEmptySetClause();
|
||||
|
||||
/**
|
||||
* Bind given the request and bean. The bean could be the oldValues bean
|
||||
* when binding a update or delete where clause with ALL concurrency mode.
|
||||
*/
|
||||
public void bindSet(DmlHandler bind, EntityBean bean) throws SQLException;
|
||||
void bindSet(DmlHandler bind, EntityBean bean) throws SQLException;
|
||||
|
||||
/**
|
||||
* Return the time this plan was created.
|
||||
*/
|
||||
public long getTimeCreated();
|
||||
long getTimeCreated();
|
||||
|
||||
/**
|
||||
* Return the time this plan was last used.
|
||||
*/
|
||||
public Long getTimeLastUsed();
|
||||
Long getTimeLastUsed();
|
||||
|
||||
/**
|
||||
* Return the hash key for this plan.
|
||||
*/
|
||||
public Integer getKey();
|
||||
Integer getKey();
|
||||
|
||||
/**
|
||||
* Return the concurrency mode for this plan.
|
||||
*/
|
||||
public ConcurrencyMode getMode();
|
||||
ConcurrencyMode getMode();
|
||||
|
||||
/**
|
||||
* Return the update SQL statement.
|
||||
*/
|
||||
public String getSql();
|
||||
String getSql();
|
||||
|
||||
/**
|
||||
* Return the set of bindable update properties.
|
||||
*/
|
||||
public Bindable getSet();
|
||||
|
||||
// /**
|
||||
// * Return the properties that where changed and should be included in the
|
||||
// * update statement.
|
||||
// */
|
||||
// public Set<String> getProperties();
|
||||
Bindable getSet();
|
||||
|
||||
}
|
||||
+354
-341
@@ -1,22 +1,18 @@
|
||||
package com.avaje.ebeaninternal.server.cache;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import com.avaje.ebean.BackgroundExecutor;
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
import com.avaje.ebean.cache.ServerCache;
|
||||
import com.avaje.ebean.cache.ServerCacheOptions;
|
||||
import com.avaje.ebean.cache.ServerCacheStatistics;
|
||||
import com.avaje.ebeaninternal.server.util.LongAdder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* The default cache implementation.
|
||||
@@ -27,375 +23,392 @@ import org.slf4j.LoggerFactory;
|
||||
*/
|
||||
public class DefaultServerCache implements ServerCache {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(DefaultServerCache.class);
|
||||
protected static final Logger logger = LoggerFactory.getLogger(DefaultServerCache.class);
|
||||
|
||||
private static final CacheEntryComparator comparator = new CacheEntryComparator();
|
||||
|
||||
private final ConcurrentHashMap<Object, CacheEntry> map = new ConcurrentHashMap<Object, CacheEntry>();
|
||||
|
||||
private final AtomicInteger missCount = new AtomicInteger();
|
||||
|
||||
private final AtomicInteger removedHitCount = new AtomicInteger();
|
||||
|
||||
private final Object monitor = new Object();
|
||||
|
||||
private final String name;
|
||||
|
||||
private int maxSize;
|
||||
|
||||
private long trimFrequency;
|
||||
|
||||
private int maxIdleSecs;
|
||||
|
||||
private int maxSecsToLive;
|
||||
|
||||
public DefaultServerCache(String name, ServerCacheOptions options) {
|
||||
this(name, options.getMaxSize(), options.getMaxIdleSecs(), options.getMaxSecsToLive());
|
||||
}
|
||||
|
||||
public DefaultServerCache(String name, int maxSize, int maxIdleSecs, int maxSecsToLive) {
|
||||
this.name = name;
|
||||
this.maxSize = maxSize;
|
||||
this.maxIdleSecs = maxIdleSecs;
|
||||
this.maxSecsToLive = maxSecsToLive;
|
||||
this.trimFrequency = 60;
|
||||
|
||||
}
|
||||
|
||||
public void init(EbeanServer server) {
|
||||
|
||||
TrimTask trim = new TrimTask();
|
||||
|
||||
BackgroundExecutor executor = server.getBackgroundExecutor();
|
||||
executor.executePeriodically(trim, trimFrequency, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public ServerCacheStatistics getStatistics(boolean reset) {
|
||||
|
||||
ServerCacheStatistics s = new ServerCacheStatistics();
|
||||
s.setCacheName(name);
|
||||
s.setMaxSize(maxSize);
|
||||
|
||||
// these counters won't necessarily be consistent with
|
||||
// respect to each other as activity can occur while
|
||||
// they are being calculated
|
||||
int mc = reset ? missCount.getAndSet(0) : missCount.get();
|
||||
int hc = getHitCount(reset);
|
||||
int size = size();
|
||||
|
||||
s.setSize(size);
|
||||
s.setHitCount(hc);
|
||||
s.setMissCount(mc);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
public int getHitRatio() {
|
||||
|
||||
int mc = missCount.get();
|
||||
int hc = getHitCount(false);
|
||||
|
||||
int totalCount = hc + mc;
|
||||
if (totalCount == 0){
|
||||
return 0;
|
||||
} else {
|
||||
return hc * 100 / totalCount;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private int getHitCount(boolean reset) {
|
||||
|
||||
int hc = reset ? removedHitCount.getAndSet(0) : removedHitCount.get();
|
||||
|
||||
for (CacheEntry cacheEntry : map.values()) {
|
||||
hc += cacheEntry.getHitCount(reset);
|
||||
}
|
||||
|
||||
return hc;
|
||||
}
|
||||
/**
|
||||
* Compare by last access time (for LRU eviction).
|
||||
*/
|
||||
public static final CompareByLastAccess BY_LAST_ACCESS = new CompareByLastAccess();
|
||||
|
||||
|
||||
public ServerCacheOptions getOptions() {
|
||||
synchronized (monitor) {
|
||||
ServerCacheOptions o = new ServerCacheOptions();
|
||||
o.setMaxIdleSecs(maxIdleSecs);
|
||||
o.setMaxSize(maxSize);
|
||||
o.setMaxSecsToLive(maxSecsToLive);
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
||||
public void setOptions(ServerCacheOptions o) {
|
||||
synchronized (monitor) {
|
||||
maxIdleSecs = o.getMaxIdleSecs();
|
||||
maxSize = o.getMaxSize();
|
||||
maxSecsToLive = o.getMaxSecsToLive();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the max cache size.
|
||||
*/
|
||||
public int getMaxSize() {
|
||||
return maxSize;
|
||||
}
|
||||
/**
|
||||
* The underlying map (ConcurrentHashMap or similar)
|
||||
*/
|
||||
protected final Map<Object, CacheEntry> map;
|
||||
|
||||
/**
|
||||
* Set the max cache size.
|
||||
*/
|
||||
public void setMaxSize(int maxSize) {
|
||||
synchronized (monitor) {
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
}
|
||||
// LongAdder is a highly concurrent low latency counter (back ported from Java8)
|
||||
protected final LongAdder missCount = new LongAdder();
|
||||
protected final LongAdder hitCount = new LongAdder();
|
||||
protected final LongAdder insertCount = new LongAdder();
|
||||
protected final LongAdder updateCount = new LongAdder();
|
||||
protected final LongAdder removeCount = new LongAdder();
|
||||
protected final LongAdder clearCount = new LongAdder();
|
||||
|
||||
/**
|
||||
* Return the max idle time.
|
||||
*/
|
||||
public long getMaxIdleSecs() {
|
||||
return maxIdleSecs;
|
||||
}
|
||||
protected final LongAdder evictByIdle = new LongAdder();
|
||||
protected final LongAdder evictByTTL = new LongAdder();
|
||||
protected final LongAdder evictByLRU = new LongAdder();
|
||||
protected final LongAdder evictCount = new LongAdder();
|
||||
protected final LongAdder evictMicros = new LongAdder();
|
||||
|
||||
/**
|
||||
* Set the max idle time.
|
||||
*/
|
||||
public void setMaxIdleSecs(int maxIdleSecs) {
|
||||
synchronized (monitor) {
|
||||
this.maxIdleSecs = maxIdleSecs;
|
||||
}
|
||||
}
|
||||
protected final Object monitor = new Object();
|
||||
|
||||
/**
|
||||
* Return the maximum time to live.
|
||||
*/
|
||||
public long getMaxSecsToLive() {
|
||||
return maxSecsToLive;
|
||||
}
|
||||
protected final String name;
|
||||
|
||||
/**
|
||||
* Set the maximum time to live.
|
||||
*/
|
||||
public void setMaxSecsToLive(int maxSecsToLive) {
|
||||
synchronized (monitor) {
|
||||
this.maxSecsToLive = maxSecsToLive;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of the cache.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
protected int maxSize;
|
||||
|
||||
/**
|
||||
* Clear the cache.
|
||||
*/
|
||||
public void clear() {
|
||||
map.clear();
|
||||
}
|
||||
protected int trimFrequency;
|
||||
|
||||
/**
|
||||
* Return a value from the cache.
|
||||
*/
|
||||
public Object get(Object key) {
|
||||
|
||||
CacheEntry entry = map.get(key);
|
||||
|
||||
if (entry == null){
|
||||
missCount.incrementAndGet();
|
||||
return null;
|
||||
|
||||
} else {
|
||||
// get value incrementing last
|
||||
// access time and hitCount
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
protected int maxIdleSecs;
|
||||
|
||||
/**
|
||||
* Put a value into the cache.
|
||||
*/
|
||||
public Object put(Object key, Object value) {
|
||||
// put new entry with create time
|
||||
CacheEntry entry = map.put(key, new CacheEntry(key, value));
|
||||
if (entry == null){
|
||||
return null;
|
||||
} else {
|
||||
int removedHits = entry.getHitCount(true);
|
||||
removedHitCount.addAndGet(removedHits);
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
protected int maxSecsToLive;
|
||||
|
||||
/**
|
||||
* Put a value into the cache but only if absent.
|
||||
*/
|
||||
public Object putIfAbsent(Object key, Object value) {
|
||||
CacheEntry entry = map.putIfAbsent(key, new CacheEntry(key, value));
|
||||
if (entry == null){
|
||||
return null;
|
||||
} else {
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Construct using a ConcurrentHashMap and cache options.
|
||||
*/
|
||||
public DefaultServerCache(String name, ServerCacheOptions options) {
|
||||
this(name, new ConcurrentHashMap<Object, CacheEntry>(), options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an entry from the cache.
|
||||
*/
|
||||
public Object remove(Object key) {
|
||||
CacheEntry entry = map.remove(key);
|
||||
if (entry == null){
|
||||
return null;
|
||||
} else {
|
||||
int removedHits = entry.getHitCount(true);
|
||||
removedHitCount.addAndGet(removedHits);
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Construct passing in name, map and base eviction controls as ServerCacheOptions.
|
||||
*/
|
||||
public DefaultServerCache(String name, Map<Object, CacheEntry> map, ServerCacheOptions options) {
|
||||
this(name, map, options.getMaxSize(), options.getMaxIdleSecs(), options.getMaxSecsToLive(), options.getTrimFrequency());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of elements in the cache.
|
||||
*/
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
/**
|
||||
* Construct passing in name, map and base eviction controls.
|
||||
*/
|
||||
public DefaultServerCache(String name, Map<Object, CacheEntry> map, int maxSize, int maxIdleSecs, int maxSecsToLive, int trimFrequency) {
|
||||
this.name = name;
|
||||
this.map = map;
|
||||
this.maxSize = maxSize;
|
||||
this.maxIdleSecs = maxIdleSecs;
|
||||
this.maxSecsToLive = maxSecsToLive;
|
||||
this.trimFrequency = trimFrequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* The task used to periodically trim the cache.
|
||||
*/
|
||||
private class TrimTask implements Runnable {
|
||||
@Override
|
||||
public void init(EbeanServer server) {
|
||||
|
||||
public void run() {
|
||||
EvictionRunnable trim = new EvictionRunnable();
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
if (logger.isTraceEnabled()){
|
||||
logger.trace("trimming cache " + name);
|
||||
}
|
||||
|
||||
int trimmedByIdle = 0;
|
||||
int trimmedByTTL = 0;
|
||||
int trimmedByLRU = 0;
|
||||
// default to trimming the cache every 60 seconds
|
||||
long trimFreqSecs = (trimFrequency == 0) ? 60 : trimFrequency;
|
||||
|
||||
boolean trimMaxSize = maxSize > 0 && maxSize < size();
|
||||
BackgroundExecutor executor = server.getBackgroundExecutor();
|
||||
executor.executePeriodically(trim, trimFreqSecs, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
ArrayList<CacheEntry> activeList = new ArrayList<CacheEntry>();
|
||||
@Override
|
||||
public ServerCacheStatistics getStatistics(boolean reset) {
|
||||
|
||||
long idleExpire = System.currentTimeMillis() - (maxIdleSecs*1000);
|
||||
long ttlExpire = System.currentTimeMillis() - (maxSecsToLive*1000);
|
||||
ServerCacheStatistics cacheStats = new ServerCacheStatistics();
|
||||
cacheStats.setCacheName(name);
|
||||
cacheStats.setMaxSize(maxSize);
|
||||
|
||||
Iterator<CacheEntry> it = map.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
CacheEntry cacheEntry = it.next();
|
||||
if (maxIdleSecs > 0 && idleExpire > cacheEntry.getLastAccessTime()) {
|
||||
it.remove();
|
||||
trimmedByIdle++;
|
||||
// these counters won't necessarily be consistent with
|
||||
// respect to each other as activity can occur while
|
||||
// they are being calculated here but they should be good enough
|
||||
// and we don't want to reduce concurrent use to make them consistent
|
||||
long clear = reset ? clearCount.sumThenReset() : clearCount.sum();
|
||||
long remove = reset ? removeCount.sumThenReset() : removeCount.sum();
|
||||
long update = reset ? updateCount.sumThenReset() : updateCount.sum();
|
||||
long insert = reset ? insertCount.sumThenReset() : insertCount.sum();
|
||||
long miss = reset ? missCount.sumThenReset() : missCount.sum();
|
||||
long hit = reset ? hitCount.sumThenReset() : hitCount.sum();
|
||||
|
||||
} else if (maxSecsToLive > 0 && ttlExpire > cacheEntry.getCreateTime()) {
|
||||
it.remove();
|
||||
trimmedByTTL++;
|
||||
long evict = reset ? evictCount.sumThenReset() : evictCount.sum();
|
||||
long evictTime = reset ? evictMicros.sumThenReset() : evictMicros.sum();
|
||||
long evictIdle = reset ? evictByIdle.sumThenReset() : evictByIdle.sum();
|
||||
long evictTTL = reset ? evictByTTL.sumThenReset() : evictByTTL.sum();
|
||||
long evictLRU = reset ? evictByLRU.sumThenReset() : evictByLRU.sum();
|
||||
|
||||
} else if (trimMaxSize) {
|
||||
activeList.add(cacheEntry);
|
||||
}
|
||||
}
|
||||
int size = size();
|
||||
|
||||
if (trimMaxSize) {
|
||||
trimmedByLRU = activeList.size() - maxSize;
|
||||
cacheStats.setSize(size);
|
||||
cacheStats.setHitCount(hit);
|
||||
cacheStats.setMissCount(miss);
|
||||
cacheStats.setInsertCount(insert);
|
||||
cacheStats.setUpdateCount(update);
|
||||
cacheStats.setRemoveCount(remove);
|
||||
cacheStats.setClearCount(clear);
|
||||
|
||||
if (trimmedByLRU > 0) {
|
||||
// sort into last access time ascending
|
||||
Collections.sort(activeList, comparator);
|
||||
for (int i = maxSize; i < activeList.size(); i++) {
|
||||
// remove if still in the cache
|
||||
map.remove(activeList.get(i).getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long exeTime = System.currentTimeMillis() - startTime;
|
||||
|
||||
if (logger.isDebugEnabled()){
|
||||
logger.debug("Executed trim of cache " + name + " in ["+exeTime
|
||||
+"]millis idle[" + trimmedByIdle + "] timeToLive["
|
||||
+ trimmedByTTL + "] accessTime["
|
||||
+ trimmedByLRU + "]");
|
||||
}
|
||||
cacheStats.setEvictionRunCount(evict);
|
||||
cacheStats.setEvictionRunMicros(evictTime);
|
||||
cacheStats.setEvictByIdle(evictIdle);
|
||||
cacheStats.setEvictByTTL(evictTTL);
|
||||
cacheStats.setEvictByLRU(evictLRU);
|
||||
|
||||
}
|
||||
return cacheStats;
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public int getHitRatio() {
|
||||
|
||||
/**
|
||||
* Comparator for sorting by last access time.
|
||||
*/
|
||||
private static class CacheEntryComparator implements Comparator<CacheEntry>, Serializable {
|
||||
long mc = missCount.sum();
|
||||
long hc = hitCount.sum();
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
long totalCount = hc + mc;
|
||||
if (totalCount == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return (int) (hc * 100 / totalCount);
|
||||
}
|
||||
}
|
||||
|
||||
public int compare(CacheEntry o1, CacheEntry o2) {
|
||||
|
||||
return o1.getLastAccessLong().compareTo(o2.getLastAccessLong());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the values to additionally hold createTime and lastAccessTime.
|
||||
*/
|
||||
public static class CacheEntry {
|
||||
/**
|
||||
* Return the options controlling the cache.
|
||||
*/
|
||||
@Override
|
||||
public ServerCacheOptions getOptions() {
|
||||
synchronized (monitor) {
|
||||
ServerCacheOptions options = new ServerCacheOptions();
|
||||
options.setMaxIdleSecs(maxIdleSecs);
|
||||
options.setMaxSize(maxSize);
|
||||
options.setMaxSecsToLive(maxSecsToLive);
|
||||
options.setTrimFrequency(trimFrequency);
|
||||
return options;
|
||||
}
|
||||
}
|
||||
|
||||
private final Object key;
|
||||
private final Object value;
|
||||
private final long createTime;
|
||||
private final AtomicInteger hitCount = new AtomicInteger();
|
||||
private Long lastAccessTime;
|
||||
/**
|
||||
* Set the options controlling the cache
|
||||
*/
|
||||
@Override
|
||||
public void setOptions(ServerCacheOptions options) {
|
||||
synchronized (monitor) {
|
||||
maxIdleSecs = options.getMaxIdleSecs();
|
||||
maxSize = options.getMaxSize();
|
||||
maxSecsToLive = options.getMaxSecsToLive();
|
||||
}
|
||||
}
|
||||
|
||||
public CacheEntry(Object key, Object value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.createTime = System.currentTimeMillis();
|
||||
this.lastAccessTime = Long.valueOf(createTime);
|
||||
}
|
||||
/**
|
||||
* Return the name of the cache.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Object getKey() {
|
||||
return key;
|
||||
}
|
||||
/**
|
||||
* Clear the cache.
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
clearCount.increment();
|
||||
map.clear();
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
// object assignment is atomic
|
||||
hitCount.incrementAndGet();
|
||||
this.lastAccessTime = Long.valueOf(System.currentTimeMillis());
|
||||
return value;
|
||||
}
|
||||
/**
|
||||
* Return a value from the cache.
|
||||
*/
|
||||
@Override
|
||||
public Object get(Object key) {
|
||||
|
||||
public long getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
CacheEntry entry = map.get(key);
|
||||
if (entry == null) {
|
||||
missCount.increment();
|
||||
return null;
|
||||
|
||||
public long getLastAccessTime() {
|
||||
return lastAccessTime.longValue();
|
||||
}
|
||||
} else {
|
||||
// Important that hitCount.increment() MUST be low latency under concurrent
|
||||
// use hence must use LongAdder or better here
|
||||
hitCount.increment();
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
public Long getLastAccessLong() {
|
||||
return lastAccessTime;
|
||||
}
|
||||
/**
|
||||
* Put a value into the cache.
|
||||
*/
|
||||
@Override
|
||||
public Object put(Object key, Object value) {
|
||||
CacheEntry entry = map.put(key, new CacheEntry(key, value));
|
||||
if (entry == null) {
|
||||
insertCount.increment();
|
||||
return null;
|
||||
} else {
|
||||
updateCount.increment();
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
public int getHitCount(boolean reset) {
|
||||
if (reset){
|
||||
return hitCount.getAndSet(0);
|
||||
/**
|
||||
* Remove an entry from the cache.
|
||||
*/
|
||||
@Override
|
||||
public Object remove(Object key) {
|
||||
CacheEntry entry = map.remove(key);
|
||||
if (entry == null) {
|
||||
return null;
|
||||
} else {
|
||||
removeCount.increment();
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of elements in the cache.
|
||||
*/
|
||||
@Override
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the size to trim to based on the max size.
|
||||
* <p>
|
||||
* This returns 90% of the max size.
|
||||
* </p>
|
||||
*/
|
||||
protected int getTrimSize() {
|
||||
return (maxSize * 90 / 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the eviction based on Idle time, Time to live and LRU last access.
|
||||
*/
|
||||
public void runEviction() {
|
||||
|
||||
long trimForMaxSize;
|
||||
if (maxSize == 0) {
|
||||
trimForMaxSize = 0;
|
||||
} else {
|
||||
trimForMaxSize = size() - maxSize;
|
||||
}
|
||||
|
||||
if (maxIdleSecs == 0 && maxSecsToLive == 0 && trimForMaxSize < 0) {
|
||||
// nothing to trim on this cache
|
||||
return;
|
||||
}
|
||||
|
||||
long startNanos = System.nanoTime();
|
||||
|
||||
long trimmedByIdle = 0;
|
||||
long trimmedByTTL = 0;
|
||||
long trimmedByLRU = 0;
|
||||
|
||||
ArrayList<CacheEntry> activeList = new ArrayList<CacheEntry>();
|
||||
|
||||
long idleExpire = System.currentTimeMillis() - (maxIdleSecs * 1000);
|
||||
long ttlExpire = System.currentTimeMillis() - (maxSecsToLive * 1000);
|
||||
|
||||
Iterator<CacheEntry> it = map.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
CacheEntry cacheEntry = it.next();
|
||||
if (maxIdleSecs > 0 && idleExpire > cacheEntry.getLastAccessTime()) {
|
||||
it.remove();
|
||||
trimmedByIdle++;
|
||||
|
||||
} else if (maxSecsToLive > 0 && ttlExpire > cacheEntry.getCreateTime()) {
|
||||
it.remove();
|
||||
trimmedByTTL++;
|
||||
|
||||
} else if (trimForMaxSize > 0) {
|
||||
activeList.add(cacheEntry);
|
||||
}
|
||||
}
|
||||
|
||||
if (trimForMaxSize > 0) {
|
||||
trimmedByLRU = activeList.size() - maxSize;
|
||||
if (trimmedByLRU > 0) {
|
||||
// sort into last access time ascending
|
||||
Collections.sort(activeList, BY_LAST_ACCESS);
|
||||
int trimSize = getTrimSize();
|
||||
for (int i = trimSize; i < activeList.size(); i++) {
|
||||
// remove if still in the cache
|
||||
map.remove(activeList.get(i).getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
long exeNanos = System.nanoTime() - startNanos;
|
||||
long exeMicros = TimeUnit.MICROSECONDS.convert(exeNanos, TimeUnit.NANOSECONDS);
|
||||
|
||||
// increment the eviction statistics
|
||||
evictMicros.add(exeMicros);
|
||||
evictCount.increment();
|
||||
evictByIdle.add(trimmedByIdle);
|
||||
evictByTTL.add(trimmedByTTL);
|
||||
evictByLRU.add(trimmedByLRU);
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Executed trim of cache {} in [{}]millis idle[{}] timeToLive[{}] accessTime[{}]"
|
||||
, name, exeMicros, trimmedByIdle, trimmedByTTL, trimmedByLRU);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runnable that calls the eviction routine.
|
||||
*/
|
||||
public class EvictionRunnable implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
runEviction();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Comparator for sorting by last access time.
|
||||
*/
|
||||
public static class CompareByLastAccess implements Comparator<CacheEntry>, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public int compare(CacheEntry entry1, CacheEntry entry2) {
|
||||
return Long.compare(entry1.getLastAccessTime(), entry2.getLastAccessTime());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the value to additionally hold createTime and lastAccessTime and hit counter.
|
||||
*/
|
||||
public static class CacheEntry {
|
||||
|
||||
private final Object key;
|
||||
private final Object value;
|
||||
private final long createTime;
|
||||
private long lastAccessTime;
|
||||
|
||||
public CacheEntry(Object key, Object value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.createTime = System.currentTimeMillis();
|
||||
this.lastAccessTime = createTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the entry key.
|
||||
*/
|
||||
public Object getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the entry value.
|
||||
*/
|
||||
public Object getValue() {
|
||||
// long assignment should be atomic these days (Ref Cliff Click)
|
||||
lastAccessTime = System.currentTimeMillis();
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the time the entry was created.
|
||||
*/
|
||||
public long getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the time the entry was last accessed.
|
||||
*/
|
||||
public long getLastAccessTime() {
|
||||
return lastAccessTime;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
return hitCount.get();
|
||||
}
|
||||
}
|
||||
public int getHitCount() {
|
||||
return hitCount.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,109 +1,128 @@
|
||||
package com.avaje.ebeaninternal.server.core;
|
||||
|
||||
import com.avaje.ebeaninternal.server.util.ClassPathSearch;
|
||||
import com.avaje.ebeaninternal.api.ClassPathSearchService;
|
||||
import com.avaje.ebeaninternal.server.util.ClassPathSearchFilter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Searches for interesting classes such as Entities, Embedded and ScalarTypes.
|
||||
*/
|
||||
public class BootupClassPathSearch {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(BootupClassPathSearch.class);
|
||||
private static final Logger logger = LoggerFactory.getLogger(BootupClassPathSearch.class);
|
||||
|
||||
private final Object monitor = new Object();
|
||||
private final Object monitor = new Object();
|
||||
|
||||
private final ClassLoader classLoader;
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
private final List<String> packages;
|
||||
private final List<String> packages;
|
||||
|
||||
private final List<String> jars;
|
||||
|
||||
private BootupClasses bootupClasses;
|
||||
|
||||
private List<ClassPathSearchService> classPathSearchServices;
|
||||
|
||||
private BootupClasses bootupClasses;
|
||||
|
||||
private final String classPathReaderClassName;
|
||||
|
||||
/**
|
||||
* Construct and search for interesting classes.
|
||||
*/
|
||||
public BootupClassPathSearch(ClassLoader classLoader, List<String> packages, List<String> jars, String classPathReaderClassName) {
|
||||
this.classLoader = (classLoader == null) ? getClass().getClassLoader() : classLoader;
|
||||
this.packages = packages;
|
||||
this.jars = jars;
|
||||
/**
|
||||
* Construct and search for interesting classes.
|
||||
*/
|
||||
public BootupClassPathSearch(ClassLoader classLoader, List<String> packages, List<String> jars, String classPathReaderClassName) {
|
||||
this.classLoader = (classLoader == null) ? getClass().getClassLoader() : classLoader;
|
||||
this.packages = packages;
|
||||
this.jars = jars;
|
||||
this.classPathReaderClassName = classPathReaderClassName;
|
||||
}
|
||||
|
||||
public BootupClasses getBootupClasses() {
|
||||
synchronized (monitor) {
|
||||
|
||||
if (bootupClasses == null){
|
||||
bootupClasses = search();
|
||||
}
|
||||
|
||||
return bootupClasses;
|
||||
}
|
||||
}
|
||||
loadAndInitializeClassPathSearchServices();
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the classPath for the classes we are interested in.
|
||||
*/
|
||||
private BootupClasses search() {
|
||||
synchronized (monitor) {
|
||||
try {
|
||||
|
||||
BootupClasses bc = new BootupClasses();
|
||||
public BootupClasses getBootupClasses() {
|
||||
synchronized (monitor) {
|
||||
|
||||
long st = System.currentTimeMillis();
|
||||
if (bootupClasses == null) {
|
||||
bootupClasses = search();
|
||||
}
|
||||
|
||||
ClassPathSearchFilter filter = createFilter();
|
||||
return bootupClasses;
|
||||
}
|
||||
}
|
||||
|
||||
ClassPathSearch finder = new ClassPathSearch(classLoader, filter, bc, classPathReaderClassName);
|
||||
/**
|
||||
* Search the classPath for the classes we are interested in.
|
||||
*/
|
||||
private BootupClasses search() {
|
||||
synchronized (monitor) {
|
||||
try {
|
||||
|
||||
finder.findClasses();
|
||||
Set<String> jars = finder.getJarHits();
|
||||
Set<String> pkgs = finder.getPackageHits();
|
||||
BootupClasses bc = new BootupClasses();
|
||||
|
||||
long searchTime = System.currentTimeMillis() - st;
|
||||
long st = System.currentTimeMillis();
|
||||
|
||||
String msg = "Classpath search hits in jars" + jars + " pkgs" + pkgs + " searchTime[" + searchTime+ "]";
|
||||
logger.info(msg);
|
||||
ClassPathSearchFilter filter = createFilter();
|
||||
|
||||
return bc;
|
||||
Set<String> foundJars = new HashSet<String>();
|
||||
Set<String> foundPkgs = new HashSet<String>();
|
||||
|
||||
} catch (Exception ex) {
|
||||
String msg = "Error in classpath search (looking for entities etc)";
|
||||
throw new RuntimeException(msg, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ClassPathSearchFilter createFilter() {
|
||||
|
||||
ClassPathSearchFilter filter = new ClassPathSearchFilter();
|
||||
filter.addDefaultExcludePackages();
|
||||
|
||||
if (packages != null && packages.size() > 0) {
|
||||
for (String packageName : packages) {
|
||||
filter.includePackage(packageName);
|
||||
}
|
||||
|
||||
// if they specified include packages, they don't want by default to include everything
|
||||
filter.setDefaultPackageMatch(false);
|
||||
for (ClassPathSearchService finder : this.classPathSearchServices) {
|
||||
finder.init(classLoader, filter, bc, classPathReaderClassName);
|
||||
finder.findClasses();
|
||||
foundJars.addAll(finder.getJarHits());
|
||||
foundPkgs.addAll(finder.getPackageHits());
|
||||
}
|
||||
|
||||
if (jars != null && jars.size() > 0) {
|
||||
for (String jarName : jars) {
|
||||
filter.includeJar(jarName);
|
||||
}
|
||||
long searchTime = System.currentTimeMillis() - st;
|
||||
|
||||
// if they specified jars to specifically include, they don't want everything included
|
||||
filter.setDefaultJarMatch(false);
|
||||
}
|
||||
logger.info("Classpath search hits in jars {} pkgs {} searchTime [{}]", foundJars, foundPkgs, searchTime);
|
||||
return bc;
|
||||
|
||||
} catch (Exception ex) {
|
||||
String msg = "Error in classpath search (looking for entities etc)";
|
||||
throw new RuntimeException(msg, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ClassPathSearchFilter createFilter() {
|
||||
|
||||
ClassPathSearchFilter filter = new ClassPathSearchFilter();
|
||||
filter.addDefaultExcludePackages();
|
||||
|
||||
if (packages != null && packages.size() > 0) {
|
||||
for (String packageName : packages) {
|
||||
filter.includePackage(packageName);
|
||||
}
|
||||
|
||||
// if they specified include packages, they don't want by default to include everything
|
||||
filter.setDefaultPackageMatch(false);
|
||||
}
|
||||
|
||||
if (jars != null && jars.size() > 0) {
|
||||
for (String jarName : jars) {
|
||||
filter.includeJar(jarName);
|
||||
}
|
||||
|
||||
// if they specified jars to specifically include, they don't want everything included
|
||||
filter.setDefaultJarMatch(false);
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and initialize all ClassPathSearchServices
|
||||
*/
|
||||
private void loadAndInitializeClassPathSearchServices() {
|
||||
if (this.classPathSearchServices == null) {
|
||||
this.classPathSearchServices = new ArrayList<ClassPathSearchService>();
|
||||
}
|
||||
|
||||
for (ClassPathSearchService searchService : ServiceLoader.load(ClassPathSearchService.class, classLoader)) {
|
||||
this.classPathSearchServices.add(searchService);
|
||||
}
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,18 +9,13 @@ import javax.persistence.Embeddable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import com.avaje.ebean.event.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.avaje.ebean.config.CompoundType;
|
||||
import com.avaje.ebean.config.ScalarTypeConverter;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.event.BeanFinder;
|
||||
import com.avaje.ebean.event.BeanPersistController;
|
||||
import com.avaje.ebean.event.BeanPersistListener;
|
||||
import com.avaje.ebean.event.BeanQueryAdapter;
|
||||
import com.avaje.ebean.event.ServerConfigStartup;
|
||||
import com.avaje.ebean.event.TransactionEventListener;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarType;
|
||||
import com.avaje.ebeaninternal.server.util.ClassPathSearchMatcher;
|
||||
|
||||
@@ -46,16 +41,15 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
|
||||
private ArrayList<Class<?>> transactionEventListenerList = new ArrayList<Class<?>>();
|
||||
|
||||
private ArrayList<Class<?>> beanFinderList = new ArrayList<Class<?>>();
|
||||
|
||||
private ArrayList<Class<?>> beanListenerList = new ArrayList<Class<?>>();
|
||||
|
||||
private ArrayList<Class<?>> beanFindControllerList = new ArrayList<Class<?>>();
|
||||
private ArrayList<Class<?>> beanQueryAdapterList = new ArrayList<Class<?>>();
|
||||
|
||||
private ArrayList<Class<?>> beanListenerList = new ArrayList<Class<?>>();
|
||||
|
||||
private ArrayList<Class<?>> serverConfigStartupList = new ArrayList<Class<?>>();
|
||||
private ArrayList<ServerConfigStartup> serverConfigStartupInstances = new ArrayList<ServerConfigStartup>();
|
||||
|
||||
private List<BeanFindController> findControllerInstances = new ArrayList<BeanFindController>();
|
||||
private List<BeanPersistController> persistControllerInstances = new ArrayList<BeanPersistController>();
|
||||
private List<BeanPersistListener> persistListenerInstances = new ArrayList<BeanPersistListener>();
|
||||
private List<BeanQueryAdapter> queryAdapterInstances = new ArrayList<BeanQueryAdapter>();
|
||||
@@ -112,6 +106,19 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add BeanFindController instances.
|
||||
*/
|
||||
public void addFindControllers(List<BeanFindController> findControllers) {
|
||||
if (findControllers != null) {
|
||||
for (BeanFindController c : findControllers) {
|
||||
this.findControllerInstances.add(c);
|
||||
// don't automatically instantiate
|
||||
this.beanFindControllerList.remove(c.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add TransactionEventListeners instances.
|
||||
*/
|
||||
@@ -161,6 +168,22 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
return queryAdapterInstances;
|
||||
}
|
||||
|
||||
public List<BeanFindController> getBeanFindControllers() {
|
||||
// add class registered BeanFindController to the
|
||||
// list of created instances
|
||||
for (Class<?> cls : beanFindControllerList) {
|
||||
try {
|
||||
BeanFindController newInstance = (BeanFindController) cls.newInstance();
|
||||
findControllerInstances.add(newInstance);
|
||||
} catch (Exception e) {
|
||||
String msg = "Error creating BeanPersistController " + cls;
|
||||
logger.error(msg, e);
|
||||
}
|
||||
}
|
||||
|
||||
return findControllerInstances;
|
||||
}
|
||||
|
||||
public List<BeanPersistListener> getBeanPersistListeners() {
|
||||
// add class registered BeanPersistController to the
|
||||
// already created instances
|
||||
@@ -212,63 +235,56 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
/**
|
||||
* Return the list of Embeddable classes.
|
||||
*/
|
||||
public ArrayList<Class<?>> getEmbeddables() {
|
||||
public List<Class<?>> getEmbeddables() {
|
||||
return embeddableList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of entity classes.
|
||||
*/
|
||||
public ArrayList<Class<?>> getEntities() {
|
||||
public List<Class<?>> getEntities() {
|
||||
return entityList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of ScalarTypes found.
|
||||
*/
|
||||
public ArrayList<Class<?>> getScalarTypes() {
|
||||
public List<Class<?>> getScalarTypes() {
|
||||
return scalarTypeList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of ScalarConverters found.
|
||||
*/
|
||||
public ArrayList<Class<?>> getScalarConverters() {
|
||||
public List<Class<?>> getScalarConverters() {
|
||||
return scalarConverterList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of ScalarConverters found.
|
||||
*/
|
||||
public ArrayList<Class<?>> getCompoundTypes() {
|
||||
public List<Class<?>> getCompoundTypes() {
|
||||
return compoundTypeList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of BeanControllers found.
|
||||
*/
|
||||
public ArrayList<Class<?>> getBeanControllers() {
|
||||
public List<Class<?>> getBeanControllers() {
|
||||
return beanControllerList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of TransactionEventListeners found
|
||||
*/
|
||||
public ArrayList<Class<?>> getTransactionEventListenerList() {
|
||||
public List<Class<?>> getTransactionEventListenerList() {
|
||||
return transactionEventListenerList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of BeanFinders found.
|
||||
*/
|
||||
public ArrayList<Class<?>> getBeanFinders() {
|
||||
return beanFinderList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of BeanListeners found.
|
||||
*/
|
||||
public ArrayList<Class<?>> getBeanListeners() {
|
||||
public List<Class<?>> getBeanListeners() {
|
||||
return beanListenerList;
|
||||
}
|
||||
|
||||
@@ -327,8 +343,8 @@ public class BootupClasses implements ClassPathSearchMatcher {
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
if (BeanFinder.class.isAssignableFrom(cls)) {
|
||||
beanFinderList.add(cls);
|
||||
if (BeanFindController.class.isAssignableFrom(cls)) {
|
||||
beanFindControllerList.add(cls);
|
||||
interesting = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,9 @@ public class DatabasePlatformFactory {
|
||||
if (dbName.equals("mysql")) {
|
||||
return new MySqlPlatform();
|
||||
}
|
||||
|
||||
if (dbName.equals("h2")) {
|
||||
return new H2Platform();
|
||||
}
|
||||
if (dbName.equals("sqlite")) {
|
||||
return new SQLitePlatform();
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ public class DefaultBeanLoader {
|
||||
query.where().raw(ew);
|
||||
}
|
||||
|
||||
query.setLazyLoadForParents(idList, many);
|
||||
query.setLazyLoadForParents(many);
|
||||
many.addWhereParentIdIn(query, idList);
|
||||
|
||||
query.setPersistenceContext(pc);
|
||||
|
||||
@@ -70,5 +70,9 @@ public class DefaultBeanState implements BeanState {
|
||||
public void setLoaded() {
|
||||
intercept.setLoaded();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setDisableLazyLoad(boolean disableLazyLoading) {
|
||||
intercept.setDisableLazyLoad(disableLazyLoading);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,7 +219,16 @@ public class DefaultContainer implements SpiContainer {
|
||||
|
||||
ServerCacheFactory cacheFactory = serverConfig.getServerCacheFactory();
|
||||
if (cacheFactory == null) {
|
||||
cacheFactory = new DefaultServerCacheFactory();
|
||||
ServiceLoader<ServerCacheFactory> cacheFactories = ServiceLoader.load(ServerCacheFactory.class);
|
||||
Iterator<ServerCacheFactory> iterator = cacheFactories.iterator();
|
||||
if (iterator.hasNext()) {
|
||||
// use the cacheFactory (via classpath service loader)
|
||||
cacheFactory = iterator.next();
|
||||
logger.debug("using ServerCacheFactory {}", cacheFactory.getClass());
|
||||
} else {
|
||||
// use the built in default
|
||||
cacheFactory = new DefaultServerCacheFactory();
|
||||
}
|
||||
}
|
||||
|
||||
return new DefaultServerCacheManager(cacheFactory, beanOptions, queryOptions);
|
||||
@@ -233,6 +242,7 @@ public class DefaultContainer implements SpiContainer {
|
||||
|
||||
BootupClasses bootupClasses = getBootupClasses1(serverConfig);
|
||||
bootupClasses.addPersistControllers(serverConfig.getPersistControllers());
|
||||
bootupClasses.addFindControllers(serverConfig.getFindControllers());
|
||||
bootupClasses.addTransactionEventListeners(serverConfig.getTransactionEventListeners());
|
||||
bootupClasses.addPersistListeners(serverConfig.getPersistListeners());
|
||||
bootupClasses.addQueryAdapters(serverConfig.getQueryAdapters());
|
||||
|
||||
@@ -38,6 +38,7 @@ import org.slf4j.LoggerFactory;
|
||||
import javax.management.InstanceAlreadyExistsException;
|
||||
import javax.management.MBeanServer;
|
||||
import javax.management.ObjectName;
|
||||
import javax.persistence.OptimisticLockException;
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@@ -87,7 +88,7 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
|
||||
private final BeanDescriptorManager beanDescriptorManager;
|
||||
|
||||
private final DiffHelp diffHelp = new DiffHelp();
|
||||
private final DiffHelp diffHelp;
|
||||
|
||||
private final AutoFetchManager autoFetchManager;
|
||||
|
||||
@@ -147,6 +148,8 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
*/
|
||||
private List<SpiEbeanPlugin> ebeanPlugins;
|
||||
|
||||
private final boolean updateAllPropertiesInBatch;
|
||||
|
||||
private final boolean collectQueryOrigins;
|
||||
|
||||
private final boolean collectQueryStatsByNode;
|
||||
@@ -170,6 +173,7 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
this.backgroundExecutor = config.getBackgroundExecutor();
|
||||
|
||||
this.serverName = serverConfig.getName();
|
||||
this.diffHelp = new DiffHelp(serverConfig.isDiffFlatMode());
|
||||
this.lazyLoadBatchSize = serverConfig.getLazyLoadBatchSize();
|
||||
this.queryBatchSize = serverConfig.getQueryBatchSize();
|
||||
this.cqueryEngine = config.getCQueryEngine();
|
||||
@@ -180,6 +184,7 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
this.beanDescriptorManager = config.getBeanDescriptorManager();
|
||||
beanDescriptorManager.setEbeanServer(this);
|
||||
|
||||
this.updateAllPropertiesInBatch = serverConfig.isUpdateAllPropertiesInBatch();
|
||||
this.collectQueryOrigins = serverConfig.isCollectQueryOrigins();
|
||||
this.collectQueryStatsByNode = serverConfig.isCollectQueryStatsByNode();
|
||||
this.maxCallStack = serverConfig.getMaxCallStack();
|
||||
@@ -198,19 +203,20 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
this.beanLoader = new DefaultBeanLoader(this);
|
||||
this.jsonContext = config.createJsonContext(this);
|
||||
|
||||
loadAndInitializePlugins(config);
|
||||
// load normal plugins late and call setup on all
|
||||
loadAndInitializePlugins(config.getServerConfig());
|
||||
|
||||
// Register with the JVM Shutdown hook
|
||||
ShutdownManager.registerEbeanServer(this);
|
||||
}
|
||||
|
||||
protected void loadAndInitializePlugins(InternalConfiguration config) {
|
||||
protected void loadAndInitializePlugins(ServerConfig config) {
|
||||
|
||||
List<SpiEbeanPlugin> spiPlugins = new ArrayList<SpiEbeanPlugin>();
|
||||
|
||||
for (SpiEbeanPlugin plugin : ServiceLoader.load(SpiEbeanPlugin.class)) {
|
||||
spiPlugins.add(plugin);
|
||||
plugin.setup(this, this.getDatabasePlatform(), config.getServerConfig());
|
||||
plugin.setup(this, this.getDatabasePlatform(), config);
|
||||
|
||||
if (plugin instanceof DdlGenerator) {
|
||||
// backwards compatible
|
||||
@@ -222,18 +228,24 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
// ServiceLoader not finding ddlGenerator (typically OSGi)
|
||||
ddlGenerator = new DdlGenerator();
|
||||
spiPlugins.add(ddlGenerator);
|
||||
ddlGenerator.setup(this, this.getDatabasePlatform(), config.getServerConfig());
|
||||
ddlGenerator.setup(this, this.getDatabasePlatform(), config);
|
||||
}
|
||||
|
||||
ebeanPlugins = Collections.unmodifiableList(spiPlugins);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of registered plugins.
|
||||
*/
|
||||
public List<SpiEbeanPlugin> getSpiEbeanPlugins() {
|
||||
return ebeanPlugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute all the plugins with an online flag indicating the DB is up or not.
|
||||
*/
|
||||
public void executePlugins(boolean online) {
|
||||
for(SpiEbeanPlugin plugin : ebeanPlugins) {
|
||||
for (SpiEbeanPlugin plugin : ebeanPlugins) {
|
||||
plugin.execute(online);
|
||||
}
|
||||
}
|
||||
@@ -243,6 +255,11 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
return collectQueryOrigins;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUpdateAllPropertiesInBatch() {
|
||||
return updateAllPropertiesInBatch;
|
||||
}
|
||||
|
||||
public int getLazyLoadBatchSize() {
|
||||
return lazyLoadBatchSize;
|
||||
}
|
||||
@@ -1155,16 +1172,15 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
public <T> T findUnique(Query<T> query, Transaction t) {
|
||||
|
||||
// actually a find by Id type of query...
|
||||
// ... perhaps with joins and cache hints?
|
||||
SpiQuery<T> q = (SpiQuery<T>) query;
|
||||
Object id = q.getId();
|
||||
// ... perhaps with joins and cache hints
|
||||
Object id = query.getId();
|
||||
if (id != null) {
|
||||
return findId(query, t);
|
||||
}
|
||||
|
||||
BeanDescriptor<T> desc = beanDescriptorManager.getBeanDescriptor(q.getBeanType());
|
||||
BeanDescriptor<T> desc = beanDescriptorManager.getBeanDescriptor(query.getBeanType());
|
||||
|
||||
T bean = desc.cacheNaturalKeyLookup(q, (SpiTransaction)t);
|
||||
T bean = desc.cacheNaturalKeyLookup((SpiQuery<T>)query, (SpiTransaction) t);
|
||||
if (bean != null) {
|
||||
return bean;
|
||||
}
|
||||
@@ -1316,15 +1332,6 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
return new LimitOffsetPagedList<T>(this, (SpiQuery<T>)query, pageIndex, pageSize);
|
||||
}
|
||||
|
||||
public <T> void findVisit(Query<T> query, QueryResultVisitor<T> visitor, Transaction t) {
|
||||
|
||||
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, t);
|
||||
|
||||
request.initTransIfRequired();
|
||||
request.findVisit(visitor);
|
||||
// no try finally - findVisit guarantee's cleanup of the transaction if required
|
||||
}
|
||||
|
||||
public <T> void findEach(Query<T> query, QueryEachConsumer<T> consumer, Transaction t) {
|
||||
|
||||
SpiOrmQueryRequest<T> request = createQueryRequest(Type.ITERATE, query, t);
|
||||
@@ -1357,6 +1364,19 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<Version<T>> findVersions(Query<T> query, Transaction transaction) {
|
||||
|
||||
SpiOrmQueryRequest<T> request = createQueryRequest(Type.LIST, query, transaction);
|
||||
try {
|
||||
request.initTransIfRequired();
|
||||
return request.findVersions();
|
||||
|
||||
} finally {
|
||||
request.endTransIfRequired();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> List<T> findList(Query<T> query, Transaction t) {
|
||||
|
||||
@@ -1492,17 +1512,15 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
persister.update(checkEntityBean(bean), t, deleteMissingChildren);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update all beans in the collection.
|
||||
*/
|
||||
public void update(Collection<?> beans) {
|
||||
update(beans, null);
|
||||
@Override
|
||||
public void updateAll(Collection<?> beans) throws OptimisticLockException {
|
||||
updateAll(beans, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update all beans in the collection with an explicit transaction.
|
||||
*/
|
||||
public void update(Collection<?> beans, Transaction t) {
|
||||
public void updateAll(Collection<?> beans, Transaction t) {
|
||||
|
||||
if (beans == null || beans.isEmpty()) {
|
||||
// Nothing to update?
|
||||
@@ -1540,14 +1558,14 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
/**
|
||||
* Insert all beans in the collection.
|
||||
*/
|
||||
public void insert(Collection<?> beans) {
|
||||
insert(beans, null);
|
||||
public void insertAll(Collection<?> beans) {
|
||||
insertAll(beans, null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Insert all beans in the collection with a transaction.
|
||||
*/
|
||||
public void insert(Collection<?> beans, Transaction t) {
|
||||
public void insertAll(Collection<?> beans, Transaction t) {
|
||||
|
||||
if (beans == null || beans.isEmpty()) {
|
||||
// Nothing to insert?
|
||||
@@ -1662,34 +1680,20 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an update or insert on each bean in the iterator. Returns the
|
||||
* number of beans that where saved.
|
||||
*/
|
||||
public int save(Iterator<?> it) {
|
||||
return save(it, null);
|
||||
@Override
|
||||
public int saveAll(Collection<?> beans, Transaction transaction) throws OptimisticLockException {
|
||||
return saveAllInternal(beans.iterator(), transaction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an update or insert on each bean in the collection. Returns the
|
||||
* number of beans that where saved.
|
||||
*/
|
||||
public int save(Collection<?> c) {
|
||||
return save(c.iterator(), null);
|
||||
@Override
|
||||
public int saveAll(Collection<?> beans) throws OptimisticLockException {
|
||||
return saveAllInternal(beans.iterator(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an update or insert on each bean in the collection. Returns the
|
||||
* number of beans that where saved.
|
||||
*/
|
||||
public int save(Collection<?> c, Transaction t) {
|
||||
return save(c.iterator(), t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save all beans in the iterator with an explicit transaction.
|
||||
*/
|
||||
public int save(Iterator<?> it, Transaction t) {
|
||||
public int saveAllInternal(Iterator<?> it, Transaction t) {
|
||||
|
||||
TransWrapper wrap = initTransIfRequired(t);
|
||||
try {
|
||||
@@ -1732,11 +1736,13 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
}
|
||||
}
|
||||
|
||||
public void delete(Class<?> beanType, Collection<?> ids) {
|
||||
delete(beanType, ids, null);
|
||||
@Override
|
||||
public void deleteAll(Class<?> beanType, Collection<?> ids) {
|
||||
deleteAll(beanType, ids, null);
|
||||
}
|
||||
|
||||
public void delete(Class<?> beanType, Collection<?> ids, Transaction t) {
|
||||
@Override
|
||||
public void deleteAll(Class<?> beanType, Collection<?> ids, Transaction t) {
|
||||
|
||||
TransWrapper wrap = initTransIfRequired(t);
|
||||
try {
|
||||
@@ -1765,24 +1771,18 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
persister.delete(checkEntityBean(bean), t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all the beans in the iterator.
|
||||
*/
|
||||
public int delete(Iterator<?> it) {
|
||||
return delete(it, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all the beans in the collection.
|
||||
*/
|
||||
public int delete(Collection<?> c) {
|
||||
return delete(c.iterator(), null);
|
||||
@Override
|
||||
public int deleteAll(Collection<?> beans) {
|
||||
return deleteAllInternal(beans.iterator(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all the beans in the iterator with an explicit transaction.
|
||||
*/
|
||||
public int delete(Iterator<?> it, Transaction t) {
|
||||
private int deleteAllInternal(Iterator<?> it, Transaction t) {
|
||||
|
||||
TransWrapper wrap = initTransIfRequired(t);
|
||||
|
||||
@@ -1995,12 +1995,6 @@ public final class DefaultServer implements SpiEbeanServer {
|
||||
// immutable thread safe so return shared instance
|
||||
return jsonContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonContext createJsonContext() {
|
||||
return json();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void collectQueryStats(ObjectGraphNode node, long loadedBeanCount, long timeMicros) {
|
||||
|
||||
@@ -18,7 +18,12 @@ import com.avaje.ebeaninternal.util.ValueUtil;
|
||||
*/
|
||||
public class DiffHelp {
|
||||
|
||||
|
||||
private final boolean flatMode;
|
||||
|
||||
public DiffHelp(boolean flatMode) {
|
||||
this.flatMode = flatMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a map of the differences between a and b.
|
||||
* <p>
|
||||
@@ -29,45 +34,45 @@ public class DiffHelp {
|
||||
* This intentionally does not include as OneToMany or ManyToMany properties.
|
||||
* </p>
|
||||
*/
|
||||
public Map<String, ValuePair> diff(Object a, Object b, BeanDescriptor<?> desc) {
|
||||
public Map<String, ValuePair> diff(Object newBean, Object oldBean, BeanDescriptor<?> desc) {
|
||||
|
||||
if (a instanceof EntityBean == false) {
|
||||
throw new IllegalArgumentException("First bean expected to be an enhanced EntityBean? bean:"+a);
|
||||
if (!(newBean instanceof EntityBean)) {
|
||||
throw new IllegalArgumentException("First bean expected to be an enhanced EntityBean? bean:"+newBean);
|
||||
}
|
||||
|
||||
if (b != null) {
|
||||
if (b instanceof EntityBean == false) {
|
||||
throw new IllegalArgumentException("Second bean expected to be an enhanced EntityBean? bean:"+b);
|
||||
if (oldBean != null) {
|
||||
if (!(oldBean instanceof EntityBean)) {
|
||||
throw new IllegalArgumentException("Second bean expected to be an enhanced EntityBean? bean:"+oldBean);
|
||||
}
|
||||
if (!a.getClass().isAssignableFrom(b.getClass())) {
|
||||
if (!newBean.getClass().isAssignableFrom(oldBean.getClass())) {
|
||||
throw new IllegalArgumentException("Second bean not assignable to the first bean?");
|
||||
}
|
||||
}
|
||||
|
||||
if (b == null) {
|
||||
return ((EntityBean) a)._ebean_getIntercept().getDirtyValues();
|
||||
if (oldBean == null) {
|
||||
return ((EntityBean) newBean)._ebean_getIntercept().getDirtyValues();
|
||||
}
|
||||
|
||||
Map<String, ValuePair> map = new LinkedHashMap<String, ValuePair>();
|
||||
diff(null, map, (EntityBean)a, (EntityBean)b, desc);
|
||||
diff(null, map, (EntityBean) newBean, (EntityBean) oldBean, desc);
|
||||
return map;
|
||||
}
|
||||
|
||||
public void diff(String prefix, Map<String, ValuePair> map, EntityBean first, EntityBean sec, BeanDescriptor<?> desc) {
|
||||
public void diff(String prefix, Map<String, ValuePair> map, EntityBean newBean, EntityBean oldBean, BeanDescriptor<?> desc) {
|
||||
|
||||
// check the simple properties
|
||||
BeanProperty[] base = desc.propertiesBaseScalar();
|
||||
for (int i = 0; i < base.length; i++) {
|
||||
Object aval = base[i].getValue(first);
|
||||
Object bval = base[i].getValue(sec);
|
||||
if (!ValueUtil.areEqual(aval, bval)) {
|
||||
Object newVal = (newBean == null) ? null : base[i].getValue(newBean);
|
||||
Object oldVal = (oldBean == null) ? null : base[i].getValue(oldBean);
|
||||
if (!ValueUtil.areEqual(newVal, oldVal)) {
|
||||
String propName = (prefix == null) ? base[i].getName() : prefix + base[i].getName();
|
||||
map.put(propName, new ValuePair(aval, bval));
|
||||
map.put(propName, new ValuePair(newVal, oldVal));
|
||||
}
|
||||
}
|
||||
|
||||
diffAssocOne(prefix, first, sec, desc, map);
|
||||
diffEmbedded(prefix, first, sec, desc, map);
|
||||
diffAssocOne(prefix, newBean, oldBean, desc, map);
|
||||
diffEmbedded(prefix, newBean, oldBean, desc, map);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,24 +82,29 @@ public class DiffHelp {
|
||||
* determined to be different as is added to the map.
|
||||
* </p>
|
||||
*/
|
||||
private void diffEmbedded(String prefix, EntityBean a, EntityBean b, BeanDescriptor<?> desc, Map<String, ValuePair> map) {
|
||||
private void diffEmbedded(String prefix, EntityBean newBean, EntityBean oldBean, BeanDescriptor<?> desc, Map<String, ValuePair> map) {
|
||||
|
||||
BeanPropertyAssocOne<?>[] emb = desc.propertiesEmbedded();
|
||||
|
||||
for (int i = 0; i < emb.length; i++) {
|
||||
EntityBean aval = (EntityBean)emb[i].getValue(a);
|
||||
EntityBean bval = (EntityBean)emb[i].getValue(b);
|
||||
EntityBean newVal = (EntityBean)emb[i].getValue(newBean);
|
||||
EntityBean oldVal = (EntityBean)emb[i].getValue(oldBean);
|
||||
|
||||
if (!isBothNull(aval, bval)) {
|
||||
if (!isBothNull(newVal, oldVal)) {
|
||||
String propName = (prefix == null) ? emb[i].getName() : prefix + emb[i].getName();
|
||||
if (isDiffNull(aval, bval)) {
|
||||
if (isDiffNull(newVal, oldVal)) {
|
||||
// one of the embedded beans is null
|
||||
map.put(propName, new ValuePair(aval, bval));
|
||||
if (flatMode) {
|
||||
BeanDescriptor<?> embDesc = emb[i].getTargetDescriptor();
|
||||
diff(emb[i].getName()+".", map, newVal, oldVal, embDesc);
|
||||
} else {
|
||||
map.put(propName, new ValuePair(newVal, oldVal));
|
||||
}
|
||||
|
||||
} else {
|
||||
// recursively diff into the embedded bean
|
||||
BeanDescriptor<?> embDesc = emb[i].getTargetDescriptor();
|
||||
diff(emb[i].getName()+".", map, aval, bval, embDesc);
|
||||
diff(emb[i].getName()+".", map, newVal, oldVal, embDesc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -104,45 +114,43 @@ public class DiffHelp {
|
||||
* If the properties are different by null OR if the id value is different,
|
||||
* then add the Assoc One bean to the map.
|
||||
*/
|
||||
private void diffAssocOne(String prefix, EntityBean a, EntityBean b, BeanDescriptor<?> desc, Map<String, ValuePair> map) {
|
||||
private void diffAssocOne(String prefix, EntityBean newBean, EntityBean oldBean, BeanDescriptor<?> desc, Map<String, ValuePair> map) {
|
||||
|
||||
BeanPropertyAssocOne<?>[] ones = desc.propertiesOne();
|
||||
|
||||
for (int i = 0; i < ones.length; i++) {
|
||||
Object aval = ones[i].getValue(a);
|
||||
Object bval = ones[i].getValue(b);
|
||||
Object newVal = ones[i].getValue(newBean);
|
||||
Object oldVal = ones[i].getValue(oldBean);
|
||||
|
||||
if (!isBothNull(aval, bval)) {
|
||||
String propName = (prefix == null) ? ones[i].getName() : prefix + ones[i].getName();
|
||||
if (isDiffNull(aval, bval)) {
|
||||
// one of them is/was null
|
||||
map.put(propName, new ValuePair(aval, bval));
|
||||
if (!isBothNull(newVal, oldVal)) {
|
||||
BeanDescriptor<?> oneDesc = ones[i].getTargetDescriptor();
|
||||
Object newId = (newVal == null) ? null : oneDesc.getId((EntityBean)newVal);
|
||||
Object oldId = (oldVal == null) ? null : oneDesc.getId((EntityBean)oldVal);
|
||||
|
||||
} else {
|
||||
// check to see if the Id properties
|
||||
// are different
|
||||
BeanDescriptor<?> oneDesc = ones[i].getTargetDescriptor();
|
||||
Object aOneId = oneDesc.getId((EntityBean)aval);
|
||||
Object bOneId = oneDesc.getId((EntityBean)bval);
|
||||
if (!ValueUtil.areEqual(newId, oldId)) {
|
||||
String propName = (prefix == null) ? ones[i].getName() : prefix + ones[i].getName();
|
||||
// the ids are different
|
||||
if (flatMode) {
|
||||
String idName = oneDesc.getIdProperty().getName();
|
||||
map.put(propName + "." + idName, new ValuePair(newId, oldId));
|
||||
|
||||
if (!ValueUtil.areEqual(aOneId, bOneId)) {
|
||||
// the ids are different
|
||||
map.put(propName, new ValuePair(aval, bval));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
map.put(propName, new ValuePair(newVal, oldVal));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBothNull(Object aval, Object bval) {
|
||||
return aval == null && bval == null;
|
||||
private boolean isBothNull(Object newVal, Object oldVal) {
|
||||
return newVal == null && oldVal == null;
|
||||
}
|
||||
|
||||
private boolean isDiffNull(Object aval, Object bval) {
|
||||
if (aval == null) {
|
||||
return bval != null;
|
||||
private boolean isDiffNull(Object newVal, Object oldVal) {
|
||||
if (newVal == null) {
|
||||
return oldVal != null;
|
||||
} else {
|
||||
return bval == null;
|
||||
return oldVal == null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.avaje.ebeaninternal.server.core;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import com.avaje.ebeaninternal.server.deploy.generatedproperty.GeneratedPropertyFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -41,6 +42,8 @@ import com.avaje.ebeaninternal.server.type.DefaultTypeManager;
|
||||
import com.avaje.ebeaninternal.server.type.TypeManager;
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Used to extend the ServerConfig with additional objects used to configure and
|
||||
* construct an EbeanServer.
|
||||
@@ -90,7 +93,7 @@ public class InternalConfiguration {
|
||||
private final XmlConfig xmlConfig;
|
||||
|
||||
private final JsonFactory jsonFactory;
|
||||
|
||||
|
||||
public InternalConfiguration(XmlConfig xmlConfig, ClusterManager clusterManager,
|
||||
ServerCacheManager cacheManager, SpiBackgroundExecutor backgroundExecutor,
|
||||
ServerConfig serverConfig, BootupClasses bootupClasses, PstmtBatch pstmtBatch) {
|
||||
@@ -103,7 +106,7 @@ public class InternalConfiguration {
|
||||
this.cacheManager = cacheManager;
|
||||
this.serverConfig = serverConfig;
|
||||
this.bootupClasses = bootupClasses;
|
||||
this.expressionFactory = new DefaultExpressionFactory();
|
||||
this.expressionFactory = new DefaultExpressionFactory(serverConfig.isExpressionEqualsWithNullAsNoop());
|
||||
|
||||
this.typeManager = new DefaultTypeManager(serverConfig, bootupClasses);
|
||||
this.binder = new Binder(typeManager);
|
||||
@@ -116,11 +119,11 @@ public class InternalConfiguration {
|
||||
this.deployUtil = new DeployUtil(typeManager, serverConfig);
|
||||
|
||||
this.beanDescriptorManager = new BeanDescriptorManager(this);
|
||||
beanDescriptorManager.deploy();
|
||||
Map<String, String> asOfTableMapping = beanDescriptorManager.deploy();
|
||||
|
||||
this.transactionManager = createTransactionManager();
|
||||
|
||||
this.cQueryEngine = new CQueryEngine(serverConfig.getDatabasePlatform(), binder);
|
||||
this.cQueryEngine = new CQueryEngine(serverConfig.getDatabasePlatform(), binder, asOfTableMapping, serverConfig.getAsOfSysPeriod());
|
||||
|
||||
ExternalTransactionManager externalTransactionManager = serverConfig.getExternalTransactionManager();
|
||||
if (externalTransactionManager == null && serverConfig.isUseJtaTransactionManager()) {
|
||||
@@ -182,7 +185,7 @@ public class InternalConfiguration {
|
||||
}
|
||||
|
||||
public OrmQueryEngine createOrmQueryEngine() {
|
||||
return new DefaultOrmQueryEngine(beanDescriptorManager, cQueryEngine);
|
||||
return new DefaultOrmQueryEngine(cQueryEngine);
|
||||
}
|
||||
|
||||
public Persister createPersister(SpiEbeanServer server) {
|
||||
@@ -265,4 +268,7 @@ public class InternalConfiguration {
|
||||
return backgroundExecutor;
|
||||
}
|
||||
|
||||
public GeneratedPropertyFactory getGeneratedPropertyFactory() {
|
||||
return new GeneratedPropertyFactory(serverConfig.getCurrentUserProvider());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,38 +1,42 @@
|
||||
package com.avaje.ebeaninternal.server.core;
|
||||
|
||||
import com.avaje.ebean.QueryIterator;
|
||||
import com.avaje.ebean.Version;
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebeaninternal.api.BeanIdList;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The Object Relational query execution API.
|
||||
*/
|
||||
public interface OrmQueryEngine {
|
||||
|
||||
/**
|
||||
* Execute the 'find by id' query returning a single bean.
|
||||
*/
|
||||
public <T> T findId(OrmQueryRequest<T> request);
|
||||
/**
|
||||
* Execute the 'find by id' query returning a single bean.
|
||||
*/
|
||||
<T> T findId(OrmQueryRequest<T> request);
|
||||
|
||||
/**
|
||||
* Execute the findList, findSet, findMap query returning an appropriate BeanCollection.
|
||||
*/
|
||||
public <T> BeanCollection<T> findMany(OrmQueryRequest<T> request);
|
||||
/**
|
||||
* Execute the findList, findSet, findMap query returning an appropriate BeanCollection.
|
||||
*/
|
||||
<T> BeanCollection<T> findMany(OrmQueryRequest<T> request);
|
||||
|
||||
/**
|
||||
* Execute the query using a QueryIterator.
|
||||
*/
|
||||
public <T> QueryIterator<T> findIterate(OrmQueryRequest<T> request);
|
||||
|
||||
/**
|
||||
* Execute the row count query.
|
||||
*/
|
||||
public <T> int findRowCount(OrmQueryRequest<T> request);
|
||||
|
||||
/**
|
||||
* Execute the find id's query.
|
||||
*/
|
||||
public <T> BeanIdList findIds(OrmQueryRequest<T> request);
|
||||
<T> List<Version<T>> findVersions(OrmQueryRequest<T> request);
|
||||
|
||||
/**
|
||||
* Execute the query using a QueryIterator.
|
||||
*/
|
||||
<T> QueryIterator<T> findIterate(OrmQueryRequest<T> request);
|
||||
|
||||
/**
|
||||
* Execute the row count query.
|
||||
*/
|
||||
<T> int findRowCount(OrmQueryRequest<T> request);
|
||||
|
||||
/**
|
||||
* Execute the find id's query.
|
||||
*/
|
||||
<T> BeanIdList findIds(OrmQueryRequest<T> request);
|
||||
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import javax.persistence.PersistenceException;
|
||||
import com.avaje.ebean.*;
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebean.bean.PersistenceContext;
|
||||
import com.avaje.ebean.event.BeanFinder;
|
||||
import com.avaje.ebean.event.BeanFindController;
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebeaninternal.api.BeanIdList;
|
||||
import com.avaje.ebeaninternal.api.HashQuery;
|
||||
@@ -40,7 +40,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
|
||||
private final SpiQuery<T> query;
|
||||
|
||||
private final BeanFinder<T> finder;
|
||||
private final BeanFindController finder;
|
||||
|
||||
private final Boolean readOnly;
|
||||
|
||||
@@ -259,19 +259,6 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
}
|
||||
}
|
||||
|
||||
public void findVisit(QueryResultVisitor<T> visitor) {
|
||||
QueryIterator<T> it = queryEngine.findIterate(this);
|
||||
try {
|
||||
while (it.hasNext()) {
|
||||
if (!visitor.accept(it.next())) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
it.close();
|
||||
}
|
||||
}
|
||||
|
||||
public QueryIterator<T> findIterate() {
|
||||
return queryEngine.findIterate(this);
|
||||
}
|
||||
@@ -284,6 +271,10 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
return (List<T>) queryEngine.findMany(this);
|
||||
}
|
||||
|
||||
public List<Version<T>> findVersions() {
|
||||
return queryEngine.findVersions(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the query as findSet.
|
||||
*/
|
||||
@@ -315,7 +306,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
/**
|
||||
* Return a bean specific finder if one has been set.
|
||||
*/
|
||||
public BeanFinder<T> getBeanFinder() {
|
||||
public BeanFindController getBeanFinder() {
|
||||
return finder;
|
||||
}
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
*/
|
||||
private boolean batchOnCascadeSet;
|
||||
|
||||
/**
|
||||
* Set for updates to determine if all loaded properties are included in the update.
|
||||
*/
|
||||
private boolean requestUpdateAllLoadedProps;
|
||||
|
||||
public PersistRequestBean(SpiEbeanServer server, T bean, Object parentBean, BeanManager<T> mgr, SpiTransaction t,
|
||||
PersistExecute persistExecute, PersistRequest.Type type, boolean saveRecurse) {
|
||||
|
||||
@@ -544,6 +549,9 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
|
||||
// if bean persisted again then should result in an update
|
||||
intercept.setLoaded();
|
||||
if (isInsert()) {
|
||||
postInsert();
|
||||
}
|
||||
|
||||
addEvent();
|
||||
|
||||
@@ -641,17 +649,21 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the property value has changed and if so include it in the update.
|
||||
* Return true if the property should be included in the update.
|
||||
*/
|
||||
public boolean isAddToUpdate(BeanProperty prop) {
|
||||
return intercept.isDirtyProperty(prop.getPropertyIndex());
|
||||
if (requestUpdateAllLoadedProps) {
|
||||
return intercept.isLoadedProperty(prop.getPropertyIndex());
|
||||
} else {
|
||||
return intercept.isDirtyProperty(prop.getPropertyIndex());
|
||||
}
|
||||
}
|
||||
|
||||
public List<DerivedRelationshipData> getDerivedRelationships() {
|
||||
return transaction.getDerivedRelationship(bean);
|
||||
}
|
||||
|
||||
public void postInsert() {
|
||||
private void postInsert() {
|
||||
// mark all properties as loaded after an insert to support immediate update
|
||||
int len = intercept.getPropertyLength();
|
||||
for (int i = 0; i < len; i++) {
|
||||
@@ -706,4 +718,24 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
return updatedManysOnly;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine if all loaded properties should be used for an update.
|
||||
* <p>
|
||||
* Takes into account transaction setting and JDBC batch.
|
||||
* </p>
|
||||
*/
|
||||
public boolean determineUpdateAllLoadedProperties() {
|
||||
|
||||
Boolean txnUpdateAll = transaction.isUpdateAllLoadedProperties();
|
||||
if (txnUpdateAll != null) {
|
||||
// use the setting explicitly set on the transaction
|
||||
requestUpdateAllLoadedProps = txnUpdateAll;
|
||||
} else {
|
||||
// if using batch use the server default setting
|
||||
requestUpdateAllLoadedProps = isBatchThisRequest() && ebeanServer.isUpdateAllPropertiesInBatch();
|
||||
}
|
||||
|
||||
return requestUpdateAllLoadedProps;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,115 +1,110 @@
|
||||
package com.avaje.ebeaninternal.server.core;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.avaje.ebean.QueryEachConsumer;
|
||||
import com.avaje.ebean.QueryEachWhileConsumer;
|
||||
import com.avaje.ebean.QueryIterator;
|
||||
import com.avaje.ebean.QueryResultVisitor;
|
||||
import com.avaje.ebean.Version;
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Defines the ORM query request api.
|
||||
*/
|
||||
public interface SpiOrmQueryRequest<T> {
|
||||
|
||||
/**
|
||||
* Return the query.
|
||||
*/
|
||||
public SpiQuery<T> getQuery();
|
||||
/**
|
||||
* Return the query.
|
||||
*/
|
||||
SpiQuery<T> getQuery();
|
||||
|
||||
/**
|
||||
* Return the associated BeanDescriptor.
|
||||
*/
|
||||
public BeanDescriptor<?> getBeanDescriptor();
|
||||
/**
|
||||
* Return the associated BeanDescriptor.
|
||||
*/
|
||||
BeanDescriptor<?> getBeanDescriptor();
|
||||
|
||||
/**
|
||||
* This will create a local (readOnly) transaction if no current transaction
|
||||
* exists.
|
||||
* <p>
|
||||
* A transaction may have been passed in explicitly or currently be active
|
||||
* in the thread local. If not, then a readOnly transaction is created to
|
||||
* execute this query.
|
||||
* </p>
|
||||
*/
|
||||
public void initTransIfRequired();
|
||||
/**
|
||||
* This will create a local (readOnly) transaction if no current transaction
|
||||
* exists.
|
||||
* <p>
|
||||
* A transaction may have been passed in explicitly or currently be active
|
||||
* in the thread local. If not, then a readOnly transaction is created to
|
||||
* execute this query.
|
||||
* </p>
|
||||
*/
|
||||
void initTransIfRequired();
|
||||
|
||||
/**
|
||||
* Will end a locally created transaction.
|
||||
* <p>
|
||||
* It ends the transaction by using a rollback() as the transaction is known
|
||||
* to be readOnly.
|
||||
* </p>
|
||||
*/
|
||||
public void endTransIfRequired();
|
||||
/**
|
||||
* Will end a locally created transaction.
|
||||
* <p>
|
||||
* It ends the transaction by using a rollback() as the transaction is known
|
||||
* to be readOnly.
|
||||
* </p>
|
||||
*/
|
||||
void endTransIfRequired();
|
||||
|
||||
/**
|
||||
* Execute the query as findById.
|
||||
*/
|
||||
public Object findId();
|
||||
/**
|
||||
* Execute the query as findById.
|
||||
*/
|
||||
Object findId();
|
||||
|
||||
/**
|
||||
* Execute the find row count query.
|
||||
*/
|
||||
public int findRowCount();
|
||||
/**
|
||||
* Execute the find row count query.
|
||||
*/
|
||||
int findRowCount();
|
||||
|
||||
/**
|
||||
* Execute the find ids query.
|
||||
*/
|
||||
public List<Object> findIds();
|
||||
|
||||
/**
|
||||
* Execute the find returning a QueryIterator and visitor pattern.
|
||||
*/
|
||||
public void findVisit(QueryResultVisitor<T> visitor);
|
||||
/**
|
||||
* Execute the find ids query.
|
||||
*/
|
||||
List<Object> findIds();
|
||||
|
||||
/**
|
||||
* Execute the find returning a QueryIterator and visitor pattern.
|
||||
*/
|
||||
public void findEach(QueryEachConsumer<T> consumer);
|
||||
void findEach(QueryEachConsumer<T> consumer);
|
||||
|
||||
/**
|
||||
* Execute the find returning a QueryIterator and visitor pattern.
|
||||
*/
|
||||
public void findEachWhile(QueryEachWhileConsumer<T> consumer);
|
||||
void findEachWhile(QueryEachWhileConsumer<T> consumer);
|
||||
|
||||
/**
|
||||
* Execute the find returning a QueryIterator.
|
||||
*/
|
||||
public QueryIterator<T> findIterate();
|
||||
|
||||
/**
|
||||
* Execute the query as findList.
|
||||
*/
|
||||
public List<T> findList();
|
||||
* Execute the find returning a QueryIterator.
|
||||
*/
|
||||
QueryIterator<T> findIterate();
|
||||
|
||||
/**
|
||||
* Execute the query as findSet.
|
||||
*/
|
||||
public Set<?> findSet();
|
||||
/**
|
||||
* Execute the finVersions() query.
|
||||
*/
|
||||
List<Version<T>> findVersions();
|
||||
|
||||
/**
|
||||
* Execute the query as findMap.
|
||||
*/
|
||||
public Map<?, ?> findMap();
|
||||
/**
|
||||
* Execute the query as findList.
|
||||
*/
|
||||
List<T> findList();
|
||||
|
||||
/**
|
||||
* Try to get the object out of the persistence context.
|
||||
*/
|
||||
//public T getFromPersistenceContextOrCache();
|
||||
/**
|
||||
* Execute the query as findSet.
|
||||
*/
|
||||
Set<?> findSet();
|
||||
|
||||
/**
|
||||
* Try to get the query result from the query cache.
|
||||
*/
|
||||
public BeanCollection<T> getFromQueryCache();
|
||||
/**
|
||||
* Execute the query as findMap.
|
||||
*/
|
||||
Map<?, ?> findMap();
|
||||
|
||||
/**
|
||||
* Return the Database platform like clause.
|
||||
*/
|
||||
public String getDBLikeClause();
|
||||
/**
|
||||
* Try to get the query result from the query cache.
|
||||
*/
|
||||
BeanCollection<T> getFromQueryCache();
|
||||
|
||||
/**
|
||||
* Return the Database platform like clause.
|
||||
*/
|
||||
String getDBLikeClause();
|
||||
|
||||
}
|
||||
@@ -10,10 +10,7 @@ import com.avaje.ebean.bean.PersistenceContext;
|
||||
import com.avaje.ebean.config.EncryptKey;
|
||||
import com.avaje.ebean.config.dbplatform.IdGenerator;
|
||||
import com.avaje.ebean.config.dbplatform.IdType;
|
||||
import com.avaje.ebean.event.BeanFinder;
|
||||
import com.avaje.ebean.event.BeanPersistController;
|
||||
import com.avaje.ebean.event.BeanPersistListener;
|
||||
import com.avaje.ebean.event.BeanQueryAdapter;
|
||||
import com.avaje.ebean.event.*;
|
||||
import com.avaje.ebean.meta.MetaBeanInfo;
|
||||
import com.avaje.ebean.meta.MetaQueryPlanStatistic;
|
||||
import com.avaje.ebeaninternal.api.*;
|
||||
@@ -115,6 +112,8 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
* The base database table.
|
||||
*/
|
||||
private final String baseTable;
|
||||
private final String baseTableAsOf;
|
||||
private final boolean historySupport;
|
||||
|
||||
/**
|
||||
* Map of BeanProperty Linked so as to preserve order.
|
||||
@@ -153,7 +152,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
/**
|
||||
* If set overrides the find implementation. Server side only.
|
||||
*/
|
||||
private final BeanFinder<T> beanFinder;
|
||||
private final BeanFindController beanFinder;
|
||||
|
||||
/**
|
||||
* The table joins for this bean.
|
||||
@@ -335,8 +334,9 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
this.updateChangesOnly = deploy.isUpdateChangesOnly();
|
||||
this.compoundUniqueConstraints = deploy.getCompoundUniqueConstraints();
|
||||
|
||||
this.historySupport = deploy.isHistorySupport();
|
||||
this.baseTable = InternString.intern(deploy.getBaseTable());
|
||||
|
||||
this.baseTableAsOf = deploy.getBaseTableAsOf();
|
||||
this.autoFetchTunable = EntityType.ORM.equals(entityType) && (beanFinder == null);
|
||||
|
||||
// helper object used to derive lists of properties
|
||||
@@ -499,13 +499,19 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
* These properties need to be initialised prior to the association properties
|
||||
* as they are used to get the imported and exported properties.
|
||||
* </p>
|
||||
* @param withHistoryTables map populated if @History is supported on this entity bean
|
||||
*/
|
||||
public void initialiseId() {
|
||||
public void initialiseId(Map<String, String> withHistoryTables) {
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("BeanDescriptor initialise " + fullName);
|
||||
}
|
||||
|
||||
if (historySupport) {
|
||||
// add mapping (used to swap out baseTable for asOf queries)
|
||||
withHistoryTables.put(baseTable, baseTableAsOf);
|
||||
}
|
||||
|
||||
if (inheritInfo != null) {
|
||||
inheritInfo.setDescriptor(this);
|
||||
}
|
||||
@@ -525,8 +531,25 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
|
||||
/**
|
||||
* Initialise the exported and imported parts for associated properties.
|
||||
*
|
||||
* @param asOfTableMap the map of base tables to associated 'with history' tables
|
||||
* @param asOfViewSuffix the suffix added to the table name to derive the 'with history' view name
|
||||
*/
|
||||
public void initialiseOther() {
|
||||
public void initialiseOther(Map<String, String> asOfTableMap, String asOfViewSuffix) {
|
||||
|
||||
if (historySupport) {
|
||||
// history support on this bean so check all associated intersection tables
|
||||
// and if they are not excluded register the associated 'with history' table
|
||||
for (int i = 0; i < propertiesManyToMany.length; i++) {
|
||||
if (!propertiesManyToMany[i].isExcludedFromHistory()) {
|
||||
// this intersection table has history support so also register
|
||||
// it into the asOfTableMap
|
||||
TableJoin intersectionTableJoin = propertiesManyToMany[i].getIntersectionTableJoin();
|
||||
String intersectionTableName = intersectionTableJoin.getTable();
|
||||
asOfTableMap.put(intersectionTableName, intersectionTableName + asOfViewSuffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isEmbedded()) {
|
||||
// initialise all the non-id properties
|
||||
@@ -634,7 +657,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
}
|
||||
|
||||
public boolean calculateUseCache(Boolean queryUseCache) {
|
||||
return (queryUseCache != null) ? queryUseCache.booleanValue() : isBeanCaching();
|
||||
return (queryUseCache != null) ? queryUseCache : isBeanCaching();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -764,7 +787,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
}
|
||||
|
||||
public void cacheBeanPut(T bean) {
|
||||
cacheBeanPutData((EntityBean)bean);
|
||||
cacheBeanPutData((EntityBean) bean);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1514,7 +1537,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
/**
|
||||
* Return the beanFinder. Usually null unless overriding the finder.
|
||||
*/
|
||||
public BeanFinder<T> getBeanFinder() {
|
||||
public BeanFindController getBeanFinder() {
|
||||
return beanFinder;
|
||||
}
|
||||
|
||||
@@ -1525,17 +1548,35 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
return queryAdapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* De-register the BeanPersistListener.
|
||||
*/
|
||||
public void deregister(BeanPersistListener listener) {
|
||||
|
||||
// volatile read...
|
||||
BeanPersistListener currentListener = persistListener;
|
||||
if (currentListener != null) {
|
||||
if (currentListener instanceof ChainedBeanPersistListener) {
|
||||
// remove it from the existing chain
|
||||
persistListener = ((ChainedBeanPersistListener) currentListener).deregister(listener);
|
||||
} else if (currentListener.equals(listener)) {
|
||||
persistListener = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* De-register the BeanPersistController.
|
||||
*/
|
||||
public void deregister(BeanPersistController controller) {
|
||||
|
||||
// volatile read...
|
||||
BeanPersistController c = persistController;
|
||||
if (c != null) {
|
||||
if (c instanceof ChainedBeanPersistController) {
|
||||
BeanPersistController currentController = persistController;
|
||||
if (currentController != null) {
|
||||
if (currentController instanceof ChainedBeanPersistController) {
|
||||
// remove it from the existing chain
|
||||
persistController = ((ChainedBeanPersistController) c).deregister(controller);
|
||||
} else if (c.equals(controller)) {
|
||||
persistController = ((ChainedBeanPersistController) currentController).deregister(controller);
|
||||
} else if (currentController.equals(controller)) {
|
||||
persistController = null;
|
||||
}
|
||||
}
|
||||
@@ -1549,16 +1590,16 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
|
||||
if (newPersistListener.isRegisterFor(beanType)) {
|
||||
// volatile read...
|
||||
BeanPersistListener currListener = persistListener;
|
||||
if (currListener == null) {
|
||||
BeanPersistListener currentListener = persistListener;
|
||||
if (currentListener == null) {
|
||||
persistListener = newPersistListener;
|
||||
} else {
|
||||
if (currListener instanceof ChainedBeanPersistListener) {
|
||||
if (currentListener instanceof ChainedBeanPersistListener) {
|
||||
// add it to the existing chain
|
||||
persistListener = ((ChainedBeanPersistListener) currListener).register(newPersistListener);
|
||||
persistListener = ((ChainedBeanPersistListener) currentListener).register(newPersistListener);
|
||||
} else {
|
||||
// build new chain of the 2
|
||||
persistListener = new ChainedBeanPersistListener(currListener, newPersistListener);
|
||||
persistListener = new ChainedBeanPersistListener(currentListener, newPersistListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1571,16 +1612,16 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
|
||||
if (newController.isRegisterFor(beanType)) {
|
||||
// volatile read...
|
||||
BeanPersistController c = persistController;
|
||||
if (c == null) {
|
||||
BeanPersistController currentController = persistController;
|
||||
if (currentController == null) {
|
||||
persistController = newController;
|
||||
} else {
|
||||
if (c instanceof ChainedBeanPersistController) {
|
||||
if (currentController instanceof ChainedBeanPersistController) {
|
||||
// add it to the existing chain
|
||||
persistController = ((ChainedBeanPersistController) c).register(newController);
|
||||
persistController = ((ChainedBeanPersistController) currentController).register(newController);
|
||||
} else {
|
||||
// build new chain of the 2
|
||||
persistController = new ChainedBeanPersistController(c, newController);
|
||||
persistController = new ChainedBeanPersistController(currentController, newController);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1613,6 +1654,24 @@ public class BeanDescriptor<T> implements MetaBeanInfo {
|
||||
return baseTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base table to use given the query temporal mode.
|
||||
*/
|
||||
public String getBaseTable(SpiQuery.TemporalMode mode) {
|
||||
switch (mode) {
|
||||
case VERSIONS: return baseTableAsOf;
|
||||
case AS_OF: return baseTableAsOf;
|
||||
default: return baseTable;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this entity bean has history support.
|
||||
*/
|
||||
public boolean isHistorySupport() {
|
||||
return historySupport;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the identity generation type.
|
||||
*/
|
||||
|
||||
@@ -303,7 +303,7 @@ public final class BeanDescriptorCacheHelp<T> {
|
||||
// try looking up into the bean cache using the id
|
||||
T cacheBean = beanCacheGetInternal(id, query.isReadOnly());
|
||||
if (cacheBean != null) {
|
||||
setupContext(cacheBean, query, getPersistenceContext(t));
|
||||
setupContext(cacheBean, getPersistenceContext(t));
|
||||
}
|
||||
return cacheBean;
|
||||
}
|
||||
@@ -320,7 +320,7 @@ public final class BeanDescriptorCacheHelp<T> {
|
||||
}
|
||||
|
||||
private boolean isNaturalKeyCaching(Boolean queryUseCache) {
|
||||
return naturalKeyCache != null && (queryUseCache == null || queryUseCache.booleanValue());
|
||||
return naturalKeyCache != null && (queryUseCache == null || queryUseCache);
|
||||
}
|
||||
|
||||
private boolean isNaturalKey(String propName) {
|
||||
@@ -332,7 +332,7 @@ public final class BeanDescriptorCacheHelp<T> {
|
||||
/**
|
||||
* For a bean built from the cache this sets up its persistence context for future lazy loading etc.
|
||||
*/
|
||||
private void setupContext(Object bean, SpiQuery<T> query, PersistenceContext context) {
|
||||
private void setupContext(Object bean, PersistenceContext context) {
|
||||
if (context == null) {
|
||||
context = new DefaultPersistenceContext();
|
||||
}
|
||||
@@ -408,7 +408,7 @@ public final class BeanDescriptorCacheHelp<T> {
|
||||
public T beanCacheGet(SpiQuery<T> query, PersistenceContext context) {
|
||||
T bean = beanCacheGetInternal(query.getId(), query.isReadOnly());
|
||||
if (bean != null) {
|
||||
setupContext(bean, query, context);
|
||||
setupContext(bean, context);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
@@ -10,11 +10,11 @@ import com.avaje.ebean.cache.ServerCacheManager;
|
||||
import com.avaje.ebean.config.EncryptKey;
|
||||
import com.avaje.ebean.config.EncryptKeyManager;
|
||||
import com.avaje.ebean.config.NamingConvention;
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebean.config.dbplatform.DatabasePlatform;
|
||||
import com.avaje.ebean.config.dbplatform.DbIdentity;
|
||||
import com.avaje.ebean.config.dbplatform.IdGenerator;
|
||||
import com.avaje.ebean.config.dbplatform.IdType;
|
||||
import com.avaje.ebean.event.BeanFinder;
|
||||
import com.avaje.ebeaninternal.api.SpiEbeanServer;
|
||||
import com.avaje.ebeaninternal.api.TransactionEventTable;
|
||||
import com.avaje.ebeaninternal.server.core.*;
|
||||
@@ -52,7 +52,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
|
||||
private static final BeanDescComparator beanDescComparator = new BeanDescComparator();
|
||||
|
||||
private final ReadAnnotations readAnnotations = new ReadAnnotations();
|
||||
private final ReadAnnotations readAnnotations;
|
||||
|
||||
private final TransientProperties transientProperties;
|
||||
|
||||
@@ -128,41 +128,51 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
|
||||
private final boolean eagerFetchLobs;
|
||||
|
||||
private final String asOfViewSuffix;
|
||||
|
||||
/**
|
||||
* Map of base tables to 'with history views' used to support 'as of' queries.
|
||||
*/
|
||||
private final Map<String,String> asOfTableMap = new HashMap<String, String>();
|
||||
|
||||
/**
|
||||
* Create for a given database dbConfig.
|
||||
*/
|
||||
public BeanDescriptorManager(InternalConfiguration config) {
|
||||
|
||||
this.serverName = InternString.intern(config.getServerConfig().getName());
|
||||
ServerConfig serverConfig = config.getServerConfig();
|
||||
|
||||
this.serverName = InternString.intern(serverConfig.getName());
|
||||
this.cacheManager = config.getCacheManager();
|
||||
this.xmlConfig = config.getXmlConfig();
|
||||
this.dbSequenceBatchSize = config.getServerConfig().getDatabaseSequenceBatchSize();
|
||||
this.dbSequenceBatchSize = serverConfig.getDatabaseSequenceBatchSize();
|
||||
this.backgroundExecutor = config.getBackgroundExecutor();
|
||||
this.dataSource = config.getServerConfig().getDataSource();
|
||||
this.encryptKeyManager = config.getServerConfig().getEncryptKeyManager();
|
||||
this.databasePlatform = config.getServerConfig().getDatabasePlatform();
|
||||
this.dataSource = serverConfig.getDataSource();
|
||||
this.encryptKeyManager = serverConfig.getEncryptKeyManager();
|
||||
this.databasePlatform = serverConfig.getDatabasePlatform();
|
||||
this.idBinderFactory = new IdBinderFactory(databasePlatform.isIdInExpandedForm());
|
||||
this.eagerFetchLobs = config.getServerConfig().isEagerFetchLobs();
|
||||
this.eagerFetchLobs = serverConfig.isEagerFetchLobs();
|
||||
|
||||
this.asOfViewSuffix = serverConfig.getAsOfViewSuffix();
|
||||
this.readAnnotations = new ReadAnnotations(config.getGeneratedPropertyFactory(), asOfViewSuffix);
|
||||
this.bootupClasses = config.getBootupClasses();
|
||||
this.createProperties = config.getDeployCreateProperties();
|
||||
this.typeManager = config.getTypeManager();
|
||||
this.namingConvention = config.getServerConfig().getNamingConvention();
|
||||
this.namingConvention = serverConfig.getNamingConvention();
|
||||
this.dbIdentity = config.getDatabasePlatform().getDbIdentity();
|
||||
this.deplyInherit = config.getDeployInherit();
|
||||
this.deployOrmXml = config.getDeployOrmXml();
|
||||
this.deployUtil = config.getDeployUtil();
|
||||
|
||||
this.beanManagerFactory = new BeanManagerFactory(config.getServerConfig(), config.getDatabasePlatform());
|
||||
this.beanManagerFactory = new BeanManagerFactory(serverConfig, config.getDatabasePlatform());
|
||||
|
||||
this.updateChangesOnly = config.getServerConfig().isUpdateChangesOnly();
|
||||
this.updateChangesOnly = serverConfig.isUpdateChangesOnly();
|
||||
|
||||
this.beanLifecycleAdapterFactory = new BeanLifecycleAdapterFactory();
|
||||
this.persistControllerManager = new PersistControllerManager(bootupClasses);
|
||||
this.persistListenerManager = new PersistListenerManager(bootupClasses);
|
||||
this.beanQueryAdapterManager = new BeanQueryAdapterManager(bootupClasses);
|
||||
|
||||
this.beanFinderManager = new DefaultBeanFinderManager();
|
||||
this.beanFinderManager = new BeanFinderManager(bootupClasses);
|
||||
|
||||
this.reflectFactory = createReflectionFactory();
|
||||
this.transientProperties = new TransientProperties();
|
||||
@@ -207,7 +217,10 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
return idBinderFactory.createIdBinder(idProperty);
|
||||
}
|
||||
|
||||
public void deploy() {
|
||||
/**
|
||||
* Deploy returning the asOfTableMap (which is required by the SQL builders).
|
||||
*/
|
||||
public Map<String,String> deploy() {
|
||||
|
||||
try {
|
||||
createListeners();
|
||||
@@ -239,6 +252,9 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
|
||||
deplyInfoMap.clear();
|
||||
deplyInfoMap = null;
|
||||
|
||||
return asOfTableMap;
|
||||
|
||||
} catch (RuntimeException e) {
|
||||
String msg = "Error in deployment";
|
||||
logger.error(msg, e);
|
||||
@@ -326,7 +342,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
// first (as they are needed to initialise the
|
||||
// associated properties in the second pass).
|
||||
for (BeanDescriptor<?> d : descMap.values()) {
|
||||
d.initialiseId();
|
||||
d.initialiseId(asOfTableMap);
|
||||
}
|
||||
|
||||
// PASS 2:
|
||||
@@ -338,7 +354,10 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
// PASS 3:
|
||||
// now initialise all the associated properties
|
||||
for (BeanDescriptor<?> d : descMap.values()) {
|
||||
d.initialiseOther();
|
||||
// also look for intersection tables with
|
||||
// associated history support and register them
|
||||
// into the asOfTableMap
|
||||
d.initialiseOther(asOfTableMap, asOfViewSuffix);
|
||||
}
|
||||
|
||||
// create BeanManager for each non-embedded entity bean
|
||||
@@ -407,7 +426,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
int qa = beanQueryAdapterManager.getRegisterCount();
|
||||
int cc = persistControllerManager.getRegisterCount();
|
||||
int lc = persistListenerManager.getRegisterCount();
|
||||
int fc = beanFinderManager.createBeanFinders(bootupClasses.getBeanFinders());
|
||||
int fc = beanFinderManager.getRegisterCount();
|
||||
|
||||
logger.debug("BeanPersistControllers[" + cc + "] BeanFinders[" + fc + "] BeanPersistListeners[" + lc + "] BeanQueryAdapters[" + qa + "]");
|
||||
}
|
||||
@@ -435,7 +454,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
*/
|
||||
private void readEmbeddedDeployment() {
|
||||
|
||||
ArrayList<Class<?>> embeddedClasses = bootupClasses.getEmbeddables();
|
||||
List<Class<?>> embeddedClasses = bootupClasses.getEmbeddables();
|
||||
for (int i = 0; i < embeddedClasses.size(); i++) {
|
||||
Class<?> cls = embeddedClasses.get(i);
|
||||
if (logger.isTraceEnabled()) {
|
||||
@@ -456,7 +475,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
*/
|
||||
private void readEntityDeploymentInitial() {
|
||||
|
||||
ArrayList<Class<?>> entityClasses = bootupClasses.getEntities();
|
||||
List<Class<?>> entityClasses = bootupClasses.getEntities();
|
||||
|
||||
for (Class<?> entityClass : entityClasses) {
|
||||
DeployBeanInfo<?> info = createDeployBeanInfo(entityClass);
|
||||
@@ -935,17 +954,10 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
|
||||
private <T> void setBeanControllerFinderListener(DeployBeanDescriptor<T> descriptor) {
|
||||
|
||||
Class<T> beanType = descriptor.getBeanType();
|
||||
|
||||
persistControllerManager.addPersistControllers(descriptor);
|
||||
persistListenerManager.addPersistListeners(descriptor);
|
||||
beanQueryAdapterManager.addQueryAdapter(descriptor);
|
||||
|
||||
BeanFinder<T> beanFinder = beanFinderManager.getBeanFinder(beanType);
|
||||
if (beanFinder != null) {
|
||||
descriptor.setBeanFinder(beanFinder);
|
||||
logger.debug("BeanFinder on[" + descriptor.getFullName() + "] " + beanFinder.getClass().getName());
|
||||
}
|
||||
beanFinderManager.addFindControllers(descriptor);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -982,7 +994,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
|
||||
if (!EntityType.ORM.equals(desc.getEntityType())) {
|
||||
// not using base table
|
||||
desc.setBaseTable(null);
|
||||
desc.setBaseTable(null, null);
|
||||
}
|
||||
|
||||
// mark transient properties
|
||||
|
||||
@@ -1,26 +1,42 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import com.avaje.ebean.event.BeanFindController;
|
||||
import com.avaje.ebeaninternal.server.core.BootupClasses;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanDescriptor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebean.event.BeanFinder;
|
||||
|
||||
/**
|
||||
* Factory for controlling the construction of BeanFinders.
|
||||
* Default implementation for BeanFinderFactory.
|
||||
*/
|
||||
public interface BeanFinderManager {
|
||||
|
||||
/**
|
||||
* Return the number of beans with a registered finder.
|
||||
*/
|
||||
public int getRegisterCount();
|
||||
public class BeanFinderManager {
|
||||
|
||||
final Logger logger = LoggerFactory.getLogger(BeanFinderManager.class);
|
||||
|
||||
private final List<BeanFindController> list;
|
||||
|
||||
public BeanFinderManager(BootupClasses bootupClasses) {
|
||||
list = bootupClasses.getBeanFindControllers();
|
||||
}
|
||||
|
||||
public int getRegisterCount() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BeanPersistController for a given entity type.
|
||||
*/
|
||||
public void addFindControllers(DeployBeanDescriptor<?> deployDesc) {
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
BeanFindController c = list.get(i);
|
||||
if (c.isRegisterFor(deployDesc.getBeanType())) {
|
||||
logger.debug("BeanFindController on[" + deployDesc.getFullName() + "] " + c.getClass().getName());
|
||||
deployDesc.setBeanFinder(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the appropriate BeanController.
|
||||
*/
|
||||
public int createBeanFinders(List<Class<?>> finderClassList);
|
||||
|
||||
/**
|
||||
* Return the BeanController for a given entity type.
|
||||
*/
|
||||
public <T> BeanFinder<T> getBeanFinder(Class<T> entityType);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import com.avaje.ebean.EbeanServer;
|
||||
@@ -141,11 +140,13 @@ public final class BeanListHelp<T> implements BeanCollectionHelp<T> {
|
||||
list = (List<?>) collection;
|
||||
}
|
||||
|
||||
ctx.writeStartArray(name);
|
||||
for (int j = 0; j < list.size(); j++) {
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean) list.get(j));
|
||||
if (!list.isEmpty() || ctx.isIncludeEmpty()) {
|
||||
ctx.writeStartArray(name);
|
||||
for (int j = 0; j < list.size(); j++) {
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean) list.get(j));
|
||||
}
|
||||
ctx.writeEndArray();
|
||||
}
|
||||
ctx.writeEndArray();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -177,12 +177,14 @@ public final class BeanMapHelp<T> implements BeanCollectionHelp<T> {
|
||||
map = (Map<?, ?>) collection;
|
||||
}
|
||||
|
||||
ctx.writeStartArray(name);
|
||||
for (Entry<?, ?> entry : map.entrySet()) {
|
||||
//FIXME: json write map key ...
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean) entry.getValue());
|
||||
if (!map.isEmpty() || ctx.isIncludeEmpty()) {
|
||||
ctx.writeStartArray(name);
|
||||
for (Entry<?, ?> entry : map.entrySet()) {
|
||||
//FIXME: json write map key ...
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean) entry.getValue());
|
||||
}
|
||||
ctx.writeEndArray();
|
||||
}
|
||||
ctx.writeEndArray();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ import com.avaje.ebeaninternal.server.text.json.WriteJson;
|
||||
import com.avaje.ebeaninternal.server.type.DataBind;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarType;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.io.DataInput;
|
||||
@@ -39,6 +41,8 @@ import java.util.Map;
|
||||
*/
|
||||
public class BeanProperty implements ElPropertyValue {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(BeanProperty.class);
|
||||
|
||||
/**
|
||||
* Flag to mark this at part of the unique id.
|
||||
*/
|
||||
@@ -169,6 +173,8 @@ public class BeanProperty implements ElPropertyValue {
|
||||
*/
|
||||
final int dbType;
|
||||
|
||||
final boolean excludedFromHistory;
|
||||
|
||||
/**
|
||||
* The default value to insert if null.
|
||||
*/
|
||||
@@ -252,6 +258,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
this.dbRead = deploy.isDbRead();
|
||||
this.dbInsertable = deploy.isDbInsertable();
|
||||
this.dbUpdatable = deploy.isDbUpdateable();
|
||||
this.excludedFromHistory = deploy.isExcludedFromHistory();
|
||||
|
||||
this.secondaryTable = deploy.isSecondaryTable();
|
||||
if (secondaryTable) {
|
||||
@@ -299,8 +306,8 @@ public class BeanProperty implements ElPropertyValue {
|
||||
this.elPlaceHolder = tableAliasIntern(descriptor, deploy.getElPlaceHolder(et), false, null);
|
||||
this.elPlaceHolderEncrypted = tableAliasIntern(descriptor, deploy.getElPlaceHolder(et), dbEncrypted, dbColumn);
|
||||
|
||||
this.jsonSerialize = deploy.isExposeSerialize();
|
||||
this.jsonDeserialize = deploy.isExposeDeserialize();
|
||||
this.jsonSerialize = deploy.isJsonSerialize();
|
||||
this.jsonDeserialize = deploy.isJsonDeserialize();
|
||||
}
|
||||
|
||||
private String tableAliasIntern(BeanDescriptor<?> descriptor, String s, boolean dbEncrypted, String dbColumn) {
|
||||
@@ -337,6 +344,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
this.sqlFormulaSelect = InternString.intern(override.getSqlFormulaSelect());
|
||||
this.formula = sqlFormulaSelect != null;
|
||||
|
||||
this.excludedFromHistory = source.excludedFromHistory;
|
||||
this.fetchEager = source.fetchEager;
|
||||
this.unidirectionalShadow = source.unidirectionalShadow;
|
||||
this.discriminator = source.discriminator;
|
||||
@@ -533,7 +541,7 @@ public class BeanProperty implements ElPropertyValue {
|
||||
sqlBeanLoad.load(this);
|
||||
}
|
||||
|
||||
public void buildSelectExpressionChain(String prefix, List<String> selectChain) {
|
||||
public void buildRawSqlSelectChain(String prefix, List<String> selectChain) {
|
||||
if (prefix == null) {
|
||||
selectChain.add(name);
|
||||
} else {
|
||||
@@ -1000,6 +1008,13 @@ public class BeanProperty implements ElPropertyValue {
|
||||
return dbEncryptedType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this property is excluded from history.
|
||||
*/
|
||||
public boolean isExcludedFromHistory() {
|
||||
return excludedFromHistory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this property should be included in an Insert.
|
||||
*/
|
||||
@@ -1070,24 +1085,42 @@ public class BeanProperty implements ElPropertyValue {
|
||||
}
|
||||
Object value = getValueIntercept(bean);
|
||||
if (value == null) {
|
||||
writeJson.writeNull(name);
|
||||
writeJson.writeNullField(name);
|
||||
} else {
|
||||
scalarType.jsonWrite(writeJson.gen(), name, value);
|
||||
if (scalarType != null) {
|
||||
scalarType.jsonWrite(writeJson, name, value);
|
||||
} else {
|
||||
writeJson.writeValueUsingObjectMapper(name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void jsonRead(ReadJson ctx, EntityBean bean) throws IOException {
|
||||
if (!jsonDeserialize) {
|
||||
return;
|
||||
}
|
||||
|
||||
JsonToken event = ctx.nextToken();
|
||||
if (JsonToken.VALUE_NULL == event) {
|
||||
setValue(bean, null);
|
||||
if (jsonDeserialize) {
|
||||
setValue(bean, null);
|
||||
}
|
||||
} else {
|
||||
// expect to read non-null json value
|
||||
Object objValue = scalarType.jsonRead(ctx.getParser(), event);
|
||||
setValue(bean, objValue);
|
||||
Object objValue;
|
||||
if (scalarType != null) {
|
||||
objValue = scalarType.jsonRead(ctx.getParser(), event);
|
||||
} else {
|
||||
try {
|
||||
objValue = ctx.readValueUsingObjectMapper(propertyType);
|
||||
} catch (IOException e) {
|
||||
// change in behavior for #318
|
||||
objValue = null;
|
||||
String msg = "Error trying to use Jackson ObjectMapper to read transient property "
|
||||
+ getFullBeanName() +" - consider marking this property with @JsonIgnore";
|
||||
logger.error(msg, e);
|
||||
}
|
||||
}
|
||||
if (jsonDeserialize) {
|
||||
setValue(bean, objValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,7 @@ import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Property mapped to a List Set or Map.
|
||||
@@ -180,9 +181,27 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
help.add(bc, detailBean);
|
||||
}
|
||||
|
||||
public boolean isEmptyBeanCollection(EntityBean bean) {
|
||||
/**
|
||||
* Return true if this is considered 'empty' from a save perspective.
|
||||
*/
|
||||
public boolean isEmptyBeanCollection(EntityBean bean, boolean insertedParent) {
|
||||
Object val = getValue(bean);
|
||||
return val == null || (val instanceof BeanCollection<?>) && ((BeanCollection<?>) val).isEmptyAndUntouched();
|
||||
if (val == null) {
|
||||
return true;
|
||||
}
|
||||
if ((val instanceof BeanCollection<?>)) {
|
||||
return ((BeanCollection<?>) val).isEmptyAndUntouched();
|
||||
}
|
||||
if (insertedParent) {
|
||||
// check 'vanilla' collection types
|
||||
if (val instanceof Collection<?>){
|
||||
return ((Collection<?>) val).isEmpty();
|
||||
}
|
||||
if (val instanceof Map<?,?>) {
|
||||
return ((Map<?,?>) val).isEmpty();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -225,7 +244,8 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
return createElPropertyValue(propName, remainder, chain, propertyDeploy);
|
||||
}
|
||||
|
||||
public void buildSelectExpressionChain(String prefix, List<String> selectChain) {
|
||||
@Override
|
||||
public void buildRawSqlSelectChain(String prefix, List<String> selectChain) {
|
||||
// do not add to the selectChain at the top level of the Many bean
|
||||
}
|
||||
|
||||
@@ -872,7 +892,14 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> {
|
||||
if (help != null) {
|
||||
help.jsonWrite(ctx, name, value, include != null);
|
||||
} else {
|
||||
ctx.toJson(name, (Collection<?>) value);
|
||||
if (isTransient) {
|
||||
ctx.writeValueUsingObjectMapper(name, value);
|
||||
} else {
|
||||
Collection<?> collection = (Collection<?>)value;
|
||||
if (!collection.isEmpty() || ctx.isIncludeEmpty()) {
|
||||
ctx.toJson(name, collection);
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.popParentBeanMany();
|
||||
}
|
||||
|
||||
+37
-2
@@ -1,23 +1,42 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.avaje.ebean.bean.BeanCollection;
|
||||
import com.avaje.ebean.bean.BeanCollectionAdd;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.api.ClassUtil;
|
||||
import com.avaje.ebeaninternal.server.text.json.ReadJson;
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Help BeanPropertyAssocMany with JSON processing.
|
||||
*/
|
||||
public class BeanPropertyAssocManyJsonHelp {
|
||||
|
||||
/**
|
||||
* The associated many property.
|
||||
*/
|
||||
private final BeanPropertyAssocMany<?> many;
|
||||
|
||||
/**
|
||||
* Helper used to read json for transient 'many' properties.
|
||||
*/
|
||||
private final BeanPropertyAssocManyJsonTransient jsonTransient;
|
||||
|
||||
/**
|
||||
* Construct for the owning many property.
|
||||
*/
|
||||
public BeanPropertyAssocManyJsonHelp(BeanPropertyAssocMany<?> many) {
|
||||
this.many = many;
|
||||
this.jsonTransient = !ClassUtil.isJacksonObjectMapperPresent() ? null : new BeanPropertyAssocManyJsonTransient();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the JSON for this property.
|
||||
*/
|
||||
public void jsonRead(ReadJson readJson, EntityBean parentBean) throws IOException {
|
||||
|
||||
if (!this.many.jsonDeserialize) {
|
||||
@@ -33,6 +52,11 @@ public class BeanPropertyAssocManyJsonHelp {
|
||||
throw new JsonParseException("Unexpected token " + event + " - expecting start_array ", parser.getCurrentLocation());
|
||||
}
|
||||
|
||||
if (many.isTransient()) {
|
||||
jsonReadTransientUsingObjectMapper(readJson, parentBean);
|
||||
return;
|
||||
}
|
||||
|
||||
BeanCollection<?> collection = many.createEmpty(parentBean);
|
||||
BeanCollectionAdd add = many.getBeanCollectionAdd(collection, null);
|
||||
do {
|
||||
@@ -51,4 +75,15 @@ public class BeanPropertyAssocManyJsonHelp {
|
||||
|
||||
many.setValue(parentBean, collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a Transient property using Jackson ObjectMapper.
|
||||
*/
|
||||
private void jsonReadTransientUsingObjectMapper(ReadJson readJson, EntityBean parentBean) throws IOException {
|
||||
|
||||
if (jsonTransient == null) {
|
||||
throw new IllegalStateException("Jackson ObjectMapper is required to read this Transient property "+many.getFullBeanName());
|
||||
}
|
||||
jsonTransient.jsonReadUsingObjectMapper(many, readJson, parentBean);
|
||||
}
|
||||
}
|
||||
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
import com.avaje.ebeaninternal.server.text.json.ReadJson;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.type.CollectionType;
|
||||
import com.fasterxml.jackson.databind.type.MapType;
|
||||
import com.fasterxml.jackson.databind.type.TypeFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
/**
|
||||
* Helper used to read transient many properties using Jackson ObjectMapper.
|
||||
*/
|
||||
public class BeanPropertyAssocManyJsonTransient {
|
||||
|
||||
/**
|
||||
* Use Jackson ObjectMapper to read the transient 'many' property.
|
||||
*/
|
||||
public void jsonReadUsingObjectMapper(BeanPropertyAssocMany<?> many, ReadJson readJson, EntityBean parentBean) throws IOException {
|
||||
|
||||
ObjectMapper mapper = readJson.getObjectMapper();
|
||||
|
||||
ManyType manyType = many.getManyType();
|
||||
|
||||
Object value;
|
||||
if (manyType.isMap()) {
|
||||
// read map using Jackson object mapper with unknown key type
|
||||
TypeFactory typeFactory = mapper.getTypeFactory();
|
||||
JavaType target = typeFactory.constructType(many.getTargetType());
|
||||
MapType jacksonType = typeFactory.constructMapType(LinkedHashMap.class, typeFactory.unknownType(), target);
|
||||
value = mapper.readValue(readJson.getParser(), jacksonType);
|
||||
|
||||
} else {
|
||||
// read list or set using Jackson object mapper
|
||||
CollectionType jacksonType = mapper.getTypeFactory().constructCollectionType(manyType.getCollectionType(), many.getTargetType());
|
||||
value = mapper.readValue(readJson.getParser(), jacksonType);
|
||||
}
|
||||
|
||||
many.setValue(parentBean, value);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -171,7 +171,7 @@ public class BeanPropertyCompound extends BeanProperty {
|
||||
}
|
||||
Object value = getValueIntercept(bean);
|
||||
if (value == null) {
|
||||
ctx.writeNull(name);
|
||||
ctx.writeNullField(name);
|
||||
} else {
|
||||
compoundType.jsonWrite(ctx, value, name);
|
||||
}
|
||||
|
||||
@@ -139,11 +139,13 @@ public final class BeanSetHelp<T> implements BeanCollectionHelp<T> {
|
||||
set = (Set<?>) collection;
|
||||
}
|
||||
|
||||
ctx.writeStartArray(name);
|
||||
Iterator<?> it = set.iterator();
|
||||
while (it.hasNext()) {
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean) it.next());
|
||||
if (!set.isEmpty() || ctx.isIncludeEmpty()) {
|
||||
ctx.writeStartArray(name);
|
||||
Iterator<?> it = set.iterator();
|
||||
while (it.hasNext()) {
|
||||
targetDescriptor.jsonWrite(ctx, (EntityBean) it.next());
|
||||
}
|
||||
ctx.writeEndArray();
|
||||
}
|
||||
ctx.writeEndArray();
|
||||
}
|
||||
}
|
||||
|
||||
+13
-2
@@ -9,6 +9,11 @@ import java.util.Set;
|
||||
import com.avaje.ebean.event.BeanPersistController;
|
||||
import com.avaje.ebean.event.BeanPersistRequest;
|
||||
|
||||
/**
|
||||
* Chains multiple BeanPersistController's together.
|
||||
*
|
||||
* Used when multiple BeanPersistController register for the same bean type.
|
||||
*/
|
||||
public class ChainedBeanPersistController implements BeanPersistController {
|
||||
|
||||
private static final Sorter SORTER = new Sorter();
|
||||
@@ -35,7 +40,6 @@ public class ChainedBeanPersistController implements BeanPersistController {
|
||||
|
||||
/**
|
||||
* Construct given the list of BeanPersistController's.
|
||||
* @param list
|
||||
*/
|
||||
public ChainedBeanPersistController(List<BeanPersistController> list) {
|
||||
this.list = list;
|
||||
@@ -43,7 +47,14 @@ public class ChainedBeanPersistController implements BeanPersistController {
|
||||
Arrays.sort(c, SORTER);
|
||||
this.chain = c;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the size of the chain.
|
||||
*/
|
||||
protected int size() {
|
||||
return chain.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new BeanPersistController and return the resulting chain.
|
||||
*/
|
||||
|
||||
@@ -22,6 +22,13 @@ public class ChainedBeanPersistListener implements BeanPersistListener {
|
||||
this(addList(c1, c2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the size of the chain.
|
||||
*/
|
||||
protected int size() {
|
||||
return chain.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRegisterFor(Class<?> cls) {
|
||||
// never called
|
||||
@@ -40,7 +47,6 @@ public class ChainedBeanPersistListener implements BeanPersistListener {
|
||||
|
||||
/**
|
||||
* Construct given the list of BeanPersistController's.
|
||||
* @param list
|
||||
*/
|
||||
public ChainedBeanPersistListener(List<BeanPersistListener> list) {
|
||||
this.list = list;
|
||||
|
||||
@@ -152,7 +152,7 @@ public class DRawSqlSelect {
|
||||
}
|
||||
}
|
||||
|
||||
SqlTreeNode sqlRoot = new SqlTreeNodeRoot(desc, selectProps, null, withId);
|
||||
SqlTreeNode sqlRoot = new SqlTreeNodeRoot(desc, selectProps, withId, false);
|
||||
|
||||
return new SqlTree(desc.getName(), sqlRoot);
|
||||
}
|
||||
|
||||
@@ -10,108 +10,114 @@ public interface DbSqlContext {
|
||||
/**
|
||||
* Add a join to the sql query.
|
||||
*/
|
||||
public void addJoin(String type, String table, TableJoinColumn[] cols, String a1, String a2, String inheritance);
|
||||
void addJoin(String type, String table, TableJoinColumn[] cols, String a1, String a2, String inheritance);
|
||||
|
||||
public void pushSecondaryTableAlias(String alias);
|
||||
void pushSecondaryTableAlias(String alias);
|
||||
|
||||
/**
|
||||
* Push the current table alias onto the stack.
|
||||
*/
|
||||
public void pushTableAlias(String tableAlias);
|
||||
void pushTableAlias(String tableAlias);
|
||||
|
||||
/**
|
||||
* Pop the current table alias from the stack.
|
||||
*/
|
||||
public void popTableAlias();
|
||||
void popTableAlias();
|
||||
|
||||
/**
|
||||
* Add an encrypted property which will require additional binding.
|
||||
*/
|
||||
public void addEncryptedProp(BeanProperty prop);
|
||||
void addEncryptedProp(BeanProperty prop);
|
||||
|
||||
/**
|
||||
* Return a list of encrypted properties which require additional binding.
|
||||
*/
|
||||
public BeanProperty[] getEncryptedProps();
|
||||
BeanProperty[] getEncryptedProps();
|
||||
|
||||
/**
|
||||
* Append a char directly to the SQL buffer.
|
||||
*/
|
||||
public DbSqlContext append(char s);
|
||||
DbSqlContext append(char s);
|
||||
|
||||
/**
|
||||
* Append a string directly to the SQL buffer.
|
||||
*/
|
||||
public DbSqlContext append(String s);
|
||||
DbSqlContext append(String s);
|
||||
|
||||
/**
|
||||
* Peek the current table alias.
|
||||
*/
|
||||
public String peekTableAlias();
|
||||
String peekTableAlias();
|
||||
|
||||
/**
|
||||
* Add a raw column to the sql.
|
||||
*/
|
||||
public void appendRawColumn(String rawcolumnWithTableAlias);
|
||||
void appendRawColumn(String rawcolumnWithTableAlias);
|
||||
|
||||
/**
|
||||
* Append a column with an explicit table alias.
|
||||
*/
|
||||
public void appendColumn(String tableAlias, String column);
|
||||
void appendColumn(String tableAlias, String column);
|
||||
|
||||
/**
|
||||
* Append a column with the current table alias.
|
||||
*/
|
||||
public void appendColumn(String column);
|
||||
void appendColumn(String column);
|
||||
|
||||
/**
|
||||
* Append a Sql Formula select. This converts the "${ta}" keyword to the
|
||||
* current table alias.
|
||||
*/
|
||||
public void appendFormulaSelect(String sqlFormulaSelect);
|
||||
void appendFormulaSelect(String sqlFormulaSelect);
|
||||
|
||||
/**
|
||||
* Append a Sql Formula join. This converts the "${ta}" keyword to the current
|
||||
* table alias.
|
||||
*/
|
||||
public void appendFormulaJoin(String sqlFormulaJoin, SqlJoinType joinType);
|
||||
void appendFormulaJoin(String sqlFormulaJoin, SqlJoinType joinType);
|
||||
|
||||
/**
|
||||
* Return the current content length.
|
||||
*/
|
||||
public int length();
|
||||
int length();
|
||||
|
||||
/**
|
||||
* Return the current context of the sql context.
|
||||
*/
|
||||
public String getContent();
|
||||
String getContent();
|
||||
|
||||
/**
|
||||
* Return the current join node.
|
||||
*/
|
||||
public String peekJoin();
|
||||
String peekJoin();
|
||||
|
||||
/**
|
||||
* Push a join node onto the stack.
|
||||
*/
|
||||
public void pushJoin(String prefix);
|
||||
void pushJoin(String prefix);
|
||||
|
||||
/**
|
||||
* Pop a join node off the stack.
|
||||
*/
|
||||
public void popJoin();
|
||||
void popJoin();
|
||||
|
||||
/**
|
||||
* Return a table alias without many where clause joins. Typically this is for
|
||||
* the select clause (fetch joins).
|
||||
*/
|
||||
public String getTableAlias(String prefix);
|
||||
String getTableAlias(String prefix);
|
||||
|
||||
/**
|
||||
* Return a table alias that takes into account many where joins.
|
||||
*/
|
||||
public String getTableAliasManyWhere(String prefix);
|
||||
String getTableAliasManyWhere(String prefix);
|
||||
|
||||
public String getRelativePrefix(String propName);
|
||||
String getRelativePrefix(String propName);
|
||||
|
||||
/**
|
||||
* Append the lower and upper bound columns into the select clause
|
||||
* for findVersions() queries.
|
||||
*/
|
||||
void appendHistorySysPeriod();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import com.avaje.ebean.event.BeanFinder;
|
||||
|
||||
/**
|
||||
* Default implementation for BeanFinderFactory.
|
||||
*/
|
||||
public class DefaultBeanFinderManager implements BeanFinderManager {
|
||||
|
||||
HashMap<Class<?>, BeanFinder<?>> registerFor = new HashMap<Class<?>, BeanFinder<?>>();
|
||||
|
||||
public int createBeanFinders(List<Class<?>> finderClassList) {
|
||||
|
||||
for (Class<?> cls : finderClassList) {
|
||||
Class<?> entityType = getEntityClass(cls);
|
||||
try {
|
||||
BeanFinder<?> beanFinder = (BeanFinder<?>) cls.newInstance();
|
||||
registerFor.put(entityType, beanFinder);
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new PersistenceException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return registerFor.size();
|
||||
}
|
||||
|
||||
public int getRegisterCount() {
|
||||
return registerFor.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BeanFinder for a given entity type.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> BeanFinder<T> getBeanFinder(Class<T> entityType) {
|
||||
return (BeanFinder<T>)registerFor.get(entityType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the entity class given the controller class.
|
||||
* <p>
|
||||
* This uses reflection to find the generics parameter type.
|
||||
* </p>
|
||||
*/
|
||||
private Class<?> getEntityClass(Class<?> controller){
|
||||
|
||||
Class<?> cls = ParamTypeUtil.findParamType(controller, BeanFinder.class);
|
||||
|
||||
if (cls == null){
|
||||
String msg = "Could not determine the entity class (generics parameter type) from "+controller+" using reflection.";
|
||||
throw new PersistenceException(msg);
|
||||
}
|
||||
return cls;
|
||||
}
|
||||
}
|
||||
@@ -2,58 +2,76 @@ package com.avaje.ebeaninternal.server.deploy;
|
||||
|
||||
import com.avaje.ebeaninternal.api.SpiQuery;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Represents the type of a OneToMany or ManyToMany property.
|
||||
*/
|
||||
public class ManyType {
|
||||
|
||||
public static final ManyType JAVA_LIST = new ManyType(Underlying.LIST);
|
||||
public static final ManyType JAVA_SET = new ManyType(Underlying.SET);
|
||||
public static final ManyType JAVA_MAP = new ManyType(Underlying.MAP);
|
||||
|
||||
public enum Underlying {
|
||||
LIST,
|
||||
SET,
|
||||
MAP
|
||||
}
|
||||
|
||||
private final SpiQuery.Type queryType;
|
||||
|
||||
private final Underlying underlying;
|
||||
|
||||
public static final ManyType JAVA_LIST = new ManyType(Underlying.LIST);
|
||||
public static final ManyType JAVA_SET = new ManyType(Underlying.SET);
|
||||
public static final ManyType JAVA_MAP = new ManyType(Underlying.MAP);
|
||||
|
||||
public ManyType(Underlying underlying) {
|
||||
this.underlying = underlying;
|
||||
switch (underlying) {
|
||||
case LIST:
|
||||
queryType = SpiQuery.Type.LIST;
|
||||
break;
|
||||
case SET:
|
||||
queryType = SpiQuery.Type.SET;
|
||||
break;
|
||||
public enum Underlying {
|
||||
|
||||
default:
|
||||
queryType = SpiQuery.Type.MAP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
LIST(List.class),
|
||||
SET(Set.class),
|
||||
MAP(null);
|
||||
|
||||
public boolean isMap() {
|
||||
return Underlying.MAP.equals(underlying);
|
||||
Class<? extends Collection> type;
|
||||
|
||||
Underlying(Class<? extends Collection> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the matching Query type.
|
||||
*/
|
||||
public SpiQuery.Type getQueryType() {
|
||||
return queryType;
|
||||
}
|
||||
|
||||
private final SpiQuery.Type queryType;
|
||||
|
||||
private final Underlying underlying;
|
||||
|
||||
|
||||
public ManyType(Underlying underlying) {
|
||||
this.underlying = underlying;
|
||||
switch (underlying) {
|
||||
case LIST:
|
||||
queryType = SpiQuery.Type.LIST;
|
||||
break;
|
||||
case SET:
|
||||
queryType = SpiQuery.Type.SET;
|
||||
break;
|
||||
|
||||
default:
|
||||
queryType = SpiQuery.Type.MAP;
|
||||
break;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying type.
|
||||
*/
|
||||
public Underlying getUnderlying() {
|
||||
return underlying;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean isMap() {
|
||||
return Underlying.MAP.equals(underlying);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the matching Query type.
|
||||
*/
|
||||
public SpiQuery.Type getQueryType() {
|
||||
return queryType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying type.
|
||||
*/
|
||||
public Underlying getUnderlying() {
|
||||
return underlying;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns List.class or Set.class and null for Map.
|
||||
* Not intended to be called for maps.
|
||||
*/
|
||||
public Class<? extends Collection> getCollectionType() {
|
||||
return underlying.type;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,31 +13,31 @@ import org.slf4j.LoggerFactory;
|
||||
*/
|
||||
public class PersistControllerManager {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PersistControllerManager.class);
|
||||
private static final Logger logger = LoggerFactory.getLogger(PersistControllerManager.class);
|
||||
|
||||
private final List<BeanPersistController> list;
|
||||
|
||||
public PersistControllerManager(BootupClasses bootupClasses){
|
||||
|
||||
list = bootupClasses.getBeanPersistControllers();
|
||||
private final List<BeanPersistController> list;
|
||||
|
||||
public PersistControllerManager(BootupClasses bootupClasses) {
|
||||
|
||||
list = bootupClasses.getBeanPersistControllers();
|
||||
}
|
||||
|
||||
public int getRegisterCount() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BeanPersistController for a given entity type.
|
||||
*/
|
||||
public void addPersistControllers(DeployBeanDescriptor<?> deployDesc) {
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
BeanPersistController c = list.get(i);
|
||||
if (c.isRegisterFor(deployDesc.getBeanType())) {
|
||||
logger.debug("BeanPersistController on[" + deployDesc.getFullName() + "] " + c.getClass().getName());
|
||||
deployDesc.addPersistController(c);
|
||||
}
|
||||
}
|
||||
|
||||
public int getRegisterCount() {
|
||||
return list.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BeanPersistController for a given entity type.
|
||||
*/
|
||||
public void addPersistControllers(DeployBeanDescriptor<?> deployDesc){
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
BeanPersistController c = list.get(i);
|
||||
if (c.isRegisterFor(deployDesc.getBeanType())){
|
||||
logger.debug("BeanPersistController on[" + deployDesc.getFullName() + "] " + c.getClass().getName());
|
||||
deployDesc.addPersistController(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+32
-9
@@ -3,6 +3,7 @@ package com.avaje.ebeaninternal.server.deploy.generatedproperty;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.avaje.ebean.config.CurrentUserProvider;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
|
||||
/**
|
||||
@@ -10,19 +11,27 @@ import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
*/
|
||||
public class GeneratedPropertyFactory {
|
||||
|
||||
CounterFactory counterFactory;
|
||||
private final CounterFactory counterFactory = new CounterFactory();;
|
||||
|
||||
InsertTimestampFactory insertFactory;
|
||||
private final InsertTimestampFactory insertFactory = new InsertTimestampFactory();
|
||||
|
||||
UpdateTimestampFactory updateFactory;
|
||||
private final UpdateTimestampFactory updateFactory = new UpdateTimestampFactory();
|
||||
|
||||
HashSet<String> numberTypes = new HashSet<String>();
|
||||
private final HashSet<String> numberTypes = new HashSet<String>();
|
||||
|
||||
public GeneratedPropertyFactory() {
|
||||
counterFactory = new CounterFactory();
|
||||
insertFactory = new InsertTimestampFactory();
|
||||
updateFactory = new UpdateTimestampFactory();
|
||||
|
||||
private final GeneratedWhoModified generatedWhoModified;
|
||||
|
||||
private final GeneratedWhoCreated generatedWhoCreated;
|
||||
|
||||
public GeneratedPropertyFactory(CurrentUserProvider currentUserProvider) {
|
||||
|
||||
if (currentUserProvider != null) {
|
||||
generatedWhoCreated = new GeneratedWhoCreated(currentUserProvider);
|
||||
generatedWhoModified = new GeneratedWhoModified(currentUserProvider);
|
||||
} else {
|
||||
generatedWhoCreated = null;
|
||||
generatedWhoModified = null;
|
||||
}
|
||||
|
||||
numberTypes.add(Integer.class.getName());
|
||||
numberTypes.add(int.class.getName());
|
||||
@@ -62,4 +71,18 @@ public class GeneratedPropertyFactory {
|
||||
updateFactory.setUpdateTimestamp(property);
|
||||
}
|
||||
|
||||
public void setWhoCreated(DeployBeanProperty property) {
|
||||
if (generatedWhoCreated == null) {
|
||||
throw new IllegalStateException("No CurrentUserProvider has been set so @WhoCreated is not supported");
|
||||
}
|
||||
property.setGeneratedProperty(generatedWhoCreated);
|
||||
}
|
||||
|
||||
public void setWhoModified(DeployBeanProperty property) {
|
||||
if (generatedWhoModified == null) {
|
||||
throw new IllegalStateException("No CurrentUserProvider has been set so @WhoModified is not supported");
|
||||
}
|
||||
property.setGeneratedProperty(generatedWhoModified);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user