mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
41
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5d9a897ae | ||
|
|
ddf200ffdd | ||
|
|
7fa5e2aa8c | ||
|
|
8bfae9deef | ||
|
|
e6c9f151c1 | ||
|
|
30a0935300 | ||
|
|
b4182d4519 | ||
|
|
93cc0399f1 | ||
|
|
5404dab5a3 | ||
|
|
d70da1d805 | ||
|
|
2225d5b7e8 | ||
|
|
270369bd65 | ||
|
|
a932d61a94 | ||
|
|
24b08663af | ||
|
|
bb6c9c84ba | ||
|
|
a1e185b0f6 | ||
|
|
e2a467ca5a | ||
|
|
4b28933298 | ||
|
|
6077acf134 | ||
|
|
8a4ffd21ab | ||
|
|
d1314124af | ||
|
|
36f018b6aa | ||
|
|
87ccb6e333 | ||
|
|
3432c365f6 | ||
|
|
b7d5aa344f | ||
|
|
7e768623e4 | ||
|
|
73ab2ee1fe | ||
|
|
122fed448c | ||
|
|
6e52bee91f | ||
|
|
cc26afad13 | ||
|
|
bf20449fb5 | ||
|
|
6af5fae8e9 | ||
|
|
e26a38ecaa | ||
|
|
1cdf68f1c0 | ||
|
|
2923dd1d96 | ||
|
|
9067508e1d | ||
|
|
385cc76e34 | ||
|
|
c14cb4b85e | ||
|
|
52644647e4 | ||
|
|
3bf9dd6743 | ||
|
|
aececa2199 |
@@ -0,0 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
custom: https://ebean.io/sponsors
|
||||
@@ -3,6 +3,7 @@ sudo: required
|
||||
language: java
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
- openjdk11
|
||||
|
||||
git:
|
||||
depth: 3
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean</artifactId>
|
||||
<version>11.39.1</version>
|
||||
<version>11.40.1</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>ebean</name>
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
|
||||
<tag>ebean-11.39.1</tag>
|
||||
<tag>ebean-11.40.1</tag>
|
||||
</scm>
|
||||
|
||||
<profiles>
|
||||
@@ -141,7 +141,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-migration</artifactId>
|
||||
<version>11.16.1</version>
|
||||
<version>11.16.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -250,7 +250,7 @@
|
||||
<dependency>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-agent</artifactId>
|
||||
<version>11.39.1</version>
|
||||
<version>11.40.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -330,7 +330,7 @@
|
||||
<plugin>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>ebean-maven-plugin</artifactId>
|
||||
<version>11.39.1</version>
|
||||
<version>11.40.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>test</id>
|
||||
|
||||
@@ -69,8 +69,8 @@ public enum CacheMode {
|
||||
*/
|
||||
GET(true, false);
|
||||
|
||||
private boolean get;
|
||||
private boolean put;
|
||||
private final boolean get;
|
||||
private final boolean put;
|
||||
|
||||
CacheMode(boolean get, boolean put) {
|
||||
this.get = get;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package io.ebean.bean;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Identifies a unique node of an object graph.
|
||||
@@ -85,8 +86,7 @@ public final class ObjectGraphNode implements Serializable {
|
||||
}
|
||||
|
||||
ObjectGraphNode e = (ObjectGraphNode) obj;
|
||||
//noinspection StringEquality
|
||||
return ((e.path == path) || (e.path != null && e.path.equals(path)))
|
||||
return (Objects.equals(e.path, path))
|
||||
&& e.originQueryPoint.equals(originQueryPoint);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ public enum ServerCacheType {
|
||||
*/
|
||||
QUERY("_Q");
|
||||
|
||||
private String code;
|
||||
private final String code;
|
||||
|
||||
ServerCacheType(String code) {
|
||||
this.code = code;
|
||||
|
||||
@@ -219,7 +219,6 @@ abstract class AbstractBeanCollection<E> implements BeanCollection<E> {
|
||||
|
||||
/**
|
||||
* Copies all relevant properties for a clone. See {@link #getShallowCopy()}
|
||||
* @param other
|
||||
*/
|
||||
protected void setFromOriginal(AbstractBeanCollection<E> other) {
|
||||
this.disableLazyLoad = other.disableLazyLoad;
|
||||
|
||||
@@ -237,7 +237,7 @@ public final class BeanMap<K, E> extends AbstractBeanCollection<E> implements Ma
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public Set<Entry<K, E>> entrySet() {
|
||||
init();
|
||||
if (isReadOnly()) {
|
||||
|
||||
@@ -77,6 +77,9 @@ public class PlatformConfig {
|
||||
this.geometrySRID = platformConfig.geometrySRID;
|
||||
this.dbUuid = platformConfig.dbUuid;
|
||||
this.caseSensitiveCollation = platformConfig.caseSensitiveCollation;
|
||||
this.allQuotedIdentifiers = platformConfig.allQuotedIdentifiers;
|
||||
this.databaseInetAddressVarchar = platformConfig.databaseInetAddressVarchar;
|
||||
this.customDbTypeMappings = platformConfig.customDbTypeMappings;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -653,6 +653,7 @@ public class ServerConfig {
|
||||
* @param cls The type of the service object to obtain
|
||||
* @return The service object given the class type
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <P> P getServiceObject(Class<P> cls) {
|
||||
return (P) serviceObject.get(serviceObjectKey(cls));
|
||||
}
|
||||
|
||||
@@ -35,9 +35,9 @@ public enum TenantMode {
|
||||
* (that holds configuration e.g.)
|
||||
*/
|
||||
DB_WITH_MASTER(true, true);
|
||||
|
||||
boolean dynamicDataSource;
|
||||
boolean ddlEnabled;
|
||||
|
||||
final boolean dynamicDataSource;
|
||||
final boolean ddlEnabled;
|
||||
|
||||
TenantMode(boolean dynamicDataSource, boolean ddlEnabled) {
|
||||
this.dynamicDataSource = dynamicDataSource;
|
||||
@@ -50,12 +50,12 @@ public enum TenantMode {
|
||||
public boolean isDynamicDataSource() {
|
||||
return dynamicDataSource;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true, if DDL is enabled.
|
||||
*/
|
||||
public boolean isDdlEnabled() {
|
||||
return ddlEnabled;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -27,15 +27,13 @@ public class DbDefaultValue {
|
||||
* The key for the NOW / current timestamp.
|
||||
*/
|
||||
public static final String NOW = "now";
|
||||
|
||||
|
||||
/**
|
||||
* The 'null' literal.
|
||||
*/
|
||||
public static final String NULL = "null";
|
||||
|
||||
|
||||
|
||||
protected Map<String, String> map = new LinkedHashMap<>();
|
||||
protected final Map<String, String> map = new LinkedHashMap<>();
|
||||
|
||||
/**
|
||||
* Set the DB now function.
|
||||
@@ -82,10 +80,9 @@ public class DbDefaultValue {
|
||||
return val != null ? val : dbDefaultLiteral;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method checks & convert the {@link DbDefault#value()} to a valid SQL literal.
|
||||
*
|
||||
*
|
||||
* This is mainly to quote string literals and verify integer/dates for correctness.
|
||||
* <p>
|
||||
* Note: There are some special cases:
|
||||
@@ -98,24 +95,24 @@ public class DbDefaultValue {
|
||||
* If you need really the String "null", you have to specify <code>@DbDefault("'null'")</code>
|
||||
* which gives you the <code>default 'null'</code> statement.</li>
|
||||
* <li>Any statement, that begins and ends with single quote will not be checked or get quoted again.</li>
|
||||
* <li>A statement that begins with "$RAW:", e.g <code>@DbDefault("$RAW:N'SANDNES'")</code> will lead to
|
||||
* <li>A statement that begins with "$RAW:", e.g <code>@DbDefault("$RAW:N'SANDNES'")</code> will lead to
|
||||
* a <code>default N'SANDNES'</code> in DDL. Note that this is platform specific!</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static String toSqlLiteral(String defaultValue, Class<?> propertyType, int sqlType) {
|
||||
if (propertyType == null
|
||||
|| defaultValue == null
|
||||
|| defaultValue == null
|
||||
|| NULL.equals(defaultValue)
|
||||
|| (defaultValue.startsWith("'") && defaultValue.endsWith("'"))
|
||||
|| (defaultValue.startsWith("$RAW:"))) {
|
||||
|| (defaultValue.startsWith("$RAW:"))) {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
if (Boolean.class.isAssignableFrom(propertyType) || Boolean.TYPE.isAssignableFrom(propertyType)) {
|
||||
return toBooleanLiteral(defaultValue);
|
||||
}
|
||||
|
||||
if (Number.class.isAssignableFrom(propertyType)
|
||||
|
||||
if (Number.class.isAssignableFrom(propertyType)
|
||||
|| Byte.TYPE.equals(propertyType)
|
||||
|| Short.TYPE.equals(propertyType)
|
||||
|| Integer.TYPE.equals(propertyType)
|
||||
@@ -126,7 +123,7 @@ public class DbDefaultValue {
|
||||
Double.valueOf(defaultValue); // verify if it is a number
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
|
||||
// check if it is a date/time - in all other cases return quoted defaultValue
|
||||
switch (sqlType) {
|
||||
// date
|
||||
@@ -155,7 +152,7 @@ public class DbDefaultValue {
|
||||
}
|
||||
throw new IllegalArgumentException("'" + value + "' is not a valid value for boolean");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This adds single qoutes around the <code>value</code> and doubles single quotes.
|
||||
* "User's home" will return "'User''s home'"
|
||||
@@ -175,7 +172,7 @@ public class DbDefaultValue {
|
||||
return sb.toString();
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static String toDateLiteral(String value) {
|
||||
if (NOW.equals(value)) {
|
||||
return value; // this will get translated later
|
||||
@@ -191,7 +188,7 @@ public class DbDefaultValue {
|
||||
DatatypeConverter.parseTime(value); // verify
|
||||
return toTextLiteral(value);
|
||||
}
|
||||
|
||||
|
||||
private static String toDateTimeLiteral(String value) {
|
||||
if (NOW.equals(value)) {
|
||||
return value; // this will get translated later
|
||||
|
||||
@@ -11,12 +11,12 @@ class DbPlatformTypeLookup {
|
||||
/**
|
||||
* A map to lookup the type by name.
|
||||
*/
|
||||
private Map<String, DbType> nameLookup = new HashMap<>();
|
||||
private final Map<String, DbType> nameLookup = new HashMap<>();
|
||||
|
||||
/**
|
||||
* A map to lookup the type by JDBC int value.
|
||||
*/
|
||||
private Map<Integer, DbType> idLookup = new HashMap<>();
|
||||
private final Map<Integer, DbType> idLookup = new HashMap<>();
|
||||
|
||||
DbPlatformTypeLookup() {
|
||||
addAll();
|
||||
|
||||
@@ -23,7 +23,7 @@ public class DbPlatformTypeMapping {
|
||||
}
|
||||
}
|
||||
|
||||
private static DbPlatformTypeLookup lookup = new DbPlatformTypeLookup();
|
||||
private static final DbPlatformTypeLookup lookup = new DbPlatformTypeLookup();
|
||||
|
||||
private static final DbPlatformType BOOLEAN_LOGICAL = new BooleanLogicalType();
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.util.Map;
|
||||
*/
|
||||
public class SqlErrorCodes {
|
||||
|
||||
private Map<String,DataErrorType> map = new HashMap<>();
|
||||
private final Map<String,DataErrorType> map = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Map the codes to AcquireLockException.
|
||||
|
||||
@@ -10,7 +10,7 @@ import java.util.Set;
|
||||
*/
|
||||
public class QueryPlanRequest {
|
||||
|
||||
private List<MetaQueryPlan> plans = new ArrayList<>();
|
||||
private final List<MetaQueryPlan> plans = new ArrayList<>();
|
||||
|
||||
private Connection connection;
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import java.util.ServiceLoader;
|
||||
*/
|
||||
class MetricServiceProvider {
|
||||
|
||||
private static MetricFactory metricFactory = init();
|
||||
private static final MetricFactory metricFactory = init();
|
||||
|
||||
private static MetricFactory init() {
|
||||
|
||||
|
||||
@@ -223,7 +223,6 @@ public interface BeanType<T> {
|
||||
|
||||
/**
|
||||
* Visit all children recursively
|
||||
* @param visitor
|
||||
*/
|
||||
void visitAllInheritanceChildren(Consumer<BeanType<?>> visitor);
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ public interface ExpressionPath {
|
||||
/**
|
||||
* Return the underlying bean property.
|
||||
*/
|
||||
public Property getProperty();
|
||||
Property getProperty();
|
||||
|
||||
/**
|
||||
* The ElPrefix plus name.
|
||||
|
||||
@@ -49,13 +49,12 @@ class PathPropertiesParser {
|
||||
private String getPath() {
|
||||
do {
|
||||
char c1 = chars[pos++];
|
||||
switch (c1) {
|
||||
case '(':
|
||||
return currentWord();
|
||||
default:
|
||||
if (pos == 1) {
|
||||
return "";
|
||||
}
|
||||
if (c1 == '(') {
|
||||
return currentWord();
|
||||
} else {
|
||||
if (pos == 1) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
} while (pos < eof);
|
||||
throw new RuntimeException("Hit EOF while reading sectionTitle from " + startPos);
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.util.List;
|
||||
*/
|
||||
public class BeanCacheResult<T> {
|
||||
|
||||
private List<Entry<T>> list = new ArrayList<>();
|
||||
private final List<Entry<T>> list = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Add an entry.
|
||||
|
||||
@@ -115,10 +115,10 @@ public class BindParams implements Serializable {
|
||||
* Return a Natural Key bind param if supported.
|
||||
*/
|
||||
public NaturalKeyBindParam getNaturalKeyBindParam() {
|
||||
if (positionedParameters != null) {
|
||||
if (!positionedParameters.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (namedParameters != null && namedParameters.size() == 1) {
|
||||
if (namedParameters.size() == 1) {
|
||||
Entry<String, Param> e = namedParameters.entrySet().iterator().next();
|
||||
return new NaturalKeyBindParam(e.getKey(), e.getValue().getInValue());
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@ import java.util.Map;
|
||||
*/
|
||||
public class NaturalKeyEntry {
|
||||
|
||||
private Map<String,Object> map = new HashMap<>();
|
||||
private Object key;
|
||||
private final Map<String,Object> map = new HashMap<>();
|
||||
private final Object key;
|
||||
private Object inValue;
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,7 @@ public class ScopedTransaction extends SpiTransactionProxy {
|
||||
/**
|
||||
* Stack of 'nested' transactions.
|
||||
*/
|
||||
private ArrayStack<ScopeTrans> stack = new ArrayStack<>();
|
||||
private final ArrayStack<ScopeTrans> stack = new ArrayStack<>();
|
||||
|
||||
private ScopeTrans current;
|
||||
|
||||
|
||||
@@ -106,9 +106,9 @@ public interface SpiQuery<T> extends Query<T>, TxnProfileEventCodes {
|
||||
*/
|
||||
UPDATE(FIND_UPDATE, "update", true);
|
||||
|
||||
private boolean update;
|
||||
private String profileEventId;
|
||||
private String label;
|
||||
private final boolean update;
|
||||
private final String profileEventId;
|
||||
private final String label;
|
||||
|
||||
Type(String profileEventId, String label) {
|
||||
this(profileEventId, label, false);
|
||||
|
||||
@@ -75,7 +75,7 @@ public class TransactionEvent implements Serializable {
|
||||
* Return the list of PersistRequestBean's for this transaction.
|
||||
*/
|
||||
public List<PersistRequestBean<?>> getListenerNotify() {
|
||||
return (listenerNotify == null) ? null : listenerNotify;
|
||||
return listenerNotify;
|
||||
}
|
||||
|
||||
public TransactionEventTable getEventTables() {
|
||||
|
||||
@@ -60,10 +60,7 @@ class LastMigration {
|
||||
}
|
||||
|
||||
private static boolean includeSqlFile(String lowerFileName) {
|
||||
if (lowerFileName.startsWith("r") || lowerFileName.startsWith("i") || !lowerFileName.endsWith(SQL)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return !lowerFileName.startsWith("r") && !lowerFileName.startsWith("i") && lowerFileName.endsWith(SQL);
|
||||
}
|
||||
|
||||
private static boolean includeModelFile(String lowerFileName) {
|
||||
|
||||
@@ -62,14 +62,14 @@ public class BaseTableDdl implements TableDdl {
|
||||
* Used to check that indexes on foreign keys should be skipped as a unique index on the columns
|
||||
* already exists.
|
||||
*/
|
||||
protected IndexSet indexSet = new IndexSet();
|
||||
protected final IndexSet indexSet = new IndexSet();
|
||||
|
||||
/**
|
||||
* Used when unique constraints specifically for OneToOne can't be created normally (MsSqlServer).
|
||||
*/
|
||||
protected List<Column> externalUnique = new ArrayList<>();
|
||||
protected final List<Column> externalUnique = new ArrayList<>();
|
||||
|
||||
protected List<UniqueConstraint> externalCompoundUnique = new ArrayList<>();
|
||||
protected final List<UniqueConstraint> externalCompoundUnique = new ArrayList<>();
|
||||
|
||||
// counters used when constraint names are truncated due to maximum length
|
||||
// and these counters are used to keep the constraint name unique
|
||||
@@ -82,9 +82,9 @@ public class BaseTableDdl implements TableDdl {
|
||||
* Base tables that have associated history tables that need their triggers/functions regenerated as
|
||||
* columns have been added, removed, included or excluded.
|
||||
*/
|
||||
protected Map<String, HistoryTableUpdate> regenerateHistoryTriggers = new LinkedHashMap<>();
|
||||
protected final Map<String, HistoryTableUpdate> regenerateHistoryTriggers = new LinkedHashMap<>();
|
||||
|
||||
private boolean strictMode;
|
||||
private final boolean strictMode;
|
||||
|
||||
private final HistorySupport historySupport;
|
||||
|
||||
@@ -134,7 +134,7 @@ public class BaseTableDdl implements TableDdl {
|
||||
if (defaultValue == null) {
|
||||
handleStrictError(tableName, columnName);
|
||||
}
|
||||
before = Arrays.asList(platformDdl.getUpdateNullWithDefault());
|
||||
before = Collections.singletonList(platformDdl.getUpdateNullWithDefault());
|
||||
} else {
|
||||
before = getScriptsForPlatform(alter.getBefore(), platformDdl.getPlatform().getName());
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ public class CurrentModel {
|
||||
List<DdlScript> ddlScript = extraDdl.getDdlScript();
|
||||
for (DdlScript script : ddlScript) {
|
||||
if (script.isInit() && ExtraDdlXmlReader.matchPlatform(server.getDatabasePlatform().getName(), script.getPlatforms())) {
|
||||
ddl.append(prefix + script.getName()).append('\n');
|
||||
ddl.append(prefix).append(script.getName()).append('\n');
|
||||
ddl.append(script.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import io.ebeaninternal.dbmigration.migration.DdlScript;
|
||||
import io.ebeaninternal.server.deploy.DbMigrationInfo;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A column in the logical model.
|
||||
@@ -309,7 +310,7 @@ public class MColumn {
|
||||
}
|
||||
|
||||
protected static boolean different(String val1, String val2) {
|
||||
return (val1 == null) ? val2 != null : !val1.equals(val2);
|
||||
return !Objects.equals(val1, val2);
|
||||
}
|
||||
|
||||
private boolean hasValue(String val) {
|
||||
|
||||
@@ -769,7 +769,7 @@ public class MTable {
|
||||
nullableColumns.add(columnName);
|
||||
}
|
||||
}
|
||||
uniq.setNullableColumns(nullableColumns.toArray(new String[nullableColumns.size()]));
|
||||
uniq.setNullableColumns(nullableColumns.toArray(new String[0]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ public class DJsonService implements SpiJsonService {
|
||||
if (modifyAware) {
|
||||
return ((ModifyAwareList<T>) list).asSet();
|
||||
} else {
|
||||
return new LinkedHashSet<T>(list);
|
||||
return new LinkedHashSet<>(list);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.util.List;
|
||||
*/
|
||||
public class AutoTuneCollection {
|
||||
|
||||
List<Entry> entries = new ArrayList<>();
|
||||
final List<Entry> entries = new ArrayList<>();
|
||||
|
||||
public Entry add(ObjectGraphOrigin origin, OrmQueryDetail detail, String sourceQuery) {
|
||||
Entry entry = new Entry(origin, detail, sourceQuery);
|
||||
|
||||
@@ -8,7 +8,7 @@ import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
import io.ebeaninternal.api.SpiSqlBinding;
|
||||
import io.ebeaninternal.api.SpiTransaction;
|
||||
import io.ebeaninternal.server.lib.util.Str;
|
||||
import io.ebeaninternal.server.lib.Str;
|
||||
import io.ebeaninternal.server.persist.Binder;
|
||||
import io.ebeaninternal.server.persist.TrimLogSql;
|
||||
import io.ebeaninternal.server.util.BindParamsParser;
|
||||
|
||||
@@ -91,17 +91,13 @@ public class DefaultBackgroundExecutor implements SpiBackgroundExecutor {
|
||||
if (map == null) {
|
||||
return schedulePool.schedule(c, delay, unit);
|
||||
} else {
|
||||
return schedulePool.schedule(new Callable<V>() {
|
||||
@Override
|
||||
public V call() throws Exception {
|
||||
MDC.setContextMap(map);
|
||||
try {
|
||||
return c.call();
|
||||
} finally {
|
||||
MDC.clear();
|
||||
}
|
||||
return schedulePool.schedule(() -> {
|
||||
MDC.setContextMap(map);
|
||||
try {
|
||||
return c.call();
|
||||
} finally {
|
||||
MDC.clear();
|
||||
}
|
||||
|
||||
}, delay, unit);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,10 +55,7 @@ public class DefaultCallStackFactory implements CallStackFactory {
|
||||
if (element.getClassName().startsWith(IO_EBEAN)) {
|
||||
return true;
|
||||
}
|
||||
if (element.getMethodName().startsWith("_ebean_")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return element.getMethodName().startsWith("_ebean_");
|
||||
}
|
||||
|
||||
private CallStack createCallStack(StackTraceElement[] finalTrace) {
|
||||
|
||||
@@ -102,7 +102,7 @@ import io.ebeaninternal.server.query.LimitOffsetPagedList;
|
||||
import io.ebeaninternal.server.query.QueryFutureIds;
|
||||
import io.ebeaninternal.server.query.QueryFutureList;
|
||||
import io.ebeaninternal.server.query.QueryFutureRowCount;
|
||||
import io.ebeaninternal.server.query.dto.DtoQueryEngine;
|
||||
import io.ebeaninternal.server.query.DtoQueryEngine;
|
||||
import io.ebeaninternal.server.querydefn.DefaultDtoQuery;
|
||||
import io.ebeaninternal.server.querydefn.DefaultOrmQuery;
|
||||
import io.ebeaninternal.server.querydefn.DefaultOrmUpdate;
|
||||
@@ -160,7 +160,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
/**
|
||||
* Clock to use for WhenModified and WhenCreated.
|
||||
*/
|
||||
private ClockService clockService;
|
||||
private final ClockService clockService;
|
||||
|
||||
private final CallStackFactory callStackFactory;
|
||||
|
||||
@@ -658,10 +658,8 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T createEntityBean(Class<T> type) {
|
||||
BeanDescriptor<T> desc = getBeanDescriptor(type);
|
||||
return (T) desc.createEntityBean(true);
|
||||
return getBeanDescriptor(type).createBean();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,7 @@ import io.ebeaninternal.server.dto.DtoColumn;
|
||||
import io.ebeaninternal.server.dto.DtoMappingRequest;
|
||||
import io.ebeaninternal.server.dto.DtoQueryPlan;
|
||||
import io.ebeaninternal.server.persist.Binder;
|
||||
import io.ebeaninternal.server.query.dto.DtoQueryEngine;
|
||||
import io.ebeaninternal.server.query.DtoQueryEngine;
|
||||
import io.ebeaninternal.server.type.DataReader;
|
||||
import io.ebeaninternal.server.type.RsetDataReader;
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ import io.ebeaninternal.server.persist.platform.PostgresMultiValueBind;
|
||||
import io.ebeaninternal.server.query.CQueryEngine;
|
||||
import io.ebeaninternal.server.query.DefaultOrmQueryEngine;
|
||||
import io.ebeaninternal.server.query.DefaultRelationalQueryEngine;
|
||||
import io.ebeaninternal.server.query.dto.DtoQueryEngine;
|
||||
import io.ebeaninternal.server.query.DtoQueryEngine;
|
||||
import io.ebeaninternal.server.readaudit.DefaultReadAuditLogger;
|
||||
import io.ebeaninternal.server.readaudit.DefaultReadAuditPrepare;
|
||||
import io.ebeaninternal.server.text.json.DJsonContext;
|
||||
@@ -328,12 +328,10 @@ public class InternalConfiguration {
|
||||
|
||||
private MultiValueBind createMultiValueBind(Platform platform) {
|
||||
// only Postgres at this stage
|
||||
switch (platform) {
|
||||
case POSTGRES:
|
||||
return new PostgresMultiValueBind();
|
||||
default:
|
||||
return new MultiValueBind();
|
||||
if (platform == Platform.POSTGRES) {
|
||||
return new PostgresMultiValueBind();
|
||||
}
|
||||
return new MultiValueBind();
|
||||
}
|
||||
|
||||
public SpiJsonContext createJsonContext(SpiEbeanServer server) {
|
||||
|
||||
@@ -24,7 +24,7 @@ public abstract class PersistRequest extends BeanRequest implements BatchPostExe
|
||||
DELETE_PERMANENT(EVT_DELETE_PERMANENT),
|
||||
UPDATESQL(EVT_UPDATESQL),
|
||||
CALLABLESQL(EVT_CALLABLESQL);
|
||||
String profileEventId;
|
||||
final String profileEventId;
|
||||
|
||||
Type(String profileEventId) {
|
||||
this.profileEventId = profileEventId;
|
||||
|
||||
@@ -85,7 +85,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
|
||||
private DocStoreMode docStoreMode;
|
||||
|
||||
private ConcurrencyMode concurrencyMode;
|
||||
private final ConcurrencyMode concurrencyMode;
|
||||
|
||||
/**
|
||||
* The unique id used for logging summary.
|
||||
@@ -223,6 +223,12 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
beanDescriptor.setDraftDirty(entityBean, true);
|
||||
}
|
||||
this.dirty = intercept.isDirty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Init generated properties for soft delete (as it's an update).
|
||||
*/
|
||||
public void initForSoftDelete() {
|
||||
initGeneratedProperties();
|
||||
}
|
||||
|
||||
@@ -1320,10 +1326,8 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
*/
|
||||
public void docStorePersist() {
|
||||
idValue = beanDescriptor.getId(entityBean);
|
||||
switch (type) {
|
||||
case UPDATE:
|
||||
dirtyProperties = intercept.getDirtyProperties();
|
||||
break;
|
||||
if (type == Type.UPDATE) {
|
||||
dirtyProperties = intercept.getDirtyProperties();
|
||||
}
|
||||
// processing now so set IGNORE (unlike DB + DocStore processing with post-commit)
|
||||
docStoreMode = DocStoreMode.IGNORE;
|
||||
@@ -1370,6 +1374,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
* Set the request flags indicating this is an insert.
|
||||
*/
|
||||
public void flagInsert() {
|
||||
initGeneratedProperties();
|
||||
if (intercept.isNew()) {
|
||||
flags = Flags.setInsertNormal(flags);
|
||||
} else {
|
||||
@@ -1381,6 +1386,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
* Unset the request insert flag indicating this is an update.
|
||||
*/
|
||||
public void flagUpdate() {
|
||||
initGeneratedProperties();
|
||||
if (intercept.isLoaded()) {
|
||||
flags = Flags.setUpdateNormal(flags);
|
||||
} else {
|
||||
|
||||
@@ -3,7 +3,7 @@ package io.ebeaninternal.server.core;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.api.SpiSqlUpdate;
|
||||
import io.ebeaninternal.api.SpiTransaction;
|
||||
import io.ebeaninternal.server.lib.util.Str;
|
||||
import io.ebeaninternal.server.lib.Str;
|
||||
import io.ebeaninternal.server.persist.BatchControl;
|
||||
import io.ebeaninternal.server.persist.PersistExecute;
|
||||
import io.ebeaninternal.server.persist.TrimLogSql;
|
||||
@@ -29,7 +29,7 @@ public final class PersistRequestUpdateSql extends PersistRequest {
|
||||
|
||||
private boolean addBatch;
|
||||
|
||||
private boolean forceNoBatch;
|
||||
private final boolean forceNoBatch;
|
||||
|
||||
private boolean batchThisRequest;
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ public final class RelationalQueryRequest extends AbstractSqlQueryRequest {
|
||||
for (int i = 1; i < columnsPlusOne; i++) {
|
||||
propNames.add(metaData.getColumnLabel(i));
|
||||
}
|
||||
return propNames.toArray(new String[propNames.size()]);
|
||||
return propNames.toArray(new String[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -235,7 +235,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
/**
|
||||
* Map of BeanProperty Linked so as to preserve order.
|
||||
*/
|
||||
protected final LinkedHashMap<String, BeanProperty> propMap;
|
||||
private final LinkedHashMap<String, BeanProperty> propMap;
|
||||
|
||||
/**
|
||||
* Map of DB column to property path (for nativeSql mapping).
|
||||
@@ -252,7 +252,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
*/
|
||||
final Class<T> beanType;
|
||||
|
||||
protected final Class<?> rootBeanType;
|
||||
final Class<?> rootBeanType;
|
||||
|
||||
/**
|
||||
* This is not sent to a remote client.
|
||||
@@ -287,11 +287,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
*/
|
||||
private final ChangeLogFilter changeLogFilter;
|
||||
|
||||
/**
|
||||
* The table joins for this bean.
|
||||
*/
|
||||
private final TableJoin[] derivedTableJoins;
|
||||
|
||||
/**
|
||||
* Inheritance information. Server side only.
|
||||
*/
|
||||
@@ -374,7 +369,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* All non transient properties excluding the id properties.
|
||||
*/
|
||||
private final BeanProperty[] propertiesNonTransient;
|
||||
protected final BeanProperty[] propertiesIndex;
|
||||
final BeanProperty[] propertiesIndex;
|
||||
private final BeanProperty[] propertiesGenInsert;
|
||||
private final BeanProperty[] propertiesGenUpdate;
|
||||
private final List<BeanProperty[]> propertiesUnique = new ArrayList<>();
|
||||
@@ -423,7 +418,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
|
||||
private final BeanDescriptorDraftHelp<T> draftHelp;
|
||||
private final BeanDescriptorCacheHelp<T> cacheHelp;
|
||||
final BeanDescriptorJsonHelp<T> jsonHelp;
|
||||
private final BeanDescriptorJsonHelp<T> jsonHelp;
|
||||
private DocStoreBeanAdapter<T> docStoreAdapter;
|
||||
private DocumentMapping docMapping;
|
||||
private boolean docStoreEmbeddedInvalidation;
|
||||
@@ -529,8 +524,6 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
this.propertiesGenInsert = listHelper.getGeneratedInsert();
|
||||
this.propertiesGenUpdate = listHelper.getGeneratedUpdate();
|
||||
|
||||
this.derivedTableJoins = listHelper.getTableJoin();
|
||||
|
||||
boolean noRelationships = propertiesOne.length + propertiesMany.length == 0;
|
||||
|
||||
this.cacheSharableBeans = noRelationships && deploy.getCacheOptions().isReadOnly();
|
||||
@@ -655,7 +648,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
/**
|
||||
* Return true if this is an abstract type.
|
||||
*/
|
||||
public boolean isAbstractType() {
|
||||
boolean isAbstractType() {
|
||||
return abstractType;
|
||||
}
|
||||
|
||||
@@ -689,7 +682,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* as they are used to get the imported and exported properties.
|
||||
* </p>
|
||||
*/
|
||||
public void initialiseId(BeanDescriptorInitContext initContext) {
|
||||
void initialiseId(BeanDescriptorInitContext initContext) {
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("BeanDescriptor initialise " + fullName);
|
||||
@@ -783,7 +776,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
/**
|
||||
* Perform last initialisation for the descriptor.
|
||||
*/
|
||||
public void initLast() {
|
||||
void initLast() {
|
||||
|
||||
for (BeanProperty prop : propertiesNonTransient) {
|
||||
if (prop.isUnique()) {
|
||||
@@ -825,7 +818,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
* Initialise the document mapping.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void initialiseDocMapping() {
|
||||
void initialiseDocMapping() {
|
||||
for (BeanPropertyAssocMany<?> many : propertiesMany) {
|
||||
many.initialisePostTarget();
|
||||
}
|
||||
@@ -840,7 +833,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
cacheHelp.deriveNotifyFlags();
|
||||
}
|
||||
|
||||
public void initInheritInfo() {
|
||||
void initInheritInfo() {
|
||||
if (inheritInfo != null) {
|
||||
// need to check every BeanDescriptor in the inheritance hierarchy
|
||||
if (saveRecurseSkippable) {
|
||||
@@ -894,7 +887,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
/**
|
||||
* Return the ReadAuditPrepare for preparing read audit events prior to logging.
|
||||
*/
|
||||
public ReadAuditPrepare getReadAuditPrepare() {
|
||||
private ReadAuditPrepare getReadAuditPrepare() {
|
||||
return ebeanServer.getReadAuditPrepare();
|
||||
}
|
||||
|
||||
@@ -980,7 +973,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
/**
|
||||
* Populate the diff for inserts with flattened non-null property values.
|
||||
*/
|
||||
protected void jsonWriteForInsert(SpiJsonWriter jsonWriter, EntityBean newBean) throws IOException {
|
||||
void jsonWriteForInsert(SpiJsonWriter jsonWriter, EntityBean newBean) throws IOException {
|
||||
jsonWriter.writeStartObject();
|
||||
for (BeanProperty prop : propertiesBaseScalar) {
|
||||
prop.jsonWriteForInsert(jsonWriter, newBean);
|
||||
@@ -1057,7 +1050,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
elDeployCache.put(fkey.getName(), fkey);
|
||||
}
|
||||
|
||||
public void initialiseFkeys() {
|
||||
void initialiseFkeys() {
|
||||
for (BeanPropertyAssocOne<?> aPropertiesOneImported : propertiesOneImported) {
|
||||
if (!aPropertiesOneImported.isFormula()) {
|
||||
aPropertiesOneImported.addFkey();
|
||||
@@ -1915,18 +1908,19 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
beanPostConstructListener.autowire(bean); // calls all registered listeners
|
||||
beanPostConstructListener.postConstruct(bean); // calls first the @PostConstruct method and then the listeners
|
||||
}
|
||||
|
||||
if (unloadProperties.length > 0) {
|
||||
if (isNew) {
|
||||
if (beanPostConstructListener != null) {
|
||||
beanPostConstructListener.postCreate(bean);
|
||||
// if bean is not new, postLoad will be executed later in the bean's lifecycle
|
||||
}
|
||||
// do not unload properties for new beans!
|
||||
} else if (unloadProperties.length > 0) {
|
||||
// 'unload' any properties initialised in the default constructor
|
||||
EntityBeanIntercept ebi = bean._ebean_getIntercept();
|
||||
for (int unloadProperty : unloadProperties) {
|
||||
ebi.setPropertyUnloaded(unloadProperty);
|
||||
}
|
||||
}
|
||||
if (beanPostConstructListener != null && isNew) {
|
||||
beanPostConstructListener.postCreate(bean);
|
||||
// if bean is not new, postLoad will be executed later in the bean's lifecycle
|
||||
}
|
||||
return bean;
|
||||
|
||||
} catch (Exception ex) {
|
||||
@@ -2575,7 +2569,7 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType {
|
||||
*/
|
||||
private STreeProperty findSqlTreeFormula(String formula, String path) {
|
||||
String key = formula + "-" + path;
|
||||
return dynamicProperty.computeIfAbsent(key, (fullKey) -> new FormulaPropertyPath(this, formula, path).build());
|
||||
return dynamicProperty.computeIfAbsent(key, (fullKey) -> FormulaPropertyPath.create(this, formula, path));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -39,7 +39,7 @@ public final class BeanDescriptorDraftHelp<T> {
|
||||
}
|
||||
}
|
||||
|
||||
return list.toArray(new BeanProperty[list.size()]);
|
||||
return list.toArray(new BeanProperty[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -815,7 +815,6 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
return new BeanTable(beanTable, this);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
private void readEntityRelationships() {
|
||||
|
||||
// We only perform 'circular' checks etc after we have
|
||||
@@ -1650,7 +1649,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
return changeLogListener;
|
||||
}
|
||||
|
||||
public void addPrimaryKeyJoin(DeployBeanPropertyAssocOne<?> prop) {
|
||||
private void addPrimaryKeyJoin(DeployBeanPropertyAssocOne<?> prop) {
|
||||
|
||||
String baseTable = prop.getDesc().getBaseTable();
|
||||
DeployTableJoin inverse = prop.getTableJoin().createInverse(baseTable);
|
||||
|
||||
@@ -142,7 +142,7 @@ class BeanLifecycleAdapterFactory {
|
||||
* Utility method to covert List of Method into array (because we care about performance here).
|
||||
*/
|
||||
static Method[] toArray(List<Method> methodList) {
|
||||
return methodList.toArray(new Method[methodList.size()]);
|
||||
return methodList.toArray(new Method[0]);
|
||||
}
|
||||
|
||||
static RuntimeException unwrapException(ReflectiveOperationException e) {
|
||||
|
||||
@@ -107,6 +107,7 @@ public abstract class BeanPropertyAssoc<T> extends BeanProperty implements STree
|
||||
/**
|
||||
* Copy constructor for ManyToOne inside Embeddable.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public BeanPropertyAssoc(BeanPropertyAssoc source, BeanPropertyOverride override) {
|
||||
super(source, override);
|
||||
foreignKey = source.foreignKey;
|
||||
|
||||
@@ -79,7 +79,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
/**
|
||||
* Descriptor for the 'target' when the property maps to an element collection.
|
||||
*/
|
||||
BeanDescriptor<T> elementDescriptor;
|
||||
final BeanDescriptor<T> elementDescriptor;
|
||||
|
||||
/**
|
||||
* Order by used when fetch joining the associated many.
|
||||
@@ -683,7 +683,7 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
}
|
||||
}
|
||||
|
||||
return list.toArray(new ExportedProperty[list.size()]);
|
||||
return list.toArray(new ExportedProperty[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,6 +23,7 @@ import io.ebeaninternal.server.query.SqlBeanLoad;
|
||||
import io.ebeaninternal.server.query.SqlJoinType;
|
||||
import io.ebeaninternal.server.type.DataReader;
|
||||
import io.ebeaninternal.server.type.ScalarDataReader;
|
||||
import io.ebeaninternal.server.type.ScalarType;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.io.IOException;
|
||||
@@ -465,6 +466,10 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
return targetDescriptor.getIdProperty();
|
||||
}
|
||||
|
||||
public ScalarType getIdScalarType() {
|
||||
return targetDescriptor.getIdProperty().scalarType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Id values from the given bean.
|
||||
*/
|
||||
@@ -577,7 +582,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
}
|
||||
}
|
||||
|
||||
return list.toArray(new ExportedProperty[list.size()]);
|
||||
return list.toArray(new ExportedProperty[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -764,10 +769,7 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> implements STr
|
||||
writeJson.writeNullField(name);
|
||||
|
||||
} else {
|
||||
if (writeJson.isParentBean(value)) {
|
||||
// bi-directional and already rendered parent
|
||||
|
||||
} else {
|
||||
if (!writeJson.isParentBean(value)) {
|
||||
// Hmmm, not writing complex non-entity bean
|
||||
if (value instanceof EntityBean) {
|
||||
writeJson.beginAssocOne(name, bean);
|
||||
|
||||
@@ -8,6 +8,7 @@ import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssocOne;
|
||||
*/
|
||||
public class BeanPropertyIdClass extends BeanPropertyAssocOne {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public BeanPropertyIdClass(BeanDescriptorMap owner, BeanDescriptor descriptor, DeployBeanPropertyAssocOne deploy) {
|
||||
super(owner, descriptor, deploy);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public class ChainedBeanPersistController implements BeanPersistController {
|
||||
*/
|
||||
public ChainedBeanPersistController(List<BeanPersistController> list) {
|
||||
this.list = list;
|
||||
BeanPersistController[] c = list.toArray(new BeanPersistController[list.size()]);
|
||||
BeanPersistController[] c = list.toArray(new BeanPersistController[0]);
|
||||
Arrays.sort(c, SORTER);
|
||||
this.chain = c;
|
||||
}
|
||||
@@ -185,7 +185,7 @@ public class ChainedBeanPersistController implements BeanPersistController {
|
||||
|
||||
int i1 = o1.getExecutionOrder();
|
||||
int i2 = o2.getExecutionOrder();
|
||||
return (i1 < i2 ? -1 : (i1 == i2 ? 0 : 1));
|
||||
return Integer.compare(i1, i2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class ChainedBeanPersistListener implements BeanPersistListener {
|
||||
*/
|
||||
public ChainedBeanPersistListener(List<BeanPersistListener> list) {
|
||||
this.list = list;
|
||||
this.chain = list.toArray(new BeanPersistListener[list.size()]);
|
||||
this.chain = list.toArray(new BeanPersistListener[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,7 +19,7 @@ public class ChainedBeanPostConstructListener implements BeanPostConstructListen
|
||||
*/
|
||||
public ChainedBeanPostConstructListener(List<BeanPostConstructListener> list) {
|
||||
this.list = list;
|
||||
this.chain = list.toArray(new BeanPostConstructListener[list.size()]);
|
||||
this.chain = list.toArray(new BeanPostConstructListener[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,7 +19,7 @@ public class ChainedBeanPostLoad implements BeanPostLoad {
|
||||
*/
|
||||
public ChainedBeanPostLoad(List<BeanPostLoad> list) {
|
||||
this.list = list;
|
||||
this.chain = list.toArray(new BeanPostLoad[list.size()]);
|
||||
this.chain = list.toArray(new BeanPostLoad[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,7 +24,7 @@ public class ChainedBeanQueryAdapter implements BeanQueryAdapter {
|
||||
*/
|
||||
public ChainedBeanQueryAdapter(List<BeanQueryAdapter> list) {
|
||||
this.list = list;
|
||||
BeanQueryAdapter[] c = list.toArray(new BeanQueryAdapter[list.size()]);
|
||||
BeanQueryAdapter[] c = list.toArray(new BeanQueryAdapter[0]);
|
||||
Arrays.sort(c, SORTER);
|
||||
this.chain = c;
|
||||
}
|
||||
@@ -89,10 +89,7 @@ public class ChainedBeanQueryAdapter implements BeanQueryAdapter {
|
||||
|
||||
@Override
|
||||
public int compare(BeanQueryAdapter o1, BeanQueryAdapter o2) {
|
||||
|
||||
int i1 = o1.getExecutionOrder();
|
||||
int i2 = o2.getExecutionOrder();
|
||||
return (i1 < i2 ? -1 : (i1 == i2 ? 0 : 1));
|
||||
return Integer.compare(o1.getExecutionOrder(), o2.getExecutionOrder());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import io.ebeaninternal.api.SpiCacheRegion;
|
||||
|
||||
class DCacheRegionNone implements SpiCacheRegion {
|
||||
|
||||
static SpiCacheRegion INSTANCE = new DCacheRegionNone();
|
||||
static final SpiCacheRegion INSTANCE = new DCacheRegionNone();
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
|
||||
@@ -31,13 +31,7 @@ public class DeployPropertyParserMap extends DeployParser {
|
||||
|
||||
@Override
|
||||
public String getDeployWord(String expression) {
|
||||
|
||||
String deployExpr = map.get(expression);
|
||||
if (deployExpr == null) {
|
||||
return null;
|
||||
} else {
|
||||
return deployExpr;
|
||||
}
|
||||
return map.get(expression);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,17 +27,19 @@ public final class DeployUpdateParser extends DeployParser {
|
||||
public String convertWord() {
|
||||
|
||||
String dbWord = getDeployWord(word);
|
||||
|
||||
if (dbWord != null) {
|
||||
return dbWord;
|
||||
}
|
||||
// maybe tableAlias.propertyName
|
||||
return convertSubword(0, word, null);
|
||||
return convertSubword(word);
|
||||
}
|
||||
|
||||
private String convertSubword(int start, String currentWord, StringBuilder localBuffer) {
|
||||
while (true) {
|
||||
private String convertSubword(String currentWord) {
|
||||
|
||||
int start = 0;
|
||||
StringBuilder localBuffer = null;
|
||||
|
||||
while (true) {
|
||||
int dotPos = currentWord.indexOf('.', start);
|
||||
if (start == 0 && dotPos == -1) {
|
||||
return currentWord;
|
||||
@@ -63,15 +65,11 @@ public final class DeployUpdateParser extends DeployParser {
|
||||
start = dotPos + 1;
|
||||
String remainder = currentWord.substring(start, currentWord.length());
|
||||
|
||||
//String dbWord = deployMap.get(remainder.toLowerCase());
|
||||
String dbWord = getDeployWord(remainder);
|
||||
if (dbWord != null) {
|
||||
// we have found a match for the remainder
|
||||
localBuffer.append(dbWord);
|
||||
return localBuffer.toString();
|
||||
} else {
|
||||
//
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,11 +82,7 @@ public final class DeployUpdateParser extends DeployParser {
|
||||
}
|
||||
|
||||
ElPropertyDeploy elProp = beanDescriptor.getElPropertyDeploy(expression);
|
||||
if (elProp != null) {
|
||||
return elProp.getDbColumn();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return elProp != null ? elProp.getDbColumn() : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ class DetermineAggPath {
|
||||
// a top level aggregation (so here we need to exclude Id property)
|
||||
return null;
|
||||
}
|
||||
return path.getManyPath(0, desc);
|
||||
return path.getManyPath(desc);
|
||||
}
|
||||
|
||||
static Path paths(String aggregation) {
|
||||
@@ -82,9 +82,9 @@ class DetermineAggPath {
|
||||
}
|
||||
}
|
||||
|
||||
String getManyPath(int pos, DeployBeanDescriptor<?> desc) {
|
||||
String getManyPath(DeployBeanDescriptor<?> desc) {
|
||||
int pos = 0;
|
||||
while (true) {
|
||||
|
||||
String path = paths[pos];
|
||||
DeployBeanProperty details = desc.getBeanProperty(path);
|
||||
if (details instanceof DeployBeanPropertyAssocMany<?>) {
|
||||
@@ -92,8 +92,7 @@ class DetermineAggPath {
|
||||
|
||||
} else if (details instanceof DeployBeanPropertyAssocOne<?>) {
|
||||
DeployBeanPropertyAssocOne<?> one = (DeployBeanPropertyAssocOne<?>) details;
|
||||
DeployBeanDescriptor<?> targetDesc = one.getTargetDeploy();
|
||||
desc = targetDesc;
|
||||
desc = one.getTargetDeploy();
|
||||
pos = pos + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ class DynamicPropertyAggregationFormula extends DynamicPropertyBase {
|
||||
|
||||
private final boolean aggregate;
|
||||
|
||||
private final BeanProperty asTarget;
|
||||
final BeanProperty asTarget;
|
||||
|
||||
private final String alias;
|
||||
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package io.ebeaninternal.server.deploy;
|
||||
|
||||
import io.ebeaninternal.server.query.SqlBeanLoad;
|
||||
|
||||
public class DynamicPropertyAggregationFormulaMTO extends DynamicPropertyAggregationFormula {
|
||||
|
||||
private final BeanPropertyAssocOne prop;
|
||||
|
||||
DynamicPropertyAggregationFormulaMTO(BeanPropertyAssocOne prop, String name, String parsedFormula, boolean aggregate, BeanProperty asTarget, String alias) {
|
||||
super(name, prop.getIdScalarType(), parsedFormula, aggregate, asTarget, alias);
|
||||
this.prop = prop;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAggregationManyToOne() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(SqlBeanLoad sqlBeanLoad) {
|
||||
Object value;
|
||||
try {
|
||||
value = prop.read(sqlBeanLoad.ctx());
|
||||
} catch (Exception e) {
|
||||
sqlBeanLoad.ctx().handleLoadError(fullName, e);
|
||||
return;
|
||||
}
|
||||
if (asTarget != null) {
|
||||
sqlBeanLoad.load(asTarget, value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,7 +11,7 @@ class ElementEntityBean implements EntityBean {
|
||||
|
||||
private Object[] data;
|
||||
|
||||
private EntityBeanIntercept intercept;
|
||||
private final EntityBeanIntercept intercept;
|
||||
|
||||
ElementEntityBean(String[] properties) {
|
||||
this.properties = properties;
|
||||
|
||||
@@ -15,7 +15,7 @@ class ElementHelpList implements ElementHelp {
|
||||
|
||||
private static class Collector implements ElementCollector {
|
||||
|
||||
private List<Object> list = new ArrayList<>();
|
||||
private final List<Object> list = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public void addElement(Object element) {
|
||||
|
||||
@@ -15,7 +15,7 @@ class ElementHelpMap implements ElementHelp {
|
||||
|
||||
private static class Collector implements ElementCollector {
|
||||
|
||||
private Map<Object, Object> map = new LinkedHashMap<>();
|
||||
private final Map<Object, Object> map = new LinkedHashMap<>();
|
||||
|
||||
@Override
|
||||
public void addElement(Object element) {
|
||||
|
||||
@@ -15,7 +15,7 @@ class ElementHelpSet implements ElementHelp {
|
||||
|
||||
private static class Collector implements ElementCollector {
|
||||
|
||||
private Set<Object> set = new LinkedHashSet<>();
|
||||
private final Set<Object> set = new LinkedHashSet<>();
|
||||
|
||||
@Override
|
||||
public void addElement(Object element) {
|
||||
|
||||
@@ -6,7 +6,7 @@ import io.ebeaninternal.server.type.ScalarType;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
class FormulaPropertyPath {
|
||||
final class FormulaPropertyPath {
|
||||
|
||||
private static final String[] AGG_FUNCTIONS = {"count", "max", "min", "avg", "sum"};
|
||||
|
||||
@@ -20,17 +20,22 @@ class FormulaPropertyPath {
|
||||
|
||||
private final String internalExpression;
|
||||
|
||||
private final String path;
|
||||
private final ElPropertyDeploy firstProp;
|
||||
|
||||
private final String parsedAggregation;
|
||||
|
||||
private boolean countDistinct;
|
||||
|
||||
private String cast;
|
||||
private String alias;
|
||||
|
||||
static STreeProperty create(BeanDescriptor<?> descriptor, String formula, String path) {
|
||||
return new FormulaPropertyPath(descriptor, formula, path).build();
|
||||
}
|
||||
|
||||
FormulaPropertyPath(BeanDescriptor<?> descriptor, String formula, String path) {
|
||||
this.descriptor = descriptor;
|
||||
this.formula = formula;
|
||||
this.path = path;
|
||||
|
||||
int openBracket = formula.indexOf('(');
|
||||
int closeBracket = formula.lastIndexOf(')');
|
||||
@@ -38,13 +43,21 @@ class FormulaPropertyPath {
|
||||
throw new IllegalStateException("Unable to parse formula [" + formula + "]");
|
||||
}
|
||||
outerFunction = formula.substring(0, openBracket).trim();
|
||||
internalExpression = trimDistinct(formula.substring(openBracket+1, closeBracket));
|
||||
internalExpression = trimDistinct(formula.substring(openBracket + 1, closeBracket));
|
||||
|
||||
if (closeBracket < formula.length() -1) {
|
||||
if (closeBracket < formula.length() - 1) {
|
||||
// ::CastType as foo
|
||||
String suffix = formula.substring(closeBracket+1).trim();
|
||||
parseSuffix(suffix);
|
||||
parseSuffix(formula.substring(closeBracket + 1).trim());
|
||||
}
|
||||
|
||||
DeployPropertyParser parser = descriptor.parser().setCatchFirst(true);
|
||||
String parsed = parser.parse(internalExpression);
|
||||
if (path != null) {
|
||||
// fetch("machineStats", "sum(hours), sum(totalKms)")
|
||||
parsed = parsed.replace("${}", "${" + path + "}");
|
||||
}
|
||||
this.parsedAggregation = buildFormula(parsed);
|
||||
this.firstProp = parser.getFirstProp();
|
||||
}
|
||||
|
||||
private void parseSuffix(String suffix) {
|
||||
@@ -93,42 +106,50 @@ class FormulaPropertyPath {
|
||||
|
||||
STreeProperty build() {
|
||||
|
||||
DeployPropertyParser parser = descriptor.parser().setCatchFirst(true);
|
||||
|
||||
String parsed = parser.parse(internalExpression);
|
||||
if (path != null) {
|
||||
// fetch("machineStats", "sum(hours), sum(totalKms)")
|
||||
parsed = parsed.replace("${}", "${" + path + "}");
|
||||
}
|
||||
|
||||
ElPropertyDeploy firstProp = parser.getFirstProp();
|
||||
|
||||
ScalarType<?> scalarType;
|
||||
if (cast != null) {
|
||||
scalarType = descriptor.getScalarType(cast);
|
||||
ScalarType<?> scalarType = descriptor.getScalarType(cast);
|
||||
if (scalarType == null) {
|
||||
throw new IllegalStateException("Unable to find scalarType for cast of ["+cast+"] on formula [" + formula + "] for type " + descriptor);
|
||||
}
|
||||
|
||||
} else if (isCount()) {
|
||||
scalarType = descriptor.getScalarType(Types.BIGINT);
|
||||
|
||||
} else if (isConcat()) {
|
||||
scalarType = descriptor.getScalarType(Types.VARCHAR);
|
||||
|
||||
} else {
|
||||
// determine scalarType based on first property found by parser
|
||||
if (firstProp != null) {
|
||||
scalarType = firstProp.getBeanProperty().getScalarType();
|
||||
} else {
|
||||
throw new IllegalStateException("unable to determine scalarType of formula [" + formula + "] for type " + descriptor + " - maybe use a cast like ::String ?");
|
||||
throw new IllegalStateException("Unable to find scalarType for cast of [" + cast + "] on formula [" + formula + "] for type " + descriptor);
|
||||
}
|
||||
return create(scalarType);
|
||||
}
|
||||
if (isCount()) {
|
||||
return create(descriptor.getScalarType(Types.BIGINT));
|
||||
}
|
||||
if (isConcat()) {
|
||||
return create(descriptor.getScalarType(Types.VARCHAR));
|
||||
}
|
||||
if (firstProp == null) {
|
||||
throw new IllegalStateException("unable to determine scalarType of formula [" + formula + "] for type " + descriptor + " - maybe use a cast like ::String ?");
|
||||
}
|
||||
|
||||
String logicalName = (alias == null) ? internalExpression : alias;
|
||||
BeanProperty targetProperty = descriptor._findBeanProperty(logicalName);
|
||||
String parsedAggregation = buildFormula(parsed);
|
||||
return new DynamicPropertyAggregationFormula(logicalName, scalarType, parsedAggregation, isAggregate(), targetProperty, alias);
|
||||
// determine scalarType based on first property found by parser
|
||||
final BeanProperty property = firstProp.getBeanProperty();
|
||||
if (!property.isAssocId()) {
|
||||
return create(property.getScalarType());
|
||||
} else {
|
||||
return createManyToOne(property);
|
||||
}
|
||||
}
|
||||
|
||||
private DynamicPropertyAggregationFormula create(ScalarType<?> scalarType) {
|
||||
|
||||
String logicalName = logicalName();
|
||||
return new DynamicPropertyAggregationFormula(logicalName, scalarType, parsedAggregation, isAggregate(), target(logicalName), alias);
|
||||
}
|
||||
|
||||
private DynamicPropertyAggregationFormula createManyToOne(BeanProperty property) {
|
||||
|
||||
String logicalName = logicalName();
|
||||
return new DynamicPropertyAggregationFormulaMTO((BeanPropertyAssocOne) property, logicalName, parsedAggregation, isAggregate(), target(logicalName), alias);
|
||||
}
|
||||
|
||||
private BeanProperty target(String logicalName) {
|
||||
return descriptor._findBeanProperty(logicalName);
|
||||
}
|
||||
|
||||
private String logicalName() {
|
||||
return (alias == null) ? internalExpression : alias;
|
||||
}
|
||||
|
||||
private boolean isAggregate() {
|
||||
|
||||
@@ -346,19 +346,20 @@ public final class IdBinderEmbedded implements IdBinder {
|
||||
public Object read(DbReadContext ctx) throws SQLException {
|
||||
|
||||
EntityBean embId = idDesc.createEntityBean();
|
||||
boolean notNull = true;
|
||||
boolean nullValue = true;
|
||||
|
||||
for (BeanProperty prop : props) {
|
||||
Object value = prop.readSet(ctx, embId);
|
||||
if (value == null) {
|
||||
notNull = false;
|
||||
Object value = prop.read(ctx);
|
||||
if (value != null) {
|
||||
prop.setValue(embId, value);
|
||||
nullValue = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (notNull) {
|
||||
return embId;
|
||||
} else {
|
||||
if (nullValue) {
|
||||
return null;
|
||||
} else {
|
||||
return embId;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ public final class ImportedIdSimple implements ImportedId, Comparable<ImportedId
|
||||
*/
|
||||
public static ImportedIdSimple[] sort(List<ImportedIdSimple> list) {
|
||||
|
||||
ImportedIdSimple[] importedIds = list.toArray(new ImportedIdSimple[list.size()]);
|
||||
ImportedIdSimple[] importedIds = list.toArray(new ImportedIdSimple[0]);
|
||||
|
||||
// sort into the same order as the BeanProperties
|
||||
Arrays.sort(importedIds, COMPARATOR);
|
||||
@@ -100,7 +100,7 @@ public final class ImportedIdSimple implements ImportedId, Comparable<ImportedId
|
||||
|
||||
@Override
|
||||
public int compareTo(ImportedIdSimple other) {
|
||||
return (position < other.position ? -1 : (position == other.position ? 0 : 1));
|
||||
return Integer.compare(position, other.position);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -561,7 +561,7 @@ public class DeployBeanDescriptor<T> {
|
||||
if (indexDefinitions == null) {
|
||||
return null;
|
||||
} else {
|
||||
return indexDefinitions.toArray(new IndexDefinition[indexDefinitions.size()]);
|
||||
return indexDefinitions.toArray(new IndexDefinition[0]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1267,6 +1267,7 @@ public class DeployBeanDescriptor<T> {
|
||||
/**
|
||||
* Returns the jackson annotated class, if jackson is present.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object /*AnnotatedClass*/ getJacksonAnnotatedClass() {
|
||||
if (jacksonAnnotatedClass == null) {
|
||||
jacksonAnnotatedClass = new DeployBeanObtainJackson(serverConfig, beanType).obtain();
|
||||
|
||||
@@ -249,7 +249,7 @@ public class DeployBeanProperty {
|
||||
/**
|
||||
* Wrap the ScalarType using a ScalarTypeConverter.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private ScalarType<?> wrapScalarType(Class<?> propertyType, ScalarType<?> scalarType, ScalarTypeConverter<?, ?> typeConverter) {
|
||||
if (typeConverter == null) {
|
||||
return scalarType;
|
||||
|
||||
@@ -71,7 +71,7 @@ public class DeployBeanPropertyLists {
|
||||
private final BeanPropertyAssocOne<?> unidirectional;
|
||||
private final BeanProperty orderColumn;
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public DeployBeanPropertyLists(BeanDescriptorMap owner, BeanDescriptor<?> desc, DeployBeanDescriptor<?> deploy) {
|
||||
this.desc = desc;
|
||||
|
||||
@@ -284,7 +284,7 @@ public class DeployBeanPropertyLists {
|
||||
* properties).
|
||||
*/
|
||||
public BeanProperty[] getBaseScalar() {
|
||||
return baseScalar.toArray(new BeanProperty[baseScalar.size()]);
|
||||
return baseScalar.toArray(new BeanProperty[0]);
|
||||
}
|
||||
|
||||
public BeanProperty getId() {
|
||||
@@ -292,11 +292,11 @@ public class DeployBeanPropertyLists {
|
||||
}
|
||||
|
||||
public BeanProperty[] getNonTransients() {
|
||||
return nonTransients.toArray(new BeanProperty[nonTransients.size()]);
|
||||
return nonTransients.toArray(new BeanProperty[0]);
|
||||
}
|
||||
|
||||
public BeanProperty[] getTransients() {
|
||||
return transients.toArray(new BeanProperty[transients.size()]);
|
||||
return transients.toArray(new BeanProperty[0]);
|
||||
}
|
||||
|
||||
public BeanProperty getVersionProperty() {
|
||||
@@ -304,23 +304,23 @@ public class DeployBeanPropertyLists {
|
||||
}
|
||||
|
||||
public BeanProperty[] getLocal() {
|
||||
return local.toArray(new BeanProperty[local.size()]);
|
||||
return local.toArray(new BeanProperty[0]);
|
||||
}
|
||||
|
||||
public BeanProperty[] getMutable() {
|
||||
return mutable.toArray(new BeanProperty[mutable.size()]);
|
||||
return mutable.toArray(new BeanProperty[0]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getEmbedded() {
|
||||
return embedded.toArray(new BeanPropertyAssocOne[embedded.size()]);
|
||||
return embedded.toArray(new BeanPropertyAssocOne[0]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOneImported() {
|
||||
return onesImported.toArray(new BeanPropertyAssocOne[onesImported.size()]);
|
||||
return onesImported.toArray(new BeanPropertyAssocOne[0]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOnes() {
|
||||
return ones.toArray(new BeanPropertyAssocOne[ones.size()]);
|
||||
return ones.toArray(new BeanPropertyAssocOne[0]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocOne<?>[] getOneExportedSave() {
|
||||
@@ -340,11 +340,11 @@ public class DeployBeanPropertyLists {
|
||||
}
|
||||
|
||||
public BeanProperty[] getNonMany() {
|
||||
return nonManys.toArray(new BeanProperty[nonManys.size()]);
|
||||
return nonManys.toArray(new BeanProperty[0]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocMany<?>[] getMany() {
|
||||
return manys.toArray(new BeanPropertyAssocMany[manys.size()]);
|
||||
return manys.toArray(new BeanPropertyAssocMany[0]);
|
||||
}
|
||||
|
||||
public BeanPropertyAssocMany<?>[] getManySave() {
|
||||
@@ -397,7 +397,7 @@ public class DeployBeanPropertyLists {
|
||||
list.add(prop);
|
||||
}
|
||||
}
|
||||
return list.toArray(new BeanProperty[list.size()]);
|
||||
return list.toArray(new BeanProperty[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -412,7 +412,7 @@ public class DeployBeanPropertyLists {
|
||||
list.add(prop);
|
||||
}
|
||||
}
|
||||
return list.toArray(new BeanProperty[list.size()]);
|
||||
return list.toArray(new BeanProperty[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -443,7 +443,7 @@ public class DeployBeanPropertyLists {
|
||||
}
|
||||
}
|
||||
|
||||
return (BeanPropertyAssocOne[]) list.toArray(new BeanPropertyAssocOne[list.size()]);
|
||||
return (BeanPropertyAssocOne[]) list.toArray(new BeanPropertyAssocOne[0]);
|
||||
}
|
||||
|
||||
private BeanPropertyAssocMany<?>[] getMany2Many() {
|
||||
@@ -454,7 +454,7 @@ public class DeployBeanPropertyLists {
|
||||
}
|
||||
}
|
||||
|
||||
return (BeanPropertyAssocMany[]) list.toArray(new BeanPropertyAssocMany[list.size()]);
|
||||
return (BeanPropertyAssocMany[]) list.toArray(new BeanPropertyAssocMany[0]);
|
||||
}
|
||||
|
||||
private BeanPropertyAssocMany<?>[] getMany(Mode mode) {
|
||||
@@ -476,7 +476,7 @@ public class DeployBeanPropertyLists {
|
||||
}
|
||||
}
|
||||
|
||||
return (BeanPropertyAssocMany[]) list.toArray(new BeanPropertyAssocMany[list.size()]);
|
||||
return (BeanPropertyAssocMany[]) list.toArray(new BeanPropertyAssocMany[0]);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
|
||||
@@ -54,7 +54,7 @@ public class DeployBeanTable {
|
||||
return idProperty == null ? null : createProperty(owner, idProperty);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private BeanProperty createProperty(BeanDescriptorMap owner, DeployBeanProperty prop) {
|
||||
|
||||
if (prop instanceof DeployBeanPropertyAssocOne<?>) {
|
||||
|
||||
@@ -106,7 +106,7 @@ public class DeployTableJoin {
|
||||
* Return the join columns.
|
||||
*/
|
||||
public DeployTableJoinColumn[] columns() {
|
||||
return columns.toArray(new DeployTableJoinColumn[columns.size()]);
|
||||
return columns.toArray(new DeployTableJoinColumn[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -183,6 +183,7 @@ class AnnotationAssocManys extends AnnotationParser {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void readElementCollection(DeployBeanPropertyAssocMany<?> prop, ElementCollection elementCollection) {
|
||||
|
||||
prop.setElementCollection();
|
||||
|
||||
@@ -189,7 +189,7 @@ public class AnnotationAssocOnes extends AnnotationParser {
|
||||
|
||||
private void checkForNoConstraint(DeployBeanPropertyAssocOne<?> prop, JoinColumn joinColumn) {
|
||||
ForeignKey foreignKey = joinColumn.foreignKey();
|
||||
if (foreignKey != null && foreignKey.value() == ConstraintMode.NO_CONSTRAINT) {
|
||||
if (foreignKey.value() == ConstraintMode.NO_CONSTRAINT) {
|
||||
prop.setForeignKey(new PropertyForeignKey());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -496,7 +496,7 @@ public class AnnotationFields extends AnnotationParser {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private ScalarTypeEncryptedWrapper<?> createScalarType(DeployBeanProperty prop, ScalarType<?> st) {
|
||||
|
||||
// Use Java Encryptor wrapping the logical scalar type
|
||||
|
||||
@@ -199,7 +199,7 @@ public class DeployCreateProperties {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private DeployBeanProperty createManyType(DeployBeanDescriptor<?> desc, Class<?> targetType, ManyType manyType) {
|
||||
|
||||
try {
|
||||
@@ -213,7 +213,7 @@ public class DeployCreateProperties {
|
||||
return new DeployBeanPropertyAssocMany(desc, targetType, manyType);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private DeployBeanProperty createProp(DeployBeanDescriptor<?> desc, Field field) {
|
||||
|
||||
Class<?> propertyType = field.getType();
|
||||
|
||||
@@ -175,7 +175,7 @@ class ElMatchBuilder {
|
||||
final Set<?> set;
|
||||
final ElPropertyValue elGetValue;
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public InSet(Set<?> set, ElPropertyValue elGetValue) {
|
||||
this.set = new HashSet(set);
|
||||
this.elGetValue = elGetValue;
|
||||
|
||||
@@ -58,13 +58,12 @@ public class ElPropertyChainBuilder {
|
||||
* Build the immutable ElGetChain from the build information.
|
||||
*/
|
||||
public ElPropertyChain build() {
|
||||
return new ElPropertyChain(containsMany, embedded, expression, chain.toArray(new ElPropertyValue[chain.size()]));
|
||||
return new ElPropertyChain(containsMany, embedded, expression, chain.toArray(new ElPropertyValue[0]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Permits to set whole chain as embedded when the leaf is embedded
|
||||
* @param embedded
|
||||
*/
|
||||
*/
|
||||
public void setEmbedded(boolean embedded) {
|
||||
this.embedded = embedded;
|
||||
}
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ import java.io.IOException;
|
||||
|
||||
class CaseInsensitiveEqualExpression extends AbstractValueExpression {
|
||||
|
||||
private boolean not;
|
||||
private final boolean not;
|
||||
|
||||
CaseInsensitiveEqualExpression(String propertyName, Object value, boolean not) {
|
||||
super(propertyName, value);
|
||||
|
||||
@@ -303,9 +303,7 @@ public class DefaultExampleExpression implements SpiExpression, ExampleExpressio
|
||||
*/
|
||||
private boolean isZero(Object value) {
|
||||
if (value instanceof Number) {
|
||||
Number num = (Number) value;
|
||||
double doubleValue = num.doubleValue();
|
||||
if (doubleValue == 0) {
|
||||
if (((Number) value).doubleValue() == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
|
||||
private final ExpressionList<T> parentExprList;
|
||||
|
||||
protected ExpressionFactory expr;
|
||||
protected final ExpressionFactory expr;
|
||||
|
||||
String allDocNestedPath;
|
||||
|
||||
@@ -495,7 +495,7 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> select(FetchGroup fetchGroup) {
|
||||
public Query<T> select(FetchGroup<T> fetchGroup) {
|
||||
return query.select(fetchGroup);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Generally speaking tests the value at a given path in the JSON document.
|
||||
@@ -91,8 +92,8 @@ class JsonPathExpression extends AbstractExpression {
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
JsonPathExpression that = (JsonPathExpression) other;
|
||||
if (value != null ? !value.equals(that.value) : that.value != null) return false;
|
||||
return upperValue != null ? upperValue.equals(that.upperValue) : that.upperValue == null;
|
||||
if (!Objects.equals(value, that.value)) return false;
|
||||
return Objects.equals(upperValue, that.upperValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Utility to help isSame methods.
|
||||
@@ -12,14 +13,14 @@ public class Same {
|
||||
* Return true if both values are null or both an not null.
|
||||
*/
|
||||
public static boolean sameByNull(Object v1, Object v2) {
|
||||
return v1 == null ? v2 == null : v2 != null;
|
||||
return (v1 == null) == (v2 == null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Null safe equals check.
|
||||
*/
|
||||
public static boolean sameByValue(Object v1, Object v2) {
|
||||
return v1 == null ? v2 == null : v1.equals(v2);
|
||||
return Objects.equals(v1, v2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -261,10 +261,7 @@ class EqlAdapter<T> extends EQLBaseListener {
|
||||
}
|
||||
|
||||
private boolean isValue(String text) {
|
||||
if (text.length() == 1 && (text.equals("(") || text.equals(")") || text.equals(","))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return text.length() != 1 || (!text.equals("(") && !text.equals(")") && !text.equals(","));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,7 +5,7 @@ import java.util.Map;
|
||||
|
||||
class OperatorMapping {
|
||||
|
||||
Map<String, EqlOperator> map = new HashMap<>();
|
||||
final Map<String, EqlOperator> map = new HashMap<>();
|
||||
|
||||
public OperatorMapping() {
|
||||
map.put("eq", EqlOperator.EQ);
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package io.ebeaninternal.server.lib.util;
|
||||
package io.ebeaninternal.server.lib;
|
||||
|
||||
/**
|
||||
* String utility for adding strings together.
|
||||
@@ -1,12 +0,0 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=iso-8859-1">
|
||||
<TITLE>AvajeLib</TITLE>
|
||||
</HEAD>
|
||||
<Body BGCOLOR="#ffffff">
|
||||
General utility objects.
|
||||
|
||||
<P>Provides general utility objects.
|
||||
</P>
|
||||
</Body>
|
||||
</HTML>
|
||||
@@ -49,7 +49,7 @@ public class DLoadContext implements LoadContext {
|
||||
private final boolean disableLazyLoading;
|
||||
private final boolean disableReadAudit;
|
||||
private final boolean includeSoftDeletes;
|
||||
protected final boolean useDocStore;
|
||||
final boolean useDocStore;
|
||||
|
||||
/**
|
||||
* The path relative to the root of the object graph.
|
||||
@@ -137,7 +137,7 @@ public class DLoadContext implements LoadContext {
|
||||
/**
|
||||
* Return the query plan label of the origin query.
|
||||
*/
|
||||
public String getPlanLabel() {
|
||||
String getPlanLabel() {
|
||||
return planLabel;
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ public class DLoadContext implements LoadContext {
|
||||
registerSecondaryNode(many, props);
|
||||
}
|
||||
|
||||
protected boolean isBeanCacheGet() {
|
||||
boolean isBeanCacheGet() {
|
||||
return useBeanCache.isGet();
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@ public class DLoadContext implements LoadContext {
|
||||
return new ObjectGraphNode(origin, path);
|
||||
}
|
||||
|
||||
protected String getFullPath(String path) {
|
||||
String getFullPath(String path) {
|
||||
if (relativePath == null) {
|
||||
return path;
|
||||
} else {
|
||||
@@ -295,12 +295,11 @@ public class DLoadContext implements LoadContext {
|
||||
getManyContext(path).register(bc);
|
||||
}
|
||||
|
||||
protected DLoadBeanContext getBeanContext(String path) {
|
||||
DLoadBeanContext getBeanContext(String path) {
|
||||
if (path == null) {
|
||||
return rootBeanContext;
|
||||
}
|
||||
DLoadBeanContext beanContext = beanMap.computeIfAbsent(path, p -> createBeanContext(p, defaultBatchSize, null));
|
||||
return beanContext;
|
||||
return beanMap.computeIfAbsent(path, p -> createBeanContext(p, defaultBatchSize, null));
|
||||
}
|
||||
|
||||
private void registerSecondaryNode(boolean many, OrmQueryProperties props) {
|
||||
@@ -321,27 +320,23 @@ public class DLoadContext implements LoadContext {
|
||||
}
|
||||
}
|
||||
|
||||
protected DLoadManyContext getManyContext(String path) {
|
||||
DLoadManyContext getManyContext(String path) {
|
||||
if (path == null) {
|
||||
throw new RuntimeException("path is null?");
|
||||
}
|
||||
DLoadManyContext ctx = manyMap.computeIfAbsent(path, p -> createManyContext(p, defaultBatchSize, null));
|
||||
return ctx;
|
||||
return manyMap.computeIfAbsent(path, p -> createManyContext(p, defaultBatchSize, null));
|
||||
}
|
||||
|
||||
private DLoadManyContext createManyContext(String path, int batchSize, OrmQueryProperties queryProps) {
|
||||
|
||||
BeanPropertyAssocMany<?> p = (BeanPropertyAssocMany<?>) getBeanProperty(rootDescriptor, path);
|
||||
|
||||
return new DLoadManyContext(this, p, path, batchSize, queryProps);
|
||||
}
|
||||
|
||||
private DLoadBeanContext createBeanContext(String path, int batchSize, OrmQueryProperties queryProps) {
|
||||
|
||||
BeanPropertyAssoc<?> p = (BeanPropertyAssoc<?>) getBeanProperty(rootDescriptor, path);
|
||||
BeanDescriptor<?> targetDescriptor = p.getTargetDescriptor();
|
||||
|
||||
return new DLoadBeanContext(this, targetDescriptor, path, batchSize, queryProps);
|
||||
return new DLoadBeanContext(this, p.getTargetDescriptor(), path, batchSize, queryProps);
|
||||
}
|
||||
|
||||
private BeanProperty getBeanProperty(BeanDescriptor<?> desc, String path) {
|
||||
@@ -351,7 +346,7 @@ public class DLoadContext implements LoadContext {
|
||||
/**
|
||||
* Propagate the original query settings (draft, asOf etc) to the secondary queries.
|
||||
*/
|
||||
public void propagateQueryState(SpiQuery<?> query, boolean docStoreMapped) {
|
||||
void propagateQueryState(SpiQuery<?> query, boolean docStoreMapped) {
|
||||
if (useDocStore && docStoreMapped) {
|
||||
query.setUseDocStore(true);
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@ import io.ebeaninternal.server.core.PersistRequest;
|
||||
import io.ebeaninternal.server.core.PersistRequestBean;
|
||||
import io.ebeaninternal.server.core.PersistRequestUpdateSql;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -29,6 +29,8 @@ import java.util.List;
|
||||
*/
|
||||
public final class BatchControl {
|
||||
|
||||
private static final Object DUMMY = new Object();
|
||||
|
||||
/**
|
||||
* Used to sort queue entries by depth.
|
||||
*/
|
||||
@@ -46,6 +48,17 @@ public final class BatchControl {
|
||||
*/
|
||||
private final HashMap<String, BatchedBeanHolder> beanHoldMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Set of beans in this batch. This is used to ensure that a single bean instance is not included
|
||||
* in the batch twice (two separate insert requests etc).
|
||||
*/
|
||||
private final IdentityHashMap<Object, Object> persistedBeans = new IdentityHashMap<>();
|
||||
|
||||
/**
|
||||
* Helper to determine statement ordering based on depth (and type).
|
||||
*/
|
||||
private final BatchDepthOrder depthOrder = new BatchDepthOrder();
|
||||
|
||||
private final SpiTransaction transaction;
|
||||
|
||||
/**
|
||||
@@ -63,13 +76,10 @@ public final class BatchControl {
|
||||
|
||||
private boolean batchFlushOnMixed = true;
|
||||
|
||||
private int maxDepth;
|
||||
|
||||
/**
|
||||
* Size of the largest buffer.
|
||||
*/
|
||||
private int bufferMax;
|
||||
private int topCounter;
|
||||
|
||||
private Queue earlyQueue;
|
||||
private Queue lateQueue;
|
||||
@@ -183,6 +193,14 @@ public final class BatchControl {
|
||||
*/
|
||||
private boolean addToBatch(PersistRequestBean<?> request) throws BatchedSqlException {
|
||||
|
||||
Object alreadyInBatch = persistedBeans.put(request.getEntityBean(), DUMMY);
|
||||
if (alreadyInBatch != null) {
|
||||
// special case where the same bean instance has already been
|
||||
// added to the batch (doesn't really occur with non-batching
|
||||
// as the bean gets changed from dirty to loaded earlier)
|
||||
return false;
|
||||
}
|
||||
|
||||
BatchedBeanHolder beanHolder = getBeanHolder(request);
|
||||
int bufferSize = beanHolder.append(request);
|
||||
|
||||
@@ -227,14 +245,14 @@ public final class BatchControl {
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush without resetting the topOrder (maintains the depth info).
|
||||
* Flush without resetting the depth info.
|
||||
*/
|
||||
public void flush() throws BatchedSqlException {
|
||||
flushBuffer(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flush with a reset the topOrder (fully empty the batch).
|
||||
* Flush with a reset of the depth info.
|
||||
*/
|
||||
public void flushReset() throws BatchedSqlException {
|
||||
flushBuffer(true);
|
||||
@@ -246,8 +264,8 @@ public final class BatchControl {
|
||||
public void clear() {
|
||||
pstmtHolder.clear();
|
||||
beanHoldMap.clear();
|
||||
maxDepth = 0;
|
||||
topCounter = 0;
|
||||
depthOrder.clear();
|
||||
persistedBeans.clear();
|
||||
}
|
||||
|
||||
private void flushBuffer(boolean resetTop) throws BatchedSqlException {
|
||||
@@ -289,10 +307,10 @@ public final class BatchControl {
|
||||
for (BatchedBeanHolder beanHolder : bsArray) {
|
||||
beanHolder.executeNow();
|
||||
}
|
||||
|
||||
persistedBeans.clear();
|
||||
if (resetTop) {
|
||||
beanHoldMap.clear();
|
||||
maxDepth = 0;
|
||||
depthOrder.clear();
|
||||
}
|
||||
} catch (BatchedSqlException e) {
|
||||
// clear the batch on error in case we want to
|
||||
@@ -306,76 +324,35 @@ public final class BatchControl {
|
||||
* Return an entry for the given type description. The type description is
|
||||
* typically the bean class name (or table name for MapBeans).
|
||||
*/
|
||||
private BatchedBeanHolder getBeanHolder(PersistRequestBean<?> request) throws BatchedSqlException {
|
||||
private BatchedBeanHolder getBeanHolder(PersistRequestBean<?> request) {
|
||||
|
||||
BeanDescriptor<?> beanDescriptor = request.getBeanDescriptor();
|
||||
BatchedBeanHolder batchBeanHolder = beanHoldMap.get(beanDescriptor.rootName());
|
||||
int depth = transaction.depth();
|
||||
BeanDescriptor<?> desc = request.getBeanDescriptor();
|
||||
|
||||
// batching by bean type AND depth
|
||||
String key = desc.rootName() + ":" + depth;
|
||||
|
||||
BatchedBeanHolder batchBeanHolder = beanHoldMap.get(key);
|
||||
if (batchBeanHolder == null) {
|
||||
int relativeDepth = transaction.depth();
|
||||
|
||||
int beanDepth = 100 + relativeDepth;
|
||||
if (relativeDepth == 0 && !beanHoldMap.isEmpty()) {
|
||||
// could be non-cascading or uni-directional relationship
|
||||
// so see look for a 'parent' in the beanHoldMap
|
||||
int maybe = relativeToParentDepth(beanDescriptor);
|
||||
if (maybe != -1) {
|
||||
beanDepth = maybe;
|
||||
} else {
|
||||
// additional "top level" bean type ordered by save() order
|
||||
beanDepth += ++topCounter;
|
||||
}
|
||||
}
|
||||
|
||||
maxDepth = Math.max(maxDepth, beanDepth);
|
||||
batchBeanHolder = new BatchedBeanHolder(this, beanDescriptor, beanDepth);
|
||||
beanHoldMap.put(beanDescriptor.rootName(), batchBeanHolder);
|
||||
int ordering = depthOrder.orderingFor(depth);
|
||||
batchBeanHolder = new BatchedBeanHolder(this, desc, ordering);
|
||||
beanHoldMap.put(key, batchBeanHolder);
|
||||
}
|
||||
return batchBeanHolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a depth based on imported relationships (to a parent that is already in the buffer).
|
||||
*/
|
||||
private int relativeToParentDepth(BeanDescriptor<?> beanDescriptor) {
|
||||
|
||||
BeanPropertyAssocOne<?>[] imported = beanDescriptor.propertiesOneImported();
|
||||
if (imported.length == 0) {
|
||||
// a top level type so just maintain the order relative to the current depth
|
||||
return maxDepth + 1;
|
||||
}
|
||||
|
||||
int parentMaxDepth = -1;
|
||||
|
||||
for (BeanPropertyAssocOne<?> parent : imported) {
|
||||
BatchedBeanHolder parentBatch = beanHoldMap.get(parent.getTargetDescriptor().rootName());
|
||||
if (parentBatch != null) {
|
||||
// deeper that the parent
|
||||
parentMaxDepth = Math.max(parentMaxDepth, parentBatch.getOrder() + 1);
|
||||
}
|
||||
}
|
||||
return parentMaxDepth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this holds no persist requests.
|
||||
*/
|
||||
private boolean isBeansEmpty() {
|
||||
if (beanHoldMap.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
for (BatchedBeanHolder beanHolder : beanHoldMap.values()) {
|
||||
if (!beanHolder.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return persistedBeans.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the BatchedBeanHolder's ready for sorting and executing.
|
||||
*/
|
||||
private BatchedBeanHolder[] getBeanHolderArray() {
|
||||
return beanHoldMap.values().toArray(new BatchedBeanHolder[beanHoldMap.size()]);
|
||||
return beanHoldMap.values().toArray(new BatchedBeanHolder[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,13 +19,7 @@ public class BatchDepthComparator implements Comparator<BatchedBeanHolder>, Seri
|
||||
@Override
|
||||
public int compare(BatchedBeanHolder b1, BatchedBeanHolder b2) {
|
||||
|
||||
if (b1.getOrder() < b2.getOrder()) {
|
||||
return -1;
|
||||
}
|
||||
if (b1.getOrder() == b2.getOrder()) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
return Integer.compare(b1.getOrder(), b2.getOrder());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package io.ebeaninternal.server.persist;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Helper to determine batch execution order for BatchedBeanHolders.
|
||||
*/
|
||||
class BatchDepthOrder {
|
||||
|
||||
private final Map<Integer, Counter> map = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Return the batch order for the given depth.
|
||||
*/
|
||||
int orderingFor(int depth) {
|
||||
final Counter slot = map.computeIfAbsent(depth, integer -> new Counter());
|
||||
return (depth * 100) + slot.increment();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
map.clear();
|
||||
}
|
||||
|
||||
private static class Counter {
|
||||
|
||||
int count;
|
||||
|
||||
public int increment() {
|
||||
return count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import io.ebeaninternal.server.core.PersistRequestBean;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.IdentityHashMap;
|
||||
|
||||
/**
|
||||
* Holds lists of persist requests for beans of a given type.
|
||||
@@ -21,8 +20,6 @@ import java.util.IdentityHashMap;
|
||||
*/
|
||||
public class BatchedBeanHolder {
|
||||
|
||||
private static final Object DUMMY = new Object();
|
||||
|
||||
/**
|
||||
* The owning queue.
|
||||
*/
|
||||
@@ -50,12 +47,6 @@ public class BatchedBeanHolder {
|
||||
*/
|
||||
private ArrayList<PersistRequest> deletes;
|
||||
|
||||
/**
|
||||
* Set of beans in this batch. This is used to ensure that a single bean instance is not included
|
||||
* in the batch twice (two separate insert requests etc).
|
||||
*/
|
||||
private final IdentityHashMap<Object, Object> persistedBeans = new IdentityHashMap<>();
|
||||
|
||||
/**
|
||||
* Create a new entry with a given type and depth.
|
||||
*/
|
||||
@@ -99,7 +90,6 @@ public class BatchedBeanHolder {
|
||||
updates = new ArrayList<>();
|
||||
control.executeNow(bufferedUpdates);
|
||||
}
|
||||
persistedBeans.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -123,14 +113,6 @@ public class BatchedBeanHolder {
|
||||
*/
|
||||
public int append(PersistRequestBean<?> request) {
|
||||
|
||||
Object alreadyInBatch = persistedBeans.put(request.getEntityBean(), DUMMY);
|
||||
if (alreadyInBatch != null) {
|
||||
// special case where the same bean instance has already been
|
||||
// added to the batch (doesn't really occur with non-batching
|
||||
// as the bean gets changed from dirty to loaded earlier)
|
||||
return 0;
|
||||
}
|
||||
|
||||
request.setBatched();
|
||||
|
||||
switch (request.getType()) {
|
||||
@@ -161,10 +143,4 @@ public class BatchedBeanHolder {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is empty containing no batched beans.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return persistedBeans.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,10 +114,9 @@ public class BatchedPstmtHolder {
|
||||
// the flush may get called recursively in executeBatch/postExecute.
|
||||
// which leads that we process stmtMap.values() twice in the loop.
|
||||
// So we copy the values, that we want to flush and clear it immediately.
|
||||
BatchedPstmt[] values = stmtMap.values().toArray(new BatchedPstmt[stmtMap.values().size()]);
|
||||
BatchedPstmt[] values = stmtMap.values().toArray(new BatchedPstmt[0]);
|
||||
clear();
|
||||
|
||||
// this loop
|
||||
for (BatchedPstmt bs : values) {
|
||||
try {
|
||||
if (!isError) {
|
||||
@@ -130,12 +129,8 @@ public class BatchedPstmtHolder {
|
||||
next = next.getNextException();
|
||||
}
|
||||
|
||||
if (firstError == null) {
|
||||
firstError = ex;
|
||||
errorSql = bs.getSql();
|
||||
} else {
|
||||
logger.error("Error executing batched PreparedStatement", ex);
|
||||
}
|
||||
firstError = ex;
|
||||
errorSql = bs.getSql();
|
||||
isError = true;
|
||||
|
||||
} finally {
|
||||
@@ -147,7 +142,6 @@ public class BatchedPstmtHolder {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (firstError != null) {
|
||||
String msg = "Error when batch flush on sql: " + errorSql;
|
||||
throw new BatchedSqlException(msg, firstError);
|
||||
|
||||
@@ -108,7 +108,7 @@ public class Binder {
|
||||
if (isLob(dt)) {
|
||||
bindBuf.append("[LOB]");
|
||||
} else {
|
||||
bindBuf.append(String.valueOf(val));
|
||||
bindBuf.append(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,7 +377,7 @@ public final class DefaultPersister implements Persister {
|
||||
* Recursively delete the bean. This calls back to the EbeanServer.
|
||||
*/
|
||||
private int deleteRecurse(EntityBean detailBean, Transaction t, DeleteMode deleteMode) {
|
||||
return deleteRequest(createRequest(detailBean, t, deleteMode.persistType()));
|
||||
return deleteRequest(createDeleteRequest(detailBean, t, deleteMode.persistType()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -578,12 +578,11 @@ public final class DefaultPersister implements Persister {
|
||||
public int delete(EntityBean bean, Transaction t, boolean permanent) {
|
||||
|
||||
Type deleteType = permanent ? Type.DELETE_PERMANENT : Type.DELETE;
|
||||
PersistRequestBean<EntityBean> originalRequest = createRequest(bean, t, deleteType);
|
||||
|
||||
PersistRequestBean<EntityBean> originalRequest = createDeleteRequest(bean, t, deleteType);
|
||||
if (originalRequest.isHardDeleteDraft()) {
|
||||
// a hard delete of a draftable bean so first we need to delete the associated 'live' bean
|
||||
// due to FK constraint and then after that execute the original delete of the draft bean
|
||||
return deleteRequest(createPublishRequest(originalRequest.createReference(), t, Type.DELETE_PERMANENT, Flags.PUBLISH), originalRequest);
|
||||
return deleteRequest(createDeleteRequest(originalRequest.createReference(), t, Type.DELETE_PERMANENT, Flags.PUBLISH), originalRequest);
|
||||
|
||||
} else {
|
||||
// normal delete or soft delete
|
||||
@@ -639,8 +638,8 @@ public final class DefaultPersister implements Persister {
|
||||
t.depth(-1);
|
||||
t.checkBatchEscalationOnCollection();
|
||||
}
|
||||
for (Object aBeanList : beanList) {
|
||||
deleteRecurse((EntityBean) aBeanList, t, deleteMode);
|
||||
for (Object bean : beanList) {
|
||||
deleteRecurse((EntityBean) bean, t, deleteMode);
|
||||
}
|
||||
if (children) {
|
||||
t.flushBatchOnCollection();
|
||||
@@ -1245,25 +1244,15 @@ public final class DefaultPersister implements Persister {
|
||||
* perform an insert, update or delete.
|
||||
*/
|
||||
private <T> PersistRequestBean<T> createRequest(T bean, Transaction t, PersistRequest.Type type) {
|
||||
return createRequestInternal(bean, t, type, Flags.ZERO);
|
||||
return createRequestInternal(bean, t, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the Persist Request Object additionally specifying the publish status.
|
||||
*/
|
||||
<T> PersistRequestBean<T> createPublishRequest(T bean, Transaction t, PersistRequest.Type type, int flags) {
|
||||
return createRequestInternal(bean, t, type, Flags.unsetRecuse(flags));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the Persist Request Object additionally specifying the publish status.
|
||||
*/
|
||||
private <T> PersistRequestBean<T> createRequestInternal(T bean, Transaction t, PersistRequest.Type type, int flags) {
|
||||
private <T> PersistRequestBean<T> createRequestInternal(T bean, Transaction t, PersistRequest.Type type) {
|
||||
BeanManager<T> mgr = getBeanManager(bean);
|
||||
if (mgr == null) {
|
||||
throw new PersistenceException(errNotRegistered(bean.getClass()));
|
||||
}
|
||||
return createRequest(bean, t, null, mgr, type, flags);
|
||||
return createRequest(bean, t, null, mgr, type, Flags.ZERO);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1273,9 +1262,6 @@ public final class DefaultPersister implements Persister {
|
||||
*/
|
||||
private <T> PersistRequestBean<T> createRequestRecurse(T bean, Transaction t, Object parentBean, int flags) {
|
||||
BeanManager<T> mgr = getBeanManager(bean);
|
||||
if (mgr == null) {
|
||||
throw new PersistenceException(errNotRegistered(bean.getClass()));
|
||||
}
|
||||
BeanDescriptor<T> desc = mgr.getBeanDescriptor();
|
||||
EntityBean entityBean = (EntityBean) bean;
|
||||
PersistRequest.Type type;
|
||||
@@ -1294,10 +1280,26 @@ public final class DefaultPersister implements Persister {
|
||||
* Create the Persist Request Object that wraps all the objects used to
|
||||
* perform an insert, update or delete.
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private <T> PersistRequestBean<T> createRequest(T bean, Transaction t, Object parentBean, BeanManager<?> mgr,
|
||||
PersistRequest.Type type, int flags) {
|
||||
|
||||
// no delete requests come here
|
||||
return new PersistRequestBean(server, bean, parentBean, mgr, (SpiTransaction) t, persistExecute, type, flags);
|
||||
}
|
||||
|
||||
<T> PersistRequestBean<T> createDeleteRemoved(T bean, Transaction t, PersistRequest.Type type, int flags) {
|
||||
return createDeleteRequest(bean, t, type, Flags.unsetRecurse(flags));
|
||||
}
|
||||
|
||||
private <T> PersistRequestBean<T> createDeleteRequest(EntityBean bean, Transaction t, Type type) {
|
||||
return createDeleteRequest(bean, t, type, Flags.ZERO);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private <T> PersistRequestBean<T> createDeleteRequest(Object bean, Transaction t, PersistRequest.Type type, int flags) {
|
||||
|
||||
BeanManager<T> mgr = getBeanManager(bean);
|
||||
if (type == Type.DELETE_PERMANENT) {
|
||||
type = Type.DELETE;
|
||||
} else if (type == Type.DELETE && mgr.getBeanDescriptor().isSoftDelete()) {
|
||||
@@ -1305,7 +1307,9 @@ public final class DefaultPersister implements Persister {
|
||||
type = Type.DELETE_SOFT;
|
||||
}
|
||||
|
||||
return new PersistRequestBean(server, bean, parentBean, mgr, (SpiTransaction) t, persistExecute, type, flags);
|
||||
PersistRequestBean<T> request = new PersistRequestBean<>(server, (T)bean, null, mgr, (SpiTransaction) t, persistExecute, type, flags);
|
||||
request.initForSoftDelete();
|
||||
return request;
|
||||
}
|
||||
|
||||
private String errNotRegistered(Class<?> beanClass) {
|
||||
@@ -1323,8 +1327,12 @@ public final class DefaultPersister implements Persister {
|
||||
* </p>
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> BeanManager<T> getBeanManager(T bean) {
|
||||
private <T> BeanManager<T> getBeanManager(Object bean) {
|
||||
|
||||
return (BeanManager<T>) beanDescriptorManager.getBeanManager(bean.getClass());
|
||||
BeanManager<T> mgr = (BeanManager<T>) beanDescriptorManager.getBeanManager(bean.getClass());
|
||||
if (mgr == null) {
|
||||
throw new PersistenceException(errNotRegistered(bean.getClass()));
|
||||
}
|
||||
return mgr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,9 +18,9 @@ public enum DeleteMode {
|
||||
*/
|
||||
HARD(PersistRequest.Type.DELETE_PERMANENT, true);
|
||||
|
||||
private boolean hard;
|
||||
private final boolean hard;
|
||||
|
||||
private PersistRequest.Type persistType;
|
||||
private final PersistRequest.Type persistType;
|
||||
|
||||
DeleteMode(PersistRequest.Type persistType, boolean hard) {
|
||||
this.persistType = persistType;
|
||||
|
||||
@@ -122,7 +122,7 @@ public final class Flags {
|
||||
return set(state, RECURSE);
|
||||
}
|
||||
|
||||
public static int unsetRecuse(int state) {
|
||||
public static int unsetRecurse(int state) {
|
||||
return unset(state, RECURSE);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.util.Collection;
|
||||
*/
|
||||
public class MultiValueWrapper {
|
||||
private final Collection<?> values;
|
||||
private Class<?> type;
|
||||
private final Class<?> type;
|
||||
|
||||
public MultiValueWrapper(Collection<?> values, Class<?> type) {
|
||||
this.values = values;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user